Skip to content

Commit d44f699

Browse files
committed
specific-named-constraints
1 parent 0baa74d commit d44f699

File tree

11 files changed

+261
-182
lines changed

11 files changed

+261
-182
lines changed

toolchain/check/handle_require.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ static auto ValidateRequire(Context& context, SemIR::LocId loc_id,
183183
return std::nullopt;
184184
}
185185

186-
auto identified_facet_type_id =
187-
RequireIdentifiedFacetType(context, *constraint_facet_type, [&] {
186+
auto identified_facet_type_id = RequireIdentifiedFacetType(
187+
context, SemIR::LocId(constraint_inst_id), *constraint_facet_type, [&] {
188188
CARBON_DIAGNOSTIC(
189189
RequireImplsUnidentifiedFacetType, Error,
190190
"facet type {0} cannot be identified in `require` declaration",

toolchain/check/impl.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,14 @@ auto CheckConstraintIsInterface(Context& context, SemIR::InstId impl_decl_id,
297297
return SemIR::SpecificInterface::None;
298298
}
299299

300-
auto identified_id = RequireIdentifiedFacetType(context, *facet_type, [&] {
301-
CARBON_DIAGNOSTIC(ImplOfUnidentifiedFacetType, Error,
302-
"facet type {0} cannot be identified in `impl as`",
303-
InstIdAsType);
304-
return context.emitter().Build(impl_decl_id, ImplOfUnidentifiedFacetType,
305-
constraint_id);
306-
});
300+
auto identified_id = RequireIdentifiedFacetType(
301+
context, SemIR::LocId(constraint_id), *facet_type, [&] {
302+
CARBON_DIAGNOSTIC(ImplOfUnidentifiedFacetType, Error,
303+
"facet type {0} cannot be identified in `impl as`",
304+
InstIdAsType);
305+
return context.emitter().Build(
306+
impl_decl_id, ImplOfUnidentifiedFacetType, constraint_id);
307+
});
307308
if (!identified_id.has_value()) {
308309
return SemIR::SpecificInterface::None;
309310
}

toolchain/check/impl_lookup.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ static auto GetInterfacesFromConstantId(
202202
const auto& facet_type_info =
203203
context.facet_types().Get(facet_type_inst.facet_type_id);
204204
auto identified_id =
205-
RequireIdentifiedFacetType(context, facet_type_inst, [&] {
205+
RequireIdentifiedFacetType(context, loc_id, facet_type_inst, [&] {
206206
CARBON_DIAGNOSTIC(ImplLookupInUnidentifiedFacetType, Error,
207207
"facet type {0} can not be identified", InstIdAsType);
208208
return context.emitter().Build(
@@ -323,7 +323,8 @@ static auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,
323323
// is allowed to be a non-canonical facet value in order to find a concrete
324324
// witness, so it's not referenced as a constant value.
325325
static auto LookupImplWitnessInSelfFacetValue(
326-
Context& context, SemIR::InstId self_facet_value_inst_id,
326+
Context& context, SemIR::LocId loc_id,
327+
SemIR::InstId self_facet_value_inst_id,
327328
SemIR::SpecificInterface query_specific_interface) -> EvalImplLookupResult {
328329
auto facet_type = context.types().TryGetAs<SemIR::FacetType>(
329330
context.insts().Get(self_facet_value_inst_id).type_id());
@@ -336,7 +337,7 @@ static auto LookupImplWitnessInSelfFacetValue(
336337
// `FacetValue` witnesses are the output of an impl lookup, which finds and
337338
// returns witnesses in the same order.
338339
auto identified_id =
339-
RequireIdentifiedFacetType(context, *facet_type, nullptr);
340+
RequireIdentifiedFacetType(context, loc_id, *facet_type, nullptr);
340341
// This should not be possible as FacetValue is constructed by a conversion
341342
// to a facet type, which performs impl lookup for that facet type, and
342343
// lookup only succeeds for complete facet types.
@@ -879,7 +880,7 @@ auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
879880
context.specific_interfaces().Get(eval_query.query_specific_interface_id);
880881

881882
auto facet_lookup_result = LookupImplWitnessInSelfFacetValue(
882-
context, self_facet_value_inst_id, query_specific_interface);
883+
context, loc_id, self_facet_value_inst_id, query_specific_interface);
883884
if (facet_lookup_result.has_final_value()) {
884885
return facet_lookup_result;
885886
}

toolchain/check/import_ref.cpp

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "toolchain/base/shared_value_stores.h"
1616
#include "toolchain/check/context.h"
1717
#include "toolchain/check/eval.h"
18+
#include "toolchain/check/facet_type.h"
1819
#include "toolchain/check/generic.h"
1920
#include "toolchain/check/import.h"
2021
#include "toolchain/check/inst.h"
@@ -494,7 +495,7 @@ static auto SetIndirectConstantValues(
494495
// Adds an import_ref instruction for an instruction that we have already loaded
495496
// from an imported IR, with a known constant value. This is useful when the
496497
// instruction has a symbolic constant value, in order to produce an instruction
497-
// that hold that symbolic constant.
498+
// that holds that symbolic constant.
498499
static auto AddLoadedImportRef(ImportContext& context,
499500
SemIR::TypeId local_type_id,
500501
SemIR::InstId import_inst_id,
@@ -869,8 +870,14 @@ static auto GetLocalConstantId(ImportRefResolver& resolver,
869870
// declaration.
870871
return GetLocalConstantId(resolver, import_decl_inst_id);
871872
}
873+
if (import_decl_inst.Is<SemIR::RequireImplsDecl>()) {
874+
// For an impl declaration, the imported entity can be found via the
875+
// declaration.
876+
return GetLocalConstantId(resolver, import_decl_inst_id);
877+
}
872878
// For all other kinds of declaration, the imported entity can be found via
873879
// the type of the declaration.
880+
CARBON_CHECK(import_decl_inst.type_id().has_value());
874881
return GetLocalConstantId(resolver, import_decl_inst.type_id());
875882
}
876883

@@ -904,6 +911,11 @@ static auto GetLocalGenericId(ImportContext& context,
904911
case CARBON_KIND(SemIR::ImplDecl impl_decl): {
905912
return context.local_impls().Get(impl_decl.impl_id).generic_id;
906913
}
914+
case CARBON_KIND(SemIR::RequireImplsDecl require_decl): {
915+
return context.local_require_impls()
916+
.Get(require_decl.require_impls_id)
917+
.generic_id;
918+
}
907919
default: {
908920
CARBON_FATAL("Unexpected inst for generic declaration: {0}", inst);
909921
}
@@ -2562,6 +2574,13 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
25622574
resolver, import_impl.constraint_id, constraint_const_id);
25632575
new_impl.interface = GetLocalSpecificInterface(
25642576
resolver, import_impl.interface, specific_interface_data);
2577+
// Create a local IdentifiedFacetType for the imported facet type, since impl
2578+
// declarations always identify the facet type.
2579+
if (auto facet_type = resolver.local_insts().TryGetAs<SemIR::FacetType>(
2580+
resolver.local_constant_values().GetInstId(constraint_const_id))) {
2581+
RequireIdentifiedFacetType(resolver.local_context(), SemIR::LocId::None,
2582+
*facet_type, nullptr);
2583+
}
25652584
if (import_impl.is_complete()) {
25662585
AddImplDefinition(resolver, import_impl, new_impl);
25672586
}
@@ -2579,10 +2598,45 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
25792598
}
25802599

25812600
static auto TryResolveTypedInst(ImportRefResolver& resolver,
2582-
SemIR::RequireImplsDecl inst) -> ResolveResult {
2601+
SemIR::RequireImplsDecl inst,
2602+
SemIR::ConstantId require_decl_const_id)
2603+
-> ResolveResult {
25832604
const auto& import_require =
25842605
resolver.import_require_impls().Get(inst.require_impls_id);
25852606

2607+
auto require_decl_id = SemIR::InstId::None;
2608+
auto require_impls_id = SemIR::RequireImplsId::None;
2609+
if (!require_decl_const_id.has_value()) {
2610+
// Phase one: Make the decl and structure with placeholder values to be
2611+
// filled in. Begin the generic so instructions can be attached to it.
2612+
SemIR::RequireImplsDecl require_decl = {
2613+
.require_impls_id = SemIR::RequireImplsId::None,
2614+
.decl_block_id = SemIR::InstBlockId::Empty};
2615+
auto require_decl_id = AddPlaceholderImportedInst(
2616+
resolver, import_require.decl_id, require_decl);
2617+
require_impls_id = resolver.local_require_impls().Add(
2618+
{.self_id = SemIR::TypeInstId::None,
2619+
.facet_type_inst_id = SemIR::TypeInstId::None,
2620+
.facet_type_id = SemIR::FacetTypeId::None,
2621+
.decl_id = require_decl_id,
2622+
.parent_scope_id = SemIR::NameScopeId::None,
2623+
.generic_id = MakeIncompleteGeneric(resolver, require_decl_id,
2624+
import_require.generic_id)});
2625+
2626+
// Write the RequireImplsId into the RequireImplsDecl.
2627+
require_decl.require_impls_id = require_impls_id;
2628+
require_decl_const_id =
2629+
ReplacePlaceholderImportedInst(resolver, require_decl_id, require_decl);
2630+
} else {
2631+
// Phase two: Get the `require_decl_id` and `require_impls_id` from the
2632+
// RequireImplsDecl constructed in phase one.
2633+
require_decl_id =
2634+
resolver.local_constant_values().GetInstId(require_decl_const_id);
2635+
require_impls_id = resolver.local_insts()
2636+
.GetAs<SemIR::RequireImplsDecl>(require_decl_id)
2637+
.require_impls_id;
2638+
}
2639+
25862640
// Load dependent constants.
25872641
auto parent_scope_id =
25882642
GetLocalNameScopeId(resolver, import_require.parent_scope_id);
@@ -2592,29 +2646,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
25922646
GetLocalConstantId(resolver, import_require.facet_type_inst_id);
25932647

25942648
if (resolver.HasNewWork()) {
2595-
return ResolveResult::Retry();
2649+
return ResolveResult::Retry(require_decl_const_id, require_decl_id);
25962650
}
25972651

2598-
// Make the decl and structure with placeholder values to be filled in.
2599-
SemIR::RequireImplsDecl require_decl = {
2600-
.require_impls_id = SemIR::RequireImplsId::None,
2601-
.decl_block_id = SemIR::InstBlockId::Empty};
2602-
auto require_decl_id = AddPlaceholderImportedInst(
2603-
resolver, import_require.decl_id, require_decl);
2604-
auto require_impls_id = resolver.local_require_impls().Add(
2605-
{.self_id = SemIR::TypeInstId::None,
2606-
.facet_type_inst_id = SemIR::TypeInstId::None,
2607-
.facet_type_id = SemIR::FacetTypeId::None,
2608-
.decl_id = require_decl_id,
2609-
.parent_scope_id = SemIR::NameScopeId::None,
2610-
.generic_id = MakeIncompleteGeneric(resolver, require_decl_id,
2611-
import_require.generic_id)});
2612-
2613-
// Write the RequireImplsId into the RequireImplsDecl.
2614-
require_decl.require_impls_id = require_impls_id;
2615-
auto require_decl_const_id =
2616-
ReplacePlaceholderImportedInst(resolver, require_decl_id, require_decl);
2617-
26182652
// Fill in the RequireImpls structure.
26192653
auto& new_require = resolver.local_require_impls().Get(require_impls_id);
26202654
new_require.self_id = AddLoadedImportRefForType(
@@ -3604,6 +3638,9 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
36043638
case CARBON_KIND(SemIR::NamedConstraintDecl inst): {
36053639
return TryResolveTypedInst(resolver, inst, const_id);
36063640
}
3641+
case CARBON_KIND(SemIR::RequireImplsDecl inst): {
3642+
return TryResolveTypedInst(resolver, inst, const_id);
3643+
}
36073644
default:
36083645
break;
36093646
}
@@ -3774,9 +3811,6 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
37743811
case CARBON_KIND(SemIR::RequireCompleteType inst): {
37753812
return TryResolveTypedInst(resolver, inst);
37763813
}
3777-
case CARBON_KIND(SemIR::RequireImplsDecl inst): {
3778-
return TryResolveTypedInst(resolver, inst);
3779-
}
37803814
case CARBON_KIND(SemIR::RequireSpecificDefinition inst): {
37813815
return TryResolveTypedInst(resolver, inst);
37823816
}

toolchain/check/testdata/facet/require_import.carbon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ fn F(A:! X, B:! Y) {}
5353
// CHECK:STDOUT: %Main.Y: type = import_ref Main//a, Y, loaded [concrete = constants.%Y.type]
5454
// CHECK:STDOUT: %Main.X: type = import_ref Main//a, X, loaded [concrete = constants.%X.type]
5555
// CHECK:STDOUT: %Main.import_ref.462 = import_ref Main//a, loc3_13, unloaded
56-
// CHECK:STDOUT: %Main.import_ref.b7c: type = import_ref Main//a, loc10_18, loaded [symbolic = constants.%Self.binding.as_type.1a1]
56+
// CHECK:STDOUT: %Main.import_ref.b7c: type = import_ref Main//a, loc10_18, loaded [symbolic = @X.require0.%Self.binding.as_type (constants.%Self.binding.as_type.1a1)]
5757
// CHECK:STDOUT: %Main.import_ref.dec: %X.type = import_ref Main//a, loc9_14, loaded [symbolic = constants.%Self.861]
5858
// CHECK:STDOUT: %Main.import_ref.cae = import_ref Main//a, loc9_14, unloaded
59-
// CHECK:STDOUT: %Main.import_ref.3e6: type = import_ref Main//a, loc6_11, loaded [symbolic = constants.%Self.binding.as_type.384]
59+
// CHECK:STDOUT: %Main.import_ref.3e6: type = import_ref Main//a, loc6_11, loaded [symbolic = @Y.require1.%Self.binding.as_type (constants.%Self.binding.as_type.384)]
6060
// CHECK:STDOUT: %Main.import_ref.35b: %Y.type = import_ref Main//a, loc5_13, loaded [symbolic = constants.%Self.29b]
6161
// CHECK:STDOUT: %Main.import_ref.581 = import_ref Main//a, loc5_13, unloaded
6262
// CHECK:STDOUT: }

toolchain/check/testdata/impl/impl_as_named_constraint.carbon

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ constraint C {
128128
// CHECK:STDERR:
129129
impl () as C {}
130130

131-
// --- todo_fail_duplicate_through_generic_constraint.carbon
131+
// --- fail_duplicate_through_generic_constraint.carbon
132132
library "[[@TEST_NAME]]";
133133

134134
interface A(T:! type) {}
@@ -140,5 +140,11 @@ constraint B(X:! type, Y:! type) {
140140
// This should impl () as A({}).
141141
impl () as B((), {}) {}
142142

143-
// This should be considered a duplicate.
143+
// CHECK:STDERR: fail_duplicate_through_generic_constraint.carbon:[[@LINE+7]]:1: error: found non-final `impl` with the same type structure as another non-final `impl` [ImplNonFinalSameTypeStructure]
144+
// CHECK:STDERR: impl () as A({}) {}
145+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
146+
// CHECK:STDERR: fail_duplicate_through_generic_constraint.carbon:[[@LINE-5]]:1: note: other `impl` here [ImplNonFinalSameTypeStructureNote]
147+
// CHECK:STDERR: impl () as B((), {}) {}
148+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
149+
// CHECK:STDERR:
144150
impl () as A({}) {}

0 commit comments

Comments
 (0)