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.