Skip to content

Commit 30c3a35

Browse files
authored
Import the full NamedConstraint from its decl (#6311)
This imports the entire `NamedConstraint` structure when importing `NamedConstraintDecl`. This will be required to identify a facet type that contains a named constraint, as we will need to pull the `require` decls out of the `NamedConstraint` structure to do so. I tried making the `InterfaceDecl` code path [templated](#6308 (comment)) to reuse it, but it was a lot of template parameters including field pointers into `InterfaceDecl`, `GenericInterfaceType`, `SpecificInterface`, and it was very hard to read so I gave up on that approach here.
1 parent 94bb6be commit 30c3a35

File tree

2 files changed

+181
-11
lines changed

2 files changed

+181
-11
lines changed

toolchain/check/import_ref.cpp

Lines changed: 166 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ class ImportContext {
264264
auto import_interfaces() -> const SemIR::InterfaceStore& {
265265
return import_ir().interfaces();
266266
}
267+
auto import_named_constraints() -> const SemIR::NamedConstraintStore& {
268+
return import_ir().named_constraints();
269+
}
267270
auto import_ints() -> const SharedValueStores::IntStore& {
268271
return import_ir().ints();
269272
}
@@ -337,6 +340,9 @@ class ImportContext {
337340
auto local_interfaces() -> SemIR::InterfaceStore& {
338341
return local_ir().interfaces();
339342
}
343+
auto local_named_constraints() -> SemIR::NamedConstraintStore& {
344+
return local_ir().named_constraints();
345+
}
340346
auto local_ints() -> SharedValueStores::IntStore& {
341347
return local_ir().ints();
342348
}
@@ -2521,7 +2527,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
25212527
const auto& import_interface =
25222528
resolver.import_interfaces().Get(inst.interface_id);
25232529

2524-
SemIR::InterfaceId interface_id = SemIR::InterfaceId::None;
2530+
auto interface_id = SemIR::InterfaceId::None;
25252531
if (!interface_const_id.has_value()) {
25262532
auto import_specific_id = SemIR::SpecificId::None;
25272533
if (auto import_generic_interface_type =
@@ -2598,6 +2604,162 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
25982604
return ResolveResult::Done(interface_const_id, new_interface.first_decl_id());
25992605
}
26002606

2607+
// Make a declaration of a named constraint. This is done as a separate step
2608+
// from importing the constraint definition in order to resolve cycles.
2609+
static auto MakeNamedConstraintDecl(
2610+
ImportContext& context,
2611+
const SemIR::NamedConstraint& import_named_constraint,
2612+
SemIR::SpecificId enclosing_specific_id)
2613+
-> std::pair<SemIR::NamedConstraintId, SemIR::ConstantId> {
2614+
SemIR::NamedConstraintDecl named_constraint_decl = {
2615+
.type_id = SemIR::TypeType::TypeId,
2616+
.named_constraint_id = SemIR::NamedConstraintId::None,
2617+
.decl_block_id = SemIR::InstBlockId::Empty};
2618+
auto named_constraint_decl_id = AddPlaceholderImportedInst(
2619+
context, import_named_constraint.first_owning_decl_id,
2620+
named_constraint_decl);
2621+
2622+
// Start with an incomplete interface.
2623+
named_constraint_decl.named_constraint_id =
2624+
context.local_named_constraints().Add(
2625+
{GetIncompleteLocalEntityBase(context, named_constraint_decl_id,
2626+
import_named_constraint),
2627+
{.scope_id = import_named_constraint.is_complete()
2628+
? AddPlaceholderNameScope(context)
2629+
: SemIR::NameScopeId::None}});
2630+
2631+
if (import_named_constraint.has_parameters()) {
2632+
named_constraint_decl.type_id = GetGenericNamedConstraintType(
2633+
context.local_context(), named_constraint_decl.named_constraint_id,
2634+
enclosing_specific_id);
2635+
}
2636+
2637+
// Write the interface ID into the InterfaceDecl.
2638+
auto interface_const_id = ReplacePlaceholderImportedInst(
2639+
context, named_constraint_decl_id, named_constraint_decl);
2640+
return {named_constraint_decl.named_constraint_id, interface_const_id};
2641+
}
2642+
2643+
// Imports the definition for a named constraint that has been imported as a
2644+
// forward declaration.
2645+
static auto AddNamedConstraintDefinition(
2646+
ImportContext& context,
2647+
const SemIR::NamedConstraint& import_named_constraint,
2648+
SemIR::NamedConstraint& new_named_constraint, SemIR::InstId self_param_id)
2649+
-> void {
2650+
auto& new_scope =
2651+
context.local_name_scopes().Get(new_named_constraint.scope_id);
2652+
const auto& import_scope =
2653+
context.import_name_scopes().Get(import_named_constraint.scope_id);
2654+
2655+
// Push a block so that we can add scoped instructions to it.
2656+
context.local_context().inst_block_stack().Push();
2657+
InitializeNameScopeAndImportRefs(context, import_scope, new_scope,
2658+
new_named_constraint.first_owning_decl_id,
2659+
SemIR::NameId::None,
2660+
new_named_constraint.parent_scope_id);
2661+
new_scope.set_is_interface_definition();
2662+
new_named_constraint.body_block_id =
2663+
context.local_context().inst_block_stack().Pop();
2664+
new_named_constraint.self_param_id = self_param_id;
2665+
2666+
CARBON_CHECK(import_scope.extended_scopes().empty(),
2667+
"Interfaces don't currently have extended scopes to support.");
2668+
}
2669+
2670+
static auto TryResolveTypedInst(ImportRefResolver& resolver,
2671+
SemIR::NamedConstraintDecl inst,
2672+
SemIR::ConstantId named_constraint_const_id)
2673+
-> ResolveResult {
2674+
const auto& import_named_constraint =
2675+
resolver.import_named_constraints().Get(inst.named_constraint_id);
2676+
2677+
auto named_constraint_id = SemIR::NamedConstraintId::None;
2678+
if (!named_constraint_const_id.has_value()) {
2679+
auto import_specific_id = SemIR::SpecificId::None;
2680+
if (auto import_generic_named_constraint_type =
2681+
resolver.import_types().TryGetAs<SemIR::GenericNamedConstraintType>(
2682+
inst.type_id)) {
2683+
import_specific_id =
2684+
import_generic_named_constraint_type->enclosing_specific_id;
2685+
}
2686+
auto specific_data = GetLocalSpecificData(resolver, import_specific_id);
2687+
if (resolver.HasNewWork()) {
2688+
// This is the end of the first phase. Don't make a new interface yet if
2689+
// we already have new work.
2690+
return ResolveResult::Retry();
2691+
}
2692+
2693+
// On the second phase, create a forward declaration of the interface.
2694+
auto enclosing_specific_id =
2695+
GetOrAddLocalSpecific(resolver, import_specific_id, specific_data);
2696+
std::tie(named_constraint_id, named_constraint_const_id) =
2697+
MakeNamedConstraintDecl(resolver, import_named_constraint,
2698+
enclosing_specific_id);
2699+
} else {
2700+
// On the third phase, compute the interface ID from the constant value of
2701+
// the declaration.
2702+
auto named_constraint_const_inst = resolver.local_insts().Get(
2703+
resolver.local_constant_values().GetInstId(named_constraint_const_id));
2704+
if (auto facet_type =
2705+
named_constraint_const_inst.TryAs<SemIR::FacetType>()) {
2706+
const SemIR::FacetTypeInfo& facet_type_info =
2707+
resolver.local_facet_types().Get(facet_type->facet_type_id);
2708+
CARBON_CHECK(facet_type_info.extend_named_constraints.size() == 1);
2709+
CARBON_CHECK(facet_type_info.extend_constraints.empty());
2710+
CARBON_CHECK(facet_type_info.self_impls_constraints.empty());
2711+
CARBON_CHECK(facet_type_info.self_impls_named_constraints.empty());
2712+
named_constraint_id =
2713+
facet_type_info.extend_named_constraints.front().named_constraint_id;
2714+
} else {
2715+
auto generic_named_constraint_type =
2716+
resolver.local_types().GetAs<SemIR::GenericNamedConstraintType>(
2717+
named_constraint_const_inst.type_id());
2718+
named_constraint_id = generic_named_constraint_type.named_constraint_id;
2719+
}
2720+
}
2721+
2722+
auto parent_scope_id =
2723+
GetLocalNameScopeId(resolver, import_named_constraint.parent_scope_id);
2724+
auto implicit_param_patterns = GetLocalInstBlockContents(
2725+
resolver, import_named_constraint.implicit_param_patterns_id);
2726+
auto param_patterns = GetLocalInstBlockContents(
2727+
resolver, import_named_constraint.param_patterns_id);
2728+
auto generic_data =
2729+
GetLocalGenericData(resolver, import_named_constraint.generic_id);
2730+
2731+
std::optional<SemIR::InstId> self_param_id;
2732+
if (import_named_constraint.is_complete()) {
2733+
self_param_id =
2734+
GetLocalConstantInstId(resolver, import_named_constraint.self_param_id);
2735+
}
2736+
auto& new_named_constraint =
2737+
resolver.local_named_constraints().Get(named_constraint_id);
2738+
2739+
if (resolver.HasNewWork()) {
2740+
return ResolveResult::Retry(named_constraint_const_id,
2741+
new_named_constraint.first_decl_id());
2742+
}
2743+
2744+
new_named_constraint.parent_scope_id = parent_scope_id;
2745+
new_named_constraint.implicit_param_patterns_id =
2746+
GetLocalCanonicalInstBlockId(
2747+
resolver, import_named_constraint.implicit_param_patterns_id,
2748+
implicit_param_patterns);
2749+
new_named_constraint.param_patterns_id = GetLocalCanonicalInstBlockId(
2750+
resolver, import_named_constraint.param_patterns_id, param_patterns);
2751+
SetGenericData(resolver, import_named_constraint.generic_id,
2752+
import_named_constraint.generic_id, generic_data);
2753+
2754+
if (import_named_constraint.is_complete()) {
2755+
CARBON_CHECK(self_param_id);
2756+
AddNamedConstraintDefinition(resolver, import_named_constraint,
2757+
new_named_constraint, *self_param_id);
2758+
}
2759+
return ResolveResult::Done(named_constraint_const_id,
2760+
new_named_constraint.first_decl_id());
2761+
}
2762+
26012763
static auto TryResolveTypedInst(ImportRefResolver& resolver,
26022764
SemIR::FacetAccessType inst) -> ResolveResult {
26032765
auto facet_value_inst_id =
@@ -3187,8 +3349,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
31873349
case CARBON_KIND(SemIR::InterfaceDecl inst): {
31883350
return TryResolveTypedInst(resolver, inst, const_id);
31893351
}
3190-
// TODO: Import NamedConstraintDecl once its FacetType constant value
3191-
// contains the NamedConstraintId.
3352+
case CARBON_KIND(SemIR::NamedConstraintDecl inst): {
3353+
return TryResolveTypedInst(resolver, inst, const_id);
3354+
}
31923355
default:
31933356
break;
31943357
}

toolchain/check/testdata/named_constraint/import_constraint_decl.carbon

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,16 @@ fn F(T:! B) {}
4949
// CHECK:STDOUT: constants {
5050
// CHECK:STDOUT: %type: type = facet_type <type> [concrete]
5151
// CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self]
52-
// CHECK:STDOUT: %T: %type = symbolic_binding T, 0 [symbolic]
53-
// CHECK:STDOUT: %pattern_type: type = pattern_type %type [concrete]
52+
// CHECK:STDOUT: %B.type: type = facet_type <@B> [concrete]
53+
// CHECK:STDOUT: %T: %B.type = symbolic_binding T, 0 [symbolic]
54+
// CHECK:STDOUT: %pattern_type: type = pattern_type %B.type [concrete]
5455
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
5556
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
5657
// CHECK:STDOUT: }
5758
// CHECK:STDOUT:
5859
// CHECK:STDOUT: imports {
59-
// CHECK:STDOUT: %Main.B: type = import_ref Main//b, B, loaded [concrete = constants.%type]
60+
// CHECK:STDOUT: %Main.B: type = import_ref Main//b, B, loaded [concrete = constants.%B.type]
61+
// CHECK:STDOUT: %Main.import_ref = import_ref Main//b, loc3_14, unloaded
6062
// CHECK:STDOUT: }
6163
// CHECK:STDOUT:
6264
// CHECK:STDOUT: file {
@@ -69,16 +71,21 @@ fn F(T:! B) {}
6971
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
7072
// CHECK:STDOUT: %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]
7173
// CHECK:STDOUT: } {
72-
// CHECK:STDOUT: %.loc4: type = splice_block %B.ref [concrete = constants.%type] {
74+
// CHECK:STDOUT: %.loc4: type = splice_block %B.ref [concrete = constants.%B.type] {
7375
// CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]
74-
// CHECK:STDOUT: %B.ref: type = name_ref B, imports.%Main.B [concrete = constants.%type]
76+
// CHECK:STDOUT: %B.ref: type = name_ref B, imports.%Main.B [concrete = constants.%B.type]
7577
// CHECK:STDOUT: }
76-
// CHECK:STDOUT: %T.loc4_6.2: %type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]
78+
// CHECK:STDOUT: %T.loc4_6.2: %B.type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]
7779
// CHECK:STDOUT: }
7880
// CHECK:STDOUT: }
7981
// CHECK:STDOUT:
80-
// CHECK:STDOUT: generic fn @F(%T.loc4_6.2: %type) {
81-
// CHECK:STDOUT: %T.loc4_6.1: %type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]
82+
// CHECK:STDOUT: constraint @B [from "b.carbon"] {
83+
// CHECK:STDOUT: !members:
84+
// CHECK:STDOUT: .Self = imports.%Main.import_ref
85+
// CHECK:STDOUT: }
86+
// CHECK:STDOUT:
87+
// CHECK:STDOUT: generic fn @F(%T.loc4_6.2: %B.type) {
88+
// CHECK:STDOUT: %T.loc4_6.1: %B.type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]
8289
// CHECK:STDOUT:
8390
// CHECK:STDOUT: !definition:
8491
// CHECK:STDOUT:

0 commit comments

Comments
 (0)