mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CSSimplify] Allow type inference through marker protocol existential casts
```swift
class A<T> {
}
class B<U> : A<U> {
}
func test(v: any B<Int> & Sendable) {
_ = v as A // infers `Int` for `A.T`
}
```
This commit is contained in:
@@ -9215,6 +9215,23 @@ ConstraintSystem::simplifyCheckedCastConstraint(
|
||||
}
|
||||
}
|
||||
|
||||
// Peel off marker protocol requirements if this is an existential->concrete
|
||||
// cast. Handles cases like `WritableKeyPath<...> & Sendable as KeyPath`
|
||||
// that require inference which is only attempted if both sides are classes.
|
||||
if (fromType->isExistentialType() && !toType->isExistentialType()) {
|
||||
if (auto *existential = fromType->getAs<ExistentialType>()) {
|
||||
if (auto *PCT = existential->getConstraintType()
|
||||
->getAs<ProtocolCompositionType>()) {
|
||||
auto newConstraintTy = PCT->withoutMarkerProtocols();
|
||||
if (!newConstraintTy->isEqual(PCT)) {
|
||||
fromType = newConstraintTy->getClassOrBoundGenericClass()
|
||||
? newConstraintTy
|
||||
: ExistentialType::get(newConstraintTy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We've decomposed the types further, so adopt the subflags.
|
||||
flags = subflags;
|
||||
|
||||
|
||||
@@ -230,3 +230,11 @@ do {
|
||||
func forward<T>(_ v: T) -> T { v }
|
||||
let _: KeyPath<String, Int> = forward(kp()) // Ok
|
||||
}
|
||||
|
||||
do {
|
||||
final class C<T> {
|
||||
let immutable: String = ""
|
||||
}
|
||||
|
||||
_ = \C<Int>.immutable as? ReferenceWritableKeyPath // Ok
|
||||
}
|
||||
|
||||
@@ -201,3 +201,16 @@ do {
|
||||
(fn as () -> Void)() // expected-error {{no exact matches in reference to local function 'fn'}}
|
||||
(fn_1 as () -> Void)() // expected-error {{cannot convert value of type '(Bool) -> ()' to type '() -> Void' in coercion}}
|
||||
}
|
||||
|
||||
// Test generic parameter inference through casts
|
||||
do {
|
||||
class A<T> {
|
||||
}
|
||||
|
||||
class B<U> : A<U> {
|
||||
}
|
||||
|
||||
func test(v: any B<Int> & Sendable) {
|
||||
_ = v as A // infers `Int` for `A.T`
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user