Skip to content

Commit e62678e

Browse files
authored
Identify and complete facet types as needed for p5168 (#6369)
Proposal #5168 defines when a facet type must be identified or complete, and what it means for an interface and a named constraint to be identified or complete. This updates the toolchain to match the requirements. This implements identification of a facet type to require completed named constraints and to include any interfaces from named constraints into the resulting IdentifiedFacetType. To complete a facet type, each interface in the IdentifiedFacetType, and any interface named though a require declaration from them, must be complete.
1 parent 0183fa3 commit e62678e

File tree

13 files changed

+320
-174
lines changed

13 files changed

+320
-174
lines changed

toolchain/check/handle_require.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "toolchain/check/subst.h"
1414
#include "toolchain/check/type.h"
1515
#include "toolchain/check/type_completion.h"
16+
#include "toolchain/diagnostics/diagnostic.h"
1617
#include "toolchain/parse/node_ids.h"
1718
#include "toolchain/sem_ir/ids.h"
1819
#include "toolchain/sem_ir/named_constraint.h"
@@ -81,6 +82,15 @@ auto HandleParseNode(Context& context, Parse::RequireDefaultSelfImplsId node_id)
8182
auto HandleParseNode(Context& context, Parse::RequireTypeImplsId node_id)
8283
-> bool {
8384
auto [self_node_id, self_inst_id] = context.node_stack().PopExprWithNodeId();
85+
86+
auto introducer = context.decl_introducer_state_stack().innermost();
87+
if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
88+
CARBON_DIAGNOSTIC(RequireImplsExtendWithExplicitSelf, Error,
89+
"`extend require impls` with explicit type");
90+
context.emitter().Emit(self_node_id, RequireImplsExtendWithExplicitSelf);
91+
self_inst_id = SemIR::ErrorInst::InstId;
92+
}
93+
8494
auto self_type = ExprAsType(context, self_node_id, self_inst_id);
8595
context.node_stack().Push(node_id, self_type.inst_id);
8696
return true;
@@ -241,6 +251,8 @@ auto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {
241251
return true;
242252
}
243253

254+
bool extend = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend);
255+
244256
auto require_impls_decl =
245257
SemIR::RequireImplsDecl{// To be filled in after.
246258
.require_impls_id = SemIR::RequireImplsId::None,
@@ -251,6 +263,7 @@ auto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {
251263
.facet_type_inst_id =
252264
context.types().GetAsTypeInstId(constraint_inst_id),
253265
.facet_type_id = constraint_facet_type.facet_type_id,
266+
.extend_self = extend,
254267
.decl_id = decl_id,
255268
.parent_scope_id = context.scope_stack().PeekNameScopeId(),
256269
.generic_id = BuildGenericDecl(context, decl_id)});

