When matching a result builder in the constraint system, the closure has already been pre-checked so we don’t need to pre-check it again. Also, we can continue type checking even if the closure contained an `ErrorExpr` since result builders are now type checked like regular closures.
I think that preferring identical over convertible makes sense in e.g. C++ where we have implicit user-defined type conversions but since we don’t have them in Swift, I think the distinction doesn’t make too much sense, because if we have a `func foo(x: Int?)`, want don’t really want to prioritize variables of type `Int?` over `Int` Similarly if we have `func foo(x: View)`, we don’t want to prioritize a variable of type `View` over e.g. `Text`.
rdar://91349364
This hooks up call argument position completion to the typeCheckForCodeCompletion API to generate completions from all the solutions the constraint solver produces (even those requiring fixes), rather than relying on a single solution being applied to the AST (if any).
Co-authored-by: Nathan Hawes <nathan.john.hawes@gmail.com>
`CodeCompletioString::getName()` was used only as the sorting keys in
`CodeCompletionContext::sortCompletionResults()` which is effectively
deprecated. There's no reason to check them in `swift-ide-test`. Instead,
check `printCodeCompletionResultFilterName()` that is actually used for
filtering.
To describe fine grained priorities.
Introduce 'CodeCompletionFlair' that is a set of more descriptive flags for
prioritizing completion items. This aims to replace '
SemanticContextKind::ExpressionSpecific' which was a "catch all"
prioritization flag.
Not-filtering solutions causes unacceptable slownesses in some cases.
For now, filter solutions as normal typechecking does to restore the
performance.
rdar://76714968
We were previously completely skipping the "best" solution filtering the solver
does to make sure we didn't miss any non-best but still viable solutions, as
the completions generated from them can make them become the best solution. E.g:
struct Foo { let onFoo = 10 }
func foo(_ x: Int) -> Int { return 1 }
func foo<T>(_ x: T) -> Foo { return Foo() }
foo(3).<here> // the "best" solution is the one with the more-specialized foo(x: Int) overload
In the example above we shouldn't remove the solution for foo(x: T) even though
there is a single "best" solution (`foo(x: Int)`) as picking a completion
result generated from it (`onFoo`) would make the foo(x: T) overload the best
and only viable solution.
Completely skipping this filtering as we were previously doing is overkill
though and adversely affects performance. E.g. it makes sense to filter out
and stop exploring solutions with overload choices for foo that required fixes
for missing arguments if there is another solution with an overload choice that
didn't require any fixes.
This patch restores best solution filtering during code completion and instead updates
the compareSolutions function it compare solutions based purely on their fixed score.
Resolves rdar://problem/73282163
If the completion loc was in a trailing closure arg, it only makes sense to
ignore later missing args if they have function type, as there's no way for the
user to complete the call for overload being matched otherwise.
Also fix a bug where we were incorrectly penalizing solutions with holes that
were ultimately due to missing arguments after the completion position.
Resolves rdar://problem/72412302
When solving for code completion, we ignore missing arguments after the one
containing the code completion location, don't favor overloads with a number of
params matching the number of arguments in a call and so on. Because of this,
we can't assume multiple solutions being formed when solving for code completion
means there won't be a single best solution formed when solving for regular
type-checking.
Resolves rdar://problem/72362275
Following on from updating regular member completion, this hooks up unresolved
member completion (i.e. .<complete here>) to the typeCheckForCodeCompletion API
to generate completions from all solutions the constraint solver produces (even
those requiring fixes), rather than relying on a single solution being applied
to the AST (if any). This lets us produce unresolved member completions even
when the contextual type is ambiguous or involves errors.
Whenever typeCheckExpression is called on an expression containing a code
completion expression and a CompletionCallback has been set, each solution
formed is passed to the callback so the type of the completion expression can
be extracted and used to lookup up the members to return.
In the single-element case, it is treated as the dictionary key.
func takesDict(_ x: [Int: String]) {}
takesDict([]) // diagnose with fixit to add missing ':'
takesDict([1]) // diagnose with fixit to add missing ': <#value#>'
takesDict([foo.<complete>]) // prioritise Int members in completion results -
// the user just hasn't written the value yet.
The above previously failed with a generic mismatch error in normal type
checking (due to the literal being parsed as an array literal) and code
completion could not pick up the expected type from the context.
Solver-based member completion performs a lookup per solution, but if the base
types in each solution are variations of the same generic (e.g. Array<Int>,
Array<String>), we can end up with the same result appearing twice (e.g. count)
"Function builders" are being renamed to "result builders". Add the
corresponding `@resultBuilder` attribute, with `@_functionBuilder` as
an alias for it, Update test cases to use @resultBuilder.
func foo(a: Int, b: Int) {}
func foo(a: String) {}
// Int and String should both be valid, despite the missing argument for the
// first overload since the second arg may just have not been written yet.
foo(a: <complete here>
func bar(a: (Int) -> ()) {}
func bar(a: (String, Int) -> ()) {}
// $0 being of type String should be valid, rather than just Int, since $1 may
// just have not been written yet.
bar { $0.<complete here> }
...and adjust the fallback context it choses now that ErrorExprs no longer
cause constraint generation to fail.
Also fix some issues with the fallback logic in typeCheckForCodeCompletion:
1) For completion expressions in multi-statement closures, we were assuming a
separate typeCheckExpression call would be made when the outer expression
produced a single solution that had a resolved type for the closure. If the
solution contained other fixes unrelated to the closure however, it wasn't
applied and a separate call for the body was never made.
2) typeCheckForCodeComplation sometimes falls back to regular expression type
checking but didn't update the passed-in target's expression after santizing
and prechecking it, which may have modified it and its sub-expressions. This
triggered assertion failures in certain cases due to the mix of the stale
top-level expression pointer being used with updated subexpressions.
This lets us still provide member completions when the base expression contains parse errors or unresolved decls
e.g. returnsAString(undefined).<complete here>
For example, the completion below would trigger error recovery within the
closure, which we recover from by skipping to the first inner closure's right
brace. The fact that we recovered though, was not recorded. The closure is
treated as still being an error, triggering another recovery after it that
skips over the 'Thing' token, giving a lone closure expression, rather than a
call.
CreateThings {
Thing { point in
print("hello")
point.#^HERE^#
}
Thing { _ in }
}
This isn't an issue for code completion when the outer closure is a regular
closure, but when it's a function builder, invalid elements result in no types
being applied (no valid solutions) and we end up with no completion results.
The fix here is removing the error status from the parser result after the
initial parser recovery.