Skip to content

Commit e354ecf

Browse files
committed
Sema: Rip out some code for diagnosing invalid patterns
The problem here is that we would just emit 'invalid pattern' instead of digging deeper, which meant that the fix-it for qualified enum element access wasn't getting inserted for more complex patterns, such as 'case X(let x)'. Unfortunately, in the matching_patterns.swift test, we emit too many diagnostics that are not really useful to figuring out the problem, and the old 'invalid pattern' made more sense. I'll work on some CSDiag tweaks to address this -- I think it makes more sense to dig there than just emit a general 'invalid pattern' diagnostic anyway. Fixes <rdar://problem/27684266>.
1 parent 22aa032 commit e354ecf

File tree

6 files changed

+21
-32
lines changed

6 files changed

+21
-32
lines changed

lib/Sema/CSApply.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3388,7 +3388,13 @@ namespace {
33883388
}
33893389

33903390
Expr *visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) {
3391-
llvm_unreachable("should have been eliminated during name binding");
3391+
// If we end up here, we should have diagnosed somewhere else
3392+
// already.
3393+
if (!SuppressDiagnostics) {
3394+
cs.TC.diagnose(expr->getLoc(), diag::pattern_in_expr,
3395+
expr->getSubPattern()->getKind());
3396+
}
3397+
return expr;
33923398
}
33933399

33943400
Expr *visitBindOptionalExpr(BindOptionalExpr *expr) {

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2627,9 +2627,7 @@ namespace {
26272627
Type visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) {
26282628
// If there are UnresolvedPatterns floating around after name binding,
26292629
// they are pattern productions in invalid positions.
2630-
CS.TC.diagnose(expr->getLoc(), diag::pattern_in_expr,
2631-
expr->getSubPattern()->getKind());
2632-
return Type();
2630+
return ErrorType::get(CS.getASTContext());
26332631
}
26342632

26352633
/// Get the type T?

lib/Sema/TypeCheckPattern.cpp

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -247,35 +247,18 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
247247
public:
248248
TypeChecker &TC;
249249
DeclContext *DC;
250-
bool &DiagnosedError;
251250

252-
ResolvePattern(TypeChecker &TC, DeclContext *DC, bool &DiagnosedError)
253-
: TC(TC), DC(DC), DiagnosedError(DiagnosedError) {}
251+
ResolvePattern(TypeChecker &TC, DeclContext *DC) : TC(TC), DC(DC) {}
254252

255253
// Convert a subexpression to a pattern if possible, or wrap it in an
256254
// ExprPattern.
257255
Pattern *getSubExprPattern(Expr *E) {
258256
if (Pattern *p = visit(E))
259257
return p;
260258

261-
foundUnknownExpr(E);
262-
263259
return new (TC.Context) ExprPattern(E, nullptr, nullptr);
264260
}
265261

266-
void foundUnknownExpr(Expr *E) {
267-
// If we find unresolved pattern, diagnose this as an illegal pattern. Sema
268-
// does later checks for UnresolvedPatternExpr's in arbitrary places, but
269-
// rejecting these early is good because we can provide better up-front
270-
// diagnostics and can recover better from it.
271-
if (!UnresolvedPatternFinder::hasAny(E) || DiagnosedError) return;
272-
273-
TC.diagnose(E->getStartLoc(), diag::invalid_pattern)
274-
.highlight(E->getSourceRange());
275-
DiagnosedError = true;
276-
}
277-
278-
279262
// Handle productions that are always leaf patterns or are already resolved.
280263
#define ALWAYS_RESOLVED_PATTERN(Id) \
281264
Pattern *visit##Id##Pattern(Id##Pattern *P) { return P; }
@@ -295,7 +278,7 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
295278

296279
// If the var pattern has no variables bound underneath it, then emit a
297280
// warning that the var/let is pointless.
298-
if (!DiagnosedError && !P->isImplicit()) {
281+
if (!P->isImplicit()) {
299282
bool HasVariable = false;
300283
P->forEachVariable([&](VarDecl *VD) { HasVariable = true; });
301284

@@ -328,7 +311,6 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
328311
Pattern *exprAsPattern = visit(P->getSubExpr());
329312
// If we failed, keep the ExprPattern as is.
330313
if (!exprAsPattern) {
331-
foundUnknownExpr(P->getSubExpr());
332314
P->setResolved(true);
333315
return P;
334316
}
@@ -606,10 +588,7 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
606588
/// disambiguate semantics-dependent pattern forms.
607589
Pattern *TypeChecker::resolvePattern(Pattern *P, DeclContext *DC,
608590
bool isStmtCondition) {
609-
bool DiagnosedError = false;
610-
P = ResolvePattern(*this, DC, DiagnosedError).visit(P);
611-
612-
if (DiagnosedError) return nullptr;
591+
P = ResolvePattern(*this, DC).visit(P);
613592

614593
// If the entire pattern is "(pattern_expr (type_expr SomeType))", then this
615594
// is an invalid pattern. If it were actually a value comparison (with ~=)

test/Parse/enum.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ enum SE0036 {
479479
switch self {
480480
case A: break // expected-error {{enum element 'A' cannot be referenced as an instance member}} {{10-10=.}}
481481
case B(_): break // expected-error {{enum element 'B' cannot be referenced as an instance member}} {{10-10=.}}
482-
case C(let x): _ = x; break // expected-error {{invalid pattern}}
482+
case C(let x): _ = x; break // expected-error {{enum element 'C' cannot be referenced as an instance member}} {{10-10=.}}
483483
}
484484
}
485485

test/Parse/matching_patterns.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,14 @@ case (1, 2, 3):
261261
()
262262

263263
// patterns in expression-only positions are errors.
264-
case +++(_, var d, 3): // expected-error{{invalid pattern}}
264+
case +++(_, var d, 3):
265+
// expected-error@-1{{'+++' is not a prefix unary operator}}
265266
()
266-
case (_, var e, 3) +++ (1, 2, 3): // expected-error{{invalid pattern}}
267+
case (_, var e, 3) +++ (1, 2, 3):
268+
// expected-error@-1{{binary operator '+++' cannot be applied to operands of type '(_, <<error type>>, Int)' and '(Int, Int, Int)'}}
269+
// expected-note@-2{{expected an argument list of type '((Int, Int, Int), (Int, Int, Int))'}}
270+
// expected-error@-3{{'var' binding pattern cannot appear in an expression}}
271+
// expected-error@-4{{'var' binding pattern cannot appear in an expression}}
267272
()
268273
}
269274

test/Sema/enum_equatable_hashable.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ private enum Bar<T> {
9696

9797
mutating func value() -> T {
9898
switch self {
99-
case E(let x): // expected-error{{invalid pattern}}
99+
// FIXME: Should diagnose here that '.' needs to be inserted, but E has an ErrorType at this point
100+
case E(let x):
100101
return x.value
101102
}
102103
}

0 commit comments

Comments
 (0)