toolchain/check/impl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ auto ImplWitnessStartDefinition(Context& context, SemIR::Impl& impl) -> void {
121121
witness_block.empty()) {
122122
if (!RequireCompleteFacetTypeForImplDefinition(
123123
context, SemIR::LocId(impl.latest_decl_id()), impl.constraint_id)) {
124+
FillImplWitnessWithErrors(context, impl);
124125
return;
125126
}
126127

toolchain/check/impl_lookup.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,10 @@ static auto GetInterfacesFromConstantId(
203203
context.facet_types().Get(facet_type_inst.facet_type_id);
204204
auto identified_id =
205205
RequireIdentifiedFacetType(context, facet_type_inst, [&] {
206-
CARBON_DIAGNOSTIC(ImplLookupInIncompleteFacetType, Error,
207-
"facet type {0} is incomplete", InstIdAsType);
208-
return context.emitter().Build(loc_id, ImplLookupInIncompleteFacetType,
209-
facet_type_inst_id);
206+
CARBON_DIAGNOSTIC(ImplLookupInUnidentifiedFacetType, Error,
207+
"facet type {0} can not be identified", InstIdAsType);
208+
return context.emitter().Build(
209+
loc_id, ImplLookupInUnidentifiedFacetType, facet_type_inst_id);
210210
});
211211
if (!identified_id.has_value()) {
212212
return std::nullopt;

toolchain/check/import_ref.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2468,6 +2468,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
24682468
resolver.local_insts().GetAs<SemIR::FacetType>(
24692469
new_canonical_facet_type_inst_id);
24702470
new_require.facet_type_id = new_canonical_facet_type.facet_type_id;
2471+
new_require.extend_self = import_require.extend_self;
24712472
new_require.parent_scope_id = parent_scope_id;
24722473

24732474
SetGenericData(resolver, import_require.generic_id, new_require.generic_id,

toolchain/check/testdata/facet/fail_incomplete.carbon

Lines changed: 95 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Exceptions. See /LICENSE for license information.
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
//
5-
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
5+
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon
66
//
77
// AUTOUPDATE
88
// TIP: To test this file alone, run:
@@ -13,95 +13,114 @@
1313
// --- fail_incomplete_interface.carbon
1414
library "[[@TEST_NAME]]";
1515

16-
interface A;
17-
interface B {}
16+
interface X;
1817
class C {}
1918

20-
fn G[T:! A](t: T) {}
21-
fn H[T:! A & B](t: T) {}
19+
// Requires X identified.
20+
impl C as X;
2221

23-
fn F() {
24-
// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE+4]]:3: error: cannot convert type `C` into type implementing `A` [ConversionFailureTypeToFacet]
25-
// CHECK:STDERR: C as A;
26-
// CHECK:STDERR: ^~~~~~
27-
// CHECK:STDERR:
28-
C as A;
22+
// Requires X complete.
23+
// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `X` [ImplAsIncompleteFacetTypeDefinition]
24+
// CHECK:STDERR: impl C as X {}
25+
// CHECK:STDERR: ^~~~~~~~~~~~~
26+
// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE-10]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
27+
// CHECK:STDERR: interface X;
28+
// CHECK:STDERR: ^~~~~~~~~~~~
29+
// CHECK:STDERR:
30+
impl C as X {}
2931

30-
// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE+4]]:3: error: cannot convert type `C` into type implementing `A & B` [ConversionFailureTypeToFacet]
31-
// CHECK:STDERR: C as (A & B);
32-
// CHECK:STDERR: ^~~~~~~~~~~~
33-
// CHECK:STDERR:
34-
C as (A & B);
35-
36-
// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `A` [ConversionFailureTypeToFacet]
37-
// CHECK:STDERR: G({} as C);
38-
// CHECK:STDERR: ^~~~~~~~~~
39-
// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE-19]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
40-
// CHECK:STDERR: fn G[T:! A](t: T) {}
41-
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
42-
// CHECK:STDERR:
43-
G({} as C);
44-
45-
// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `A & B` [ConversionFailureTypeToFacet]
46-
// CHECK:STDERR: H({} as C);
47-
// CHECK:STDERR: ^~~~~~~~~~
48-
// CHECK:STDERR: fail_incomplete_interface.carbon:[[@LINE-27]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
49-
// CHECK:STDERR: fn H[T:! A & B](t: T) {}
50-
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
51-
// CHECK:STDERR:
52-
H({} as C);
32+
// --- fail_incomplete_interface_without_forward_decl.carbon
33+
library "[[@TEST_NAME]]";
34+
35+
interface X;
36+
class C {}
37+
38+
// Requires X complete.
39+
// CHECK:STDERR: fail_incomplete_interface_without_forward_decl.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `X` [ImplAsIncompleteFacetTypeDefinition]
40+
// CHECK:STDERR: impl C as X {}
41+
// CHECK:STDERR: ^~~~~~~~~~~~~
42+
// CHECK:STDERR: fail_incomplete_interface_without_forward_decl.carbon:[[@LINE-7]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
43+
// CHECK:STDERR: interface X;
44+
// CHECK:STDERR: ^~~~~~~~~~~~
45+
// CHECK:STDERR:
46+
impl C as X {}
47+
48+
// --- fail_unidentified_constraint.carbon
49+
library "[[@TEST_NAME]]";
50+
51+
constraint X;
52+
class C {}
53+
54+
// Requires X identified.
55+
// CHECK:STDERR: fail_unidentified_constraint.carbon:[[@LINE+7]]:1: error: facet type `X` cannot be identified in `impl as` [ImplOfUnidentifiedFacetType]
56+
// CHECK:STDERR: impl C as X;
57+
// CHECK:STDERR: ^~~~~~~~~~~~
58+
// CHECK:STDERR: fail_unidentified_constraint.carbon:[[@LINE-7]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
59+
// CHECK:STDERR: constraint X;
60+
// CHECK:STDERR: ^~~~~~~~~~~~~
61+
// CHECK:STDERR:
62+
impl C as X;
63+
64+
// --- nested_require_incomplete_interface.carbon
65+
library "[[@TEST_NAME]]";
66+
67+
interface Z;
68+
constraint Y {
69+
require impls Z;
5370
}
71+
interface X {
72+
require impls Y;
73+
}
74+
75+
class C {}
76+
77+
// Requires X identified.
78+
impl C as X;
79+
80+
// Requires X complete.
81+
impl C as X {}
5482

55-
// --- fail_incomplete_constraint.carbon
83+
// --- fail_incomplete_through_constraint.carbon
5684
library "[[@TEST_NAME]]";
5785

58-
constraint A;
59-
interface B {}
86+
interface Z;
87+
constraint Y {
88+
extend require impls Z;
89+
}
90+
6091
class C {}
6192

62-
fn G[T:! A](t: T) {}
63-
fn H[T:! A & B](t: T) {}
93+
// Requires Y identified.
94+
impl C as Y;
6495

65-
fn F() {
66-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE+7]]:3: error: facet type `A` is incomplete [ImplLookupInIncompleteFacetType]
67-
// CHECK:STDERR: C as A;
68-
// CHECK:STDERR: ^~~~~~
69-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE-11]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
70-
// CHECK:STDERR: constraint A;
71-
// CHECK:STDERR: ^~~~~~~~~~~~~
72-
// CHECK:STDERR:
73-
C as A;
96+
// Requires Y complete.
97+
// CHECK:STDERR: fail_incomplete_through_constraint.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `Y` [ImplAsIncompleteFacetTypeDefinition]
98+
// CHECK:STDERR: impl C as Y {}
99+
// CHECK:STDERR: ^~~~~~~~~~~~~
100+
// CHECK:STDERR: fail_incomplete_through_constraint.carbon:[[@LINE-14]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
101+
// CHECK:STDERR: interface Z;
102+
// CHECK:STDERR: ^~~~~~~~~~~~
103+
// CHECK:STDERR:
104+
impl C as Y {}
74105

75-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE+7]]:3: error: facet type `B & A` is incomplete [ImplLookupInIncompleteFacetType]
76-
// CHECK:STDERR: C as (A & B);
77-
// CHECK:STDERR: ^~~~~~~~~~~~
78-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE-20]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
79-
// CHECK:STDERR: constraint A;
80-
// CHECK:STDERR: ^~~~~~~~~~~~~
81-
// CHECK:STDERR:
82-
C as (A & B);
106+
// --- fail_impl_lookup_incomplete.carbon
107+
library "[[@TEST_NAME]]";
83108

