Skip to content

Commit 101a5c1

Browse files
[TypeChecker] Adjusting existential and archetype logic to check inside couldDynamicConform
1 parent 969ede9 commit 101a5c1

File tree

2 files changed

+24
-19
lines changed

2 files changed

+24
-19
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3548,16 +3548,15 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
35483548
// }
35493549
// }
35503550
//
3551-
// Except when the toType is a generic archetype, because then it may
3552-
// have protocol conformances we cannot know statically.
3553-
if (fromExistential && (!toExistential && !toArchetype)) {
3554-
auto protocolDecl =
3555-
dyn_cast_or_null<ProtocolDecl>(fromType->getAnyNominal());
3556-
// Checking for possible dynamic conformances because we cannot fail
3557-
// in those cases.
3558-
if (protocolDecl &&
3559-
!couldDynamicallyConformToProtocol(toType, protocolDecl, dc)) {
3560-
return failed();
3551+
if (auto *protocolDecl =
3552+
dyn_cast_or_null<ProtocolDecl>(fromType->getAnyNominal())){
3553+
if (!toExistential) {
3554+
// Checking for possible dynamic conformances because we cannot fail
3555+
// in those cases.
3556+
if (protocolDecl &&
3557+
!couldDynamicallyConformToProtocol(toType, protocolDecl, dc)) {
3558+
return failed();
3559+
}
35613560
}
35623561
}
35633562

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4473,21 +4473,27 @@ TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, DeclContext *DC,
44734473
bool
44744474
TypeChecker::couldDynamicallyConformToProtocol(Type type, ProtocolDecl *Proto,
44754475
DeclContext *DC) {
4476-
// We may have types that can dynamically conform to a protocol, e.g. a non-final
4477-
// class which might have a subclass that conforms to the protocol, or standard
4478-
// library collection types such as Array, Set or Dictionary which have custom
4479-
// casting machinery implemented in situations like:
4480-
//
4481-
// func encodable(_ value: Encodable) {
4482-
// _ = value as! [String : Encodable]
4483-
// }
4484-
//
4476+
// A generic archetype may have protocol conformances we cannot know
4477+
// statically.
4478+
if (type->is<ArchetypeType>())
4479+
return true;
4480+
4481+
// A non-final class might have a subclass that conforms to the protocol.
44854482
if (auto *classDecl = type->getClassOrBoundGenericClass()) {
44864483
if (!classDecl->isFinal())
44874484
return true;
44884485
}
44894486

44904487
ModuleDecl *M = DC->getParentModule();
4488+
// For standard library collection types such as Array, Set or Dictionary
4489+
// which have custom casting machinery implemented in situations like:
4490+
//
4491+
// func encodable(_ value: Encodable) {
4492+
// _ = value as! [String : Encodable]
4493+
// }
4494+
// we are skipping checking conditional requirements using lookupConformance,
4495+
// as an intermediate collection cast can dynamically change if the conditions
4496+
// are met or not.
44914497
if (type->isKnownStdlibCollectionType())
44924498
return !M->lookupConformance(type, Proto).isInvalid();
44934499
return !conformsToProtocol(type, Proto, DC).isInvalid();

0 commit comments

Comments
 (0)