Skip to content

Commit e68e4ea

Browse files
committed
[CSFix] Add a new kind of invalid ref in key path - unsupported static members
Replaces feature flag check with module compiler version check which implements the behavior discussed in the SE-0438.
1 parent 07583f5 commit e68e4ea

File tree

3 files changed

+36
-21
lines changed

3 files changed

+36
-21
lines changed

include/swift/Sema/CSFix.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,9 +2026,11 @@ class TreatKeyPathSubscriptIndexAsHashable final : public ConstraintFix {
20262026

20272027
class AllowInvalidRefInKeyPath final : public ConstraintFix {
20282028
enum RefKind {
2029+
// Allow invalid references to static members i.e. on instance of a type.
2030+
StaticMember,
20292031
// Allow a reference to a static member as a key path component if it is
20302032
// declared in a module with built with Swift 6.0 compiler version or older.
2031-
StaticMember,
2033+
UnsupportedStaticMember,
20322034
// Allow a reference to a declaration with mutating getter as
20332035
// a key path component.
20342036
MutatingGetter,
@@ -2054,7 +2056,10 @@ class AllowInvalidRefInKeyPath final : public ConstraintFix {
20542056
std::string getName() const override {
20552057
switch (Kind) {
20562058
case RefKind::StaticMember:
2057-
return "allow reference to a static member as a key path component";
2059+
return "allow reference to a static member on invalid base in key path "
2060+
"context";
2061+
case RefKind::UnsupportedStaticMember:
2062+
return "allow unsupported static member reference";
20582063
case RefKind::MutatingGetter:
20592064
return "allow reference to a member with mutating getter as a key "
20602065
"path component";

lib/Sema/CSDiagnostics.cpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6337,22 +6337,15 @@ SourceLoc InvalidMemberRefInKeyPath::getLoc() const {
63376337
}
63386338

63396339
bool InvalidStaticMemberRefInKeyPath::diagnoseAsError() {
6340-
auto *KPE = getAsExpr<KeyPathExpr>(getRawAnchor());
6341-
auto rootTyRepr = KPE->getExplicitRootType();
6342-
auto isProtocol = getBaseType()->isExistentialType();
6343-
6344-
if (!getConstraintSystem().getASTContext().LangOpts.hasFeature(
6345-
Feature::KeyPathWithStaticMembers)) {
6346-
emitDiagnostic(diag::expr_keypath_static_member, getMember(),
6347-
isForKeyPathDynamicMemberLookup());
6348-
} else {
6349-
if (rootTyRepr && !isProtocol) {
6350-
emitDiagnostic(diag::could_not_use_type_member_on_instance, getBaseType(),
6351-
DeclNameRef(getMember()->getName()))
6352-
.fixItInsert(rootTyRepr->getEndLoc(), ".Type");
6353-
} else {
6340+
auto diagnostic =
63546341
emitDiagnostic(diag::could_not_use_type_member_on_instance, getBaseType(),
63556342
DeclNameRef(getMember()->getName()));
6343+
6344+
// Suggest adding `.Type` to an explicit root if possible.
6345+
if (auto *keyPath = getAsExpr<KeyPathExpr>(getRawAnchor())) {
6346+
if (auto *explicitRoot = keyPath->getExplicitRootType()) {
6347+
if (explicitRoot && !getBaseType()->isExistentialType())
6348+
diagnostic.fixItInsert(explicitRoot->getEndLoc(), ".Type");
63566349
}
63576350
}
63586351

lib/Sema/CSFix.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,12 @@ bool AllowInvalidRefInKeyPath::diagnose(const Solution &solution,
12311231
bool asNote) const {
12321232
switch (Kind) {
12331233
case RefKind::StaticMember: {
1234+
InvalidStaticMemberRefInKeyPath failure(solution, BaseType, Member,
1235+
getLocator());
1236+
return failure.diagnose(asNote);
1237+
}
1238+
1239+
case RefKind::UnsupportedStaticMember: {
12341240
return false;
12351241
}
12361242

@@ -1281,12 +1287,23 @@ AllowInvalidRefInKeyPath *
12811287
AllowInvalidRefInKeyPath::forRef(ConstraintSystem &cs, Type baseType,
12821288
ValueDecl *member,
12831289
ConstraintLocator *locator) {
1290+
if (member->isStatic() && !isa<FuncDecl>(member)) {
1291+
// References to static members are supported only for modules that
1292+
// are built with 6.1+ compilers, libraries produced by earlier
1293+
// compilers don't have required symbols.
1294+
if (auto *module = member->getDeclContext()->getParentModule()) {
1295+
if (module->isBuiltFromInterface() &&
1296+
module->getSwiftInterfaceCompilerVersion() <
1297+
llvm::VersionTuple(6, 1)) {
1298+
return AllowInvalidRefInKeyPath::create(
1299+
cs, baseType, RefKind::UnsupportedStaticMember, member, locator);
1300+
}
1301+
}
12841302

1285-
if (!cs.getASTContext().LangOpts.hasFeature(
1286-
Feature::KeyPathWithStaticMembers) &&
1287-
member->isStatic())
1288-
return AllowInvalidRefInKeyPath::create(cs, baseType, RefKind::StaticMember,
1289-
member, locator);
1303+
if (!baseType->getRValueType()->is<AnyMetatypeType>())
1304+
return AllowInvalidRefInKeyPath::create(
1305+
cs, baseType, RefKind::StaticMember, member, locator);
1306+
}
12901307

12911308
// Referencing (instance or static) methods in key path is
12921309
// not currently allowed.

0 commit comments

Comments
 (0)