Add tests for returning a C++ reference type, rvalue and const reference (#6149)

Part of #6148.
This commit is contained in:
Boaz Brickner
2025-10-02 08:49:10 +00:00
committed by GitHub
parent 31d88633e3
commit a16102b249
+281 -47
View File
@@ -14,18 +14,18 @@
// Lvalue reference as a parameter type
// ============================================================================
// --- lvalue_ref.h
// --- param_lvalue_ref.h
struct S {};
struct T {};
auto TakesLValue(S&) -> void;
// --- call_lvalue_ref.carbon
// --- call_param_lvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp library "lvalue_ref.h";
import Cpp library "param_lvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
@@ -34,43 +34,43 @@ fn F() {
//@dump-sem-ir-end
}
// --- fail_lvalue_ref.carbon
// --- fail_param_lvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp library "lvalue_ref.h";
import Cpp library "param_lvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
var v: Cpp.S;
let s: Cpp.S = v;
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesLValue' [CppInteropParseError]
// CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesLValue' [CppInteropParseError]
// CHECK:STDERR: 18 | Cpp.TakesLValue(s);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-9]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: expects an lvalue for 1st argument [CppInteropParseNote]
// CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE-9]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./param_lvalue_ref.h:5:6: note: candidate function not viable: expects an lvalue for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesLValue(S&) -> void;
// CHECK:STDERR: | ^ ~~
// CHECK:STDERR:
Cpp.TakesLValue(s);
var t: Cpp.T;
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesLValue' [CppInteropParseError]
// CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesLValue' [CppInteropParseError]
// CHECK:STDERR: 29 | Cpp.TakesLValue(t);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S &' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./param_lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S &' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesLValue(S&) -> void;
// CHECK:STDERR: | ^ ~~
// CHECK:STDERR:
Cpp.TakesLValue(t);
var u: Cpp.S;
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE+8]]:35: error: no matching function for call to 'TakesLValue' [CppInteropParseError]
// CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE+8]]:35: error: no matching function for call to 'TakesLValue' [CppInteropParseError]
// CHECK:STDERR: 40 | Cpp.TakesLValue(u as const Cpp.S);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-31]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote]
// CHECK:STDERR: fail_param_lvalue_ref.carbon:[[@LINE-31]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./param_lvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesLValue(S&) -> void;
// CHECK:STDERR: | ^ ~~
// CHECK:STDERR:
@@ -82,18 +82,18 @@ fn F() {
// Rvalue reference as a parameter type
// ============================================================================
// --- rvalue_ref.h
// --- param_rvalue_ref.h
struct S {};
struct T {};
auto TakesRValue(S&&) -> void;
// --- call_rvalue_ref.carbon
// --- call_param_rvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp library "rvalue_ref.h";
import Cpp library "param_rvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
@@ -101,11 +101,11 @@ fn F() {
//@dump-sem-ir-end
}
// --- todo_fail_value_arg_for_rvalue_ref.carbon
// --- todo_fail_param_value_arg_for_rvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp library "rvalue_ref.h";
import Cpp library "param_rvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
@@ -118,41 +118,41 @@ fn F() {
//@dump-sem-ir-end
}
// --- fail_rvalue_ref.carbon
// --- fail_param_rvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp library "rvalue_ref.h";
import Cpp library "param_rvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
var s: Cpp.S;
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesRValue' [CppInteropParseError]
// CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesRValue' [CppInteropParseError]
// CHECK:STDERR: 17 | Cpp.TakesRValue(s);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-8]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: expects an rvalue for 1st argument [CppInteropParseNote]
// CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE-8]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./param_rvalue_ref.h:5:6: note: candidate function not viable: expects an rvalue for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void;
// CHECK:STDERR: | ^ ~~~
// CHECK:STDERR:
Cpp.TakesRValue(s);
var t: Cpp.T;
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesRValue' [CppInteropParseError]
// CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE+8]]:20: error: no matching function for call to 'TakesRValue' [CppInteropParseError]
// CHECK:STDERR: 28 | Cpp.TakesRValue(t);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-19]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE-19]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./param_rvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void;
// CHECK:STDERR: | ^ ~~~
// CHECK:STDERR:
Cpp.TakesRValue(t);
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE+8]]:47: error: no matching function for call to 'TakesRValue' [CppInteropParseError]
// CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE+8]]:47: error: no matching function for call to 'TakesRValue' [CppInteropParseError]
// CHECK:STDERR: 38 | Cpp.TakesRValue(({} as Cpp.S) as const Cpp.S);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-29]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote]
// CHECK:STDERR: fail_param_rvalue_ref.carbon:[[@LINE-29]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./param_rvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void;
// CHECK:STDERR: | ^ ~~~
// CHECK:STDERR:
@@ -164,18 +164,18 @@ fn F() {
// Const reference as a parameter type
// ============================================================================
// --- const_lvalue_ref.h
// --- param_const_lvalue_ref.h
struct S {};
struct T {};
auto TakesConstLValue(const S&) -> void;
// --- call_const_lvalue_ref.carbon
// --- call_param_const_lvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp library "const_lvalue_ref.h";
import Cpp library "param_const_lvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
@@ -186,11 +186,11 @@ fn F() {
//@dump-sem-ir-end
}
// --- fail_const_lvalue_ref.carbon
// --- fail_param_const_lvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp library "const_lvalue_ref.h";
import Cpp library "param_const_lvalue_ref.h";
fn F() {
//@dump-sem-ir-begin
@@ -199,19 +199,19 @@ fn F() {
// TODO: The diagnostic here is wrong; we're internally using `addr` but this
// is not `addr self`.
let s: Cpp.S = {};
// CHECK:STDERR: fail_const_lvalue_ref.carbon:[[@LINE+5]]:24: error: `addr self` method cannot be invoked on a value [AddrSelfIsNonRef]
// CHECK:STDERR: fail_param_const_lvalue_ref.carbon:[[@LINE+5]]:24: error: `addr self` method cannot be invoked on a value [AddrSelfIsNonRef]
// CHECK:STDERR: Cpp.TakesConstLValue(s);
// CHECK:STDERR: ^
// CHECK:STDERR: fail_const_lvalue_ref.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR: fail_param_const_lvalue_ref.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
Cpp.TakesConstLValue(s);
var t: Cpp.T;
// CHECK:STDERR: fail_const_lvalue_ref.carbon:[[@LINE+8]]:25: error: no matching function for call to 'TakesConstLValue' [CppInteropParseError]
// CHECK:STDERR: fail_param_const_lvalue_ref.carbon:[[@LINE+8]]:25: error: no matching function for call to 'TakesConstLValue' [CppInteropParseError]
// CHECK:STDERR: 29 | Cpp.TakesConstLValue(t);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_const_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./const_lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'const S' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: fail_param_const_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./param_const_lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'const S' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesConstLValue(const S&) -> void;
// CHECK:STDERR: | ^ ~~~~~~~~
// CHECK:STDERR:
@@ -219,7 +219,79 @@ fn F() {
//@dump-sem-ir-end
}
// CHECK:STDOUT: --- call_lvalue_ref.carbon
// ============================================================================
// Lvalue reference as return type
// ============================================================================
// --- fail_todo_call_return_lvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp inline '''
struct S {};
auto ReturnsLValue() -> S&;
''';
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_call_return_lvalue_ref.carbon:[[@LINE+4]]:19: error: semantics TODO: `Unsupported: return type: S &` [SemanticsTodo]
// CHECK:STDERR: let s: Cpp.S* = Cpp.ReturnsLValue();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
let s: Cpp.S* = Cpp.ReturnsLValue();
//@dump-sem-ir-end
}
// ============================================================================
// Rvalue reference as return type
// ============================================================================
// --- fail_todo_call_return_rvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp inline '''
struct S {};
auto ReturnsRValue() -> S&&;
''';
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_call_return_rvalue_ref.carbon:[[@LINE+4]]:18: error: semantics TODO: `Unsupported: return type: S &&` [SemanticsTodo]
// CHECK:STDERR: var s: Cpp.S = Cpp.ReturnsRValue();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
var s: Cpp.S = Cpp.ReturnsRValue();
//@dump-sem-ir-end
}
// ============================================================================
// Const reference as return type
// ============================================================================
// --- fail_todo_call_return_const_lvalue_ref.carbon
library "[[@TEST_NAME]]";
import Cpp inline '''
struct S {};
auto ReturnConstLValue() -> const S&;
''';
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_todo_call_return_const_lvalue_ref.carbon:[[@LINE+4]]:24: error: semantics TODO: `Unsupported: return type: const S &` [SemanticsTodo]
// CHECK:STDERR: var s: const Cpp.S = Cpp.ReturnConstLValue();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
var s: const Cpp.S = Cpp.ReturnConstLValue();
//@dump-sem-ir-end
}
// CHECK:STDOUT: --- call_param_lvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -284,7 +356,7 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_lvalue_ref.carbon
// CHECK:STDOUT: --- fail_param_lvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -398,7 +470,7 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- call_rvalue_ref.carbon
// CHECK:STDOUT: --- call_param_rvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -456,7 +528,7 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- todo_fail_value_arg_for_rvalue_ref.carbon
// CHECK:STDOUT: --- todo_fail_param_value_arg_for_rvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -522,7 +594,7 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_rvalue_ref.carbon
// CHECK:STDOUT: --- fail_param_rvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -624,7 +696,7 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- call_const_lvalue_ref.carbon
// CHECK:STDOUT: --- call_param_const_lvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -703,7 +775,7 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_const_lvalue_ref.carbon
// CHECK:STDOUT: --- fail_param_const_lvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
@@ -801,3 +873,165 @@ fn F() {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_call_return_lvalue_ref.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %S: type = class_type @S [concrete]
// CHECK:STDOUT: %ptr: type = ptr_type %S [concrete]
// CHECK:STDOUT: %pattern_type: type = pattern_type %ptr [concrete]
// CHECK:STDOUT: %.041: type = cpp_overload_set_type @ReturnsLValue [concrete]
// CHECK:STDOUT: %.03d: %.041 = cpp_overload_set_value @ReturnsLValue [concrete]
// CHECK:STDOUT: %ReturnsLValue.type: type = fn_type @ReturnsLValue [concrete]
// CHECK:STDOUT: %ReturnsLValue: %ReturnsLValue.type = struct_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .S = %S.decl
// CHECK:STDOUT: .ReturnsLValue = %.03d
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
// CHECK:STDOUT: %.03d: %.041 = cpp_overload_set_value @ReturnsLValue [concrete = constants.%.03d]
// CHECK:STDOUT: %ReturnsLValue.decl: %ReturnsLValue.type = fn_decl @ReturnsLValue [concrete = constants.%ReturnsLValue] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type = binding_pattern s [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp.ref.loc16_19: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnsLValue.ref: %.041 = name_ref ReturnsLValue, imports.%.03d [concrete = constants.%.03d]
// CHECK:STDOUT: %ReturnsLValue.call: init <error> = call imports.%ReturnsLValue.decl()
// CHECK:STDOUT: %.loc16: type = splice_block %ptr [concrete = constants.%ptr] {
// CHECK:STDOUT: %Cpp.ref.loc16_10: <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: %ptr = bind_name s, <error> [concrete = <error>]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_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: %pattern_type.7da: type = pattern_type %S [concrete]
// CHECK:STDOUT: %.c60: type = cpp_overload_set_type @ReturnsRValue [concrete]
// CHECK:STDOUT: %.99d: %.c60 = cpp_overload_set_value @ReturnsRValue [concrete]
// CHECK:STDOUT: %ReturnsRValue.type: type = fn_type @ReturnsRValue [concrete]
// CHECK:STDOUT: %ReturnsRValue: %ReturnsRValue.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %S, () [concrete]
// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.type.df1: type = fn_type @DestroyT.as_type.as.Destroy.impl.Op, @DestroyT.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.cc2: %DestroyT.as_type.as.Destroy.impl.Op.type.df1 = struct_value () [concrete]
// CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .S = %S.decl
// CHECK:STDOUT: .ReturnsRValue = %.99d
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
// CHECK:STDOUT: %.99d: %.c60 = cpp_overload_set_value @ReturnsRValue [concrete = constants.%.99d]
// CHECK:STDOUT: %ReturnsRValue.decl: %ReturnsRValue.type = fn_decl @ReturnsRValue [concrete = constants.%ReturnsRValue] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.7da = binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.7da = var_pattern %s.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt
// CHECK:STDOUT: %Cpp.ref.loc16_18: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnsRValue.ref: %.c60 = name_ref ReturnsRValue, imports.%.99d [concrete = constants.%.99d]
// CHECK:STDOUT: %ReturnsRValue.call: init <error> = call imports.%ReturnsRValue.decl()
// CHECK:STDOUT: assign %s.var, <error>
// CHECK:STDOUT: %.loc16_13: type = splice_block %S.ref [concrete = constants.%S] {
// CHECK:STDOUT: %Cpp.ref.loc16_10: <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: }
// CHECK:STDOUT: %s: ref %S = bind_name s, %s.var
// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%S, () [concrete = constants.%facet_value]
// CHECK:STDOUT: %.loc16_3: %type_where = converted constants.%S, %facet_value [concrete = constants.%facet_value]
// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %s.var, constants.%DestroyT.as_type.as.Destroy.impl.Op.cc2
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %s.var, %DestroyT.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr: %ptr.5c7 = addr_of %s.var
// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_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: type = const_type %S [concrete]
// CHECK:STDOUT: %pattern_type.9be: type = pattern_type %const [concrete]
// CHECK:STDOUT: %.c99: type = cpp_overload_set_type @ReturnConstLValue [concrete]
// CHECK:STDOUT: %.bf8: %.c99 = cpp_overload_set_value @ReturnConstLValue [concrete]
// CHECK:STDOUT: %ReturnConstLValue.type: type = fn_type @ReturnConstLValue [concrete]
// CHECK:STDOUT: %ReturnConstLValue: %ReturnConstLValue.type = struct_value () [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %const, () [concrete]
// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.type.31d: type = fn_type @DestroyT.as_type.as.Destroy.impl.Op, @DestroyT.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.818: %DestroyT.as_type.as.Destroy.impl.Op.type.31d = struct_value () [concrete]
// CHECK:STDOUT: %ptr.ff5: type = ptr_type %const [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .S = %S.decl
// CHECK:STDOUT: .ReturnConstLValue = %.bf8
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
// CHECK:STDOUT: %.bf8: %.c99 = cpp_overload_set_value @ReturnConstLValue [concrete = constants.%.bf8]
// CHECK:STDOUT: %ReturnConstLValue.decl: %ReturnConstLValue.type = fn_decl @ReturnConstLValue [concrete = constants.%ReturnConstLValue] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: } {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %s.patt: %pattern_type.9be = binding_pattern s [concrete]
// CHECK:STDOUT: %s.var_patt: %pattern_type.9be = var_pattern %s.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s.var: ref %const = var %s.var_patt
// CHECK:STDOUT: %Cpp.ref.loc16_24: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %ReturnConstLValue.ref: %.c99 = name_ref ReturnConstLValue, imports.%.bf8 [concrete = constants.%.bf8]
// CHECK:STDOUT: %ReturnConstLValue.call: init <error> = call imports.%ReturnConstLValue.decl()
// CHECK:STDOUT: assign %s.var, <error>
// CHECK:STDOUT: %.loc16_10: type = splice_block %const [concrete = constants.%const] {
// CHECK:STDOUT: %Cpp.ref.loc16_16: <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]
// CHECK:STDOUT: }
// CHECK:STDOUT: %s: ref %const = bind_name s, %s.var
// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%const, () [concrete = constants.%facet_value]
// CHECK:STDOUT: %.loc16_3: %type_where = converted constants.%const, %facet_value [concrete = constants.%facet_value]
// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %s.var, constants.%DestroyT.as_type.as.Destroy.impl.Op.818
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %s.var, %DestroyT.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr: %ptr.ff5 = addr_of %s.var
// CHECK:STDOUT: %DestroyT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: