diff --git a/lib/Sema/CSStep.cpp b/lib/Sema/CSStep.cpp index 45c2e10d20bd3..a13787aa5227b 100644 --- a/lib/Sema/CSStep.cpp +++ b/lib/Sema/CSStep.cpp @@ -981,7 +981,15 @@ StepResult ConjunctionStep::resume(bool prevFailed) { ++numHoles; } } - CS.increaseScore(SK_Hole, Conjunction->getLocator(), numHoles); + // Increase the score for each hole we bind. Avoid doing this for + // completion since it's entirely expected we'll end up with + // ambiguities in the body of a closure if we're completing e.g + // `someOverloadedFn(#^CC^#)`. As such we don't want to penalize the + // solution for unbound type variables outside of the body since + // that will prevent us from being able to eagerly prune e.g + // disfavored overloads in the outer scope. + if (!CS.isForCodeCompletion()) + CS.increaseScore(SK_Hole, Conjunction->getLocator(), numHoles); } if (CS.worseThanBestSolution()) diff --git a/test/IDE/complete_closure_ambiguity.swift b/test/IDE/complete_closure_ambiguity.swift new file mode 100644 index 0000000000000..a1daa7be26079 --- /dev/null +++ b/test/IDE/complete_closure_ambiguity.swift @@ -0,0 +1,31 @@ +// RUN: %empty-directory(%t) +// RUN: %batch-code-completion -debug-constraints 2> %t/constraints.log +// RUN: %FileCheck %s -check-prefix CONSTRAINTS < %t/constraints.log +// RUN: %FileCheck %s -check-prefix CONSTRAINTS-NOT < %t/constraints.log + +protocol P1 {} +protocol P2 {} + +func foo(_ fn: () -> T) {} + +@_disfavoredOverload +func foo(_ fn: () -> T) {} + +func bar(_ x: Int) -> Int {} +func bar(_ x: String) -> String {} + +// Make sure we eagerly prune the disfavored overload of 'foo', despite the +// ambiguity in the closure body. +foo { + let x = bar(#^COMPLETE^#) + // COMPLETE: Decl[FreeFunction]/CurrModule/Flair[ArgLabels]: ['(']{#(x): Int#}[')'][#Int#]; name=: + // COMPLETE: Decl[FreeFunction]/CurrModule/Flair[ArgLabels]: ['(']{#(x): String#}[')'][#String#]; name=: + + return x +} + +// CONSTRAINTS: attempting disjunction choice {{.*}}:12:6 +// CONSTRAINTS: increasing 'disfavored overload' score +// CONSTRAINTS: solution is worse than the best solution + +// CONSTRAINTS-NOT-NOT: increasing 'hole'