Skip to content

Commit da86703

Browse files
committed
[CS] Fix coercePatternToType enum cast handling
Previously if the cast was unresolved, we would emit a warning and bail with `nullptr`. This is wrong, because the caller expects a `nullptr` return to mean we emitted an error. Change the diagnostic to an error to fix this. This may appear source breaking, but in reality previously we were failing to add the cast at all in this case, which lead to a crash in SILGen. We really do want to reject these cases as errors, as this will give us a better opportunity to fall back to type-checking as ExprPatterns, and better matches the constraint solver type-checking. Also while we're here, change the diagnostic for the case where we don't have an existential context type from the confusing "enum doesn't have member" diagnostic to the pattern mismatch diagnostic. rdar://107420031
1 parent b43d351 commit da86703

File tree

5 files changed

+26
-9
lines changed

5 files changed

+26
-9
lines changed

lib/Sema/TypeCheckPattern.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,9 +1570,8 @@ Pattern *TypeChecker::coercePatternToType(
15701570
type, parentTy, CheckedCastContextKind::EnumElementPattern, dc);
15711571
// If the cast failed, we can't resolve the pattern.
15721572
if (foundCastKind < CheckedCastKind::First_Resolved) {
1573-
diags
1574-
.diagnose(EEP->getLoc(), diag::downcast_to_unrelated, type,
1575-
parentTy)
1573+
diags.diagnose(EEP->getLoc(), diag::cannot_match_value_with_pattern,
1574+
type, parentTy)
15761575
.highlight(EEP->getSourceRange());
15771576
return nullptr;
15781577
}
@@ -1582,9 +1581,9 @@ Pattern *TypeChecker::coercePatternToType(
15821581
castKind = foundCastKind;
15831582
enumTy = parentTy;
15841583
} else {
1585-
diags.diagnose(EEP->getLoc(),
1586-
diag::enum_element_pattern_not_member_of_enum,
1587-
EEP->getName(), type);
1584+
diags.diagnose(EEP->getLoc(), diag::cannot_match_value_with_pattern,
1585+
type, parentTy)
1586+
.highlight(EEP->getSourceRange());
15881587
return nullptr;
15891588
}
15901589
}

test/Constraints/patterns.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ case iPadHair<E>.HairForceOne:
120120
()
121121
case iPadHair.HairForceOne: // expected-error{{generic enum type 'iPadHair' is ambiguous without explicit generic parameters when matching value of type 'any HairType'}}
122122
()
123-
case Watch.Edition: // expected-warning {{cast from 'any HairType' to unrelated type 'Watch' always fails}}
123+
case Watch.Edition: // expected-error {{pattern of type 'Watch' cannot match 'any HairType'}}
124124
()
125125
case .HairForceOne: // expected-error{{type 'any HairType' has no member 'HairForceOne'}}
126126
()

test/Constraints/rdar107420031.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
enum E {
4+
case e
5+
}
6+
7+
func ~= (lhs: any Error, rhs: E) -> Bool { true }
8+
9+
// rdar://107420031 – Make sure we don't crash.
10+
// TODO: This ought to compile.
11+
func foo(_ error: any Error) {
12+
switch error {
13+
case E.e: // expected-error {{pattern of type 'E' cannot match 'any Error'}}
14+
break
15+
default:
16+
break
17+
}
18+
}

test/Parse/matching_patterns.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ if case let .Naught(value1, value2, value3) = n {} // expected-error{{pattern wi
122122

123123

124124
switch n {
125-
case Foo.A: // expected-error{{enum case 'A' is not a member of type 'Voluntary<Int>'}}
125+
case Foo.A: // expected-error{{pattern of type 'Foo' cannot match 'Voluntary<Int>'}}
126126
()
127127
case Voluntary<Int>.Naught,
128128
Voluntary<Int>.Naught(), // expected-error {{pattern with associated values does not match enum case 'Naught'}}

test/Parse/matching_patterns_reference_bindings.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ if case inout .Naught(value1, value2, value3) = n {} // expected-error{{pattern
140140

141141

142142
switch n {
143-
case Foo.A: // expected-error{{enum case 'A' is not a member of type 'Voluntary<Int>'}}
143+
case Foo.A: // expected-error{{pattern of type 'Foo' cannot match 'Voluntary<Int>'}}
144144
()
145145
case Voluntary<Int>.Naught,
146146
Voluntary<Int>.Naught(), // expected-error {{pattern with associated values does not match enum case 'Naught'}}

0 commit comments

Comments
 (0)