Skip to content

Commit d22b98b

Browse files
committed
Sema: function casts ignore marker protocols
Dynamically they have no influence on whether the cast will succeed or not, as there is no way to tell if a type conforms to such a protocol at runtime.
1 parent bf1cec2 commit d22b98b

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1964,7 +1964,9 @@ TypeChecker::typeCheckCheckedCast(Type fromType, Type toType,
19641964
auto toConstrainedArchetype = false;
19651965
if (toArchetypeType) {
19661966
auto archetype = toType->castTo<ArchetypeType>();
1967-
toConstrainedArchetype = !archetype->getConformsTo().empty();
1967+
// If the archetype conforms to any non-marker protocols, it's constrained.
1968+
toConstrainedArchetype = llvm::any_of(archetype->getConformsTo(),
1969+
[](ProtocolDecl *proto){ return !proto->isMarkerProtocol(); });
19681970
}
19691971

19701972
if (fromFunctionType &&

test/Interpreter/casts.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,13 @@ Casts.test("testCastProtocolWithAnyObjectToProtocolCompoTypeSuperclass") {
142142
let shouldBeNil = (F() as QAny) as? KQAny
143143
expectNil(shouldBeNil)
144144
}
145+
146+
func f1() -> Any { return 1 }
147+
func attemptFunctionCast<U>(_ u: U.Type) -> U? {
148+
return f1 as? U
149+
}
150+
Casts.test("testFunctionCastToArchetype") {
151+
expectNil(attemptFunctionCast(Int.self))
152+
expectNil(attemptFunctionCast(K.self))
153+
expectTrue(attemptFunctionCast(Any.self) != nil)
154+
}

test/expr/cast/as_coerce.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,29 @@ do {
133133
_ = f2 as? Any // expected-warning {{conditional cast from '() -> ()' to 'Any' always succeeds}}
134134

135135

136-
func test1<T: P_48579>(_: T.Type) {
136+
func test1<T: P_48579, V: P_48579 & Sendable>(_: T.Type, _: V.Type) {
137137
_ = f1 is T // expected-warning {{cast from '() -> Any' to unrelated type 'T' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{11-11=()}}
138-
_ = f1 as! T // expected-warning {{cast from '() -> Any' to unrelated type 'T' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{11-11=()}}
138+
_ = f1 as! V // expected-warning {{cast from '() -> Any' to unrelated type 'V' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{11-11=()}}
139139
_ = f1 as? T // expected-warning {{cast from '() -> Any' to unrelated type 'T' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{11-11=()}}
140140
_ = f2 is T // expected-warning {{cast from '() -> ()' to unrelated type 'T' always fails}}
141-
_ = f2 as! T // expected-warning {{cast from '() -> ()' to unrelated type 'T' always fails}}
141+
_ = f2 as! V // expected-warning {{cast from '() -> ()' to unrelated type 'V' always fails}}
142142
_ = f2 as? T // expected-warning {{cast from '() -> ()' to unrelated type 'T' always fails}}
143143
}
144144

145-
func test2<U>(_: U.Type) {
145+
func test2<U, S: Sendable>(_: U.Type, _: S.Type) {
146+
_ = f1 is U // Okay
146147
_ = f1 as! U // Okay
147148
_ = f1 as? U // Okay
149+
_ = f1 is U // Okay
148150
_ = f2 as! U // Okay
149151
_ = f2 as? U // Okay
152+
153+
_ = f1 is S // Okay
154+
_ = f1 as! S // Okay
155+
_ = f1 as? S // Okay
156+
_ = f1 is S // Okay
157+
_ = f2 as! S // Okay
158+
_ = f2 as? S // Okay
150159
}
151160
}
152161

0 commit comments

Comments
 (0)