Skip to content

Commit c680466

Browse files
Merge pull request swiftlang#37521 from LucianoPAlmeida/SR-14644-keypath
[Sema][Diagnostics][SR-14644] Improving diagnostics for key path with invalid components
2 parents cb69f2e + 9f42c69 commit c680466

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

include/swift/AST/Expr.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5842,7 +5842,10 @@ class KeyPathExpr : public Expr {
58425842
/// Indicates if the key path expression is composed by a single invalid
58435843
/// component. e.g. missing component `\Root`
58445844
bool hasSingleInvalidComponent() const {
5845-
return Components.size() == 1 && !Components.front().isValid();
5845+
if (ParsedRoot && ParsedRoot->getKind() == ExprKind::Type) {
5846+
return Components.size() == 1 && !Components.front().isValid();
5847+
}
5848+
return false;
58465849
}
58475850

58485851
/// Retrieve the string literal expression, which will be \c NULL prior to

lib/Sema/CSBindings.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,15 @@ TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
18511851
if (cs.hasFixFor(kpLocator, FixKind::AllowKeyPathWithoutComponents))
18521852
return None;
18531853

1854+
// If key path has any invalid component, let's just skip fix because the
1855+
// invalid component would be already diagnosed.
1856+
auto keyPath = castToExpr<KeyPathExpr>(srcLocator->getAnchor());
1857+
if (llvm::any_of(keyPath->getComponents(),
1858+
[](KeyPathExpr::Component component) {
1859+
return !component.isValid();
1860+
}))
1861+
return None;
1862+
18541863
ConstraintFix *fix = SpecifyKeyPathRootType::create(cs, dstLocator);
18551864
return std::make_pair(fix, defaultImpact);
18561865
}

test/expr/unary/keypath/keypath.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,16 @@ func testSyntaxErrors() {
10541054
_ = \A.a!;
10551055
}
10561056

1057+
// SR-14644
1058+
func sr14644() {
1059+
_ = \Int.byteSwapped.signum() // expected-error {{invalid component of Swift key path}}
1060+
_ = \Int.byteSwapped.init() // expected-error {{invalid component of Swift key path}}
1061+
_ = \Int // expected-error {{key path must have at least one component}}
1062+
_ = \Int? // expected-error {{key path must have at least one component}}
1063+
_ = \Int. // expected-error {{invalid component of Swift key path}}
1064+
// expected-error@-1 {{expected member name following '.'}}
1065+
}
1066+
10571067
// SR-13364 - keypath missing optional crashes compiler: "Inactive constraints left over?"
10581068
func sr13364() {
10591069
let _: KeyPath<String?, Int?> = \.utf8.count // expected-error {{no exact matches in reference to property 'count'}}

0 commit comments

Comments
 (0)