Skip to content

Commit 18ed193

Browse files
authored
Merge pull request #70662 from xedin/fix-crash-in-simplifyKeyPathConstraint
[ConstraintSystem] Teach inference to never select unresolved key path types
2 parents c0673f9 + e4f9965 commit 18ed193

File tree

6 files changed

+29
-17
lines changed

6 files changed

+29
-17
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,10 @@ class BindingSet {
576576

577577
/// Finalize binding computation for this type variable by
578578
/// inferring bindings from context e.g. transitive bindings.
579-
void finalize(
579+
///
580+
/// \returns true if finalization successful (which makes binding set viable),
581+
/// and false otherwise.
582+
bool finalize(
580583
llvm::SmallDenseMap<TypeVariableType *, BindingSet> &inferredBindings);
581584

582585
static BindingScore formBindingScore(const BindingSet &b);

lib/Sema/CSBindings.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ static Type getKeyPathType(ASTContext &ctx, KeyPathCapability capability,
600600
return keyPathTy;
601601
}
602602

603-
void BindingSet::finalize(
603+
bool BindingSet::finalize(
604604
llvm::SmallDenseMap<TypeVariableType *, BindingSet> &inferredBindings) {
605605
inferTransitiveBindings(inferredBindings);
606606

@@ -654,9 +654,10 @@ void BindingSet::finalize(
654654

655655
std::tie(isValid, capability) = CS.inferKeyPathLiteralCapability(TypeVar);
656656

657-
// Key path literal is not yet sufficiently resolved.
657+
// Key path literal is not yet sufficiently resolved, this binding
658+
// set is not viable.
658659
if (isValid && !capability)
659-
return;
660+
return false;
660661

661662
// If the key path is sufficiently resolved we can add inferred binding
662663
// to the set.
@@ -728,7 +729,7 @@ void BindingSet::finalize(
728729
Bindings = std::move(updatedBindings);
729730
Defaults.clear();
730731

731-
return;
732+
return true;
732733
}
733734

734735
if (CS.shouldAttemptFixes() &&
@@ -752,6 +753,8 @@ void BindingSet::finalize(
752753
});
753754
}
754755
}
756+
757+
return true;
755758
}
756759
}
757760

@@ -1030,7 +1033,8 @@ llvm::Optional<BindingSet> ConstraintSystem::determineBestBindings(
10301033
// produce a default type.
10311034
bool isViable = isViableForRanking(bindings);
10321035

1033-
bindings.finalize(cache);
1036+
if (!bindings.finalize(cache))
1037+
continue;
10341038

10351039
if (!bindings || !isViable)
10361040
continue;

lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12207,13 +12207,6 @@ ConstraintSystem::simplifyKeyPathConstraint(
1220712207
assert(contextualTy);
1220812208
}
1220912209

12210-
// If there are no other options the solver might end up picking
12211-
// `AnyKeyPath` or `PartialKeyPath` based on a contextual conversion.
12212-
// This is an error during normal type-checking but okay in
12213-
// diagnostic mode because root and value are allowed to be holes.
12214-
if (contextualTy->isAnyKeyPath() || contextualTy->isPartialKeyPath())
12215-
return shouldAttemptFixes();
12216-
1221712210
if (auto bgt = contextualTy->getAs<BoundGenericType>()) {
1221812211
// We can get root and value from a concrete key path type.
1221912212
assert(bgt->isKeyPath() || bgt->isWritableKeyPath() ||

lib/Sema/ConstraintSystem.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7648,6 +7648,13 @@ ConstraintSystem::inferKeyPathLiteralCapability(KeyPathExpr *keyPath) {
76487648
if (keyPath->hasSingleInvalidComponent())
76497649
return fail();
76507650

7651+
// If root is determined to be a hole it means that none of the components
7652+
// are resolvable and key path is not viable.
7653+
auto rootTy =
7654+
getFixedTypeRecursive(getKeyPathRootType(keyPath), /*wantRValue=*/false);
7655+
if (rootTy->isPlaceholder())
7656+
return fail();
7657+
76517658
auto mutability = KeyPathMutability::Writable;
76527659
for (unsigned i : indices(keyPath->getComponents())) {
76537660
auto &component = keyPath->getComponents()[i];

test/expr/unary/keypath/keypath.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -914,13 +914,13 @@ func testKeyPathHole() {
914914

915915
func f(_ i: Int) {}
916916
f(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{6-6=<#Root#>}}
917-
// expected-error@-1 {{cannot convert value of key path type to expected argument type 'Int'}}
918917
f(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{6-6=<#Root#>}}
919-
// expected-error@-1 {{cannot convert value of key path type to expected argument type 'Int'}}
920918

921-
func provideValueButNotRoot<T>(_ fn: (T) -> String) {}
919+
func provideValueButNotRoot<T>(_ fn: (T) -> String) {} // expected-note 2 {{in call to function 'provideValueButNotRoot'}}
922920
provideValueButNotRoot(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}}
921+
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
923922
provideValueButNotRoot(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}}
923+
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
924924
provideValueButNotRoot(\String.foo) // expected-error {{value of type 'String' has no member 'foo'}}
925925

926926
func provideKPValueButNotRoot<T>(_ kp: KeyPath<T, String>) {}
@@ -1237,3 +1237,9 @@ func test_keypath_coercion_to_function() {
12371237
func test_keypath_application_with_composition(v: String, kp: any KeyPath<String, Int> & PP) {
12381238
_ = v[keyPath: kp] // Ok
12391239
}
1240+
1241+
func test_leading_dot_key_path_without_context() {
1242+
func test(_: AnyKeyPath?) {}
1243+
test(\.utf8)
1244+
// expected-error@-1 {{cannot infer key path type from context; consider explicitly specifying a root type}}
1245+
}

validation-test/Sema/SwiftUI/rdar84580119.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ extension EnvironmentValues {
1616
set { self[\.MyHorizontalAlignmentEnvironmentKey.self] = newValue }
1717
// expected-error@-1 {{generic parameter 'K' could not be inferred}}
1818
// expected-error@-2 {{cannot infer key path type from context; consider explicitly specifying a root type}}
19-
// expected-error@-3 {{cannot convert value of key path type to expected argument type 'K.Type'}}
2019
}
2120
}
2221

0 commit comments

Comments
 (0)