Expose C++ reference returns as Carbon reference returns (#6618)

Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
This commit is contained in:
Geoff Romer
2026-01-16 18:08:42 +00:00
committed by GitHub
co-authored by Carbon Infra Bot
parent 94d9bff541
commit 95eb7b16bb
5 changed files with 162 additions and 258 deletions
@@ -248,7 +248,7 @@ import Cpp library "return_lvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
let s: Cpp.S* = Cpp.ReturnsLValue();
let ref s: Cpp.S = Cpp.ReturnsLValue();
//@dump-sem-ir-end
}
@@ -270,7 +270,7 @@ import Cpp library "return_rvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
var s: Cpp.S* = Cpp.ReturnsRValue();
let ref s: Cpp.S = Cpp.ReturnsRValue();
//@dump-sem-ir-end
}
@@ -292,7 +292,7 @@ import Cpp library "return_const_lvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
var s: const Cpp.S* = Cpp.ReturnConstLValue();
let ref s: const Cpp.S = Cpp.ReturnConstLValue();
//@dump-sem-ir-end
}
@@ -303,16 +303,17 @@ library "[[@TEST_NAME]]";
import Cpp library "return_const_lvalue_ref.h";
fn F() {
// CHECK:STDERR: fail_call_return_const_lvalue_ref_const_correctness.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `const (const Cpp.S*)` to `Cpp.S*` [ConversionFailure]
// CHECK:STDERR: var s: Cpp.S* = Cpp.ReturnConstLValue();
// CHECK:STDERR: ^~~~~~~~~~~~~
// CHECK:STDERR: fail_call_return_const_lvalue_ref_const_correctness.carbon:[[@LINE+4]]:3: note: type `const (const Cpp.S*)` does not implement interface `Core.ImplicitAs(Cpp.S*)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: var s: Cpp.S* = Cpp.ReturnConstLValue();
// CHECK:STDERR: ^~~~~~~~~~~~~
// CHECK:STDERR: fail_call_return_const_lvalue_ref_const_correctness.carbon:[[@LINE+7]]:22: error: cannot implicitly convert expression of type `const Cpp.S` to `Cpp.S` [ConversionFailure]
// CHECK:STDERR: let ref s: Cpp.S = Cpp.ReturnConstLValue();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_call_return_const_lvalue_ref_const_correctness.carbon:[[@LINE+4]]:22: note: type `const Cpp.S` does not implement interface `Core.ImplicitAs(Cpp.S)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: let ref s: Cpp.S = Cpp.ReturnConstLValue();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
var s: Cpp.S* = Cpp.ReturnConstLValue();
let ref s: Cpp.S = Cpp.ReturnConstLValue();
}
// CHECK:STDOUT: --- call_param_lvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
@@ -849,17 +850,12 @@ fn F() {
// CHECK:STDOUT: --- call_return_lvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %S [concrete]
// CHECK:STDOUT: %pattern_type.259: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %S [concrete]
// CHECK:STDOUT: %ReturnsLValue.cpp_overload_set.type: type = cpp_overload_set_type @ReturnsLValue.cpp_overload_set [concrete]
// CHECK:STDOUT: %ReturnsLValue.cpp_overload_set.value: %ReturnsLValue.cpp_overload_set.type = cpp_overload_set_value @ReturnsLValue.cpp_overload_set [concrete]
// CHECK:STDOUT: %const: type = const_type %ptr [concrete]
// CHECK:STDOUT: %ReturnsLValue.type: type = fn_type @ReturnsLValue [concrete]
// CHECK:STDOUT: %ReturnsLValue: %ReturnsLValue.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete]
// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -870,53 +866,34 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
// CHECK:STDOUT: %ReturnsLValue.cpp_overload_set.value: %ReturnsLValue.cpp_overload_set.type = cpp_overload_set_value @ReturnsLValue.cpp_overload_set [concrete = constants.%ReturnsLValue.cpp_overload_set.value]
// CHECK:STDOUT: %ReturnsLValue.decl: %ReturnsLValue.type = fn_decl @ReturnsLValue [concrete = constants.%ReturnsLValue] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %ReturnsLValue.decl: %ReturnsLValue.type = fn_decl @ReturnsLValue [concrete = constants.%ReturnsLValue] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.259 = value_binding_pattern s [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type = ref_binding_pattern s [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp.ref.loc8_19: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8_22: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnsLValue.ref: %ReturnsLValue.cpp_overload_set.type = name_ref ReturnsLValue, imports.%ReturnsLValue.cpp_overload_set.value [concrete = constants.%ReturnsLValue.cpp_overload_set.value]
// CHECK:STDOUT: %ReturnsLValue.call: init %const = call imports.%ReturnsLValue.decl()
// CHECK:STDOUT: %.loc8_15: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref.loc8_10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnsLValue.call: ref %S = call imports.%ReturnsLValue.decl()
// CHECK:STDOUT: %.loc8: type = splice_block %S.ref [concrete = constants.%S] {
// CHECK:STDOUT: %Cpp.ref.loc8_14: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
// CHECK:STDOUT: %ptr: type = ptr_type %S.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc8_37.1: init %ptr = as_compatible %ReturnsLValue.call
// CHECK:STDOUT: %.loc8_37.2: init %ptr = converted %ReturnsLValue.call, %.loc8_37.1
// CHECK:STDOUT: %.loc8_37.3: ref %ptr = temporary_storage
// CHECK:STDOUT: %.loc8_37.4: ref %ptr = temporary %.loc8_37.3, %.loc8_37.2
// CHECK:STDOUT: %.loc8_37.5: %ptr = acquire_value %.loc8_37.4
// CHECK:STDOUT: %s: %ptr = value_binding s, %.loc8_37.5
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %.loc8_37.4, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%.loc8_37.4)
// CHECK:STDOUT: %s: ref %S = ref_binding s, %ReturnsLValue.call
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: %ptr) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- call_return_rvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %S [concrete]
// CHECK:STDOUT: %pattern_type.259: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %S [concrete]
// CHECK:STDOUT: %ReturnsRValue.cpp_overload_set.type: type = cpp_overload_set_type @ReturnsRValue.cpp_overload_set [concrete]
// CHECK:STDOUT: %ReturnsRValue.cpp_overload_set.value: %ReturnsRValue.cpp_overload_set.type = cpp_overload_set_value @ReturnsRValue.cpp_overload_set [concrete]
// CHECK:STDOUT: %const: type = const_type %ptr [concrete]
// CHECK:STDOUT: %ReturnsRValue.type: type = fn_type @ReturnsRValue [concrete]
// CHECK:STDOUT: %ReturnsRValue: %ReturnsRValue.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete]
// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -927,54 +904,35 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
// CHECK:STDOUT: %ReturnsRValue.cpp_overload_set.value: %ReturnsRValue.cpp_overload_set.type = cpp_overload_set_value @ReturnsRValue.cpp_overload_set [concrete = constants.%ReturnsRValue.cpp_overload_set.value]
// CHECK:STDOUT: %ReturnsRValue.decl: %ReturnsRValue.type = fn_decl @ReturnsRValue [concrete = constants.%ReturnsRValue] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %ReturnsRValue.decl: %ReturnsRValue.type = fn_decl @ReturnsRValue [concrete = constants.%ReturnsRValue] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.259 = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.259 = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type = ref_binding_pattern s [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %ptr = var %s.var_patt
// CHECK:STDOUT: %Cpp.ref.loc8_19: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8_22: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnsRValue.ref: %ReturnsRValue.cpp_overload_set.type = name_ref ReturnsRValue, imports.%ReturnsRValue.cpp_overload_set.value [concrete = constants.%ReturnsRValue.cpp_overload_set.value]
// CHECK:STDOUT: %ReturnsRValue.call: init %const = call imports.%ReturnsRValue.decl()
// CHECK:STDOUT: %.loc8_3.1: init %ptr = as_compatible %ReturnsRValue.call
// CHECK:STDOUT: %.loc8_3.2: init %ptr = converted %ReturnsRValue.call, %.loc8_3.1
// CHECK:STDOUT: assign %s.var, %.loc8_3.2
// CHECK:STDOUT: %.loc8_15: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref.loc8_10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnsRValue.call: ref %S = call imports.%ReturnsRValue.decl()
// CHECK:STDOUT: %.loc8: type = splice_block %S.ref [concrete = constants.%S] {
// CHECK:STDOUT: %Cpp.ref.loc8_14: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
// CHECK:STDOUT: %ptr: type = ptr_type %S.ref [concrete = constants.%ptr]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: ref %ptr = ref_binding s, %s.var
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %s.var, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%s.var)
// CHECK:STDOUT: %s: ref %S = ref_binding s, %ReturnsRValue.call
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: %ptr) = "no_op";
// CHECK:STDOUT:
// CHECK:STDOUT: --- call_return_const_lvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %const.e39: type = const_type %S [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %const.e39 [concrete]
// CHECK:STDOUT: %pattern_type.32f: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %const: type = const_type %S [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %const [concrete]
// CHECK:STDOUT: %ReturnConstLValue.cpp_overload_set.type: type = cpp_overload_set_type @ReturnConstLValue.cpp_overload_set [concrete]
// CHECK:STDOUT: %ReturnConstLValue.cpp_overload_set.value: %ReturnConstLValue.cpp_overload_set.type = cpp_overload_set_value @ReturnConstLValue.cpp_overload_set [concrete]
// CHECK:STDOUT: %const.179: type = const_type %ptr [concrete]
// CHECK:STDOUT: %ReturnConstLValue.type: type = fn_type @ReturnConstLValue [concrete]
// CHECK:STDOUT: %ReturnConstLValue: %ReturnConstLValue.type = struct_value () [concrete]
// CHECK:STDOUT: %DestroyOp.type: type = fn_type @DestroyOp [concrete]
// CHECK:STDOUT: %DestroyOp: %DestroyOp.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -985,37 +943,23 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
// CHECK:STDOUT: %ReturnConstLValue.cpp_overload_set.value: %ReturnConstLValue.cpp_overload_set.type = cpp_overload_set_value @ReturnConstLValue.cpp_overload_set [concrete = constants.%ReturnConstLValue.cpp_overload_set.value]
// CHECK:STDOUT: %ReturnConstLValue.decl: %ReturnConstLValue.type = fn_decl @ReturnConstLValue [concrete = constants.%ReturnConstLValue] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: %ReturnConstLValue.decl: %ReturnConstLValue.type = fn_decl @ReturnConstLValue [concrete = constants.%ReturnConstLValue] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.32f = ref_binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.32f = var_pattern %s.patt [concrete]
// CHECK:STDOUT: %s.patt: %pattern_type = ref_binding_pattern s [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %ptr = var %s.var_patt
// CHECK:STDOUT: %Cpp.ref.loc8_25: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Cpp.ref.loc8_28: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnConstLValue.ref: %ReturnConstLValue.cpp_overload_set.type = name_ref ReturnConstLValue, imports.%ReturnConstLValue.cpp_overload_set.value [concrete = constants.%ReturnConstLValue.cpp_overload_set.value]
// CHECK:STDOUT: %ReturnConstLValue.call: init %const.179 = call imports.%ReturnConstLValue.decl()
// CHECK:STDOUT: %.loc8_3.1: init %ptr = as_compatible %ReturnConstLValue.call
// CHECK:STDOUT: %.loc8_3.2: init %ptr = converted %ReturnConstLValue.call, %.loc8_3.1
// CHECK:STDOUT: assign %s.var, %.loc8_3.2
// CHECK:STDOUT: %.loc8_21: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref.loc8_16: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnConstLValue.call: ref %const = call imports.%ReturnConstLValue.decl()
// CHECK:STDOUT: %.loc8: type = splice_block %const [concrete = constants.%const] {
// CHECK:STDOUT: %Cpp.ref.loc8_20: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
// CHECK:STDOUT: %const: type = const_type %S.ref [concrete = constants.%const.e39]
// CHECK:STDOUT: %ptr: type = ptr_type %const [concrete = constants.%ptr]
// CHECK:STDOUT: %const: type = const_type %S.ref [concrete = constants.%const]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: ref %ptr = ref_binding s, %s.var
// CHECK:STDOUT: %DestroyOp.bound: <bound method> = bound_method %s.var, constants.%DestroyOp
// CHECK:STDOUT: %DestroyOp.call: init %empty_tuple.type = call %DestroyOp.bound(%s.var)
// CHECK:STDOUT: %s: ref %const = ref_binding s, %ReturnConstLValue.call
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @DestroyOp(%self.param: %ptr) = "no_op";
// CHECK:STDOUT: