Skip to content

Commit b4cf34b

Browse files
committed
[Sema] Warn about 'Any' to 'any Sendable' override
Until Swift 6, warn about overriding Any property in parent class to any Sendable
1 parent 180bc51 commit b4cf34b

File tree

3 files changed

+73
-28
lines changed

3 files changed

+73
-28
lines changed

lib/AST/Type.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,25 @@ unsigned int TypeBase::getOptionalityDepth() {
898898
}
899899

900900
Type TypeBase::stripConcurrency(bool recurse, bool dropGlobalActor) {
901+
if (auto *arrayTy = dyn_cast<ArraySliceType>(this)) {
902+
auto newBaseTy =
903+
arrayTy->getBaseType()->stripConcurrency(recurse, dropGlobalActor);
904+
return newBaseTy->isEqual(arrayTy->getBaseType())
905+
? Type(this)
906+
: ArraySliceType::get(newBaseTy);
907+
}
908+
909+
if (auto *dictTy = dyn_cast<DictionaryType>(this)) {
910+
auto keyTy = dictTy->getKeyType();
911+
auto strippedKeyTy = keyTy->stripConcurrency(recurse, dropGlobalActor);
912+
auto valueTy = dictTy->getValueType();
913+
auto strippedValueTy = valueTy->stripConcurrency(recurse, dropGlobalActor);
914+
915+
return keyTy->isEqual(strippedKeyTy) && valueTy->isEqual(strippedValueTy)
916+
? Type(this)
917+
: DictionaryType::get(strippedKeyTy, strippedValueTy);
918+
}
919+
901920
// Look through optionals.
902921
if (Type optionalObject = getOptionalObjectType()) {
903922
Type newOptionalObject =
@@ -1083,25 +1102,6 @@ Type TypeBase::stripConcurrency(bool recurse, bool dropGlobalActor) {
10831102
return anyChanged ? TupleType::get(elts, getASTContext()) : Type(this);
10841103
}
10851104

1086-
if (auto *arrayTy = dyn_cast<ArraySliceType>(this)) {
1087-
auto newBaseTy =
1088-
arrayTy->getBaseType()->stripConcurrency(recurse, dropGlobalActor);
1089-
return newBaseTy->isEqual(arrayTy->getBaseType())
1090-
? Type(this)
1091-
: ArraySliceType::get(newBaseTy);
1092-
}
1093-
1094-
if (auto *dictTy = dyn_cast<DictionaryType>(this)) {
1095-
auto keyTy = dictTy->getKeyType();
1096-
auto strippedKeyTy = keyTy->stripConcurrency(recurse, dropGlobalActor);
1097-
auto valueTy = dictTy->getValueType();
1098-
auto strippedValueTy = valueTy->stripConcurrency(recurse, dropGlobalActor);
1099-
1100-
return keyTy->isEqual(strippedKeyTy) && valueTy->isEqual(strippedValueTy)
1101-
? Type(this)
1102-
: DictionaryType::get(strippedKeyTy, strippedValueTy);
1103-
}
1104-
11051105
return Type(this);
11061106
}
11071107

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,8 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
12021202
// If this is an exact type match, we're successful!
12031203
Type declTy = getDeclComparisonType();
12041204
Type owningTy = dc->getDeclaredInterfaceType();
1205+
bool mismatchedOnSendability =
1206+
attempt == OverrideCheckingAttempt::MismatchedSendability;
12051207
auto isClassContext = classDecl != nullptr;
12061208
if (declIUOAttr == matchDeclIUOAttr && declTy->isEqual(baseTy)) {
12071209
// Nothing to do.
@@ -1263,17 +1265,42 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
12631265
CanType parentPropertyCanTy =
12641266
parentPropertyTy->getReducedType(
12651267
decl->getInnermostDeclContext()->getGenericSignatureOfContext());
1266-
if (!propertyTy->matches(parentPropertyCanTy,
1267-
TypeMatchFlags::AllowOverride)) {
1268-
diags.diagnose(property, diag::override_property_type_mismatch,
1269-
property->getName(), propertyTy, parentPropertyTy);
1270-
noteFixableMismatchedTypes(decl, baseDecl);
1271-
diags.diagnose(baseDecl, diag::property_override_here);
1272-
return true;
1268+
1269+
auto options = TypeMatchFlags::AllowOverride;
1270+
if (!propertyTy->matches(parentPropertyCanTy, options)) {
1271+
// The perfect match failed
1272+
bool failed = true;
1273+
if (baseDecl->preconcurrency() &&
1274+
(attempt == OverrideCheckingAttempt::PerfectMatch ||
1275+
attempt == OverrideCheckingAttempt::MismatchedSendability)) {
1276+
propertyTy = propertyTy->stripConcurrency(/*recursive=*/true,
1277+
/*dropGlobalActor=*/true);
1278+
parentPropertyCanTy =
1279+
Type(parentPropertyCanTy)->stripConcurrency(/*recursive=*/true,
1280+
/*dropGlobalActor=*/true)->getCanonicalType();
1281+
1282+
parentPropertyTy =
1283+
parentPropertyTy->stripConcurrency(/*recursive=*/true,
1284+
/*dropGlobalActor=*/true);
1285+
1286+
1287+
if (propertyTy->matches(parentPropertyCanTy, options)) {
1288+
mismatchedOnSendability = true;
1289+
failed = false;
1290+
}
1291+
}
1292+
1293+
if (failed) {
1294+
diags.diagnose(property, diag::override_property_type_mismatch,
1295+
property->getName(), propertyTy, parentPropertyTy);
1296+
noteFixableMismatchedTypes(decl, baseDecl);
1297+
diags.diagnose(baseDecl, diag::property_override_here);
1298+
return true;
1299+
}
12731300
}
12741301

12751302
// Differing only in Optional vs. ImplicitlyUnwrappedOptional is fine.
1276-
bool IsSilentDifference = false;
1303+
bool IsSilentDifference = mismatchedOnSendability;
12771304
if (auto propertyTyNoOptional = propertyTy->getOptionalObjectType())
12781305
if (auto parentPropertyTyNoOptional =
12791306
parentPropertyTy->getOptionalObjectType())
@@ -1293,7 +1320,7 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
12931320
if (emittedMatchError)
12941321
return true;
12951322

1296-
if (attempt == OverrideCheckingAttempt::MismatchedSendability) {
1323+
if (mismatchedOnSendability) {
12971324
SendableCheckContext fromContext(decl->getDeclContext(),
12981325
SendableCheck::Explicit);
12991326
auto baseDeclClass = baseDecl->getDeclContext()->getSelfClassDecl();

test/Concurrency/predates_concurrency.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,21 @@ extension MainActorPreconcurrency: NotIsolated {
249249
}
250250
}
251251
}
252+
253+
254+
open class Parent {
255+
init(userInfo: [String : Any]) {
256+
self.userInfo = userInfo
257+
}
258+
259+
@preconcurrency open var userInfo : [String : any Sendable] // expected-note {{overridden declaration is here}}
260+
}
261+
262+
class Child : Parent {
263+
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}}
264+
get {
265+
[:]
266+
}
267+
set {}
268+
}
269+
}

0 commit comments

Comments
 (0)