Skip to content

Commit faba29a

Browse files
[Diagnostics] Diagnose key path reference to initializer methods.
1 parent 4981da4 commit faba29a

File tree

4 files changed

+19
-3
lines changed

4 files changed

+19
-3
lines changed

lib/Sema/CSDiagnostics.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,24 +1519,26 @@ class InvalidMemberWithMutatingGetterInKeyPath final
15191519
bool diagnoseAsError() override;
15201520
};
15211521

1522-
/// Diagnose an attempt to reference a method as a key path component
1522+
/// Diagnose an attempt to reference a method or initializer as a key path component
15231523
/// e.g.
15241524
///
15251525
/// ```swift
15261526
/// struct S {
1527+
/// init() { }
15271528
/// func foo() -> Int { return 42 }
15281529
/// static func bar() -> Int { return 0 }
15291530
/// }
15301531
///
15311532
/// _ = \S.foo
15321533
/// _ = \S.Type.bar
1534+
/// _ = \S.init
15331535
/// ```
15341536
class InvalidMethodRefInKeyPath final : public InvalidMemberRefInKeyPath {
15351537
public:
15361538
InvalidMethodRefInKeyPath(const Solution &solution, ValueDecl *method,
15371539
ConstraintLocator *locator)
15381540
: InvalidMemberRefInKeyPath(solution, method, locator) {
1539-
assert(isa<FuncDecl>(method));
1541+
assert(isa<FuncDecl>(method) || isa<ConstructorDecl>(method));
15401542
}
15411543

15421544
bool diagnoseAsError() override;

lib/Sema/CSFix.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,8 @@ bool AllowInvalidRefInKeyPath::diagnose(const Solution &solution,
747747
return failure.diagnose(asNote);
748748
}
749749

750-
case RefKind::Method: {
750+
case RefKind::Method:
751+
case RefKind::Initializer: {
751752
InvalidMethodRefInKeyPath failure(solution, Member, getLocator());
752753
return failure.diagnose(asNote);
753754
}
@@ -764,6 +765,11 @@ AllowInvalidRefInKeyPath::forRef(ConstraintSystem &cs, ValueDecl *member,
764765
return AllowInvalidRefInKeyPath::create(cs, RefKind::Method, member,
765766
locator);
766767

768+
// Referencing initializers in key path is not currently allowed.
769+
if (isa<ConstructorDecl>(member))
770+
return AllowInvalidRefInKeyPath::create(cs, RefKind::Initializer,
771+
member, locator);
772+
767773
// Referencing static members in key path is not currently allowed.
768774
if (member->isStatic())
769775
return AllowInvalidRefInKeyPath::create(cs, RefKind::StaticMember, member,

lib/Sema/CSFix.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,9 @@ class AllowInvalidRefInKeyPath final : public ConstraintFix {
12781278
// Allow a reference to a method (instance or static) as
12791279
// a key path component.
12801280
Method,
1281+
// Allow a reference to a initializer instance as a key path
1282+
// component.
1283+
Initializer,
12811284
} Kind;
12821285

12831286
ValueDecl *Member;
@@ -1297,6 +1300,8 @@ class AllowInvalidRefInKeyPath final : public ConstraintFix {
12971300
"path component";
12981301
case RefKind::Method:
12991302
return "allow reference to a method as a key path component";
1303+
case RefKind::Initializer:
1304+
return "allow reference to an init method as a key path component";
13001305
}
13011306
llvm_unreachable("covered switch");
13021307
}

lib/Sema/CSSimplify.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6305,6 +6305,9 @@ static ConstraintFix *validateInitializerRef(ConstraintSystem &cs,
63056305
// which means MetatypeType has to be added after finding a type variable.
63066306
if (locatorEndsWith(baseLocator, ConstraintLocator::MemberRefBase))
63076307
baseType = MetatypeType::get(baseType);
6308+
} else if (auto *keyPathExpr = dyn_cast<KeyPathExpr>(anchor)) {
6309+
// Key path can't refer to initializers e.g. `\Type.init`
6310+
return AllowInvalidRefInKeyPath::forRef(cs, init, locator);
63086311
}
63096312

63106313
if (!baseType)

0 commit comments

Comments
 (0)