mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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
This commit is contained in:
@@ -1570,9 +1570,8 @@ Pattern *TypeChecker::coercePatternToType(
|
|||||||
type, parentTy, CheckedCastContextKind::EnumElementPattern, dc);
|
type, parentTy, CheckedCastContextKind::EnumElementPattern, dc);
|
||||||
// If the cast failed, we can't resolve the pattern.
|
// If the cast failed, we can't resolve the pattern.
|
||||||
if (foundCastKind < CheckedCastKind::First_Resolved) {
|
if (foundCastKind < CheckedCastKind::First_Resolved) {
|
||||||
diags
|
diags.diagnose(EEP->getLoc(), diag::cannot_match_value_with_pattern,
|
||||||
.diagnose(EEP->getLoc(), diag::downcast_to_unrelated, type,
|
type, parentTy)
|
||||||
parentTy)
|
|
||||||
.highlight(EEP->getSourceRange());
|
.highlight(EEP->getSourceRange());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1582,9 +1581,9 @@ Pattern *TypeChecker::coercePatternToType(
|
|||||||
castKind = foundCastKind;
|
castKind = foundCastKind;
|
||||||
enumTy = parentTy;
|
enumTy = parentTy;
|
||||||
} else {
|
} else {
|
||||||
diags.diagnose(EEP->getLoc(),
|
diags.diagnose(EEP->getLoc(), diag::cannot_match_value_with_pattern,
|
||||||
diag::enum_element_pattern_not_member_of_enum,
|
type, parentTy)
|
||||||
EEP->getName(), type);
|
.highlight(EEP->getSourceRange());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ case iPadHair<E>.HairForceOne:
|
|||||||
()
|
()
|
||||||
case iPadHair.HairForceOne: // expected-error{{generic enum type 'iPadHair' is ambiguous without explicit generic parameters when matching value of type 'any HairType'}}
|
case iPadHair.HairForceOne: // expected-error{{generic enum type 'iPadHair' is ambiguous without explicit generic parameters when matching value of type 'any HairType'}}
|
||||||
()
|
()
|
||||||
case Watch.Edition: // expected-warning {{cast from 'any HairType' to unrelated type 'Watch' always fails}}
|
case Watch.Edition: // expected-error {{pattern of type 'Watch' cannot match 'any HairType'}}
|
||||||
()
|
()
|
||||||
case .HairForceOne: // expected-error{{type 'any HairType' has no member 'HairForceOne'}}
|
case .HairForceOne: // expected-error{{type 'any HairType' has no member 'HairForceOne'}}
|
||||||
()
|
()
|
||||||
|
|||||||
18
test/Constraints/rdar107420031.swift
Normal file
18
test/Constraints/rdar107420031.swift
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// RUN: %target-typecheck-verify-swift
|
||||||
|
|
||||||
|
enum E {
|
||||||
|
case e
|
||||||
|
}
|
||||||
|
|
||||||
|
func ~= (lhs: any Error, rhs: E) -> Bool { true }
|
||||||
|
|
||||||
|
// rdar://107420031 – Make sure we don't crash.
|
||||||
|
// TODO: This ought to compile.
|
||||||
|
func foo(_ error: any Error) {
|
||||||
|
switch error {
|
||||||
|
case E.e: // expected-error {{pattern of type 'E' cannot match 'any Error'}}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -122,7 +122,7 @@ if case let .Naught(value1, value2, value3) = n {} // expected-error{{pattern wi
|
|||||||
|
|
||||||
|
|
||||||
switch n {
|
switch n {
|
||||||
case Foo.A: // expected-error{{enum case 'A' is not a member of type 'Voluntary<Int>'}}
|
case Foo.A: // expected-error{{pattern of type 'Foo' cannot match 'Voluntary<Int>'}}
|
||||||
()
|
()
|
||||||
case Voluntary<Int>.Naught,
|
case Voluntary<Int>.Naught,
|
||||||
Voluntary<Int>.Naught(), // expected-error {{pattern with associated values does not match enum case 'Naught'}}
|
Voluntary<Int>.Naught(), // expected-error {{pattern with associated values does not match enum case 'Naught'}}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ if case inout .Naught(value1, value2, value3) = n {} // expected-error{{pattern
|
|||||||
|
|
||||||
|
|
||||||
switch n {
|
switch n {
|
||||||
case Foo.A: // expected-error{{enum case 'A' is not a member of type 'Voluntary<Int>'}}
|
case Foo.A: // expected-error{{pattern of type 'Foo' cannot match 'Voluntary<Int>'}}
|
||||||
()
|
()
|
||||||
case Voluntary<Int>.Naught,
|
case Voluntary<Int>.Naught,
|
||||||
Voluntary<Int>.Naught(), // expected-error {{pattern with associated values does not match enum case 'Naught'}}
|
Voluntary<Int>.Naught(), // expected-error {{pattern with associated values does not match enum case 'Naught'}}
|
||||||
|
|||||||
Reference in New Issue
Block a user