Skip to content

Commit c7e3481

Browse files
committed
complete-at-require-decl
1 parent ae7635f commit c7e3481

File tree

4 files changed

+76
-77
lines changed

4 files changed

+76
-77
lines changed

toolchain/check/handle_require.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ struct ValidateRequireResult {
163163
static auto ValidateRequire(Context& context, SemIR::LocId loc_id,
164164
SemIR::TypeInstId self_inst_id,
165165
SemIR::InstId constraint_inst_id,
166-
SemIR::InstId scope_inst_id)
166+
SemIR::InstId scope_inst_id, bool extend)
167167
-> std::optional<ValidateRequireResult> {
168168
auto constraint_constant_value_id =
169169
context.constant_values().Get(constraint_inst_id);
@@ -210,6 +210,22 @@ static auto ValidateRequire(Context& context, SemIR::LocId loc_id,
210210
return std::nullopt;
211211
}
212212

213+
if (extend) {
214+
if (!RequireCompleteType(
215+
context, constraint_type_id, SemIR::LocId(constraint_inst_id), [&] {
216+
CARBON_DIAGNOSTIC(RequireImplsIncompleteFacetType, Error,
217+
"`extend require` of incomplete facet type {0}",
218+
InstIdAsType);
219+
return context.emitter().Build(constraint_inst_id,
220+
RequireImplsIncompleteFacetType,
221+
constraint_inst_id);
222+
})) {
223+
// The constraint is invalid, and a diagnostic was emitted by
224+
// RequireCompleteType().
225+
return std::nullopt;
226+
}
227+
}
228+
213229
if (scope_inst_id == SemIR::ErrorInst::InstId) {
214230
// `require` is in the wrong scope.
215231
return std::nullopt;
@@ -241,8 +257,10 @@ auto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {
241257
auto scope_inst_id =
242258
context.node_stack().Pop<Parse::NodeKind::RequireIntroducer>();
243259

260+
bool extend = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend);
261+
244262
auto validated = ValidateRequire(context, node_id, self_inst_id,
245-
constraint_inst_id, scope_inst_id);
263+
constraint_inst_id, scope_inst_id, extend);
246264
if (!validated) {
247265
DiscardGenericDecl(context);
248266
return true;
@@ -255,8 +273,6 @@ auto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {
255273
return true;
256274
}
257275

258-
bool extend = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend);
259-
260276
auto require_impls_decl =
261277
SemIR::RequireImplsDecl{// To be filled in after.
262278
.require_impls_id = SemIR::RequireImplsId::None,

toolchain/check/testdata/facet/fail_incomplete.carbon

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -80,29 +80,6 @@ impl C as X;
8080
// Requires X complete.
8181
impl C as X {}
8282

83-
// --- fail_incomplete_through_constraint.carbon
84-
library "[[@TEST_NAME]]";
85-
86-
interface Z;
87-
constraint Y {
88-
extend require impls Z;
89-
}
90-
91-
class C {}
92-
93-
// Requires Y identified.
94-
impl C as Y;
95-
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 {}
105-
10683
// --- fail_impl_lookup_incomplete.carbon
10784
library "[[@TEST_NAME]]";
10885

toolchain/check/testdata/impl/impl_as_named_constraint.carbon

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ impl () as A {}
2424
// --- fail_too_many_interfaces_in_constraint.carbon
2525
library "[[@TEST_NAME]]";
2626

27-
interface A1;
28-
interface A2;
27+
interface A1 {}
28+
interface A2 {}
2929
constraint B {
3030
extend require impls A1;
3131
extend require impls A2;
@@ -40,17 +40,11 @@ impl () as B {}
4040
// --- one_extend_impls_interface_in_constraint.carbon
4141
library "[[@TEST_NAME]]";
4242

43-
interface A;
43+
interface A {}
4444
constraint B {
4545
extend require impls A;
4646
}
4747

48-
// Requries B identified.
49-
impl () as B;
50-
51-
interface A {}
52-
53-
// Requries B complete.
5448
impl () as B {}
5549

5650
// --- fail_one_impls_interface_in_constraint.carbon

toolchain/check/testdata/interface/incomplete.carbon

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ interface B {
4444
require impls A;
4545
}
4646

47+
// --- fail_incomplete_extend_constraint.carbon
48+
library "[[@TEST_NAME]]";
49+
50+
constraint A;
51+
52+
interface B {
53+
// CHECK:STDERR: fail_incomplete_extend_constraint.carbon:[[@LINE+7]]:24: error: facet type `A` cannot be identified in `require` declaration [RequireImplsUnidentifiedFacetType]
54+
// CHECK:STDERR: extend require impls A;
55+
// CHECK:STDERR: ^
56+
// CHECK:STDERR: fail_incomplete_extend_constraint.carbon:[[@LINE-6]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]
57+
// CHECK:STDERR: constraint A;
58+
// CHECK:STDERR: ^~~~~~~~~~~~~
59+
// CHECK:STDERR:
60+
extend require impls A;
61+
}
62+
4763
// --- incomplete_interface.carbon
4864
library "[[@TEST_NAME]]";
4965

@@ -61,18 +77,16 @@ library "[[@TEST_NAME]]";
6177
interface A;
6278

6379
interface B {
80+
// CHECK:STDERR: fail_incomplete_extend_interface.carbon:[[@LINE+7]]:24: error: `extend require` of incomplete facet type `A` [RequireImplsIncompleteFacetType]
81+
// CHECK:STDERR: extend require impls A;
82+
// CHECK:STDERR: ^
83+
// CHECK:STDERR: fail_incomplete_extend_interface.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
84+
// CHECK:STDERR: interface A;
85+
// CHECK:STDERR: ^~~~~~~~~~~~
86+
// CHECK:STDERR:
6487
extend require impls A;
6588
}
6689

67-
// CHECK:STDERR: fail_incomplete_extend_interface.carbon:[[@LINE+7]]:1: error: definition of impl as incomplete facet type `B` [ImplAsIncompleteFacetTypeDefinition]
68-
// CHECK:STDERR: impl () as B {}
69-
// CHECK:STDERR: ^~~~~~~~~~~~~~
70-
// CHECK:STDERR: fail_incomplete_extend_interface.carbon:[[@LINE-9]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]
71-
// CHECK:STDERR: interface A;
72-
// CHECK:STDERR: ^~~~~~~~~~~~
73-
// CHECK:STDERR:
74-
impl () as B {}
75-
7690
// --- fail_incomplete_interface_in_where.carbon
7791
library "[[@TEST_NAME]]";
7892

@@ -161,6 +175,36 @@ interface B {
161175
// CHECK:STDOUT:
162176
// CHECK:STDOUT: constraint @A;
163177
// CHECK:STDOUT:
178+
// CHECK:STDOUT: --- fail_incomplete_extend_constraint.carbon
179+
// CHECK:STDOUT:
180+
// CHECK:STDOUT: constants {
181+
// CHECK:STDOUT: %A.type: type = facet_type <@A> [concrete]
182+
// CHECK:STDOUT: %B.type: type = facet_type <@B> [concrete]
183+
// CHECK:STDOUT: %Self: %B.type = symbolic_binding Self, 0 [symbolic]
184+
// CHECK:STDOUT: }
185+
// CHECK:STDOUT:
186+
// CHECK:STDOUT: file {
187+
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
188+
// CHECK:STDOUT: .A = %A.decl
189+
// CHECK:STDOUT: .B = %B.decl
190+
// CHECK:STDOUT: }
191+
// CHECK:STDOUT: %A.decl: type = constraint_decl @A [concrete = constants.%A.type] {} {}
192+
// CHECK:STDOUT: %B.decl: type = interface_decl @B [concrete = constants.%B.type] {} {}
193+
// CHECK:STDOUT: }
194+
// CHECK:STDOUT:
195+
// CHECK:STDOUT: interface @B {
196+
// CHECK:STDOUT: %Self: %B.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
197+
// CHECK:STDOUT:
198+
// CHECK:STDOUT: !members:
199+
// CHECK:STDOUT: .Self = %Self
200+
// CHECK:STDOUT: .A = <poisoned>
201+
// CHECK:STDOUT: witness = ()
202+
// CHECK:STDOUT:
203+
// CHECK:STDOUT: !requires:
204+
// CHECK:STDOUT: }
205+
// CHECK:STDOUT:
206+
// CHECK:STDOUT: constraint @A;
207+
// CHECK:STDOUT:
164208
// CHECK:STDOUT: --- incomplete_interface.carbon
165209
// CHECK:STDOUT:
166210
// CHECK:STDOUT: constants {
@@ -232,9 +276,6 @@ interface B {
232276
// CHECK:STDOUT: %A.type: type = facet_type <@A> [concrete]
233277
// CHECK:STDOUT: %B.type: type = facet_type <@B> [concrete]
234278
// CHECK:STDOUT: %Self: %B.type = symbolic_binding Self, 0 [symbolic]
235-
// CHECK:STDOUT: %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic]
236-
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
237-
// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
238279
// CHECK:STDOUT: }
239280
// CHECK:STDOUT:
240281
// CHECK:STDOUT: file {
@@ -244,48 +285,19 @@ interface B {
244285
// CHECK:STDOUT: }
245286
// CHECK:STDOUT: %A.decl: type = interface_decl @A [concrete = constants.%A.type] {} {}
246287
// CHECK:STDOUT: %B.decl: type = interface_decl @B [concrete = constants.%B.type] {} {}
247-
// CHECK:STDOUT: impl_decl @empty_tuple.type.as.B.impl [concrete] {} {
248-
// CHECK:STDOUT: %.loc16_7.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]
249-
// CHECK:STDOUT: %.loc16_7.2: type = converted %.loc16_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]
250-
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B.type]
251-
// CHECK:STDOUT: }
252288
// CHECK:STDOUT: }
253289
// CHECK:STDOUT:
254290
// CHECK:STDOUT: interface @A;
255291
// CHECK:STDOUT:
256292
// CHECK:STDOUT: interface @B {
257293
// CHECK:STDOUT: %Self: %B.type = symbolic_binding Self, 0 [symbolic = constants.%Self]
258-
// CHECK:STDOUT: %B.require0.decl = require_decl @B.require0 [concrete] {
259-
// CHECK:STDOUT: require %Self.as_type impls <@A>
260-
// CHECK:STDOUT: } {
261-
// CHECK:STDOUT: %Self.as_type: type = facet_access_type @B.%Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
262-
// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]
263-
// CHECK:STDOUT: }
264294
// CHECK:STDOUT:
265295
// CHECK:STDOUT: !members:
266296
// CHECK:STDOUT: .Self = %Self
267297
// CHECK:STDOUT: .A = <poisoned>
268298
// CHECK:STDOUT: witness = ()
269299
// CHECK:STDOUT:
270300
// CHECK:STDOUT: !requires:
271-
// CHECK:STDOUT: @B.require0 {
272-
// CHECK:STDOUT: require @B.require0.%Self.as_type impls <@A>
273-
// CHECK:STDOUT: }
274-
// CHECK:STDOUT: }
275-
// CHECK:STDOUT:
276-
// CHECK:STDOUT: generic require @B.require0(@B.%Self: %B.type) {
277-
// CHECK:STDOUT: %Self: %B.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]
278-
// CHECK:STDOUT: %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]
279-
// CHECK:STDOUT: }
280-
// CHECK:STDOUT:
281-
// CHECK:STDOUT: impl @empty_tuple.type.as.B.impl: %.loc16_7.2 as %B.ref {
282-
// CHECK:STDOUT: !members:
283-
// CHECK:STDOUT: witness = <error>
284-
// CHECK:STDOUT: }
285-
// CHECK:STDOUT:
286-
// CHECK:STDOUT: specific @B.require0(constants.%Self) {
287-
// CHECK:STDOUT: %Self => constants.%Self
288-
// CHECK:STDOUT: %Self.binding.as_type => constants.%Self.binding.as_type
289301
// CHECK:STDOUT: }
290302
// CHECK:STDOUT:
291303
// CHECK:STDOUT: --- fail_incomplete_interface_in_where.carbon

0 commit comments

Comments
 (0)