Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion lib/Sema/CSStep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
31 changes: 31 additions & 0 deletions test/IDE/complete_closure_ambiguity.swift
Original file line number Diff line number Diff line change
@@ -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<T: P1>(_ fn: () -> T) {}

@_disfavoredOverload
func foo<T: P2>(_ 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'