84-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE+10]]:3: error: facet type `A` is incomplete [ImplLookupInIncompleteFacetType]
85-
// CHECK:STDERR: G({} as C);
86-
// CHECK:STDERR: ^~~~~~~~~~
87-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE-29]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
88-
// CHECK:STDERR: constraint A;
89-
// CHECK:STDERR: ^~~~~~~~~~~~~
90-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE-28]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
91-
// CHECK:STDERR: fn G[T:! A](t: T) {}
92-
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~
93-
// CHECK:STDERR:
94-
G({} as C);
109+
constraint Z;
95110

96-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE+10]]:3: error: facet type `B & A` is incomplete [ImplLookupInIncompleteFacetType]
97-
// CHECK:STDERR: H({} as C);
98-
// CHECK:STDERR: ^~~~~~~~~~
99-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE-41]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
100-
// CHECK:STDERR: constraint A;
111+
fn AsZ(T:! Z) {}
112+
113+
fn F() {
114+
// Requires Z identified.
115+
// CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE+10]]:3: error: facet type `Z` can not be identified [ImplLookupInUnidentifiedFacetType]
116+
// CHECK:STDERR: AsZ(());
117+
// CHECK:STDERR: ^~~~~~~
118+
// CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE-9]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
119+
// CHECK:STDERR: constraint Z;
101120
// CHECK:STDERR: ^~~~~~~~~~~~~
102-
// CHECK:STDERR: fail_incomplete_constraint.carbon:[[@LINE-39]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
103-
// CHECK:STDERR: fn H[T:! A & B](t: T) {}
104-
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
121+
// CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE-10]]:8: note: initializing generic parameter `T` declared here [InitializingGenericParam]
122+
// CHECK:STDERR: fn AsZ(T:! Z) {}
123+
// CHECK:STDERR: ^
105124
// CHECK:STDERR:
106-
H({} as C);
125+
AsZ(());
107126
}

toolchain/check/testdata/facet/require_invalid.carbon

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,16 @@ class C {
110110
// CHECK:STDERR:
111111
require impls Y;
112112
}
113+
114+
// --- fail_extend_require_type.carbon
115+
library "[[@TEST_NAME]]";
116+
117+
interface Y {}
118+
119+
interface Z {
120+
// CHECK:STDERR: fail_extend_require_type.carbon:[[@LINE+4]]:18: error: `extend require impls` with explicit type [RequireImplsExtendWithExplicitSelf]
121+
// CHECK:STDERR: extend require () impls Y;
122+
// CHECK:STDERR: ^~
123+
// CHECK:STDERR:
124+
extend require () impls Y;
125+
}

0 commit comments

Comments
 (0)