-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SR-13088] Fix false positive downcast unrelated of types that cannot be statically known #32592
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
LucianoPAlmeida
merged 16 commits into
swiftlang:master
from
LucianoPAlmeida:SR-13081-cast-unrelated
Jul 3, 2020
Merged
Changes from 4 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
addc6b8
[TypeCheckConstraints] Adjusting cases where checked casts that canno…
LucianoPAlmeida 6bcb9a9
[tests] Adding regression tests for SR-13088
LucianoPAlmeida 43f1401
[TypeCheckConstraints] Adjusting comment and adding an extra test cas…
LucianoPAlmeida a563883
[TypeCheckConstraints] Fixing typos in comments
LucianoPAlmeida 2a06563
[AST] Moving implementation of isCollection from ConstraintSystem to …
LucianoPAlmeida b09e34a
[TypeCheckConstraints] Adjusting logic to verify specific conformance…
LucianoPAlmeida 8ea2a69
[TypeCheckConstraints] Creating new CheckedCastContextKind::Collectio…
LucianoPAlmeida ec3acbf
[TypeCheckConstraints] Adjusting logic around generic substitution to…
LucianoPAlmeida 53e1278
[Sema] Adding isKnownStdlibCollectionType and replacing all usages co…
LucianoPAlmeida c2e060e
[TypeChecker] Reverting fixes around array element types
LucianoPAlmeida d01e808
[TypeChecker] Abstract logic of check for conditional requirements on…
LucianoPAlmeida b14dc2d
[TypeChecker] Ajdustinc can conformDynamically conform and adjust rev…
LucianoPAlmeida 969ede9
[TypeChecker] Ajusting comments and fixing typos
LucianoPAlmeida 101a5c1
[TypeChecker] Adjusting existential and archetype logic to check insi…
LucianoPAlmeida 026f697
[TypeChecker] Adjusting minor and adding existential check into could…
LucianoPAlmeida 31808e8
[TypeChecker] Adjusting comments
LucianoPAlmeida File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3249,6 +3249,11 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, | |
|
||
auto checkElementCast = [&](Type fromElt, Type toElt, | ||
CheckedCastKind castKind) -> CheckedCastKind { | ||
// Let's not emit diagnostic when the element type is erased because | ||
// we can't statically know if element is convertible. | ||
if (fromElt->isAny() || toElt->isAny()) | ||
return castKind; | ||
|
||
switch (typeCheckCheckedCast(fromElt, toElt, CheckedCastContextKind::None, | ||
dc, SourceLoc(), nullptr, SourceRange())) { | ||
case CheckedCastKind::Coercion: | ||
|
@@ -3357,7 +3362,14 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, | |
const auto &fromElt = fromTuple->getElement(i); | ||
const auto &toElt = toTuple->getElement(i); | ||
|
||
if (fromElt.getName() != toElt.getName()) | ||
// We should only perform name validation if both element have a label, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. - if both element
+ if both elements |
||
// because unlabeled tuple elements can be converted to labeled ones | ||
// e.g. | ||
// | ||
// let tup: (Any, Any) = (1, 1) | ||
// _ = tup as! (a: Int, Int) | ||
if ((!fromElt.getName().empty() && !toElt.getName().empty()) && | ||
fromElt.getName() != toElt.getName()) | ||
return failed(); | ||
|
||
auto result = checkElementCast(fromElt.getType(), toElt.getType(), | ||
|
@@ -3487,6 +3499,17 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, | |
bool toExistential = toType->isExistentialType(); | ||
bool fromExistential = fromType->isExistentialType(); | ||
|
||
auto genericTypeHasExistentialArgument = [](Type type) { | ||
if (auto toGeneric = type->getAs<BoundGenericType>()) { | ||
return llvm::any_of(toGeneric->getGenericArgs(), [](Type argumentType) { | ||
return argumentType->isExistentialType(); | ||
}); | ||
} | ||
return false; | ||
}; | ||
|
||
bool toHasGenericExistential = genericTypeHasExistentialArgument(toType); | ||
|
||
bool toRequiresClass; | ||
if (toType->isExistentialType()) | ||
toRequiresClass = toType->getExistentialLayout().requiresClass(); | ||
|
@@ -3544,7 +3567,16 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, | |
// Note: we relax the restriction if the type we're casting to is a | ||
// non-final class because it's possible that we might have a subclass | ||
// that conforms to the protocol. | ||
if (fromExistential && !toExistential) { | ||
// | ||
// Also, relax the restriction when toType is a bounded generic with | ||
// an existential argument because it may have conditional protocol | ||
// conformances. e.g. | ||
// | ||
// func encodable(_ value: Encodable) { | ||
// _ = value as! [String : Encodable] | ||
// } | ||
LucianoPAlmeida marked this conversation as resolved.
Show resolved
Hide resolved
hamishknight marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// | ||
if (fromExistential && (!toExistential && !toHasGenericExistential)) { | ||
if (auto NTD = toType->getAnyNominal()) { | ||
if (!toType->is<ClassType>() || NTD->isFinal()) { | ||
hamishknight marked this conversation as resolved.
Show resolved
Hide resolved
|
||
auto protocolDecl = | ||
|
@@ -3616,10 +3648,10 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, | |
return CheckedCastKind::ValueCast; | ||
} | ||
|
||
// If the destination type can be a supertype of the source type, we are | ||
// performing what looks like an upcast except it rebinds generic | ||
// parameters. | ||
if (fromType->isBindableTo(toType)) | ||
// If it is possible to substitute the generic arguments of source type | ||
// with the destination generic archetypes, we are performing what looks | ||
// like an upcast except it rebinds generic parameters. | ||
if (toType->isBindableTo(fromType)) | ||
hamishknight marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return CheckedCastKind::ValueCast; | ||
|
||
// Objective-C metaclasses are subclasses of NSObject in the ObjC runtime, | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.