Skip to content

Commit e539428

Browse files
committed
Update SK_LastScoreKind to SK_KeyPathSubscript.
When this score kind was added, the marker for the last score kind was not updated. As a result, increasing the score for SK_KeyPathSubscript was not actually having an effect. Add tests that include a type with subscripts that also take the key paths as their argument with an identical argument label ("keyPath"). These tests show that we're actually falling back on the keypath application in many cases despite the score kind specific to keypath application. I'll open a couple new JIRAs to investigate this behavior. The update to SK_LastScoreKind results in fixing a crash in these tests that happens as a result of an assumption in CSRanking.cpp that if we're comparing two solutions we end up with decls for overloads to compare, which isn't the case here due to the keypath application.
1 parent 9e76bc3 commit e539428

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

lib/Sema/ConstraintSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ enum ScoreKind {
417417
/// A key path application subscript.
418418
SK_KeyPathSubscript,
419419

420-
SK_LastScoreKind = SK_EmptyExistentialConversion,
420+
SK_LastScoreKind = SK_KeyPathSubscript,
421421
};
422422

423423
/// The number of score kinds.

test/expr/unary/keypath/keypath.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,63 @@ func testKeyPathSubscript(readonly: Z, writable: inout Z,
230230
writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign to immutable}}
231231
}
232232

233+
struct ZwithSubscript {
234+
subscript(keyPath: KeyPath<ZwithSubscript, Int>) -> Int { return 0 }
235+
subscript(keyPath: WritableKeyPath<ZwithSubscript, Int>) -> Int { return 0 }
236+
subscript(keyPath: ReferenceWritableKeyPath<ZwithSubscript, Int>) -> Int { return 0 }
237+
subscript(keyPath: PartialKeyPath<ZwithSubscript>) -> Any { return 0 }
238+
}
239+
240+
func testKeyPathSubscript(readonly: ZwithSubscript, writable: inout ZwithSubscript,
241+
kp: KeyPath<ZwithSubscript, Int>,
242+
wkp: WritableKeyPath<ZwithSubscript, Int>,
243+
rkp: ReferenceWritableKeyPath<ZwithSubscript, Int>) {
244+
var sink: Int
245+
sink = readonly[keyPath: kp]
246+
sink = writable[keyPath: kp]
247+
sink = readonly[keyPath: wkp]
248+
sink = writable[keyPath: wkp]
249+
sink = readonly[keyPath: rkp]
250+
sink = writable[keyPath: rkp]
251+
252+
// FIXME: keypath application rather than subscripting if subscript parameter defined without a separate internal name
253+
readonly[keyPath: kp] = sink // expected-error{{cannot assign to immutable expression of type 'Int'}}
254+
// FIXME: keypath application rather than subscripting if subscript parameter defined without a separate internal name
255+
writable[keyPath: kp] = sink // expected-error{{cannot assign to immutable expression of type 'Int'}}
256+
// FIXME: keypath application rather than subscripting if subscript parameter defined without a separate internal name
257+
readonly[keyPath: wkp] = sink // expected-error{{cannot assign to immutable expression of type 'Int'}}
258+
// FIXME: silently falls back to keypath application, which seems inconsistent
259+
writable[keyPath: wkp] = sink
260+
// FIXME: silently falls back to keypath application, which seems inconsistent
261+
readonly[keyPath: rkp] = sink
262+
// FIXME: silently falls back to keypath application, which seems inconsistent
263+
writable[keyPath: rkp] = sink
264+
265+
let pkp: PartialKeyPath = rkp
266+
267+
var anySink1 = readonly[keyPath: pkp]
268+
expect(&anySink1, toHaveType: Exactly<Any>.self)
269+
var anySink2 = writable[keyPath: pkp]
270+
expect(&anySink2, toHaveType: Exactly<Any>.self)
271+
272+
// FIXME: keypath application rather than subscripting if subscript parameter defined without a separate internal name
273+
readonly[keyPath: pkp] = anySink1 // expected-error{{cannot assign to immutable expression of type 'Any'}}
274+
// FIXME: keypath application rather than subscripting if subscript parameter defined without a separate internal name
275+
writable[keyPath: pkp] = anySink2 // expected-error{{cannot assign to immutable expression of type 'Any'}}
276+
277+
let akp: AnyKeyPath = pkp
278+
279+
var anyqSink1 = readonly[keyPath: akp]
280+
expect(&anyqSink1, toHaveType: Exactly<Any?>.self)
281+
var anyqSink2 = writable[keyPath: akp]
282+
expect(&anyqSink2, toHaveType: Exactly<Any?>.self)
283+
284+
// FIXME: silently falls back to keypath application, which seems inconsistent
285+
readonly[keyPath: akp] = anyqSink1 // expected-error{{cannot assign to immutable}}
286+
// FIXME: silently falls back to keypath application, which seems inconsistent
287+
writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign to immutable}}
288+
}
289+
233290
func testKeyPathSubscriptMetatype(readonly: Z.Type, writable: inout Z.Type,
234291
kp: KeyPath<Z.Type, Int>,
235292
wkp: WritableKeyPath<Z.Type, Int>,

0 commit comments

Comments
 (0)