Skip to content

Commit 6fd139b

Browse files
authored
Renumber inner parameters when checking an impl function against an interface function. (#5113)
This allows the numbering of the parameters to match when checking for a valid redeclaration. It also prepares us to produce the proper numbering when generating a thunk.
1 parent e6872f9 commit 6fd139b

File tree

6 files changed

+626
-6
lines changed

6 files changed

+626
-6
lines changed

toolchain/check/eval.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,6 +1661,8 @@ auto TryEvalTypedInst<SemIR::SymbolicBindingPattern>(EvalContext& eval_context,
16611661
// argument value.
16621662
if (auto value = eval_context.GetCompileTimeBindValue(bind_name.bind_index());
16631663
value.has_value()) {
1664+
// TODO: This seems incorrect: patterns don't typically evaluate to the
1665+
// value matched by the pattern.
16641666
return value;
16651667
}
16661668

toolchain/check/impl.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ static auto CheckAssociatedFunctionImplementation(
5858
return SemIR::ErrorInst::SingletonInstId;
5959
}
6060

61+
auto impl_enclosing_specific_id =
62+
context.types()
63+
.GetAs<SemIR::FunctionType>(impl_function_decl->type_id)
64+
.specific_id;
65+
6166
// Map from the specific for the function type to the specific for the
6267
// function signature. The function signature may have additional generic
6368
// parameters.
@@ -67,7 +72,7 @@ static auto CheckAssociatedFunctionImplementation(
6772
context.functions()
6873
.Get(interface_function_type.function_id)
6974
.generic_id,
70-
self_type_id, witness_inst_id);
75+
impl_enclosing_specific_id, self_type_id, witness_inst_id);
7176

7277
if (!CheckFunctionTypeMatches(
7378
context, context.functions().Get(impl_function_decl->function_id),

toolchain/check/interface.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,9 @@ static auto GetGenericArgsWithSelfType(Context& context,
126126

127127
auto GetSelfSpecificForInterfaceMemberWithSelfType(
128128
Context& context, SemIRLoc loc, SemIR::SpecificId interface_specific_id,
129-
SemIR::GenericId generic_id, SemIR::TypeId self_type_id,
130-
SemIR::InstId witness_inst_id) -> SemIR::SpecificId {
129+
SemIR::GenericId generic_id, SemIR::SpecificId enclosing_specific_id,
130+
SemIR::TypeId self_type_id, SemIR::InstId witness_inst_id)
131+
-> SemIR::SpecificId {
131132
const auto& generic = context.generics().Get(generic_id);
132133
auto self_specific_args = context.inst_blocks().Get(
133134
context.specifics().Get(generic.self_specific_id).args_id);
@@ -136,11 +137,36 @@ auto GetSelfSpecificForInterfaceMemberWithSelfType(
136137
context, interface_specific_id, generic_id, self_type_id, witness_inst_id,
137138
self_specific_args.size());
138139

140+
// Determine the number of specific arguments that enclose the point where
141+
// this self specific will be used from. In an impl, this will be the number
142+
// of parameters that the impl has.
143+
int num_enclosing_specific_args =
144+
context.inst_blocks()
145+
.Get(context.specifics().GetArgsOrEmpty(enclosing_specific_id))
146+
.size();
147+
// The index of each remaining generic parameter is adjusted to match the
148+
// numbering at the point where the self specific is used.
149+
int index_delta = num_enclosing_specific_args - arg_ids.size();
150+
139151
// Take any trailing argument values from the self specific.
140152
// TODO: If these refer to outer arguments, for example in their types, we may
141153
// need to perform extra substitutions here.
142154
for (auto arg_id : self_specific_args.drop_front(arg_ids.size())) {
143-
arg_ids.push_back(context.constant_values().GetConstantInstId(arg_id));
155+
auto new_arg_id = context.constant_values().GetConstantInstId(arg_id);
156+
if (index_delta) {
157+
// If this parameter would have a new index in the context described by
158+
// `enclosing_specific_id`, form a new binding with an adjusted index.
159+
auto bind_name = context.insts().GetAs<SemIR::BindSymbolicName>(
160+
context.constant_values().GetConstantInstId(arg_id));
161+
auto entity_name = context.entity_names().Get(bind_name.entity_name_id);
162+
entity_name.bind_index_value += index_delta;
163+
CARBON_CHECK(entity_name.bind_index_value >= 0);
164+
bind_name.entity_name_id =
165+
context.entity_names().AddCanonical(entity_name);
166+
new_arg_id = context.constant_values().GetInstId(
167+
TryEvalInst(context, arg_id, bind_name));
168+
}
169+
arg_ids.push_back(new_arg_id);
144170
}
145171

146172
return MakeSpecific(context, loc, generic_id, arg_ids);

toolchain/check/interface.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,
2121
// given a specific for the interface plus a type to use as `Self`.
2222
auto GetSelfSpecificForInterfaceMemberWithSelfType(
2323
Context& context, SemIRLoc loc, SemIR::SpecificId interface_specific_id,
24-
SemIR::GenericId generic_id, SemIR::TypeId self_type_id,
25-
SemIR::InstId witness_inst_id) -> SemIR::SpecificId;
24+
SemIR::GenericId generic_id, SemIR::SpecificId enclosing_specific_id,
25+
SemIR::TypeId self_type_id, SemIR::InstId witness_inst_id)
26+
-> SemIR::SpecificId;
2627

2728
// Gets the type of the specified associated entity, given the specific for the
2829
// interface and the type of `Self`.

0 commit comments

Comments
 (0)