Skip to content

Conversation

ivanaivanovska
Copy link
Contributor

@ivanaivanovska ivanaivanovska commented Sep 19, 2025

Following up on comments from #5891 ( 1, 2).

Lowering CppOverloadSetValue as an empty struct value, using context.GetLiteralAsValue(). Also changed its constant kind to InstConstantKind::WheneverPossible, same as CppOverloadSetType.

Part of #5915

@ivanaivanovska ivanaivanovska marked this pull request as ready for review September 24, 2025 13:36
@github-actions github-actions bot requested a review from jonmeow September 24, 2025 13:37
Copy link
Contributor

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR says it's adding lowering, but doesn't have any changes to lowering tests. Can you please add tests that demonstrate why this is being lowered?

@ivanaivanovska
Copy link
Contributor Author

This PR says it's adding lowering, but doesn't have any changes to lowering tests. Can you please add tests that demonstrate why this is being lowered?

I added the test toolchain/lower/testdata/interop/cpp/overloads.carbon, with the the example from the comment, however I don't see this lowered. When I also tried to build and run this example in a demo, that also worked as expected:

// main.carbon
library "Main";
import Core library "io";

import Cpp inline '''
int foo() {
  return 0;
}
int foo(int a) {
  return a + 1;
}
''';

fn Run() {
  var n: i32 = 1;
  n = Cpp.foo(n);
  Core.Print(n);
} 
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link main.o \--output=demo_carbon
$ ./demo_carbon
2 

While I'll look into why this is not lowered (maybe filling in HandleInst?), @zygoloid could you please confirm that this should be lowered in this example? Wouldn't the issue be visible somewhere when running it, if something is not lowered properly?

Copy link
Contributor

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the test toolchain/lower/testdata/interop/cpp/overloads.carbon, with the the example from the comment, however I don't see this lowered.

Looking at that comment, I see:

import Cpp inline "void foo(); void foo(int);";
fn F() {
  Cpp.foo;
}

It looks like you added a function call to that example, but I think that actually drifts away from what zygoloid was suggesting to test. In the above example, Cpp.foo is the actual value of the statement.

You might want to look at toolchain/lower/testdata/primitives/type_values.carbon for an example test that may also be helpful, if zygoloid's example doesn't work -- in particular putting the value on a return boundary.


auto HandleInst(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
SemIR::CppOverloadSetValue /*inst*/) -> void {
// lowered as an empty struct value.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// lowered as an empty struct value.
// Lowered as an empty struct value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@ivanaivanovska
Copy link
Contributor Author

It looks like you added a function call to that example, but I think that actually drifts away from what zygoloid was suggesting to test. In the above example, Cpp.foo is the actual value of the statement.

I changed the test to use the value Cpp.foo, but I still see no difference. You can see the output in the current version of toolchain/lower/testdata/interop/cpp/overloads.carbon.

You might want to look at toolchain/lower/testdata/primitives/type_values.carbon for an example test that may also be helpful, if zygoloid's example doesn't work -- in particular putting the value on a return boundary.

I also tried the following, but without any success:

library "[[@TEST_NAME]]";

import Cpp inline "void foo(); void foo(int);";

fn F() {
  // CHECK:STDERR: import_overload_set.carbon:[[@LINE+4]]:11: error: semantics TODO: `HandleAutoTypeLiteral` [SemanticsTodo]
  // CHECK:STDERR:   var x : auto = Cpp.foo;
  // CHECK:STDERR:           ^~~~
  // CHECK:STDERR:
  var x : auto = Cpp.foo;
  x();
}

As well as:

// --- import_overload_set.carbon

library "[[@TEST_NAME]]";

import Cpp inline "void foo(); void foo(int);";

fn F() -> type {
  // CHECK:STDERR: import_overload_set.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `<type of Cpp.foo>` to `type` [ConversionFailureNonTypeToFacet]
  // CHECK:STDERR:   return Cpp.foo;
  // CHECK:STDERR:   ^~~~~~~~~~~~~~~
  // CHECK:STDERR: import_overload_set.carbon:[[@LINE+4]]:3: note: type `<type of Cpp.foo>` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessNote]
  // CHECK:STDERR:   return Cpp.foo;
  // CHECK:STDERR:   ^~~~~~~~~~~~~~~
  // CHECK:STDERR:
  return Cpp.foo;
}

The code of EmitAsConstant() seems to be executed, maybe it is cleaned up afterwards?

If you have any further suggestions please let me know. Thanks.

@jonmeow
Copy link
Contributor

jonmeow commented Sep 29, 2025

Here's a test that uses a generic to expose a value:

import Cpp inline '''
  void foo();
  void foo(int);
''';

fn EchoValue[ValueT:! Core.Copy](value:! ValueT) -> ValueT {
  return value;
}

fn CppOverloadSet() {
  EchoValue(Cpp.foo);
}

If you replace Cpp.foo with true, then you'll see something like:

// CHECK:STDOUT: define linkonce_odr i1 @_CEchoValue.Main.13326305c9417809() !dbg !18 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT:   ret i1 true, !dbg !19
// CHECK:STDOUT: }

So that's demonstrating that, if Cpp.foo can be treated as a value, it'll show up in the LLVM IR.

However, this crashes right now because you're not handling the new instructions in TypeIterator. Also, this approach assumes you implementing copying of the value (Core.Copy), which hopefully is reasonable for an overload? I think it'd be harder to test if it remains non-copyable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants