Skip to content

Commit e4cba88

Browse files
committed
[RequirementMachine] Diagnose concrete same-type mismatches, such as
`where String == Int`.
1 parent 3c2b588 commit e4cba88

File tree

3 files changed

+52
-9
lines changed

3 files changed

+52
-9
lines changed

include/swift/AST/Requirement.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,19 @@ struct StructuralRequirement {
132132
struct RequirementError {
133133
enum class Kind {
134134
InvalidConformance,
135+
ConcreteTypeMismatch,
135136
} kind;
136137

137138
union {
138139
struct {
139140
Type subjectType;
140141
Type constraint;
141142
} invalidConformance;
143+
144+
struct {
145+
Type type1;
146+
Type type2;
147+
} concreteTypeMismatch;
142148
};
143149

144150
SourceLoc loc;
@@ -156,6 +162,15 @@ struct RequirementError {
156162
error.invalidConformance.constraint = constraint;
157163
return error;
158164
}
165+
166+
static RequirementError forConcreteTypeMismatch(Type type1,
167+
Type type2,
168+
SourceLoc loc) {
169+
RequirementError error(Kind::ConcreteTypeMismatch, loc);
170+
error.concreteTypeMismatch.type1 = type1;
171+
error.concreteTypeMismatch.type2 = type2;
172+
return error;
173+
}
159174
};
160175

161176
} // end namespace swift

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,19 @@ using namespace rewriting;
5454
/// Desugar a same-type requirement that possibly has concrete types on either
5555
/// side into a series of same-type and concrete-type requirements where the
5656
/// left hand side is always a type parameter.
57-
static void desugarSameTypeRequirement(Type lhs, Type rhs,
57+
static void desugarSameTypeRequirement(Type lhs, Type rhs, SourceLoc loc,
5858
SmallVectorImpl<Requirement> &result,
5959
SmallVectorImpl<RequirementError> &errors) {
6060
class Matcher : public TypeMatcher<Matcher> {
61+
SourceLoc loc;
6162
SmallVectorImpl<Requirement> &result;
6263
SmallVectorImpl<RequirementError> &errors;
6364

6465
public:
65-
explicit Matcher(SmallVectorImpl<Requirement> &result,
66+
explicit Matcher(SourceLoc loc,
67+
SmallVectorImpl<Requirement> &result,
6668
SmallVectorImpl<RequirementError> &errors)
67-
: result(result), errors(errors) {}
69+
: loc(loc), result(result), errors(errors) {}
6870

6971
bool mismatch(TypeBase *firstType, TypeBase *secondType,
7072
Type sugaredFirstType) {
@@ -86,10 +88,13 @@ static void desugarSameTypeRequirement(Type lhs, Type rhs,
8688
return true;
8789
}
8890

89-
// FIXME: Record concrete type conflict, diagnose upstream
91+
errors.push_back(
92+
RequirementError::forConcreteTypeMismatch(firstType,
93+
secondType,
94+
loc));
9095
return true;
9196
}
92-
} matcher(result, errors);
97+
} matcher(loc, result, errors);
9398

9499
if (lhs->hasError() || rhs->hasError())
95100
return;
@@ -178,7 +183,7 @@ static void desugarConformanceRequirement(Type subjectType, Type constraintType,
178183

179184
auto memberType = lookupMemberType(subjectType, protoDecl, assocType);
180185
desugarSameTypeRequirement(memberType, paramType->getArgumentType(),
181-
result, errors);
186+
SourceLoc(), result, errors);
182187
return;
183188
}
184189

@@ -226,7 +231,7 @@ swift::rewriting::desugarRequirement(Requirement req,
226231

227232
case RequirementKind::SameType:
228233
desugarSameTypeRequirement(firstType, req.getSecondType(),
229-
result, errors);
234+
SourceLoc(), result, errors);
230235
break;
231236
}
232237
}
@@ -443,7 +448,8 @@ void swift::rewriting::realizeRequirement(
443448
}
444449

445450
SmallVector<Requirement, 2> reqs;
446-
desugarSameTypeRequirement(req.getFirstType(), secondType, reqs, errors);
451+
desugarSameTypeRequirement(req.getFirstType(), secondType, loc,
452+
reqs, errors);
447453

448454
for (auto req : reqs)
449455
result.push_back({req, loc, /*wasInferred=*/false});
@@ -488,6 +494,8 @@ void swift::rewriting::diagnoseRequirementErrors(
488494

489495
for (auto error : errors) {
490496
SourceLoc loc = error.loc;
497+
if (!loc.isValid())
498+
continue;
491499

492500
switch (error.kind) {
493501
case RequirementError::Kind::InvalidConformance: {
@@ -525,6 +533,18 @@ void swift::rewriting::diagnoseRequirementErrors(
525533

526534
break;
527535
}
536+
537+
case RequirementError::Kind::ConcreteTypeMismatch: {
538+
auto type1 = error.concreteTypeMismatch.type1;
539+
auto type2 = error.concreteTypeMismatch.type2;
540+
541+
if (!type1->hasError() && !type2->hasError()) {
542+
ctx.Diags.diagnose(loc, diag::requires_same_concrete_type,
543+
type1, type2);
544+
}
545+
546+
break;
547+
}
528548
}
529549
}
530550
}
@@ -672,7 +692,7 @@ TypeAliasRequirementsRequest::evaluate(Evaluator &evaluator,
672692
auto recordInheritedTypeRequirement = [&](TypeDecl *first, TypeDecl *second) {
673693
desugarSameTypeRequirement(getStructuralType(first),
674694
getStructuralType(second),
675-
result, errors);
695+
SourceLoc(), result, errors);
676696
};
677697

678698
// Local function to find the insertion point for the protocol's "where"

test/Generics/requirement_machine_diagnostics.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,11 @@ func testInvalidConformance() {
1313
func method() where T: Int {}
1414
}
1515
}
16+
17+
// Check directly-concrete same-type constraints
18+
typealias NotAnInt = Double
19+
20+
protocol X {}
21+
22+
// expected-error@+1{{generic signature requires types 'Double' and 'Int' to be the same}}
23+
extension X where NotAnInt == Int {}

0 commit comments

Comments
 (0)