diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 77a0d80979eea..1e64c1bc633e8 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -3168,10 +3168,25 @@ class ConstraintSystem { if (solutions.size() < 2) return; - if (auto best = findBestSolution(solutions, minimize)) { - if (*best != 0) - solutions[0] = std::move(solutions[*best]); - solutions.erase(solutions.begin() + 1, solutions.end()); + if (hasCodeCompletionTypeVar()) { + // For code completion remove solutions that have more fixes than the + // minimum but don't filter based on the lower-priority scores because we + // want to show all options even if they need to go through more + // conversions. + Score minScore = std::min_element(solutions.begin(), solutions.end(), + [](const Solution &a, const Solution &b) { + return a.getFixedScore() < b.getFixedScore(); + })->getFixedScore(); + + llvm::erase_if(solutions, [&](const Solution &S) { + return S.getFixedScore().Data[SK_Fix] > minScore.Data[SK_Fix]; + }); + } else { + if (auto best = findBestSolution(solutions, minimize)) { + if (*best != 0) + solutions[0] = std::move(solutions[*best]); + solutions.erase(solutions.begin() + 1, solutions.end()); + } } } @@ -3234,6 +3249,8 @@ class ConstraintSystem { bool containsCodeCompletionLoc(ASTNode node) const; bool containsCodeCompletionLoc(const ArgumentList *args) const; + bool hasCodeCompletionTypeVar() const; + /// Marks the argument \p Arg as being ignored because it occurs after the /// code completion token. This assumes that the argument is not type checked /// (by assigning it a fresh type variable) and prevents fixes from being diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index 6811f365feecc..207d4abb57a16 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -130,10 +130,21 @@ bool ConstraintSystem::worseThanBestSolution() const { if (getASTContext().TypeCheckerOpts.DisableConstraintSolverPerformanceHacks) return false; - if (!solverState || !solverState->BestScore || - CurrentScore <= *solverState->BestScore) + if (!solverState || !solverState->BestScore) return false; + if (hasCodeCompletionTypeVar()) { + // For code completion, we only filter based on SK_Fix, not the entire + // score. See ConstraintSystem::filterSolutions. + if (CurrentScore.Data[SK_Fix] <= solverState->BestScore->Data[SK_Fix]) { + return false; + } + } else { + if (CurrentScore <= *solverState->BestScore) { + return false; + } + } + if (isDebugMode()) { llvm::errs().indent(solverState->depth * 2) << "(solution is worse than the best solution)\n"; diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 10e1e2642a593..b66bb53e848ce 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -73,8 +73,14 @@ Solution ConstraintSystem::finalize() { // Update the best score we've seen so far. auto &ctx = getASTContext(); - assert(ctx.TypeCheckerOpts.DisableConstraintSolverPerformanceHacks || - !solverState->BestScore || CurrentScore <= *solverState->BestScore); + if (hasCodeCompletionTypeVar()) { + assert(ctx.TypeCheckerOpts.DisableConstraintSolverPerformanceHacks || + !solverState->BestScore || + CurrentScore.Data[SK_Fix] <= solverState->BestScore->Data[SK_Fix]); + } else { + assert(ctx.TypeCheckerOpts.DisableConstraintSolverPerformanceHacks || + !solverState->BestScore || CurrentScore <= *solverState->BestScore); + } if (!solverState->BestScore || CurrentScore <= *solverState->BestScore) { solverState->BestScore = CurrentScore; diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 115474377cb17..4ff4f151de65f 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -359,6 +359,15 @@ bool ConstraintSystem::containsCodeCompletionLoc( return Context.SourceMgr.rangeContainsCodeCompletionLoc(range); } +bool ConstraintSystem::hasCodeCompletionTypeVar() const { + for (auto ty : TypeVariables) { + if (ty->getImpl().isCodeCompletionToken()) { + return true; + } + } + return false; +} + ConstraintLocator *ConstraintSystem::getConstraintLocator( ASTNode anchor, ArrayRef path) { auto summaryFlags = ConstraintLocator::getSummaryFlagsForPath(path); diff --git a/test/IDE/complete_ambiguous.swift b/test/IDE/complete_ambiguous.swift index d4e840bbf8983..4da366f54d6cf 100644 --- a/test/IDE/complete_ambiguous.swift +++ b/test/IDE/complete_ambiguous.swift @@ -483,7 +483,7 @@ func testBestSolutionGeneric() { func genAndInt(_ x: Int) -> Int { return 1 } func genAndInt(_ x: T) -> Test1 { return Test1() } - genAndInt(2).#^BEST_SOLUTION_FILTER_GEN?xfail=rdar73282163^# + genAndInt(2).#^BEST_SOLUTION_FILTER_GEN^# } // BEST_SOLUTION_FILTER_GEN: Begin completions diff --git a/test/IDE/complete_assignment.swift b/test/IDE/complete_assignment.swift index 5eed19944bc99..02920e9b1f557 100644 --- a/test/IDE/complete_assignment.swift +++ b/test/IDE/complete_assignment.swift @@ -87,10 +87,10 @@ func f2() { // ASSIGN_2-DAG: Begin completions // ASSIGN_2-DAG: Decl[LocalVar]/Local/TypeRelation[Identical]: I3[#Int?#]; name=I3 -// ASSIGN_2-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Convertible]: I1[#Int#]; name=I1 -// ASSIGN_2-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Convertible]: I2[#Int#]; name=I2 +// ASSIGN_2-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: I1[#Int#]; name=I1 +// ASSIGN_2-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: I2[#Int#]; name=I2 // ASSIGN_2-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: IO1[#Int?#]; name=IO1 -// ASSIGN_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: IntGenerator()[#Int#]; name=IntGenerator() +// ASSIGN_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntGenerator()[#Int#]; name=IntGenerator() // ASSIGN_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntOpGenerator()[#Int?#]; name=IntOpGenerator() // ASSIGN_2-DAG: Decl[InstanceVar]/CurrNominal: S1[#String#]; name=S1 @@ -114,10 +114,10 @@ func f2() { // ASSIGN_4-DAG: Begin completions // ASSIGN_4-DAG: Decl[LocalVar]/Local/TypeRelation[Identical]: S4[#String?#]; name=S4 -// ASSIGN_4-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Convertible]: S1[#String#]; name=S1 -// ASSIGN_4-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Convertible]: S2[#String#]; name=S2 +// ASSIGN_4-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: S1[#String#]; name=S1 +// ASSIGN_4-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: S2[#String#]; name=S2 // ASSIGN_4-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: SO1[#String?#]; name=SO1 -// ASSIGN_4-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: StringGenerator()[#String#]; name=StringGenerator() +// ASSIGN_4-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: StringGenerator()[#String#]; name=StringGenerator() // ASSIGN_4-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: StringOpGenerator()[#String?#]; name=StringOpGenerator() // ASSIGN_4-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: VoidGen()[#Void#]; name=VoidGen() // ASSIGN_4-DAG: Decl[InstanceVar]/CurrNominal: I1[#Int#]; name=I1 @@ -160,7 +160,7 @@ func f2() { } // ASSIGN_8: Begin completions -// ASSIGN_8-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: IntGen()[#Int#] +// ASSIGN_8-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntGen()[#Int#] // ASSIGN_8-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntOpGen()[#Int?#] // ASSIGN_8-DAG: Decl[InstanceMethod]/CurrNominal: D1Gen()[#D1#] // ASSIGN_8-DAG: Decl[InstanceMethod]/CurrNominal: D2Gen()[#D2#] @@ -233,10 +233,10 @@ func f2() { } // ASSIGN_14-DAG: Begin completions -// ASSIGN_14-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Convertible]: I1[#Int#]; name=I1 -// ASSIGN_14-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Convertible]: I2[#Int#]; name=I2 +// ASSIGN_14-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: I1[#Int#]; name=I1 +// ASSIGN_14-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: I2[#Int#]; name=I2 // ASSIGN_14-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: IO1[#Int?#]; name=IO1 -// ASSIGN_14-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: IntGenerator()[#Int#]; name=IntGenerator() +// ASSIGN_14-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntGenerator()[#Int#]; name=IntGenerator() // ASSIGN_14-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntOpGenerator()[#Int?#]; name=IntOpGenerator() // ASSIGN_14-DAG: Decl[InstanceVar]/CurrNominal: S1[#String#]; name=S1 diff --git a/test/IDE/complete_call_arg.swift b/test/IDE/complete_call_arg.swift index 5bbceb99a29a2..665fb699de3e9 100644 --- a/test/IDE/complete_call_arg.swift +++ b/test/IDE/complete_call_arg.swift @@ -326,7 +326,7 @@ class C4 { } // MEMBER1: Begin completions -// MEMBER1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: IntGen()[#Int#]; name=IntGen() +// MEMBER1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntGen()[#Int#]; name=IntGen() // MEMBER1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntOpGen()[#Int?#]; name=IntOpGen() // MEMBER1-DAG: Decl[InstanceMethod]/CurrNominal: StringGen()[#String#]; name=StringGen() // MEMBER1-DAG: Decl[InstanceMethod]/CurrNominal: StringOpGen()[#String?#]; name=StringOpGen() @@ -349,7 +349,7 @@ class C4 { // MEMBER3: Begin completions // MEMBER3-DAG: Decl[InstanceMethod]/CurrNominal: IntGen()[#Int#]; name=IntGen() // MEMBER3-DAG: Decl[InstanceMethod]/CurrNominal: IntOpGen()[#Int?#]; name=IntOpGen() -// MEMBER3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: StringGen()[#String#]; name=StringGen() +// MEMBER3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: StringGen()[#String#]; name=StringGen() // MEMBER3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: StringOpGen()[#String?#]; name=StringOpGen() // MEMBER3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: IntTaker({#(i1): Int#}, {#i2: Int#})[#Void#]; name=IntTaker(:i2:) // MEMBER3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: StringTaker({#(s1): String#}, {#s2: String#})[#Void#]; name=StringTaker(:s2:) @@ -365,11 +365,11 @@ class C4 { // MEMBER7: Begin completions // MEMBER7-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem/TypeRelation[Invalid]: removeAll()[#Void#]; name=removeAll() // MEMBER7-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem/TypeRelation[Invalid]: removeAll({#keepingCapacity: Bool#})[#Void#]; name=removeAll(keepingCapacity:) -// MEMBER7-DAG: Decl[InstanceVar]/CurrNominal/IsSystem/TypeRelation[Convertible]: count[#Int#]; name=count -// MEMBER7-DAG: Decl[InstanceVar]/CurrNominal/IsSystem/TypeRelation[Convertible]: capacity[#Int#]; name=capacity +// MEMBER7-DAG: Decl[InstanceVar]/CurrNominal/IsSystem/TypeRelation[Identical]: count[#Int#]; name=count +// MEMBER7-DAG: Decl[InstanceVar]/CurrNominal/IsSystem/TypeRelation[Identical]: capacity[#Int#]; name=capacity // MEMBER8: Begin completions -// MEMBER8-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: InternalIntGen()[#Int#]; name=InternalIntGen() +// MEMBER8-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: InternalIntGen()[#Int#]; name=InternalIntGen() // MEMBER8-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: InternalIntOpGen()[#Int?#]; name=InternalIntOpGen() // MEMBER8-DAG: Decl[InstanceMethod]/CurrNominal: InternalStringGen()[#String#]; name=InternalStringGen() // MEMBER8-DAG: Decl[InstanceMethod]/CurrNominal: InternalStringOpGen()[#String?#]; name=InternalStringOpGen() diff --git a/test/IDE/complete_return.swift b/test/IDE/complete_return.swift index 5bbd563efe83f..fc89a5f6cc549 100644 --- a/test/IDE/complete_return.swift +++ b/test/IDE/complete_return.swift @@ -14,8 +14,8 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RETURN_TR2_STATICMETHOD | %FileCheck %s -check-prefix=RETURN_TR2 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RETURN_TR3_STATICMETHOD | %FileCheck %s -check-prefix=RETURN_TR3 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RETURN_TR1_CLOSURE | %FileCheck %s -check-prefix=RETURN_TR1 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RETURN_TR2_CLOSURE | %FileCheck %s -check-prefix=RETURN_TR2 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RETURN_TR3_CLOSURE | %FileCheck %s -check-prefix=RETURN_TR3 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RETURN_TR2_CLOSURE | %FileCheck %s -check-prefix=RETURN_TR2_CLOSURE +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RETURN_TR3_CLOSURE | %FileCheck %s -check-prefix=RETURN_TR3_CLOSURE struct FooStruct { var instanceVar : Int @@ -153,7 +153,23 @@ func testClosures(_ g: Gen) { _ = { () -> Int? in return g.#^RETURN_TR2_CLOSURE^# } +// RETURN_TR2_CLOSURE: Begin completions +// RETURN_TR2_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntGen()[#Int#]{{; name=.+$}} +// RETURN_TR2_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: IntOpGen()[#Int?#]{{; name=.+$}} +// RETURN_TR2_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal: StringGen()[#String#]{{; name=.+$}} +// RETURN_TR2_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal: StringOpGen()[#String?#]{{; name=.+$}} +// RETURN_TR2_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: IntTaker({#(i1): Int#}, {#i2: Int#})[#Void#]{{; name=.+$}} +// RETURN_TR2_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: StringTaker({#(s1): String#}, {#s2: String#})[#Void#]{{; name=.+$}} + _ = { () -> Int? in return g.IG.#^RETURN_TR3_CLOSURE^# } +// RETURN_TR3_CLOSURE: Begin completions +// RETURN_TR3_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: InternalIntGen()[#Int#]{{; name=.+$}} +// RETURN_TR3_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: InternalIntOpGen()[#Int?#]{{; name=.+$}} +// RETURN_TR3_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal: InternalStringGen()[#String#]{{; name=.+$}} +// RETURN_TR3_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal: InternalStringOpGen()[#String?#]{{; name=.+$}} +// RETURN_TR3_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: InternalIntTaker({#(i1): Int#}, {#i2: Int#})[#Void#]{{; name=.+$}} +// RETURN_TR3_CLOSURE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: InternalStringTaker({#(s1): String#}, {#s2: String#})[#Void#]{{; name=.+$}} + } diff --git a/test/IDE/complete_unresolved_members.swift b/test/IDE/complete_unresolved_members.swift index 8fbf88d5045ff..c4c2e30c59f5a 100644 --- a/test/IDE/complete_unresolved_members.swift +++ b/test/IDE/complete_unresolved_members.swift @@ -152,8 +152,8 @@ class C4 { // Exhaustive to make sure we don't include `init({#(some):` or `init({#nilLiteral:` entries // UNRESOLVED_3_OPT: Begin completions, 9 items -// UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: North[#SomeEnum1#]; -// UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: South[#SomeEnum1#]; +// UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: North[#SomeEnum1#]; +// UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: South[#SomeEnum1#]; // UNRESOLVED_3_OPT-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; // UNRESOLVED_3_OPT-DAG: Keyword[nil]/None/Erase[1]/TypeRelation[Identical]: nil[#SomeEnum1?#]; name=nil // UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: none[#Optional#]; name=none @@ -165,8 +165,8 @@ class C4 { // Exhaustive to make sure we don't include `init({#(some):` or `init({#nilLiteral:` entries // UNRESOLVED_3_OPTOPTOPT: Begin completions, 9 items -// UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: North[#SomeEnum1#]; -// UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: South[#SomeEnum1#]; +// UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: North[#SomeEnum1#]; +// UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: South[#SomeEnum1#]; // UNRESOLVED_3_OPTOPTOPT-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; // UNRESOLVED_3_OPTOPTOPT-DAG: Keyword[nil]/None/Erase[1]/TypeRelation[Identical]: nil[#SomeEnum1???#]; name=nil // UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: none[#Optional#]; name=none @@ -186,8 +186,8 @@ extension Optional where Wrapped == Somewhere { func testOptionalWithCustomExtension() { var _: Somewhere? = .#^UNRESOLVED_OPT_4^# // UNRESOLVED_OPT_4: Begin completions, 11 items -// UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: earth[#Somewhere#]; -// UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: mars[#Somewhere#]; +// UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: earth[#Somewhere#]; +// UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: mars[#Somewhere#]; // UNRESOLVED_OPT_4-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): Somewhere#})[#(into: inout Hasher) -> Void#]; // UNRESOLVED_OPT_4-DAG: Keyword[nil]/None/Erase[1]/TypeRelation[Identical]: nil[#Somewhere?#]; name=nil // UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: none[#Optional#]; name=none @@ -270,7 +270,18 @@ class C6 { class C6 { func f1(e: SomeEnum1) { - if let x = Optional(e) where x == .#^UNRESOLVED_25?check=UNRESOLVED_3^# + if let x = Optional(e) where x == .#^UNRESOLVED_25^# +// UNRESOLVED_25: Begin completions, 9 items +// UNRESOLVED_25-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: North[#SomeEnum1#]; +// UNRESOLVED_25-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: South[#SomeEnum1#]; +// UNRESOLVED_25-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; +// UNRESOLVED_25-DAG: Keyword[nil]/None/Erase[1]/TypeRelation[Identical]: nil[#SomeEnum1?#]; name=nil +// UNRESOLVED_25-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: none[#Optional#]; name=none +// UNRESOLVED_25-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: some({#SomeEnum1#})[#Optional#]; +// UNRESOLVED_25-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(self): Optional#})[#((SomeEnum1) throws -> U) -> U?#]; +// UNRESOLVED_25-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: flatMap({#(self): Optional#})[#((SomeEnum1) throws -> U?) -> U?#]; +// UNRESOLVED_25-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem/TypeRelation[Invalid]: hash({#(self): Optional#})[#(into: inout Hasher) -> Void#]; +// UNRESOLVED_25: End completions } } class C7 {} @@ -732,3 +743,56 @@ func testSameType() { // SUGAR_TYPE: End completions } +func testOverloadWithConvertibleArg() { + // This test case used to cause problems because the second overload needs a value to optional conversion, which increases the solution’s score in one of the later compontens. + // We were prematurely filtering the solution because its score is worse than the 0-score of the first overload (which only ignores the second argument, which doesn't increase the score) + struct S { + func xxx(_ foo: Foo) { } + func xxx(_ bar: Bar, _ other: Int?) { } + } + + struct Foo { + init(x: String) {} + } + + struct Bar { + static let top: Bar = Bar() + } + + S().xxx(.#^CONVERTIBLE_ARG_OVERLOAD^#, 32) +// CONVERTIBLE_ARG_OVERLOAD: Begin completions, 2 items +// CONVERTIBLE_ARG_OVERLOAD-DAG: Decl[StaticVar]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: top[#Bar#]; +// CONVERTIBLE_ARG_OVERLOAD-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init()[#Bar#]; +// CONVERTIBLE_ARG_OVERLOAD: End completions +} + +func testOverloadWithConvertibleArgWithFixesInScore() { + // same as testOverloadWithConvertibleArg but with solutions that contain a fix-score > 0 because the result builder has no body for the initialization of FStack. + + @resultBuilder struct ResBuilder { + static func buildBlock(_ content: Content) -> Content { fatalError() } + } + + struct S { + init(@ResBuilder content: () -> Content) {} + + func xxx(_ foo: Foo) -> Self { return self } + func xxx(_ bar: Bar = .top, _ other: Int?) -> Self { return self } + } + + struct Foo { + init(x: String) {} + } + + struct Bar { + static let top: Bar = Bar() + } + + S() {} + .xxx(.#^CONVERTIBLE_ARG_OVERLOAD_WITH_FIX_IN_SCORE^#top, 32) +// CONVERTIBLE_ARG_OVERLOAD_WITH_FIX_IN_SCORE: Begin completions, 2 items +// CONVERTIBLE_ARG_OVERLOAD_WITH_FIX_IN_SCORE-DAG: Decl[StaticVar]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: top[#Bar#]; name=top +// CONVERTIBLE_ARG_OVERLOAD_WITH_FIX_IN_SCORE-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init()[#Bar#]; name=init() +// CONVERTIBLE_ARG_OVERLOAD_WITH_FIX_IN_SCORE: End completions + +} diff --git a/test/IDE/complete_value_literals.swift b/test/IDE/complete_value_literals.swift index 25582a8849d07..79f97ce73f994 100644 --- a/test/IDE/complete_value_literals.swift +++ b/test/IDE/complete_value_literals.swift @@ -89,14 +89,14 @@ func testBool2() { func testBool3() { let x: Bool? = #^BOOL_3^# } -// BOOL_3: Literal[Boolean]/None/TypeRelation[Convertible]: true[#Bool#]; -// BOOL_3: Literal[Boolean]/None/TypeRelation[Convertible]: false[#Bool#]; +// BOOL_3: Literal[Boolean]/None/TypeRelation[Identical]: true[#Bool#]; +// BOOL_3: Literal[Boolean]/None/TypeRelation[Identical]: false[#Bool#]; func testBool4() { let x: Bool! = #^BOOL_4^# } -// BOOL_4: Literal[Boolean]/None/TypeRelation[Convertible]: true[#Bool#]; -// BOOL_4: Literal[Boolean]/None/TypeRelation[Convertible]: false[#Bool#]; +// BOOL_4: Literal[Boolean]/None/TypeRelation[Identical]: true[#Bool#]; +// BOOL_4: Literal[Boolean]/None/TypeRelation[Identical]: false[#Bool#]; func testInt0() { let x: Bool = #^INT_0^# @@ -208,7 +208,7 @@ func testColor1() { func testColor2() { let x: MyColor1? = #^COLOR_2^# } -// COLOR_2: Literal[_Color]/None/TypeRelation[Convertible]: #colorLiteral({#red: Float#}, {#green: Float#}, {#blue: Float#}, {#alpha: Float#})[#MyColor1#]; +// COLOR_2: Literal[_Color]/None/TypeRelation[Identical]: #colorLiteral({#red: Float#}, {#green: Float#}, {#blue: Float#}, {#alpha: Float#})[#MyColor1#]; struct MyImage1: _ExpressibleByImageLiteral { init(imageLiteralResourceName: String) {}