Allow derived->base conversions with compatible qualifiers (#7415)

Move the existing derived->base conversion earlier in
`PerformBuiltinConversion`, into the block that handles qualifier
conversions. This allows, for example, converting from `partial Derived`
to `partial Base` -- see the tests in
`toolchain/check/testdata/class/inheritance/derived_to_base.carbon`.
This commit is contained in:
Nicholas Bishop
2026-06-24 21:08:24 +00:00
committed by GitHub
parent f2d99f31f0
commit 885b1110d5
20 changed files with 345 additions and 288 deletions
@@ -1696,12 +1696,13 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: }
// CHECK:STDOUT: %d.ref: %Derived = name_ref d, %d
// CHECK:STDOUT: %instance_data.ref: %S.elem = name_ref instance_data, @S.%.1 [concrete = @S.%.1]
// CHECK:STDOUT: %.loc12_36.1: ref %S = class_element_access %d.ref, element0
// CHECK:STDOUT: %.loc12_36.2: ref %S = converted %d.ref, %.loc12_36.1
// CHECK:STDOUT: %.loc12_36.3: ref %i32 = class_element_access %.loc12_36.2, element0
// CHECK:STDOUT: %.loc12_36.4: %i32 = acquire_value %.loc12_36.3
// CHECK:STDOUT: %.loc12_36.1: %S = as_compatible %d.ref
// CHECK:STDOUT: %.loc12_36.2: ref %S = class_element_access %.loc12_36.1, element0
// CHECK:STDOUT: %.loc12_36.3: ref %S = converted %d.ref, %.loc12_36.2
// CHECK:STDOUT: %.loc12_36.4: ref %i32 = class_element_access %.loc12_36.3, element0
// CHECK:STDOUT: %.loc12_36.5: %i32 = acquire_value %.loc12_36.4
// CHECK:STDOUT: %i32.loc12: type = type_literal constants.%i32 [concrete = constants.%i32]
// CHECK:STDOUT: %instance_data: %i32 = value_binding instance_data, %.loc12_36.4
// CHECK:STDOUT: %instance_data: %i32 = value_binding instance_data, %.loc12_36.5
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %static_data.patt: %pattern_type.6b6 = value_binding_pattern static_data [concrete = constants.%static_data.patt.405]
// CHECK:STDOUT: }
@@ -1763,12 +1764,13 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: }
// CHECK:STDOUT: %self.ref: %Derived = name_ref self, %self
// CHECK:STDOUT: %instance_data.ref: %C.elem = name_ref instance_data, @C.%.1 [concrete = @C.%.1]
// CHECK:STDOUT: %.loc10_41.1: ref %C = class_element_access %self.ref, element0
// CHECK:STDOUT: %.loc10_41.2: ref %C = converted %self.ref, %.loc10_41.1
// CHECK:STDOUT: %.loc10_41.3: ref %i32 = class_element_access %.loc10_41.2, element0
// CHECK:STDOUT: %.loc10_41.4: %i32 = acquire_value %.loc10_41.3
// CHECK:STDOUT: %.loc10_41.1: %C = as_compatible %self.ref
// CHECK:STDOUT: %.loc10_41.2: ref %C = class_element_access %.loc10_41.1, element0
// CHECK:STDOUT: %.loc10_41.3: ref %C = converted %self.ref, %.loc10_41.2
// CHECK:STDOUT: %.loc10_41.4: ref %i32 = class_element_access %.loc10_41.3, element0
// CHECK:STDOUT: %.loc10_41.5: %i32 = acquire_value %.loc10_41.4
// CHECK:STDOUT: %i32.loc10: type = type_literal constants.%i32 [concrete = constants.%i32]
// CHECK:STDOUT: %instance_data: %i32 = value_binding instance_data, %.loc10_41.4
// CHECK:STDOUT: %instance_data: %i32 = value_binding instance_data, %.loc10_41.5
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %unqualified_static_data.patt: %pattern_type.6b6 = value_binding_pattern unqualified_static_data [concrete = constants.%unqualified_static_data.patt]
// CHECK:STDOUT: }
@@ -2597,15 +2599,17 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %instance.ref.loc24: ref %Public = name_ref instance, %instance
// CHECK:STDOUT: %PublicInstance.ref: %Public.PublicInstance.cpp_overload_set.type = name_ref PublicInstance, imports.%Public.PublicInstance.cpp_overload_set.value [concrete = constants.%Public.PublicInstance.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc24: <bound method> = bound_method %instance.ref.loc24, %PublicInstance.ref
// CHECK:STDOUT: %.loc24_5.1: ref %Base = class_element_access %instance.ref.loc24, element0
// CHECK:STDOUT: %.loc24_5.2: ref %Base = converted %instance.ref.loc24, %.loc24_5.1
// CHECK:STDOUT: %Base.PublicInstance.call: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc24_5.2)
// CHECK:STDOUT: %.loc24_5.1: ref %Base = as_compatible %instance.ref.loc24
// CHECK:STDOUT: %.loc24_5.2: ref %Base = class_element_access %.loc24_5.1, element0
// CHECK:STDOUT: %.loc24_5.3: ref %Base = converted %instance.ref.loc24, %.loc24_5.2
// CHECK:STDOUT: %Base.PublicInstance.call: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc24_5.3)
// CHECK:STDOUT: %instance.ref.loc26: ref %Public = name_ref instance, %instance
// CHECK:STDOUT: %ProtectedInstance.ref: %Public.ProtectedInstance.cpp_overload_set.type = name_ref ProtectedInstance, imports.%Public.ProtectedInstance.cpp_overload_set.value [concrete = constants.%Public.ProtectedInstance.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc26: <bound method> = bound_method %instance.ref.loc26, %ProtectedInstance.ref
// CHECK:STDOUT: %.loc26_5.1: ref %Base = class_element_access %instance.ref.loc26, element0
// CHECK:STDOUT: %.loc26_5.2: ref %Base = converted %instance.ref.loc26, %.loc26_5.1
// CHECK:STDOUT: %Base.ProtectedInstance.call: init %empty_tuple.type = call imports.%Base.ProtectedInstance.decl(%.loc26_5.2)
// CHECK:STDOUT: %.loc26_5.1: ref %Base = as_compatible %instance.ref.loc26
// CHECK:STDOUT: %.loc26_5.2: ref %Base = class_element_access %.loc26_5.1, element0
// CHECK:STDOUT: %.loc26_5.3: ref %Base = converted %instance.ref.loc26, %.loc26_5.2
// CHECK:STDOUT: %Base.ProtectedInstance.call: init %empty_tuple.type = call imports.%Base.ProtectedInstance.decl(%.loc26_5.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2621,15 +2625,17 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %instance.ref.loc36: ref %Public = name_ref instance, %instance
// CHECK:STDOUT: %PublicInstance.ref.loc36: %Public.PublicInstance.cpp_overload_set.type = name_ref PublicInstance, imports.%Public.PublicInstance.cpp_overload_set.value [concrete = constants.%Public.PublicInstance.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc36: <bound method> = bound_method %instance.ref.loc36, %PublicInstance.ref.loc36
// CHECK:STDOUT: %.loc36_3.1: ref %Base = class_element_access %instance.ref.loc36, element0
// CHECK:STDOUT: %.loc36_3.2: ref %Base = converted %instance.ref.loc36, %.loc36_3.1
// CHECK:STDOUT: %Base.PublicInstance.call.loc36: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc36_3.2)
// CHECK:STDOUT: %.loc36_3.1: ref %Base = as_compatible %instance.ref.loc36
// CHECK:STDOUT: %.loc36_3.2: ref %Base = class_element_access %.loc36_3.1, element0
// CHECK:STDOUT: %.loc36_3.3: ref %Base = converted %instance.ref.loc36, %.loc36_3.2
// CHECK:STDOUT: %Base.PublicInstance.call.loc36: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc36_3.3)
// CHECK:STDOUT: %instance.ref.loc37: ref %Public = name_ref instance, %instance
// CHECK:STDOUT: %PublicInstance.ref.loc37: %Public.PublicInstance.cpp_overload_set.type = name_ref PublicInstance, imports.%Public.PublicInstance.cpp_overload_set.value [concrete = constants.%Public.PublicInstance.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc37: <bound method> = bound_method %instance.ref.loc37, %PublicInstance.ref.loc37
// CHECK:STDOUT: %.loc37_3.1: ref %Base = class_element_access %instance.ref.loc37, element0
// CHECK:STDOUT: %.loc37_3.2: ref %Base = converted %instance.ref.loc37, %.loc37_3.1
// CHECK:STDOUT: %Base.PublicInstance.call.loc37: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc37_3.2)
// CHECK:STDOUT: %.loc37_3.1: ref %Base = as_compatible %instance.ref.loc37
// CHECK:STDOUT: %.loc37_3.2: ref %Base = class_element_access %.loc37_3.1, element0
// CHECK:STDOUT: %.loc37_3.3: ref %Base = converted %instance.ref.loc37, %.loc37_3.2
// CHECK:STDOUT: %Base.PublicInstance.call.loc37: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc37_3.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2748,15 +2754,17 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %instance.ref.loc24: ref %Protected = name_ref instance, %instance
// CHECK:STDOUT: %PublicInstance.ref: %Protected.PublicInstance.cpp_overload_set.type = name_ref PublicInstance, imports.%Protected.PublicInstance.cpp_overload_set.value [concrete = constants.%Protected.PublicInstance.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc24: <bound method> = bound_method %instance.ref.loc24, %PublicInstance.ref
// CHECK:STDOUT: %.loc24_5.1: ref %Base = class_element_access %instance.ref.loc24, element0
// CHECK:STDOUT: %.loc24_5.2: ref %Base = converted %instance.ref.loc24, %.loc24_5.1
// CHECK:STDOUT: %Base.PublicInstance.call: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc24_5.2)
// CHECK:STDOUT: %.loc24_5.1: ref %Base = as_compatible %instance.ref.loc24
// CHECK:STDOUT: %.loc24_5.2: ref %Base = class_element_access %.loc24_5.1, element0
// CHECK:STDOUT: %.loc24_5.3: ref %Base = converted %instance.ref.loc24, %.loc24_5.2
// CHECK:STDOUT: %Base.PublicInstance.call: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc24_5.3)
// CHECK:STDOUT: %instance.ref.loc26: ref %Protected = name_ref instance, %instance
// CHECK:STDOUT: %ProtectedInstance.ref: %Protected.ProtectedInstance.cpp_overload_set.type = name_ref ProtectedInstance, imports.%Protected.ProtectedInstance.cpp_overload_set.value [concrete = constants.%Protected.ProtectedInstance.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc26: <bound method> = bound_method %instance.ref.loc26, %ProtectedInstance.ref
// CHECK:STDOUT: %.loc26_5.1: ref %Base = class_element_access %instance.ref.loc26, element0
// CHECK:STDOUT: %.loc26_5.2: ref %Base = converted %instance.ref.loc26, %.loc26_5.1
// CHECK:STDOUT: %Base.ProtectedInstance.call: init %empty_tuple.type = call imports.%Base.ProtectedInstance.decl(%.loc26_5.2)
// CHECK:STDOUT: %.loc26_5.1: ref %Base = as_compatible %instance.ref.loc26
// CHECK:STDOUT: %.loc26_5.2: ref %Base = class_element_access %.loc26_5.1, element0
// CHECK:STDOUT: %.loc26_5.3: ref %Base = converted %instance.ref.loc26, %.loc26_5.2
// CHECK:STDOUT: %Base.ProtectedInstance.call: init %empty_tuple.type = call imports.%Base.ProtectedInstance.decl(%.loc26_5.3)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2848,17 +2856,19 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT: %instance.ref.loc24: ref %PublicProtected = name_ref instance, %instance
// CHECK:STDOUT: %PublicInstance.ref: %PublicProtected.PublicInstance.cpp_overload_set.type = name_ref PublicInstance, imports.%PublicProtected.PublicInstance.cpp_overload_set.value [concrete = constants.%PublicProtected.PublicInstance.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc24: <bound method> = bound_method %instance.ref.loc24, %PublicInstance.ref
// CHECK:STDOUT: %.loc24_5.1: ref %Protected = class_element_access %instance.ref.loc24, element0
// CHECK:STDOUT: %.loc24_5.2: ref %Base = class_element_access %.loc24_5.1, element0
// CHECK:STDOUT: %.loc24_5.3: ref %Base = converted %instance.ref.loc24, %.loc24_5.2
// CHECK:STDOUT: %Base.PublicInstance.call: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc24_5.3)
// CHECK:STDOUT: %.loc24_5.1: ref %Base = as_compatible %instance.ref.loc24
// CHECK:STDOUT: %.loc24_5.2: ref %Protected = class_element_access %.loc24_5.1, element0
// CHECK:STDOUT: %.loc24_5.3: ref %Base = class_element_access %.loc24_5.2, element0
// CHECK:STDOUT: %.loc24_5.4: ref %Base = converted %instance.ref.loc24, %.loc24_5.3
// CHECK:STDOUT: %Base.PublicInstance.call: init %empty_tuple.type = call imports.%Base.PublicInstance.decl(%.loc24_5.4)
// CHECK:STDOUT: %instance.ref.loc26: ref %PublicProtected = name_ref instance, %instance
// CHECK:STDOUT: %ProtectedInstance.ref: %PublicProtected.ProtectedInstance.cpp_overload_set.type = name_ref ProtectedInstance, imports.%PublicProtected.ProtectedInstance.cpp_overload_set.value [concrete = constants.%PublicProtected.ProtectedInstance.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc26: <bound method> = bound_method %instance.ref.loc26, %ProtectedInstance.ref
// CHECK:STDOUT: %.loc26_5.1: ref %Protected = class_element_access %instance.ref.loc26, element0
// CHECK:STDOUT: %.loc26_5.2: ref %Base = class_element_access %.loc26_5.1, element0
// CHECK:STDOUT: %.loc26_5.3: ref %Base = converted %instance.ref.loc26, %.loc26_5.2
// CHECK:STDOUT: %Base.ProtectedInstance.call: init %empty_tuple.type = call imports.%Base.ProtectedInstance.decl(%.loc26_5.3)
// CHECK:STDOUT: %.loc26_5.1: ref %Base = as_compatible %instance.ref.loc26
// CHECK:STDOUT: %.loc26_5.2: ref %Protected = class_element_access %.loc26_5.1, element0
// CHECK:STDOUT: %.loc26_5.3: ref %Base = class_element_access %.loc26_5.2, element0
// CHECK:STDOUT: %.loc26_5.4: ref %Base = converted %instance.ref.loc26, %.loc26_5.3
// CHECK:STDOUT: %Base.ProtectedInstance.call: init %empty_tuple.type = call imports.%Base.ProtectedInstance.decl(%.loc26_5.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+36 -30
View File
@@ -568,10 +568,11 @@ class V {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %AcceptVal.ref: %AcceptVal.type = name_ref AcceptVal, file.%AcceptVal.decl [concrete = constants.%AcceptVal]
// CHECK:STDOUT: %d.ref: %Derived = name_ref d, %d
// CHECK:STDOUT: %.loc16_13.1: ref %Base = class_element_access %d.ref, element0
// CHECK:STDOUT: %.loc16_13.2: ref %Base = converted %d.ref, %.loc16_13.1
// CHECK:STDOUT: %.loc16_13.3: %Base = acquire_value %.loc16_13.2
// CHECK:STDOUT: %AcceptVal.call: init %empty_tuple.type = call %AcceptVal.ref(%.loc16_13.3)
// CHECK:STDOUT: %.loc16_13.1: %Base = as_compatible %d.ref
// CHECK:STDOUT: %.loc16_13.2: ref %Base = class_element_access %.loc16_13.1, element0
// CHECK:STDOUT: %.loc16_13.3: ref %Base = converted %d.ref, %.loc16_13.2
// CHECK:STDOUT: %.loc16_13.4: %Base = acquire_value %.loc16_13.3
// CHECK:STDOUT: %AcceptVal.call: init %empty_tuple.type = call %AcceptVal.ref(%.loc16_13.4)
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -662,15 +663,16 @@ class V {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %d.ref: %Derived = name_ref d, %d
// CHECK:STDOUT: %a.ref: %Base.elem = name_ref a, @Base.%.1 [concrete = @Base.%.1]
// CHECK:STDOUT: %.loc8_11.1: ref %Base = class_element_access %d.ref, element0
// CHECK:STDOUT: %.loc8_11.2: ref %Base = converted %d.ref, %.loc8_11.1
// CHECK:STDOUT: %.loc8_11.3: ref %i32 = class_element_access %.loc8_11.2, element0
// CHECK:STDOUT: %.loc8_11.4: %i32 = acquire_value %.loc8_11.3
// CHECK:STDOUT: %.loc8_11.1: %Base = as_compatible %d.ref
// CHECK:STDOUT: %.loc8_11.2: ref %Base = class_element_access %.loc8_11.1, element0
// CHECK:STDOUT: %.loc8_11.3: ref %Base = converted %d.ref, %.loc8_11.2
// CHECK:STDOUT: %.loc8_11.4: ref %i32 = class_element_access %.loc8_11.3, element0
// CHECK:STDOUT: %.loc8_11.5: %i32 = acquire_value %.loc8_11.4
// CHECK:STDOUT: %impl.elem0: %.7a6 = impl_witness_access constants.%Copy.impl_witness.0e0, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6]
// CHECK:STDOUT: %bound_method.loc8_11.1: <bound method> = bound_method %.loc8_11.4, %impl.elem0
// CHECK:STDOUT: %bound_method.loc8_11.1: <bound method> = bound_method %.loc8_11.5, %impl.elem0
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc8_11.2: <bound method> = bound_method %.loc8_11.4, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc8_11.2(%.loc8_11.4)
// CHECK:STDOUT: %bound_method.loc8_11.2: <bound method> = bound_method %.loc8_11.5, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc8_11.2(%.loc8_11.5)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -680,15 +682,16 @@ class V {
// CHECK:STDOUT: %Cpp.ref.loc14: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Base.ref: type = name_ref Base, imports.%Base.decl [concrete = constants.%Base]
// CHECK:STDOUT: %b.ref: %Base.elem = name_ref b, @Base.%.2 [concrete = @Base.%.2]
// CHECK:STDOUT: %.loc14_11.1: ref %Base = class_element_access %d.ref, element0
// CHECK:STDOUT: %.loc14_11.2: ref %Base = converted %d.ref, %.loc14_11.1
// CHECK:STDOUT: %.loc14_11.3: ref %i32 = class_element_access %.loc14_11.2, element1
// CHECK:STDOUT: %.loc14_11.4: %i32 = acquire_value %.loc14_11.3
// CHECK:STDOUT: %.loc14_11.1: %Base = as_compatible %d.ref
// CHECK:STDOUT: %.loc14_11.2: ref %Base = class_element_access %.loc14_11.1, element0
// CHECK:STDOUT: %.loc14_11.3: ref %Base = converted %d.ref, %.loc14_11.2
// CHECK:STDOUT: %.loc14_11.4: ref %i32 = class_element_access %.loc14_11.3, element1
// CHECK:STDOUT: %.loc14_11.5: %i32 = acquire_value %.loc14_11.4
// CHECK:STDOUT: %impl.elem0: %.7a6 = impl_witness_access constants.%Copy.impl_witness.0e0, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6]
// CHECK:STDOUT: %bound_method.loc14_11.1: <bound method> = bound_method %.loc14_11.4, %impl.elem0
// CHECK:STDOUT: %bound_method.loc14_11.1: <bound method> = bound_method %.loc14_11.5, %impl.elem0
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc14_11.2: <bound method> = bound_method %.loc14_11.4, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc14_11.2(%.loc14_11.4)
// CHECK:STDOUT: %bound_method.loc14_11.2: <bound method> = bound_method %.loc14_11.5, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc14_11.2(%.loc14_11.5)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -735,10 +738,11 @@ class V {
// CHECK:STDOUT: %d.ref: %Derived = name_ref d, %d
// CHECK:STDOUT: %f.ref: %Derived.f.cpp_overload_set.type = name_ref f, imports.%Derived.f.cpp_overload_set.value [concrete = constants.%Derived.f.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %d.ref, %f.ref
// CHECK:STDOUT: %.loc8_3.1: ref %Base = class_element_access %d.ref, element0
// CHECK:STDOUT: %.loc8_3.2: ref %Base = converted %d.ref, %.loc8_3.1
// CHECK:STDOUT: %.loc8_3.3: %Base = acquire_value %.loc8_3.2
// CHECK:STDOUT: %f__carbon_thunk.call: init %empty_tuple.type = call imports.%f__carbon_thunk.decl(%.loc8_3.3)
// CHECK:STDOUT: %.loc8_3.1: %Base = as_compatible %d.ref
// CHECK:STDOUT: %.loc8_3.2: ref %Base = class_element_access %.loc8_3.1, element0
// CHECK:STDOUT: %.loc8_3.3: ref %Base = converted %d.ref, %.loc8_3.2
// CHECK:STDOUT: %.loc8_3.4: %Base = acquire_value %.loc8_3.3
// CHECK:STDOUT: %f__carbon_thunk.call: init %empty_tuple.type = call imports.%f__carbon_thunk.decl(%.loc8_3.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -749,10 +753,11 @@ class V {
// CHECK:STDOUT: %Base.ref: type = name_ref Base, imports.%Base.decl [concrete = constants.%Base]
// CHECK:STDOUT: %g.ref: %Base.g.cpp_overload_set.type = name_ref g, imports.%Base.g.cpp_overload_set.value [concrete = constants.%Base.g.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %d.ref, %g.ref
// CHECK:STDOUT: %.loc14_3.1: ref %Base = class_element_access %d.ref, element0
// CHECK:STDOUT: %.loc14_3.2: ref %Base = converted %d.ref, %.loc14_3.1
// CHECK:STDOUT: %.loc14_3.3: %Base = acquire_value %.loc14_3.2
// CHECK:STDOUT: %g__carbon_thunk.call: init %empty_tuple.type = call imports.%g__carbon_thunk.decl(%.loc14_3.3)
// CHECK:STDOUT: %.loc14_3.1: %Base = as_compatible %d.ref
// CHECK:STDOUT: %.loc14_3.2: ref %Base = class_element_access %.loc14_3.1, element0
// CHECK:STDOUT: %.loc14_3.3: ref %Base = converted %d.ref, %.loc14_3.2
// CHECK:STDOUT: %.loc14_3.4: %Base = acquire_value %.loc14_3.3
// CHECK:STDOUT: %g__carbon_thunk.call: init %empty_tuple.type = call imports.%g__carbon_thunk.decl(%.loc14_3.4)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -763,10 +768,11 @@ class V {
// CHECK:STDOUT: %Derived.ref.loc23: type = name_ref Derived, imports.%Derived.decl [concrete = constants.%Derived]
// CHECK:STDOUT: %f.ref.loc23: %Derived.f.cpp_overload_set.type = name_ref f, imports.%Derived.f.cpp_overload_set.value [concrete = constants.%Derived.f.cpp_overload_set.value]
// CHECK:STDOUT: %bound_method.loc23: <bound method> = bound_method %d.ref, %f.ref.loc23
// CHECK:STDOUT: %.loc23_3.1: ref %Base = class_element_access %d.ref, element0
// CHECK:STDOUT: %.loc23_3.2: ref %Base = converted %d.ref, %.loc23_3.1
// CHECK:STDOUT: %.loc23_3.3: %Base = acquire_value %.loc23_3.2
// CHECK:STDOUT: %f__carbon_thunk.call.loc23: init %empty_tuple.type = call imports.%f__carbon_thunk.decl(%.loc23_3.3)
// CHECK:STDOUT: %.loc23_3.1: %Base = as_compatible %d.ref
// CHECK:STDOUT: %.loc23_3.2: ref %Base = class_element_access %.loc23_3.1, element0
// CHECK:STDOUT: %.loc23_3.3: ref %Base = converted %d.ref, %.loc23_3.2
// CHECK:STDOUT: %.loc23_3.4: %Base = acquire_value %.loc23_3.3
// CHECK:STDOUT: %f__carbon_thunk.call.loc23: init %empty_tuple.type = call imports.%f__carbon_thunk.decl(%.loc23_3.4)
// CHECK:STDOUT: %b.ref: %Base = name_ref b, %b
// CHECK:STDOUT: %Cpp.ref.loc24: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %Derived.ref.loc24: type = name_ref Derived, imports.%Derived.decl [concrete = constants.%Derived]