Skip to content

Commit d08f6ff

Browse files
committed
Sema: Fix some keypath diagnostic crashers
We would crash in these cases: - If all lookup results were subscripts - If all results were unavailable
1 parent df9258b commit d08f6ff

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6949,13 +6949,18 @@ static bool diagnoseKeyPathComponents(ConstraintSystem &CS, KeyPathExpr *KPE,
69496949

69506950
// Drop non-property, non-type candidates.
69516951
if (!isa<VarDecl>(result.getValueDecl()) &&
6952-
!isa<TypeDecl>(result.getValueDecl()))
6952+
!isa<TypeDecl>(result.getValueDecl()) &&
6953+
!isa<SubscriptDecl>(result.getValueDecl()))
69536954
return false;
69546955

69556956
return true;
69566957
});
69576958
}
69586959

6960+
// If all results were unavailable, fail.
6961+
if (!lookup)
6962+
break;
6963+
69596964
// If we *still* have more than one result, fail.
69606965
if (lookup.size() > 1) {
69616966
// Don't diagnose ambiguities if the results are from typo correction.

test/expr/unary/keypath/keypath.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,33 @@ func testImplicitConversionInSubscriptIndex() {
495495
_ = \BassSubscript.["hello"] // expected-error{{must be Hashable}}
496496
}
497497

498+
// Crash in diagnostics
499+
struct AmbiguousSubscript {
500+
subscript(sub: Sub) -> Int { get { } set { } }
501+
// expected-note@-1 {{'subscript' declared here}}
502+
503+
subscript(y y: Sub) -> Int { get { } set { } }
504+
// expected-note@-1 {{'subscript(y:)' declared here}}
505+
}
506+
507+
func useAmbiguousSubscript(_ sub: Sub) {
508+
let _: PartialKeyPath<AmbiguousSubscript> = \.[sub]
509+
// expected-error@-1 {{ambiguous reference to member 'subscript'}}
510+
}
511+
512+
struct BothUnavailableSubscript {
513+
@available(*, unavailable)
514+
subscript(sub: Sub) -> Int { get { } set { } }
515+
516+
@available(*, unavailable)
517+
subscript(y y: Sub) -> Int { get { } set { } }
518+
}
519+
520+
func useBothUnavailableSubscript(_ sub: Sub) {
521+
let _: PartialKeyPath<BothUnavailableSubscript> = \.[sub]
522+
// expected-error@-1 {{type of expression is ambiguous without more context}}
523+
}
524+
498525
// SR-6106
499526
func sr6106() {
500527
class B {}

0 commit comments

Comments
 (0)