Reverse nesting of BoundMethod and SpecificFunction. (#5079)

During SemIR, when identifying a specific in a specific context, we'd
have to either look through a specific or through a bound method.
Canonicalize which one to look through first, by having the BoundMethod
created around a SpecificFunction instead.
This changes a lot of check tests.

TODO: As the SemIr does not currently allow removal (access to insts()
is intentionally const), the bound instruction created prior to finding
the specific is not removed from the instructions.
Options: (1) leave as is, (2) add a way to remove the previous bound,
(3) rethink how/when the BoundMethod inst is created.
This commit is contained in:
Alina Sbirlea
2025-03-08 01:34:06 +00:00
committed by GitHub
parent 820ace95e8
commit 7fd54eded0
165 changed files with 2795 additions and 1958 deletions
+12 -8
View File
@@ -781,7 +781,8 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.205 = facet_value Core.IntLiteral, %impl_witness.d39 [concrete]
// CHECK:STDOUT: %.a0b: type = fn_type_with_self_type %Convert.type.1b6, %ImplicitAs.facet [concrete]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_2.ecc, %Convert.956 [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(%int_32) [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_2.ecc, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_2.ef8: %i32 = int_value 2 [concrete]
// CHECK:STDOUT: %tuple: %tuple.type.4c8 = tuple_value (%int_1, %int_2.ef8) [concrete]
// CHECK:STDOUT: %complete_type.c49: <witness> = complete_type_witness %tuple.type.4c8 [concrete]
@@ -844,9 +845,10 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %.loc7_19.1: %tuple.type.f94 = tuple_literal (%int_1, %int_2)
// CHECK:STDOUT: %TupleParam.specific_fn: <specific function> = specific_function %TupleParam.ref, @TupleParam(Core.IntLiteral) [concrete = constants.%TupleParam.specific_fn]
// CHECK:STDOUT: %impl.elem0: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %bound_method, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %specific_fn(%int_2) [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %bound_method.loc7_19.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc7_19.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc7_19.2(%int_2) [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %.loc7_19.2: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %.loc7_19.3: %i32 = converted %int_2, %.loc7_19.2 [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %tuple: %tuple.type.4c8 = tuple_value (%int_1, %.loc7_19.3) [concrete = constants.%tuple]
@@ -897,7 +899,8 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.205 = facet_value Core.IntLiteral, %impl_witness.d39 [concrete]
// CHECK:STDOUT: %.a0b: type = fn_type_with_self_type %Convert.type.1b6, %ImplicitAs.facet [concrete]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_2.ecc, %Convert.956 [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(%int_32) [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_2.ecc, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_2.ef8: %i32 = int_value 2 [concrete]
// CHECK:STDOUT: %struct: %struct_type.a.b.a13 = struct_value (%int_1, %int_2.ef8) [concrete]
// CHECK:STDOUT: %complete_type.a4a: <witness> = complete_type_witness %struct_type.a.b.a13 [concrete]
@@ -959,9 +962,10 @@ fn CallImplicitNotDeducible() {
// CHECK:STDOUT: %.loc7_30.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2)
// CHECK:STDOUT: %StructParam.specific_fn: <specific function> = specific_function %StructParam.ref, @StructParam(Core.IntLiteral) [concrete = constants.%StructParam.specific_fn]
// CHECK:STDOUT: %impl.elem0: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %bound_method, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %specific_fn(%int_2) [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %bound_method.loc7_30.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc7_30.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc7_30.2(%int_2) [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %.loc7_30.2: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %.loc7_30.3: %i32 = converted %int_2, %.loc7_30.2 [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %struct: %struct_type.a.b.a13 = struct_value (%int_1, %.loc7_30.3) [concrete = constants.%struct]
@@ -25,8 +25,9 @@ fn F(N:! i32, a: array(i32, N)*);
// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.2fd = facet_value %i32, %impl_witness.023 [concrete]
// CHECK:STDOUT: %.10e: type = fn_type_with_self_type %Convert.type.71e, %ImplicitAs.facet [concrete]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %N.51e, %Convert.960 [symbolic]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.3(%int_32) [symbolic]
// CHECK:STDOUT: %int.convert_checked: init Core.IntLiteral = call %Convert.specific_fn(%N.51e) [symbolic]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.960, @Convert.3(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %N.51e, %Convert.specific_fn [symbolic]
// CHECK:STDOUT: %int.convert_checked: init Core.IntLiteral = call %bound_method(%N.51e) [symbolic]
// CHECK:STDOUT: %array_type: type = array_type %int.convert_checked, %i32 [symbolic]
// CHECK:STDOUT: %ptr: type = ptr_type %array_type [symbolic]
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
@@ -64,9 +65,10 @@ fn F(N:! i32, a: array(i32, N)*);
// CHECK:STDOUT: %i32.loc11_24: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %N.ref: %i32 = name_ref N, %N.loc11_6.1 [symbolic = %N.loc11_6.2 (constants.%N.51e)]
// CHECK:STDOUT: %impl.elem0: %.10e = impl_witness_access constants.%impl_witness.023, element0 [concrete = constants.%Convert.960]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %N.ref, %impl.elem0 [symbolic = %Convert.bound (constants.%Convert.bound)]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %bound_method, @Convert.3(constants.%int_32) [symbolic = %Convert.specific_fn (constants.%Convert.specific_fn)]
// CHECK:STDOUT: %int.convert_checked.loc11_29.1: init Core.IntLiteral = call %specific_fn(%N.ref) [symbolic = %int.convert_checked.loc11_29.2 (constants.%int.convert_checked)]
// CHECK:STDOUT: %bound_method.loc11_29.1: <bound method> = bound_method %N.ref, %impl.elem0 [symbolic = %Convert.bound (constants.%Convert.bound)]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.3(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc11_29.2: <bound method> = bound_method %N.ref, %specific_fn [symbolic = %bound_method.loc11_29.3 (constants.%bound_method)]
// CHECK:STDOUT: %int.convert_checked.loc11_29.1: init Core.IntLiteral = call %bound_method.loc11_29.2(%N.ref) [symbolic = %int.convert_checked.loc11_29.2 (constants.%int.convert_checked)]
// CHECK:STDOUT: %.loc11_29.1: Core.IntLiteral = value_of_initializer %int.convert_checked.loc11_29.1 [symbolic = %int.convert_checked.loc11_29.2 (constants.%int.convert_checked)]
// CHECK:STDOUT: %.loc11_29.2: Core.IntLiteral = converted %N.ref, %.loc11_29.1 [symbolic = %int.convert_checked.loc11_29.2 (constants.%int.convert_checked)]
// CHECK:STDOUT: %array_type.loc11_30.1: type = array_type %.loc11_29.2, %i32 [symbolic = %array_type.loc11_30.2 (constants.%array_type)]
@@ -80,8 +82,8 @@ fn F(N:! i32, a: array(i32, N)*);
// CHECK:STDOUT: %N.loc11_6.2: %i32 = bind_symbolic_name N, 0 [symbolic = %N.loc11_6.2 (constants.%N.51e)]
// CHECK:STDOUT: %N.patt.loc11_6.2: %i32 = symbolic_binding_pattern N, 0 [symbolic = %N.patt.loc11_6.2 (constants.%N.patt.8e2)]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %N.loc11_6.2, constants.%Convert.960 [symbolic = %Convert.bound (constants.%Convert.bound)]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.3(constants.%int_32) [symbolic = %Convert.specific_fn (constants.%Convert.specific_fn)]
// CHECK:STDOUT: %int.convert_checked.loc11_29.2: init Core.IntLiteral = call %Convert.specific_fn(%N.loc11_6.2) [symbolic = %int.convert_checked.loc11_29.2 (constants.%int.convert_checked)]
// CHECK:STDOUT: %bound_method.loc11_29.3: <bound method> = bound_method %N.loc11_6.2, constants.%Convert.specific_fn [symbolic = %bound_method.loc11_29.3 (constants.%bound_method)]
// CHECK:STDOUT: %int.convert_checked.loc11_29.2: init Core.IntLiteral = call %bound_method.loc11_29.3(%N.loc11_6.2) [symbolic = %int.convert_checked.loc11_29.2 (constants.%int.convert_checked)]
// CHECK:STDOUT: %array_type.loc11_30.2: type = array_type %int.convert_checked.loc11_29.2, %i32 [symbolic = %array_type.loc11_30.2 (constants.%array_type)]
// CHECK:STDOUT: %ptr.loc11_31.2: type = ptr_type @F.%array_type.loc11_30.2 (%array_type) [symbolic = %ptr.loc11_31.2 (constants.%ptr)]
// CHECK:STDOUT:
@@ -92,7 +94,7 @@ fn F(N:! i32, a: array(i32, N)*);
// CHECK:STDOUT: %N.loc11_6.2 => constants.%N.51e
// CHECK:STDOUT: %N.patt.loc11_6.2 => constants.%N.51e
// CHECK:STDOUT: %Convert.bound => constants.%Convert.bound
// CHECK:STDOUT: %Convert.specific_fn => constants.%Convert.specific_fn
// CHECK:STDOUT: %bound_method.loc11_29.3 => constants.%bound_method
// CHECK:STDOUT: %int.convert_checked.loc11_29.2 => constants.%int.convert_checked
// CHECK:STDOUT: %array_type.loc11_30.2 => constants.%array_type
// CHECK:STDOUT: %ptr.loc11_31.2 => constants.%ptr
+18 -12
View File
@@ -74,7 +74,8 @@ fn CallUndefined() -> i32 {
// CHECK:STDOUT: %As.facet: %As.type.fd4 = facet_value Core.IntLiteral, %impl_witness.882 [concrete]
// CHECK:STDOUT: %.214: type = fn_type_with_self_type %Convert.type.99b, %As.facet [concrete]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_0.5c6, %Convert.197 [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.5(%int_32) [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.197, @Convert.5(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_0.6a9: %i32 = int_value 0 [concrete]
// CHECK:STDOUT: %Defined.specific_fn: <specific function> = specific_function %Defined, @Defined(%i32) [concrete]
// CHECK:STDOUT: }
@@ -142,9 +143,10 @@ fn CallUndefined() -> i32 {
// CHECK:STDOUT: %int_32.loc9: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc9: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %impl.elem0: %.214 = impl_witness_access constants.%impl_witness.882, element0 [concrete = constants.%Convert.197]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %bound_method, @Convert.5(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %specific_fn(%int_0) [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %bound_method.loc9_20.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.5(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc9_20.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc9_20.2(%int_0) [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %.loc9_20.1: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %.loc9_20.2: %i32 = converted %int_0, %.loc9_20.1 [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %Defined.specific_fn: <specific function> = specific_function %Defined.ref, @Defined(constants.%i32) [concrete = constants.%Defined.specific_fn]
@@ -190,7 +192,8 @@ fn CallUndefined() -> i32 {
// CHECK:STDOUT: %As.facet: %As.type.fd4 = facet_value Core.IntLiteral, %impl_witness.882 [concrete]
// CHECK:STDOUT: %.214: type = fn_type_with_self_type %Convert.type.99b, %As.facet [concrete]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_0.5c6, %Convert.197 [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.5(%int_32) [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.197, @Convert.5(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_0.6a9: %i32 = int_value 0 [concrete]
// CHECK:STDOUT: %Defined.specific_fn: <specific function> = specific_function %Defined, @Defined(%i32) [concrete]
// CHECK:STDOUT: }
@@ -273,9 +276,10 @@ fn CallUndefined() -> i32 {
// CHECK:STDOUT: %int_32.loc7: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc7: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %impl.elem0: %.214 = impl_witness_access constants.%impl_witness.882, element0 [concrete = constants.%Convert.197]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %bound_method, @Convert.5(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %specific_fn(%int_0) [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %bound_method.loc7_20.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.5(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc7_20.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc7_20.2(%int_0) [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %.loc7_20.1: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %.loc7_20.2: %i32 = converted %int_0, %.loc7_20.1 [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %Defined.specific_fn: <specific function> = specific_function %Defined.ref, @Defined(constants.%i32) [concrete = constants.%Defined.specific_fn]
@@ -318,7 +322,8 @@ fn CallUndefined() -> i32 {
// CHECK:STDOUT: %As.facet: %As.type.fd4 = facet_value Core.IntLiteral, %impl_witness.882 [concrete]
// CHECK:STDOUT: %.214: type = fn_type_with_self_type %Convert.type.99b, %As.facet [concrete]
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_0.5c6, %Convert.197 [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.5(%int_32) [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.197, @Convert.5(%int_32) [concrete]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_0.6a9: %i32 = int_value 0 [concrete]
// CHECK:STDOUT: %Undefined.specific_fn: <specific function> = specific_function %Undefined, @Undefined(%i32) [concrete]
// CHECK:STDOUT: }
@@ -379,9 +384,10 @@ fn CallUndefined() -> i32 {
// CHECK:STDOUT: %int_32.loc14: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc14: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %impl.elem0: %.214 = impl_witness_access constants.%impl_witness.882, element0 [concrete = constants.%Convert.197]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %bound_method, @Convert.5(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %specific_fn(%int_0) [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %bound_method.loc14_22.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.5(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc14_22.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc14_22.2(%int_0) [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %.loc14_22.1: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %.loc14_22.2: %i32 = converted %int_0, %.loc14_22.1 [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %Undefined.specific_fn: <specific function> = specific_function %Undefined.ref, @Undefined(constants.%i32) [concrete = constants.%Undefined.specific_fn]