Skip to content

Commit 992322b

Browse files
committed
Allow dependendent specific definition resolution
1 parent 167b45c commit 992322b

File tree

60 files changed

+3085
-2338
lines changed

Some content is hidden

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

60 files changed

+3085
-2338
lines changed

toolchain/check/eval_inst.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,12 @@ auto EvalConstantInst(Context& context, SemIR::InstId inst_id,
516516
return ConstantEvalResult::NewSamePhase(inst);
517517
}
518518

519+
auto EvalConstantInst(Context& context, SemIR::RequireSpecificDefinition inst)
520+
-> ConstantEvalResult {
521+
ResolveSpecificDefinition(context, SemIR::LocId::None, inst.specific_id);
522+
return ConstantEvalResult::NewSamePhase(inst);
523+
}
524+
519525
auto EvalConstantInst(Context& context, SemIR::SpecificConstant inst)
520526
-> ConstantEvalResult {
521527
// Pull the constant value out of the specific.

toolchain/check/generic.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ auto ResolveSpecificDefinition(Context& context, SemIR::LocId loc_id,
719719
if (!specific.definition_block_id.has_value()) {
720720
// Evaluate the eval block for the definition of the generic.
721721
auto& generic = context.generics().Get(generic_id);
722+
CARBON_CHECK(generic.decl_block_id.has_value(), "missing declaration");
722723
if (!generic.definition_block_id.has_value()) {
723724
// The generic is not defined yet.
724725
return false;

toolchain/check/impl_lookup.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,15 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
239239

240240
// The self type of the impl must match the type in the query, or this is an
241241
// `impl T as ...` for some other type `T` and should not be considered.
242-
auto deduced_self_const_id = SemIR::GetConstantValueInSpecific(
242+
auto noncanonical_deduced_self_const_id = SemIR::GetConstantValueInSpecific(
243243
context.sem_ir(), specific_id, impl.self_id);
244+
244245
// In a generic `impl forall` the self type can be a FacetAccessType, which
245246
// will not be the same constant value as a query facet value. We move through
246247
// to the facet value here, and if the query was a FacetAccessType we did the
247248
// same there so they still match.
248-
deduced_self_const_id =
249-
GetCanonicalFacetOrTypeValue(context, deduced_self_const_id);
249+
auto deduced_self_const_id =
250+
GetCanonicalFacetOrTypeValue(context, noncanonical_deduced_self_const_id);
250251
if (query_self_const_id != deduced_self_const_id) {
251252
return EvalImplLookupResult::MakeNone();
252253
}
@@ -287,6 +288,16 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
287288

288289
LoadImportRef(context, impl.witness_id);
289290
if (specific_id.has_value()) {
291+
// When working with a symbolic constant and a `final` impl, add an
292+
// instruction to support requiring an impl definition which may not
293+
// otherwise be generated.
294+
AddInstInNoBlock(
295+
context, loc_id,
296+
SemIR::RequireSpecificDefinition{
297+
.type_id = GetSingletonType(
298+
context, SemIR::RequireSpecificDefinitionType::TypeInstId),
299+
.specific_id = specific_id});
300+
290301
// We need a definition of the specific `impl` so we can access its
291302
// witness.
292303
ResolveSpecificDefinition(context, loc_id, specific_id);

toolchain/check/import_ref.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3302,6 +3302,28 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
33023302
.complete_type_inst_id = complete_type_inst_id});
33033303
}
33043304

3305+
static auto TryResolveTypedInst(ImportRefResolver& resolver,
3306+
SemIR::RequireSpecificDefinition inst)
3307+
-> ResolveResult {
3308+
CARBON_CHECK(resolver.import_types().GetInstId(inst.type_id) ==
3309+
SemIR::RequireSpecificDefinitionType::TypeInstId);
3310+
3311+
auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);
3312+
3313+
if (resolver.HasNewWork()) {
3314+
return ResolveResult::Retry();
3315+
}
3316+
3317+
auto specific_id =
3318+
GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data);
3319+
3320+
return ResolveResult::Deduplicated<SemIR::RequireSpecificDefinition>(
3321+
resolver, {.type_id = GetSingletonType(
3322+
resolver.local_context(),
3323+
SemIR::RequireSpecificDefinitionType::TypeInstId),
3324+
.specific_id = specific_id});
3325+
}
3326+
33053327
static auto TryResolveTypedInst(ImportRefResolver& resolver,
33063328
SemIR::ReturnSlotPattern inst,
33073329
SemIR::InstId import_inst_id) -> ResolveResult {
@@ -3769,6 +3791,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
37693791
case CARBON_KIND(SemIR::RequireImplsDecl inst): {
37703792
return TryResolveTypedInst(resolver, inst);
37713793
}
3794+
case CARBON_KIND(SemIR::RequireSpecificDefinition inst): {
3795+
return TryResolveTypedInst(resolver, inst);
3796+
}
37723797
case CARBON_KIND(SemIR::ReturnSlotPattern inst): {
37733798
return TryResolveTypedInst(resolver, inst, constant_inst_id);
37743799
}

toolchain/check/testdata/array/bound_values.carbon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
// TIP: To dump output, run:
1111
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/bound_values.carbon
1212

13+
// TODO
14+
1315
// --- addition.carbon
1416

1517
library "[[@TEST_NAME]]";

toolchain/check/testdata/array/init_dependent_bound.carbon

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ fn H() { G(3); }
7777
// CHECK:STDOUT: %Destroy.impl_witness.aa0: <witness> = impl_witness imports.%Destroy.impl_witness_table, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.30f) [symbolic]
7878
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.cc4: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.30f) [symbolic]
7979
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.44f: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.cc4 = struct_value () [symbolic]
80+
// CHECK:STDOUT: %.019: require_specific_def_type = require_specific_def @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.30f) [symbolic]
8081
// CHECK:STDOUT: %Destroy.facet.49e: %Destroy.type = facet_value %array_type.512, (%Destroy.impl_witness.aa0) [symbolic]
8182
// CHECK:STDOUT: %.fb1: type = fn_type_with_self_type %Destroy.Op.type, %Destroy.facet.49e [symbolic]
8283
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.91d: <specific function> = specific_function %DestroyT.binding.as_type.as.Destroy.impl.Op.44f, @DestroyT.binding.as_type.as.Destroy.impl.Op(%facet_value.30f) [symbolic]
@@ -87,10 +88,11 @@ fn H() { G(3); }
8788
// CHECK:STDOUT: %array.2e5: %array_type.6f1 = tuple_value () [concrete]
8889
// CHECK:STDOUT: %facet_value.cba: %type_where = facet_value %array_type.6f1, () [concrete]
8990
// CHECK:STDOUT: %Destroy.impl_witness.dff: <witness> = impl_witness imports.%Destroy.impl_witness_table, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.cba) [concrete]
90-
// CHECK:STDOUT: %Destroy.facet.105: %Destroy.type = facet_value %array_type.6f1, (%Destroy.impl_witness.dff) [concrete]
91-
// CHECK:STDOUT: %.0c7: type = fn_type_with_self_type %Destroy.Op.type, %Destroy.facet.105 [concrete]
9291
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.cc8: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.cba) [concrete]
9392
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.dcd: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.cc8 = struct_value () [concrete]
93+
// CHECK:STDOUT: %.793: require_specific_def_type = require_specific_def @DestroyT.binding.as_type.as.Destroy.impl(%facet_value.cba) [concrete]
94+
// CHECK:STDOUT: %Destroy.facet.105: %Destroy.type = facet_value %array_type.6f1, (%Destroy.impl_witness.dff) [concrete]
95+
// CHECK:STDOUT: %.0c7: type = fn_type_with_self_type %Destroy.Op.type, %Destroy.facet.105 [concrete]
9496
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.bf3: <specific function> = specific_function %DestroyT.binding.as_type.as.Destroy.impl.Op.dcd, @DestroyT.binding.as_type.as.Destroy.impl.Op(%facet_value.cba) [concrete]
9597
// CHECK:STDOUT: }
9698
// CHECK:STDOUT:
@@ -108,9 +110,10 @@ fn H() { G(3); }
108110
// CHECK:STDOUT: %pattern_type: type = pattern_type %array_type.loc7_22.2 [symbolic = %pattern_type (constants.%pattern_type.b5c)]
109111
// CHECK:STDOUT: %array: @G.%array_type.loc7_22.2 (%array_type.512) = tuple_value () [symbolic = %array (constants.%array.8ba)]
110112
// CHECK:STDOUT: %facet_value: %type_where = facet_value %array_type.loc7_22.2, () [symbolic = %facet_value (constants.%facet_value.30f)]
113+
// CHECK:STDOUT: %.loc7_3.2: require_specific_def_type = require_specific_def @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %.loc7_3.2 (constants.%.019)]
111114
// CHECK:STDOUT: %Destroy.impl_witness: <witness> = impl_witness imports.%Destroy.impl_witness_table, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %Destroy.impl_witness (constants.%Destroy.impl_witness.aa0)]
112115
// CHECK:STDOUT: %Destroy.facet: %Destroy.type = facet_value %array_type.loc7_22.2, (%Destroy.impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.49e)]
113-
// CHECK:STDOUT: %.loc7_3.2: type = fn_type_with_self_type constants.%Destroy.Op.type, %Destroy.facet [symbolic = %.loc7_3.2 (constants.%.fb1)]
116+
// CHECK:STDOUT: %.loc7_3.3: type = fn_type_with_self_type constants.%Destroy.Op.type, %Destroy.facet [symbolic = %.loc7_3.3 (constants.%.fb1)]
114117
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.type (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.type.cc4)]
115118
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op: @G.%DestroyT.binding.as_type.as.Destroy.impl.Op.type (%DestroyT.binding.as_type.as.Destroy.impl.Op.type.cc4) = struct_value () [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.44f)]
116119
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function %DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl.Op(%facet_value) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.91d)]
@@ -132,7 +135,7 @@ fn H() { G(3); }
132135
// CHECK:STDOUT: %array_type.loc7_22.1: type = array_type %int_0, %T.ref [symbolic = %array_type.loc7_22.2 (constants.%array_type.512)]
133136
// CHECK:STDOUT: }
134137
// CHECK:STDOUT: %arr: ref @G.%array_type.loc7_22.2 (%array_type.512) = ref_binding arr, %arr.var
135-
// CHECK:STDOUT: %impl.elem0: @G.%.loc7_3.2 (%.fb1) = impl_witness_access constants.%Destroy.impl_witness.aa0, element0 [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.44f)]
138+
// CHECK:STDOUT: %impl.elem0: @G.%.loc7_3.3 (%.fb1) = impl_witness_access constants.%Destroy.impl_witness.aa0, element0 [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.44f)]
136139
// CHECK:STDOUT: %bound_method.loc7_3.1: <bound method> = bound_method %arr.var, %impl.elem0
137140
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @DestroyT.binding.as_type.as.Destroy.impl.Op(constants.%facet_value.30f) [symbolic = %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn (constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.91d)]
138141
// CHECK:STDOUT: %bound_method.loc7_3.2: <bound method> = bound_method %arr.var, %specific_fn
@@ -154,9 +157,10 @@ fn H() { G(3); }
154157
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.9c8
155158
// CHECK:STDOUT: %array => constants.%array.2e5
156159
// CHECK:STDOUT: %facet_value => constants.%facet_value.cba
160+
// CHECK:STDOUT: %.loc7_3.2 => constants.%.793
157161
// CHECK:STDOUT: %Destroy.impl_witness => constants.%Destroy.impl_witness.dff
158162
// CHECK:STDOUT: %Destroy.facet => constants.%Destroy.facet.105
159-
// CHECK:STDOUT: %.loc7_3.2 => constants.%.0c7
163+
// CHECK:STDOUT: %.loc7_3.3 => constants.%.0c7
160164
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.type.cc8
161165
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.dcd
162166
// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn => constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.bf3

toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// CHECK:STDOUT: import_ir_insts: {}
2121
// CHECK:STDOUT: clang_decls: {}
2222
// CHECK:STDOUT: name_scopes:
23-
// CHECK:STDOUT: name_scope0: {inst: instD, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
23+
// CHECK:STDOUT: name_scope0: {inst: instE, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
2424
// CHECK:STDOUT: entity_names: {}
2525
// CHECK:STDOUT: cpp_global_vars: {}
2626
// CHECK:STDOUT: functions: {}
@@ -47,10 +47,11 @@
4747
// CHECK:STDOUT: 'inst(InstType)': {kind: InstType, type: type(TypeType)}
4848
// CHECK:STDOUT: 'inst(IntLiteralType)': {kind: IntLiteralType, type: type(TypeType)}
4949
// CHECK:STDOUT: 'inst(NamespaceType)': {kind: NamespaceType, type: type(TypeType)}
50+
// CHECK:STDOUT: 'inst(RequireSpecificDefinitionType)': {kind: RequireSpecificDefinitionType, type: type(TypeType)}
5051
// CHECK:STDOUT: 'inst(SpecificFunctionType)': {kind: SpecificFunctionType, type: type(TypeType)}
5152
// CHECK:STDOUT: 'inst(VtableType)': {kind: VtableType, type: type(TypeType)}
5253
// CHECK:STDOUT: 'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)}
53-
// CHECK:STDOUT: instD: {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}
54+
// CHECK:STDOUT: instE: {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}
5455
// CHECK:STDOUT: constant_values:
5556
// CHECK:STDOUT: values:
5657
// CHECK:STDOUT: 'inst(TypeType)': concrete_constant(inst(TypeType))
@@ -63,16 +64,17 @@
6364
// CHECK:STDOUT: 'inst(InstType)': concrete_constant(inst(InstType))
6465
// CHECK:STDOUT: 'inst(IntLiteralType)': concrete_constant(inst(IntLiteralType))
6566
// CHECK:STDOUT: 'inst(NamespaceType)': concrete_constant(inst(NamespaceType))
67+
// CHECK:STDOUT: 'inst(RequireSpecificDefinitionType)': concrete_constant(inst(RequireSpecificDefinitionType))
6668
// CHECK:STDOUT: 'inst(SpecificFunctionType)': concrete_constant(inst(SpecificFunctionType))
6769
// CHECK:STDOUT: 'inst(VtableType)': concrete_constant(inst(VtableType))
6870
// CHECK:STDOUT: 'inst(WitnessType)': concrete_constant(inst(WitnessType))
69-
// CHECK:STDOUT: instD: concrete_constant(instD)
71+
// CHECK:STDOUT: instE: concrete_constant(instE)
7072
// CHECK:STDOUT: symbolic_constants: {}
7173
// CHECK:STDOUT: inst_blocks:
7274
// CHECK:STDOUT: inst_block_empty: {}
7375
// CHECK:STDOUT: exports: {}
7476
// CHECK:STDOUT: imports: {}
7577
// CHECK:STDOUT: global_init: {}
7678
// CHECK:STDOUT: inst_block60000004:
77-
// CHECK:STDOUT: 0: instD
79+
// CHECK:STDOUT: 0: instE
7880
// CHECK:STDOUT: ...

0 commit comments

Comments
 (0)