mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 20:42:01 +01:00
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](https://github.com/carbon-language/carbon-lang/pull/6308#discussion_r2482655927) 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.
This commit is contained in:
@@ -264,6 +264,9 @@ class ImportContext {
|
||||
auto import_interfaces() -> const SemIR::InterfaceStore& {
|
||||
return import_ir().interfaces();
|
||||
}
|
||||
auto import_named_constraints() -> const SemIR::NamedConstraintStore& {
|
||||
return import_ir().named_constraints();
|
||||
}
|
||||
auto import_ints() -> const SharedValueStores::IntStore& {
|
||||
return import_ir().ints();
|
||||
}
|
||||
@@ -337,6 +340,9 @@ class ImportContext {
|
||||
auto local_interfaces() -> SemIR::InterfaceStore& {
|
||||
return local_ir().interfaces();
|
||||
}
|
||||
auto local_named_constraints() -> SemIR::NamedConstraintStore& {
|
||||
return local_ir().named_constraints();
|
||||
}
|
||||
auto local_ints() -> SharedValueStores::IntStore& {
|
||||
return local_ir().ints();
|
||||
}
|
||||
@@ -2521,7 +2527,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
const auto& import_interface =
|
||||
resolver.import_interfaces().Get(inst.interface_id);
|
||||
|
||||
SemIR::InterfaceId interface_id = SemIR::InterfaceId::None;
|
||||
auto interface_id = SemIR::InterfaceId::None;
|
||||
if (!interface_const_id.has_value()) {
|
||||
auto import_specific_id = SemIR::SpecificId::None;
|
||||
if (auto import_generic_interface_type =
|
||||
@@ -2598,6 +2604,162 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
return ResolveResult::Done(interface_const_id, new_interface.first_decl_id());
|
||||
}
|
||||
|
||||
// Make a declaration of a named constraint. This is done as a separate step
|
||||
// from importing the constraint definition in order to resolve cycles.
|
||||
static auto MakeNamedConstraintDecl(
|
||||
ImportContext& context,
|
||||
const SemIR::NamedConstraint& import_named_constraint,
|
||||
SemIR::SpecificId enclosing_specific_id)
|
||||
-> std::pair<SemIR::NamedConstraintId, SemIR::ConstantId> {
|
||||
SemIR::NamedConstraintDecl named_constraint_decl = {
|
||||
.type_id = SemIR::TypeType::TypeId,
|
||||
.named_constraint_id = SemIR::NamedConstraintId::None,
|
||||
.decl_block_id = SemIR::InstBlockId::Empty};
|
||||
auto named_constraint_decl_id = AddPlaceholderImportedInst(
|
||||
context, import_named_constraint.first_owning_decl_id,
|
||||
named_constraint_decl);
|
||||
|
||||
// Start with an incomplete interface.
|
||||
named_constraint_decl.named_constraint_id =
|
||||
context.local_named_constraints().Add(
|
||||
{GetIncompleteLocalEntityBase(context, named_constraint_decl_id,
|
||||
import_named_constraint),
|
||||
{.scope_id = import_named_constraint.is_complete()
|
||||
? AddPlaceholderNameScope(context)
|
||||
: SemIR::NameScopeId::None}});
|
||||
|
||||
if (import_named_constraint.has_parameters()) {
|
||||
named_constraint_decl.type_id = GetGenericNamedConstraintType(
|
||||
context.local_context(), named_constraint_decl.named_constraint_id,
|
||||
enclosing_specific_id);
|
||||
}
|
||||
|
||||
// Write the interface ID into the InterfaceDecl.
|
||||
auto interface_const_id = ReplacePlaceholderImportedInst(
|
||||
context, named_constraint_decl_id, named_constraint_decl);
|
||||
return {named_constraint_decl.named_constraint_id, interface_const_id};
|
||||
}
|
||||
|
||||
// Imports the definition for a named constraint that has been imported as a
|
||||
// forward declaration.
|
||||
static auto AddNamedConstraintDefinition(
|
||||
ImportContext& context,
|
||||
const SemIR::NamedConstraint& import_named_constraint,
|
||||
SemIR::NamedConstraint& new_named_constraint, SemIR::InstId self_param_id)
|
||||
-> void {
|
||||
auto& new_scope =
|
||||
context.local_name_scopes().Get(new_named_constraint.scope_id);
|
||||
const auto& import_scope =
|
||||
context.import_name_scopes().Get(import_named_constraint.scope_id);
|
||||
|
||||
// Push a block so that we can add scoped instructions to it.
|
||||
context.local_context().inst_block_stack().Push();
|
||||
InitializeNameScopeAndImportRefs(context, import_scope, new_scope,
|
||||
new_named_constraint.first_owning_decl_id,
|
||||
SemIR::NameId::None,
|
||||
new_named_constraint.parent_scope_id);
|
||||
new_scope.set_is_interface_definition();
|
||||
new_named_constraint.body_block_id =
|
||||
context.local_context().inst_block_stack().Pop();
|
||||
new_named_constraint.self_param_id = self_param_id;
|
||||
|
||||
CARBON_CHECK(import_scope.extended_scopes().empty(),
|
||||
"Interfaces don't currently have extended scopes to support.");
|
||||
}
|
||||
|
||||
static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
SemIR::NamedConstraintDecl inst,
|
||||
SemIR::ConstantId named_constraint_const_id)
|
||||
-> ResolveResult {
|
||||
const auto& import_named_constraint =
|
||||
resolver.import_named_constraints().Get(inst.named_constraint_id);
|
||||
|
||||
auto named_constraint_id = SemIR::NamedConstraintId::None;
|
||||
if (!named_constraint_const_id.has_value()) {
|
||||
auto import_specific_id = SemIR::SpecificId::None;
|
||||
if (auto import_generic_named_constraint_type =
|
||||
resolver.import_types().TryGetAs<SemIR::GenericNamedConstraintType>(
|
||||
inst.type_id)) {
|
||||
import_specific_id =
|
||||
import_generic_named_constraint_type->enclosing_specific_id;
|
||||
}
|
||||
auto specific_data = GetLocalSpecificData(resolver, import_specific_id);
|
||||
if (resolver.HasNewWork()) {
|
||||
// This is the end of the first phase. Don't make a new interface yet if
|
||||
// we already have new work.
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
|
||||
// On the second phase, create a forward declaration of the interface.
|
||||
auto enclosing_specific_id =
|
||||
GetOrAddLocalSpecific(resolver, import_specific_id, specific_data);
|
||||
std::tie(named_constraint_id, named_constraint_const_id) =
|
||||
MakeNamedConstraintDecl(resolver, import_named_constraint,
|
||||
enclosing_specific_id);
|
||||
} else {
|
||||
// On the third phase, compute the interface ID from the constant value of
|
||||
// the declaration.
|
||||
auto named_constraint_const_inst = resolver.local_insts().Get(
|
||||
resolver.local_constant_values().GetInstId(named_constraint_const_id));
|
||||
if (auto facet_type =
|
||||
named_constraint_const_inst.TryAs<SemIR::FacetType>()) {
|
||||
const SemIR::FacetTypeInfo& facet_type_info =
|
||||
resolver.local_facet_types().Get(facet_type->facet_type_id);
|
||||
CARBON_CHECK(facet_type_info.extend_named_constraints.size() == 1);
|
||||
CARBON_CHECK(facet_type_info.extend_constraints.empty());
|
||||
CARBON_CHECK(facet_type_info.self_impls_constraints.empty());
|
||||
CARBON_CHECK(facet_type_info.self_impls_named_constraints.empty());
|
||||
named_constraint_id =
|
||||
facet_type_info.extend_named_constraints.front().named_constraint_id;
|
||||
} else {
|
||||
auto generic_named_constraint_type =
|
||||
resolver.local_types().GetAs<SemIR::GenericNamedConstraintType>(
|
||||
named_constraint_const_inst.type_id());
|
||||
named_constraint_id = generic_named_constraint_type.named_constraint_id;
|
||||
}
|
||||
}
|
||||
|
||||
auto parent_scope_id =
|
||||
GetLocalNameScopeId(resolver, import_named_constraint.parent_scope_id);
|
||||
auto implicit_param_patterns = GetLocalInstBlockContents(
|
||||
resolver, import_named_constraint.implicit_param_patterns_id);
|
||||
auto param_patterns = GetLocalInstBlockContents(
|
||||
resolver, import_named_constraint.param_patterns_id);
|
||||
auto generic_data =
|
||||
GetLocalGenericData(resolver, import_named_constraint.generic_id);
|
||||
|
||||
std::optional<SemIR::InstId> self_param_id;
|
||||
if (import_named_constraint.is_complete()) {
|
||||
self_param_id =
|
||||
GetLocalConstantInstId(resolver, import_named_constraint.self_param_id);
|
||||
}
|
||||
auto& new_named_constraint =
|
||||
resolver.local_named_constraints().Get(named_constraint_id);
|
||||
|
||||
if (resolver.HasNewWork()) {
|
||||
return ResolveResult::Retry(named_constraint_const_id,
|
||||
new_named_constraint.first_decl_id());
|
||||
}
|
||||
|
||||
new_named_constraint.parent_scope_id = parent_scope_id;
|
||||
new_named_constraint.implicit_param_patterns_id =
|
||||
GetLocalCanonicalInstBlockId(
|
||||
resolver, import_named_constraint.implicit_param_patterns_id,
|
||||
implicit_param_patterns);
|
||||
new_named_constraint.param_patterns_id = GetLocalCanonicalInstBlockId(
|
||||
resolver, import_named_constraint.param_patterns_id, param_patterns);
|
||||
SetGenericData(resolver, import_named_constraint.generic_id,
|
||||
import_named_constraint.generic_id, generic_data);
|
||||
|
||||
if (import_named_constraint.is_complete()) {
|
||||
CARBON_CHECK(self_param_id);
|
||||
AddNamedConstraintDefinition(resolver, import_named_constraint,
|
||||
new_named_constraint, *self_param_id);
|
||||
}
|
||||
return ResolveResult::Done(named_constraint_const_id,
|
||||
new_named_constraint.first_decl_id());
|
||||
}
|
||||
|
||||
static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
SemIR::FacetAccessType inst) -> ResolveResult {
|
||||
auto facet_value_inst_id =
|
||||
@@ -3187,8 +3349,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
|
||||
case CARBON_KIND(SemIR::InterfaceDecl inst): {
|
||||
return TryResolveTypedInst(resolver, inst, const_id);
|
||||
}
|
||||
// TODO: Import NamedConstraintDecl once its FacetType constant value
|
||||
// contains the NamedConstraintId.
|
||||
case CARBON_KIND(SemIR::NamedConstraintDecl inst): {
|
||||
return TryResolveTypedInst(resolver, inst, const_id);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -49,14 +49,16 @@ fn F(T:! B) {}
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %type: type = facet_type <type> [concrete]
|
||||
// CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self]
|
||||
// CHECK:STDOUT: %T: %type = symbolic_binding T, 0 [symbolic]
|
||||
// CHECK:STDOUT: %pattern_type: type = pattern_type %type [concrete]
|
||||
// CHECK:STDOUT: %B.type: type = facet_type <@B> [concrete]
|
||||
// CHECK:STDOUT: %T: %B.type = symbolic_binding T, 0 [symbolic]
|
||||
// CHECK:STDOUT: %pattern_type: type = pattern_type %B.type [concrete]
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Main.B: type = import_ref Main//b, B, loaded [concrete = constants.%type]
|
||||
// CHECK:STDOUT: %Main.B: type = import_ref Main//b, B, loaded [concrete = constants.%B.type]
|
||||
// CHECK:STDOUT: %Main.import_ref = import_ref Main//b, loc3_14, unloaded
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -69,16 +71,21 @@ fn F(T:! B) {}
|
||||
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
|
||||
// CHECK:STDOUT: %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %.loc4: type = splice_block %B.ref [concrete = constants.%type] {
|
||||
// CHECK:STDOUT: %.loc4: type = splice_block %B.ref [concrete = constants.%B.type] {
|
||||
// CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, imports.%Main.B [concrete = constants.%type]
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, imports.%Main.B [concrete = constants.%B.type]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %T.loc4_6.2: %type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]
|
||||
// CHECK:STDOUT: %T.loc4_6.2: %B.type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: generic fn @F(%T.loc4_6.2: %type) {
|
||||
// CHECK:STDOUT: %T.loc4_6.1: %type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]
|
||||
// CHECK:STDOUT: constraint @B [from "b.carbon"] {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = imports.%Main.import_ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: generic fn @F(%T.loc4_6.2: %B.type) {
|
||||
// CHECK:STDOUT: %T.loc4_6.1: %B.type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user