Skip to content

Commit 7fd54ed

Browse files
authored
Reverse nesting of BoundMethod and SpecificFunction. (carbon-language#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.
1 parent 820ace9 commit 7fd54ed

File tree

165 files changed

+2794
-1957
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

165 files changed

+2794
-1957
lines changed

toolchain/check/call.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "toolchain/check/deduce.h"
1111
#include "toolchain/check/facet_type.h"
1212
#include "toolchain/check/function.h"
13+
#include "toolchain/check/inst.h"
1314
#include "toolchain/check/type.h"
1415
#include "toolchain/diagnostics/format_providers.h"
1516
#include "toolchain/sem_ir/builtin_function_kind.h"
@@ -164,19 +165,38 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
164165
if (!callee_specific_id) {
165166
return SemIR::ErrorInst::SingletonInstId;
166167
}
168+
167169
if (callee_specific_id->has_value()) {
168-
callee_id = GetOrAddInst(
169-
context, context.insts().GetLocId(callee_id),
170-
SemIR::SpecificFunction{
171-
.type_id = GetSingletonType(
172-
context, SemIR::SpecificFunctionType::SingletonInstId),
173-
.callee_id = callee_id,
174-
.specific_id = *callee_specific_id});
170+
auto inner_callee_id = callee_id;
171+
if (auto bound_method =
172+
context.insts().TryGetAs<SemIR::BoundMethod>(callee_id)) {
173+
inner_callee_id = GetOrAddInst(
174+
context, context.insts().GetLocId(bound_method->function_decl_id),
175+
SemIR::SpecificFunction{
176+
.type_id = GetSingletonType(
177+
context, SemIR::SpecificFunctionType::SingletonInstId),
178+
.callee_id = bound_method->function_decl_id,
179+
.specific_id = *callee_specific_id});
180+
callee_id = GetOrAddInst<SemIR::BoundMethod>(
181+
context, loc_id,
182+
{.type_id = bound_method->type_id,
183+
.object_id = bound_method->object_id,
184+
.function_decl_id = inner_callee_id});
185+
} else {
186+
callee_id = GetOrAddInst(
187+
context, context.insts().GetLocId(callee_id),
188+
SemIR::SpecificFunction{
189+
.type_id = GetSingletonType(
190+
context, SemIR::SpecificFunctionType::SingletonInstId),
191+
.callee_id = callee_id,
192+
.specific_id = *callee_specific_id});
193+
inner_callee_id = callee_id;
194+
}
175195
if (callee_function.self_type_id.has_value()) {
176196
// This is an associated function, and will be required to be defined as
177197
// part of checking that the impl is complete.
178198
} else {
179-
context.definitions_required().push_back(callee_id);
199+
context.definitions_required().push_back(inner_callee_id);
180200
}
181201
}
182202

toolchain/check/testdata/array/array_vs_tuple.carbon

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ fn G() {
3535
// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.205 = facet_value Core.IntLiteral, %impl_witness.d39 [concrete]
3636
// CHECK:STDOUT: %.a0b: type = fn_type_with_self_type %Convert.type.1b6, %ImplicitAs.facet [concrete]
3737
// CHECK:STDOUT: %Convert.bound.ab5: <bound method> = bound_method %int_1.5b8, %Convert.956 [concrete]
38-
// CHECK:STDOUT: %Convert.specific_fn.70c: <specific function> = specific_function %Convert.bound.ab5, @Convert.2(%int_32) [concrete]
38+
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
39+
// CHECK:STDOUT: %bound_method.9a1: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
3940
// CHECK:STDOUT: %int_1.5d2: %i32 = int_value 1 [concrete]
4041
// CHECK:STDOUT: %Convert.bound.ef9: <bound method> = bound_method %int_2.ecc, %Convert.956 [concrete]
41-
// CHECK:STDOUT: %Convert.specific_fn.787: <specific function> = specific_function %Convert.bound.ef9, @Convert.2(%int_32) [concrete]
42+
// CHECK:STDOUT: %bound_method.b92: <bound method> = bound_method %int_2.ecc, %Convert.specific_fn [concrete]
4243
// CHECK:STDOUT: %int_2.ef8: %i32 = int_value 2 [concrete]
4344
// CHECK:STDOUT: %Convert.bound.b30: <bound method> = bound_method %int_3.1ba, %Convert.956 [concrete]
44-
// CHECK:STDOUT: %Convert.specific_fn.b42: <specific function> = specific_function %Convert.bound.b30, @Convert.2(%int_32) [concrete]
45+
// CHECK:STDOUT: %bound_method.047: <bound method> = bound_method %int_3.1ba, %Convert.specific_fn [concrete]
4546
// CHECK:STDOUT: %int_3.822: %i32 = int_value 3 [concrete]
4647
// CHECK:STDOUT: %array: %array_type = tuple_value (%int_1.5d2, %int_2.ef8, %int_3.822) [concrete]
4748
// CHECK:STDOUT: %tuple.type.ff9: type = tuple_type (type, type, type) [concrete]
@@ -80,24 +81,27 @@ fn G() {
8081
// CHECK:STDOUT: %.loc13_34.1: %tuple.type.37f = tuple_literal (%int_1.loc13_27, %int_2.loc13_30, %int_3.loc13_33)
8182
// CHECK:STDOUT: %impl.elem0.loc13_34.1: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
8283
// CHECK:STDOUT: %bound_method.loc13_34.1: <bound method> = bound_method %int_1.loc13_27, %impl.elem0.loc13_34.1 [concrete = constants.%Convert.bound.ab5]
83-
// CHECK:STDOUT: %specific_fn.loc13_34.1: <specific function> = specific_function %bound_method.loc13_34.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn.70c]
84-
// CHECK:STDOUT: %int.convert_checked.loc13_34.1: init %i32 = call %specific_fn.loc13_34.1(%int_1.loc13_27) [concrete = constants.%int_1.5d2]
84+
// CHECK:STDOUT: %specific_fn.loc13_34.1: <specific function> = specific_function %impl.elem0.loc13_34.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
85+
// CHECK:STDOUT: %bound_method.loc13_34.2: <bound method> = bound_method %int_1.loc13_27, %specific_fn.loc13_34.1 [concrete = constants.%bound_method.9a1]
86+
// CHECK:STDOUT: %int.convert_checked.loc13_34.1: init %i32 = call %bound_method.loc13_34.2(%int_1.loc13_27) [concrete = constants.%int_1.5d2]
8587
// CHECK:STDOUT: %.loc13_34.2: init %i32 = converted %int_1.loc13_27, %int.convert_checked.loc13_34.1 [concrete = constants.%int_1.5d2]
8688
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]
8789
// CHECK:STDOUT: %.loc13_34.3: ref %i32 = array_index %a.var, %int_0
8890
// CHECK:STDOUT: %.loc13_34.4: init %i32 = initialize_from %.loc13_34.2 to %.loc13_34.3 [concrete = constants.%int_1.5d2]
8991
// CHECK:STDOUT: %impl.elem0.loc13_34.2: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
90-
// CHECK:STDOUT: %bound_method.loc13_34.2: <bound method> = bound_method %int_2.loc13_30, %impl.elem0.loc13_34.2 [concrete = constants.%Convert.bound.ef9]
91-
// CHECK:STDOUT: %specific_fn.loc13_34.2: <specific function> = specific_function %bound_method.loc13_34.2, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn.787]
92-
// CHECK:STDOUT: %int.convert_checked.loc13_34.2: init %i32 = call %specific_fn.loc13_34.2(%int_2.loc13_30) [concrete = constants.%int_2.ef8]
92+
// CHECK:STDOUT: %bound_method.loc13_34.3: <bound method> = bound_method %int_2.loc13_30, %impl.elem0.loc13_34.2 [concrete = constants.%Convert.bound.ef9]
93+
// CHECK:STDOUT: %specific_fn.loc13_34.2: <specific function> = specific_function %impl.elem0.loc13_34.2, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
94+
// CHECK:STDOUT: %bound_method.loc13_34.4: <bound method> = bound_method %int_2.loc13_30, %specific_fn.loc13_34.2 [concrete = constants.%bound_method.b92]
95+
// CHECK:STDOUT: %int.convert_checked.loc13_34.2: init %i32 = call %bound_method.loc13_34.4(%int_2.loc13_30) [concrete = constants.%int_2.ef8]
9396
// CHECK:STDOUT: %.loc13_34.5: init %i32 = converted %int_2.loc13_30, %int.convert_checked.loc13_34.2 [concrete = constants.%int_2.ef8]
9497
// CHECK:STDOUT: %int_1.loc13_34: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
9598
// CHECK:STDOUT: %.loc13_34.6: ref %i32 = array_index %a.var, %int_1.loc13_34
9699
// CHECK:STDOUT: %.loc13_34.7: init %i32 = initialize_from %.loc13_34.5 to %.loc13_34.6 [concrete = constants.%int_2.ef8]
97100
// CHECK:STDOUT: %impl.elem0.loc13_34.3: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
98-
// CHECK:STDOUT: %bound_method.loc13_34.3: <bound method> = bound_method %int_3.loc13_33, %impl.elem0.loc13_34.3 [concrete = constants.%Convert.bound.b30]
99-
// CHECK:STDOUT: %specific_fn.loc13_34.3: <specific function> = specific_function %bound_method.loc13_34.3, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn.b42]
100-
// CHECK:STDOUT: %int.convert_checked.loc13_34.3: init %i32 = call %specific_fn.loc13_34.3(%int_3.loc13_33) [concrete = constants.%int_3.822]
101+
// CHECK:STDOUT: %bound_method.loc13_34.5: <bound method> = bound_method %int_3.loc13_33, %impl.elem0.loc13_34.3 [concrete = constants.%Convert.bound.b30]
102+
// CHECK:STDOUT: %specific_fn.loc13_34.3: <specific function> = specific_function %impl.elem0.loc13_34.3, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
103+
// CHECK:STDOUT: %bound_method.loc13_34.6: <bound method> = bound_method %int_3.loc13_33, %specific_fn.loc13_34.3 [concrete = constants.%bound_method.047]
104+
// CHECK:STDOUT: %int.convert_checked.loc13_34.3: init %i32 = call %bound_method.loc13_34.6(%int_3.loc13_33) [concrete = constants.%int_3.822]
101105
// CHECK:STDOUT: %.loc13_34.8: init %i32 = converted %int_3.loc13_33, %int.convert_checked.loc13_34.3 [concrete = constants.%int_3.822]
102106
// CHECK:STDOUT: %int_2.loc13_34: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
103107
// CHECK:STDOUT: %.loc13_34.9: ref %i32 = array_index %a.var, %int_2.loc13_34
@@ -123,22 +127,25 @@ fn G() {
123127
// CHECK:STDOUT: %.loc14_36.1: %tuple.type.37f = tuple_literal (%int_1.loc14, %int_2.loc14, %int_3.loc14)
124128
// CHECK:STDOUT: %impl.elem0.loc14_36.1: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
125129
// CHECK:STDOUT: %bound_method.loc14_36.1: <bound method> = bound_method %int_1.loc14, %impl.elem0.loc14_36.1 [concrete = constants.%Convert.bound.ab5]
126-
// CHECK:STDOUT: %specific_fn.loc14_36.1: <specific function> = specific_function %bound_method.loc14_36.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn.70c]
127-
// CHECK:STDOUT: %int.convert_checked.loc14_36.1: init %i32 = call %specific_fn.loc14_36.1(%int_1.loc14) [concrete = constants.%int_1.5d2]
130+
// CHECK:STDOUT: %specific_fn.loc14_36.1: <specific function> = specific_function %impl.elem0.loc14_36.1, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
131+
// CHECK:STDOUT: %bound_method.loc14_36.2: <bound method> = bound_method %int_1.loc14, %specific_fn.loc14_36.1 [concrete = constants.%bound_method.9a1]
132+
// CHECK:STDOUT: %int.convert_checked.loc14_36.1: init %i32 = call %bound_method.loc14_36.2(%int_1.loc14) [concrete = constants.%int_1.5d2]
128133
// CHECK:STDOUT: %.loc14_36.2: init %i32 = converted %int_1.loc14, %int.convert_checked.loc14_36.1 [concrete = constants.%int_1.5d2]
129134
// CHECK:STDOUT: %tuple.elem0: ref %i32 = tuple_access %b.var, element0
130135
// CHECK:STDOUT: %.loc14_36.3: init %i32 = initialize_from %.loc14_36.2 to %tuple.elem0 [concrete = constants.%int_1.5d2]
131136
// CHECK:STDOUT: %impl.elem0.loc14_36.2: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
132-
// CHECK:STDOUT: %bound_method.loc14_36.2: <bound method> = bound_method %int_2.loc14, %impl.elem0.loc14_36.2 [concrete = constants.%Convert.bound.ef9]
133-
// CHECK:STDOUT: %specific_fn.loc14_36.2: <specific function> = specific_function %bound_method.loc14_36.2, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn.787]
134-
// CHECK:STDOUT: %int.convert_checked.loc14_36.2: init %i32 = call %specific_fn.loc14_36.2(%int_2.loc14) [concrete = constants.%int_2.ef8]
137+
// CHECK:STDOUT: %bound_method.loc14_36.3: <bound method> = bound_method %int_2.loc14, %impl.elem0.loc14_36.2 [concrete = constants.%Convert.bound.ef9]
138+
// CHECK:STDOUT: %specific_fn.loc14_36.2: <specific function> = specific_function %impl.elem0.loc14_36.2, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
139+
// CHECK:STDOUT: %bound_method.loc14_36.4: <bound method> = bound_method %int_2.loc14, %specific_fn.loc14_36.2 [concrete = constants.%bound_method.b92]
140+
// CHECK:STDOUT: %int.convert_checked.loc14_36.2: init %i32 = call %bound_method.loc14_36.4(%int_2.loc14) [concrete = constants.%int_2.ef8]
135141
// CHECK:STDOUT: %.loc14_36.4: init %i32 = converted %int_2.loc14, %int.convert_checked.loc14_36.2 [concrete = constants.%int_2.ef8]
136142
// CHECK:STDOUT: %tuple.elem1: ref %i32 = tuple_access %b.var, element1
137143
// CHECK:STDOUT: %.loc14_36.5: init %i32 = initialize_from %.loc14_36.4 to %tuple.elem1 [concrete = constants.%int_2.ef8]
138144
// CHECK:STDOUT: %impl.elem0.loc14_36.3: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
139-
// CHECK:STDOUT: %bound_method.loc14_36.3: <bound method> = bound_method %int_3.loc14, %impl.elem0.loc14_36.3 [concrete = constants.%Convert.bound.b30]
140-
// CHECK:STDOUT: %specific_fn.loc14_36.3: <specific function> = specific_function %bound_method.loc14_36.3, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn.b42]
141-
// CHECK:STDOUT: %int.convert_checked.loc14_36.3: init %i32 = call %specific_fn.loc14_36.3(%int_3.loc14) [concrete = constants.%int_3.822]
145+
// CHECK:STDOUT: %bound_method.loc14_36.5: <bound method> = bound_method %int_3.loc14, %impl.elem0.loc14_36.3 [concrete = constants.%Convert.bound.b30]
146+
// CHECK:STDOUT: %specific_fn.loc14_36.3: <specific function> = specific_function %impl.elem0.loc14_36.3, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
147+
// CHECK:STDOUT: %bound_method.loc14_36.6: <bound method> = bound_method %int_3.loc14, %specific_fn.loc14_36.3 [concrete = constants.%bound_method.047]
148+
// CHECK:STDOUT: %int.convert_checked.loc14_36.3: init %i32 = call %bound_method.loc14_36.6(%int_3.loc14) [concrete = constants.%int_3.822]
142149
// CHECK:STDOUT: %.loc14_36.6: init %i32 = converted %int_3.loc14, %int.convert_checked.loc14_36.3 [concrete = constants.%int_3.822]
143150
// CHECK:STDOUT: %tuple.elem2: ref %i32 = tuple_access %b.var, element2
144151
// CHECK:STDOUT: %.loc14_36.7: init %i32 = initialize_from %.loc14_36.6 to %tuple.elem2 [concrete = constants.%int_3.822]

toolchain/check/testdata/array/assign_return_value.carbon

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ fn Run() {
3333
// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.205 = facet_value Core.IntLiteral, %impl_witness.d39 [concrete]
3434
// CHECK:STDOUT: %.a0b: type = fn_type_with_self_type %Convert.type.1b6, %ImplicitAs.facet [concrete]
3535
// CHECK:STDOUT: %Convert.bound: <bound method> = bound_method %int_0.5c6, %Convert.956 [concrete]
36-
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.bound, @Convert.2(%int_32) [concrete]
36+
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.2(%int_32) [concrete]
37+
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0.5c6, %Convert.specific_fn [concrete]
3738
// CHECK:STDOUT: %int_0.6a9: %i32 = int_value 0 [concrete]
3839
// CHECK:STDOUT: %tuple: %tuple.type.a1c = tuple_value (%int_0.6a9) [concrete]
3940
// CHECK:STDOUT: %Run.type: type = fn_type @Run [concrete]
@@ -77,9 +78,10 @@ fn Run() {
7778
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]
7879
// CHECK:STDOUT: %.loc11_30.1: %tuple.type.985 = tuple_literal (%int_0)
7980
// CHECK:STDOUT: %impl.elem0: %.a0b = impl_witness_access constants.%impl_witness.d39, element0 [concrete = constants.%Convert.956]
80-
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
81-
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %bound_method, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
82-
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %specific_fn(%int_0) [concrete = constants.%int_0.6a9]
81+
// CHECK:STDOUT: %bound_method.loc11_30.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Convert.bound]
82+
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Convert.2(constants.%int_32) [concrete = constants.%Convert.specific_fn]
83+
// CHECK:STDOUT: %bound_method.loc11_30.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]
84+
// CHECK:STDOUT: %int.convert_checked: init %i32 = call %bound_method.loc11_30.2(%int_0) [concrete = constants.%int_0.6a9]
8385
// CHECK:STDOUT: %.loc11_30.2: %i32 = value_of_initializer %int.convert_checked [concrete = constants.%int_0.6a9]
8486
// CHECK:STDOUT: %.loc11_30.3: %i32 = converted %int_0, %.loc11_30.2 [concrete = constants.%int_0.6a9]
8587
// CHECK:STDOUT: %tuple: %tuple.type.a1c = tuple_value (%.loc11_30.3) [concrete = constants.%tuple]

0 commit comments

Comments
 (0)