-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Sema] Warn about 'Any' to 'any Sendable' override #73543
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1202,6 +1202,8 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl, | |
// If this is an exact type match, we're successful! | ||
Type declTy = getDeclComparisonType(); | ||
Type owningTy = dc->getDeclaredInterfaceType(); | ||
bool mismatchedOnSendability = | ||
attempt == OverrideCheckingAttempt::MismatchedSendability; | ||
auto isClassContext = classDecl != nullptr; | ||
if (declIUOAttr == matchDeclIUOAttr && declTy->isEqual(baseTy)) { | ||
// Nothing to do. | ||
|
@@ -1263,17 +1265,42 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl, | |
CanType parentPropertyCanTy = | ||
parentPropertyTy->getReducedType( | ||
decl->getInnermostDeclContext()->getGenericSignatureOfContext()); | ||
if (!propertyTy->matches(parentPropertyCanTy, | ||
TypeMatchFlags::AllowOverride)) { | ||
diags.diagnose(property, diag::override_property_type_mismatch, | ||
property->getName(), propertyTy, parentPropertyTy); | ||
noteFixableMismatchedTypes(decl, baseDecl); | ||
diags.diagnose(baseDecl, diag::property_override_here); | ||
return true; | ||
|
||
auto options = TypeMatchFlags::AllowOverride; | ||
if (!propertyTy->matches(parentPropertyCanTy, options)) { | ||
// The perfect match failed | ||
bool failed = true; | ||
if (baseDecl->preconcurrency() && | ||
(attempt == OverrideCheckingAttempt::PerfectMatch || | ||
attempt == OverrideCheckingAttempt::MismatchedSendability)) { | ||
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. One major drawback of this approach is that it strips concurrency annotations from both sides which means that override with concurrency annotations would match against parent without annotation(s) in the same position which is not the case for witness matching today. For example: protocol P {
@preconcurrency func test(_: Any)
}
struct S : P {
func test(_: any Sendable) {}
} Produces the following error:
Taking a step back here, at line https://github.com/apple/swift/pull/73543/files#diff-149ea7785899898da39642522a1b7d555757f96e8a3d53f045f9ae80e04c361bR1208 the types are checked for exact match which means that it should be possible to set a new flag based on whether base is marked as preconcurrency or not before attempting
|
||
propertyTy = propertyTy->stripConcurrency(/*recursive=*/true, | ||
/*dropGlobalActor=*/true); | ||
parentPropertyCanTy = | ||
Type(parentPropertyCanTy)->stripConcurrency(/*recursive=*/true, | ||
/*dropGlobalActor=*/true)->getCanonicalType(); | ||
|
||
parentPropertyTy = | ||
parentPropertyTy->stripConcurrency(/*recursive=*/true, | ||
/*dropGlobalActor=*/true); | ||
|
||
|
||
if (propertyTy->matches(parentPropertyCanTy, options)) { | ||
mismatchedOnSendability = true; | ||
failed = false; | ||
} | ||
} | ||
|
||
if (failed) { | ||
diags.diagnose(property, diag::override_property_type_mismatch, | ||
property->getName(), propertyTy, parentPropertyTy); | ||
noteFixableMismatchedTypes(decl, baseDecl); | ||
diags.diagnose(baseDecl, diag::property_override_here); | ||
return true; | ||
} | ||
} | ||
|
||
// Differing only in Optional vs. ImplicitlyUnwrappedOptional is fine. | ||
bool IsSilentDifference = false; | ||
bool IsSilentDifference = mismatchedOnSendability; | ||
if (auto propertyTyNoOptional = propertyTy->getOptionalObjectType()) | ||
if (auto parentPropertyTyNoOptional = | ||
parentPropertyTy->getOptionalObjectType()) | ||
|
@@ -1293,7 +1320,7 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl, | |
if (emittedMatchError) | ||
return true; | ||
|
||
if (attempt == OverrideCheckingAttempt::MismatchedSendability) { | ||
if (mismatchedOnSendability) { | ||
SendableCheckContext fromContext(decl->getDeclContext(), | ||
SendableCheck::Explicit); | ||
auto baseDeclClass = baseDecl->getDeclContext()->getSelfClassDecl(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -249,3 +249,21 @@ extension MainActorPreconcurrency: NotIsolated { | |
} | ||
} | ||
} | ||
|
||
|
||
open class Parent { | ||
init(userInfo: [String : Any]) { | ||
self.userInfo = userInfo | ||
} | ||
|
||
@preconcurrency open var userInfo : [String : any Sendable] // expected-note {{overridden declaration is here}} | ||
} | ||
|
||
class Child : Parent { | ||
override var userInfo: [String : Any] { // expected-warning {{declaration 'userInfo' has a type with different sendability from any potential overrides; this is an error in the Swift 6 language mode}} | ||
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. I left a comment about adding more tests with different combinations of attributes and |
||
get { | ||
[:] | ||
} | ||
set {} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is not technically tied for this PR since matching happens on canonical types, you can land this separately.