Skip to content

Commit f13e529

Browse files
committed
[CSRanking] Detect cases where overload choices are incomparable
If constraint system is underconstrained e.g. because there are editor placeholders, it's possible to end up with multiple solutions where each ambiguous declaration is going to have its own overload kind: ```swift func foo(_: Int) -> [Int] { ... } func foo(_: Double) -> (result: String, count: Int) { ... } _ = foo(<#arg#>).count ``` In this case solver would produce 2 solutions: one where `count` is a property reference on `[Int]` and another one is tuple access for a `count:` element. Resolves: rdar://problem/49712598 (cherry picked from commit 288a776)
1 parent 998f2de commit f13e529

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,21 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
761761
if (sameOverloadChoice(choice1, choice2))
762762
continue;
763763

764+
// If constraint system is underconstrained e.g. because there are
765+
// editor placeholders, it's possible to end up with multiple solutions
766+
// where each ambiguous declaration is going to have its own overload kind:
767+
//
768+
// func foo(_: Int) -> [Int] { ... }
769+
// func foo(_: Double) -> (result: String, count: Int) { ... }
770+
//
771+
// _ = foo(<#arg#>).count
772+
//
773+
// In this case solver would produce 2 solutions: one where `count`
774+
// is a property reference on `[Int]` and another one is tuple access
775+
// for a `count:` element.
776+
if (choice1.isDecl() != choice2.isDecl())
777+
return SolutionCompareResult::Incomparable;
778+
764779
auto decl1 = choice1.getDecl();
765780
auto dc1 = decl1->getDeclContext();
766781
auto decl2 = choice2.getDecl();

test/Sema/editor_placeholders.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,10 @@ f(<#T##String#>) // expected-error{{editor placeholder in source file}} expected
2929
for x in <#T#> { // expected-error{{editor placeholder in source file}} expected-error{{for-in loop requires '()' to conform to 'Sequence'}}
3030

3131
}
32+
33+
// rdar://problem/49712598 - crash while trying to rank solutions with different kinds of overloads
34+
func test_ambiguity_with_placeholders(pairs: [(rank: Int, count: Int)]) -> Bool {
35+
return pairs[<#^ARG^#>].count == 2
36+
// expected-error@-1 {{editor placeholder in source file}}
37+
// expected-error@-2 {{ambiguous use of 'subscript(_:)'}}
38+
}

0 commit comments

Comments
 (0)