mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[ConstraintSystem] Special case keypath dynamic member lookup in disjunction filtering
Since filtering currently runs as part of the `applicable function` constraint processing, "keypath dynamic member lookup" choice can't be attempted in-place because that would also try to operate on that constraint, so instead let's keep the disjunction, but disable all unviable choices. Resolves: rdar://problem/49533404
This commit is contained in:
@@ -1348,12 +1348,26 @@ ConstraintSystem::filterDisjunction(
|
|||||||
|
|
||||||
// This can only happen when subscript syntax is used to lookup
|
// This can only happen when subscript syntax is used to lookup
|
||||||
// something which doesn't exist in type marked with
|
// something which doesn't exist in type marked with
|
||||||
// `@dynamicMemberLookup`. Early simplification of the key path
|
// `@dynamicMemberLookup`.
|
||||||
// dynamic member lookup choice is impossible because it requires
|
// Since filtering currently runs as part of the `applicable function`
|
||||||
// constraints associated with subscript index expression to be present.
|
// constraint processing, "keypath dynamic member lookup" choice can't
|
||||||
if (!solverState && choice->getOverloadChoice().getKind() ==
|
// be attempted in-place because that would also try to operate on that
|
||||||
OverloadChoiceKind::KeyPathDynamicMemberLookup)
|
// constraint, so instead let's keep the disjunction, but disable all
|
||||||
return SolutionKind::Unsolved;
|
// unviable choices.
|
||||||
|
if (choice->getOverloadChoice().getKind() ==
|
||||||
|
OverloadChoiceKind::KeyPathDynamicMemberLookup) {
|
||||||
|
// Early simplification of the "keypath dynamic member lookup" choice
|
||||||
|
// is impossible because it requires constraints associated with
|
||||||
|
// subscript index expression to be present.
|
||||||
|
if (!solverState)
|
||||||
|
return SolutionKind::Unsolved;
|
||||||
|
|
||||||
|
for (auto *currentChoice : disjunction->getNestedConstraints()) {
|
||||||
|
if (currentChoice != choice)
|
||||||
|
solverState->disableContraint(currentChoice);
|
||||||
|
}
|
||||||
|
return SolutionKind::Solved;
|
||||||
|
}
|
||||||
|
|
||||||
// Retire the disjunction. It's been solved.
|
// Retire the disjunction. It's been solved.
|
||||||
retireConstraint(disjunction);
|
retireConstraint(disjunction);
|
||||||
|
|||||||
@@ -633,3 +633,24 @@ func keypath_to_subscript_to_property(_ lens: inout Lens<Array<Rectangle>>) {
|
|||||||
_ = lens[0].topLeft.y = Lens(1)
|
_ = lens[0].topLeft.y = Lens(1)
|
||||||
// expected-error@-1 {{cannot assign to property: 'y' is a 'let' constant}}
|
// expected-error@-1 {{cannot assign to property: 'y' is a 'let' constant}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@dynamicMemberLookup
|
||||||
|
struct SingleChoiceLens<T> {
|
||||||
|
var obj: T
|
||||||
|
|
||||||
|
init(_ obj: T) {
|
||||||
|
self.obj = obj
|
||||||
|
}
|
||||||
|
|
||||||
|
subscript<U>(dynamicMember member: WritableKeyPath<T, U>) -> U {
|
||||||
|
get { return obj[keyPath: member] }
|
||||||
|
set { obj[keyPath: member] = newValue }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that disjunction filtering optimization doesn't
|
||||||
|
// impede keypath dynamic member lookup by eagerly trying to
|
||||||
|
// simplify disjunctions with a single viable choice.
|
||||||
|
func test_lens_with_a_single_choice(a: inout SingleChoiceLens<[Int]>) {
|
||||||
|
a[0] = 1 // Ok
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user