Skip to content

Commit 203734b

Browse files
committed
[RequirementMachine] Diagnose conformance, layout, and superclass constraints
on non-type-parameters in the requirement machine.
1 parent e4cba88 commit 203734b

File tree

3 files changed

+57
-14
lines changed

3 files changed

+57
-14
lines changed

include/swift/AST/Requirement.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct RequirementError {
133133
enum class Kind {
134134
InvalidConformance,
135135
ConcreteTypeMismatch,
136+
NonTypeParameter,
136137
} kind;
137138

138139
union {
@@ -145,6 +146,8 @@ struct RequirementError {
145146
Type type1;
146147
Type type2;
147148
} concreteTypeMismatch;
149+
150+
Type nonTypeParameter;
148151
};
149152

150153
SourceLoc loc;
@@ -171,6 +174,13 @@ struct RequirementError {
171174
error.concreteTypeMismatch.type2 = type2;
172175
return error;
173176
}
177+
178+
static RequirementError forNonTypeParameter(Type subject,
179+
SourceLoc loc) {
180+
RequirementError error(Kind::NonTypeParameter, loc);
181+
error.nonTypeParameter = subject;
182+
return error;
183+
}
174184
};
175185

176186
} // end namespace swift

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,12 @@ static void desugarSameTypeRequirement(Type lhs, Type rhs, SourceLoc loc,
105105

106106
static void desugarSuperclassRequirement(Type subjectType,
107107
Type constraintType,
108+
SourceLoc loc,
108109
SmallVectorImpl<Requirement> &result,
109110
SmallVectorImpl<RequirementError> &errors) {
110111
if (!subjectType->isTypeParameter()) {
111-
// FIXME: Perform unification, diagnose redundancy or conflict upstream
112+
errors.push_back(
113+
RequirementError::forNonTypeParameter(subjectType, loc));
112114
return;
113115
}
114116

@@ -117,10 +119,12 @@ static void desugarSuperclassRequirement(Type subjectType,
117119

118120
static void desugarLayoutRequirement(Type subjectType,
119121
LayoutConstraint layout,
122+
SourceLoc loc,
120123
SmallVectorImpl<Requirement> &result,
121124
SmallVectorImpl<RequirementError> &errors) {
122125
if (!subjectType->isTypeParameter()) {
123-
// FIXME: Diagnose redundancy or conflict upstream
126+
errors.push_back(
127+
RequirementError::forNonTypeParameter(subjectType, loc));
124128
return;
125129
}
126130

@@ -143,6 +147,7 @@ static Type lookupMemberType(Type subjectType, ProtocolDecl *protoDecl,
143147
/// compositions on the right hand side into conformance and superclass
144148
/// requirements.
145149
static void desugarConformanceRequirement(Type subjectType, Type constraintType,
150+
SourceLoc loc,
146151
SmallVectorImpl<Requirement> &result,
147152
SmallVectorImpl<RequirementError> &errors) {
148153
// Fast path.
@@ -153,7 +158,8 @@ static void desugarConformanceRequirement(Type subjectType, Type constraintType,
153158
auto *module = protoDecl->getParentModule();
154159
auto conformance = module->lookupConformance(subjectType, protoDecl);
155160
if (conformance.isInvalid()) {
156-
// FIXME: Diagnose a conflict.
161+
errors.push_back(
162+
RequirementError::forNonTypeParameter(subjectType, loc));
157163
return;
158164
}
159165

@@ -177,13 +183,13 @@ static void desugarConformanceRequirement(Type subjectType, Type constraintType,
177183
auto *protoDecl = paramType->getBaseType()->getDecl();
178184

179185
desugarConformanceRequirement(subjectType, paramType->getBaseType(),
180-
result, errors);
186+
loc, result, errors);
181187

182188
auto *assocType = protoDecl->getPrimaryAssociatedType();
183189

184190
auto memberType = lookupMemberType(subjectType, protoDecl, assocType);
185191
desugarSameTypeRequirement(memberType, paramType->getArgumentType(),
186-
SourceLoc(), result, errors);
192+
loc, result, errors);
187193
return;
188194
}
189195

@@ -192,14 +198,16 @@ static void desugarConformanceRequirement(Type subjectType, Type constraintType,
192198
desugarLayoutRequirement(subjectType,
193199
LayoutConstraint::getLayoutConstraint(
194200
LayoutConstraintKind::Class),
195-
result, errors);
201+
loc, result, errors);
196202
}
197203

198204
for (auto memberType : compositionType->getMembers()) {
199205
if (memberType->isExistentialType())
200-
desugarConformanceRequirement(subjectType, memberType, result, errors);
206+
desugarConformanceRequirement(subjectType, memberType,
207+
loc, result, errors);
201208
else
202-
desugarSuperclassRequirement(subjectType, memberType, result, errors);
209+
desugarSuperclassRequirement(subjectType, memberType,
210+
loc, result, errors);
203211
}
204212
}
205213

@@ -216,17 +224,17 @@ swift::rewriting::desugarRequirement(Requirement req,
216224
switch (req.getKind()) {
217225
case RequirementKind::Conformance:
218226
desugarConformanceRequirement(firstType, req.getSecondType(),
219-
result, errors);
227+
SourceLoc(), result, errors);
220228
break;
221229

222230
case RequirementKind::Superclass:
223231
desugarSuperclassRequirement(firstType, req.getSecondType(),
224-
result, errors);
232+
SourceLoc(), result, errors);
225233
break;
226234

227235
case RequirementKind::Layout:
228236
desugarLayoutRequirement(firstType, req.getLayoutConstraint(),
229-
result, errors);
237+
SourceLoc(), result, errors);
230238
break;
231239

232240
case RequirementKind::SameType:
@@ -252,10 +260,10 @@ static void realizeTypeRequirement(Type subjectType, Type constraintType,
252260

253261
if (constraintType->isConstraintType()) {
254262
// Handle conformance requirements.
255-
desugarConformanceRequirement(subjectType, constraintType, reqs, errors);
263+
desugarConformanceRequirement(subjectType, constraintType, loc, reqs, errors);
256264
} else if (constraintType->getClassOrBoundGenericClass()) {
257265
// Handle superclass requirements.
258-
desugarSuperclassRequirement(subjectType, constraintType, reqs, errors);
266+
desugarSuperclassRequirement(subjectType, constraintType, loc, reqs, errors);
259267
} else {
260268
errors.push_back(
261269
RequirementError::forInvalidConformance(subjectType,
@@ -427,7 +435,7 @@ void swift::rewriting::realizeRequirement(
427435

428436
SmallVector<Requirement, 2> reqs;
429437
desugarLayoutRequirement(firstType, req.getLayoutConstraint(),
430-
reqs, errors);
438+
loc, reqs, errors);
431439

432440
for (auto req : reqs)
433441
result.push_back({req, loc, /*wasInferred=*/false});
@@ -545,6 +553,12 @@ void swift::rewriting::diagnoseRequirementErrors(
545553

546554
break;
547555
}
556+
557+
case RequirementError::Kind::NonTypeParameter: {
558+
ctx.Diags.diagnose(loc, diag::requires_not_suitable_archetype,
559+
error.nonTypeParameter);
560+
break;
561+
}
548562
}
549563
}
550564
}

test/Generics/requirement_machine_diagnostics.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,22 @@ protocol X {}
2121

2222
// expected-error@+1{{generic signature requires types 'Double' and 'Int' to be the same}}
2323
extension X where NotAnInt == Int {}
24+
25+
protocol EqualComparable {
26+
func isEqual(_ other: Self) -> Bool
27+
}
28+
29+
func badTypeConformance1<T>(_: T) where Int : EqualComparable {} // expected-error{{type 'Int' in conformance requirement does not refer to a generic parameter or associated type}}
30+
31+
func badTypeConformance2<T>(_: T) where T.Blarg : EqualComparable { } // expected-error{{'Blarg' is not a member type of type 'T'}}
32+
33+
func badTypeConformance3<T>(_: T) where (T) -> () : EqualComparable { }
34+
// expected-error@-1{{type '(T) -> ()' in conformance requirement does not refer to a generic parameter or associated type}}
35+
36+
func badTypeConformance4<T>(_: T) where @escaping (inout T) throws -> () : EqualComparable { }
37+
// expected-error@-1{{type '(inout T) throws -> ()' in conformance requirement does not refer to a generic parameter or associated type}}
38+
// expected-error@-2 2 {{@escaping attribute may only be used in function parameter position}}
39+
40+
func badTypeConformance5<T>(_: T) where T & Sequence : EqualComparable { }
41+
// expected-error@-1 2 {{non-protocol, non-class type 'T' cannot be used within a protocol-constrained type}}
42+
// expected-error@-2{{type 'Sequence' in conformance requirement does not refer to a generic parameter or associated type}}

0 commit comments

Comments
 (0)