Merge pull request #12303 from jckarter/keypath-subscript-coerce-index-4.0
[4.0] Sema: Coerce the type of the index expression in a key path component to match the subscript decl's index type.
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index e84e714..f370cc9 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -4172,9 +4172,14 @@
auto dc = subscript->getInnermostDeclContext();
SmallVector<Substitution, 4> subs;
+ SubstitutionMap subMap;
+ auto indexType = subscript->getIndicesInterfaceType();
+
if (auto sig = dc->getGenericSignatureOfContext()) {
// Compute substitutions to refer to the member.
solution.computeSubstitutions(sig, locator, subs);
+ subMap = sig->getSubstitutionMap(subs);
+ indexType = indexType.subst(subMap);
}
auto resolvedTy = foundDecl->openedType->castTo<AnyFunctionType>()
@@ -4183,9 +4188,13 @@
auto ref = ConcreteDeclRef(cs.getASTContext(), subscript, subs);
+ // Coerce the indices to the type the subscript expects.
+ auto indexExpr = coerceToType(origComponent.getIndexExpr(),
+ indexType,
+ locator);
+
component = KeyPathExpr::Component
- ::forSubscriptWithPrebuiltIndexExpr(ref,
- origComponent.getIndexExpr(),
+ ::forSubscriptWithPrebuiltIndexExpr(ref, indexExpr,
origComponent.getSubscriptLabels(),
resolvedTy,
origComponent.getLoc(),
diff --git a/test/SILGen/keypaths.swift b/test/SILGen/keypaths.swift
index 5f425ad..7d28bd1 100644
--- a/test/SILGen/keypaths.swift
+++ b/test/SILGen/keypaths.swift
@@ -267,6 +267,13 @@
_ = \IUOProperty.iuo!.x
}
+class Bass: Hashable {
+ static func ==(_: Bass, _: Bass) -> Bool { return false }
+ var hashValue: Int { return 0 }
+}
+
+class Treble: Bass { }
+
struct Subscripts<T> {
subscript() -> T {
get { fatalError() }
@@ -292,6 +299,10 @@
get { fatalError() }
set { fatalError() }
}
+ subscript(bass: Bass) -> Bass {
+ get { return bass }
+ set { }
+ }
}
// CHECK-LABEL: sil hidden @{{.*}}10subscripts
@@ -321,4 +332,7 @@
_ = \Subscripts<String>.[subGeneric: y]
_ = \Subscripts<T>.[s, s].count
+
+ _ = \Subscripts<T>.[Bass()]
+ _ = \Subscripts<T>.[Treble()]
}
diff --git a/test/expr/unary/keypath/keypath.swift b/test/expr/unary/keypath/keypath.swift
index f45b9b4..d95c2a6 100644
--- a/test/expr/unary/keypath/keypath.swift
+++ b/test/expr/unary/keypath/keypath.swift
@@ -409,6 +409,23 @@
_ = \X.Type.b // expected-error{{cannot refer to static member}}
}
+class Bass: Hashable {
+ static func ==(_: Bass, _: Bass) -> Bool { return false }
+ var hashValue: Int { return 0 }
+}
+
+class Treble: Bass { }
+
+struct BassSubscript {
+ subscript(_: Bass) -> Int { fatalError() }
+ subscript(_: @autoclosure () -> String) -> Int { fatalError() }
+}
+
+func testImplicitConversionInSubscriptIndex() {
+ _ = \BassSubscript.[Treble()]
+ _ = \BassSubscript.["hello"] // expected-error{{must be Hashable}}
+}
+
func testSyntaxErrors() { // expected-note{{}}
_ = \. ; // expected-error{{expected member name following '.'}}
_ = \.a ;