Handle PatternBindingDecls with missing var locations, which can
happen for loop iterator vars, and FuncDecls with missing name and
func locations, which can happen for `defer`. Also while here make
sure we set the source location of a parser-produced ErrorExpr.
* Include `DeclContext` of the node where possible
* Add 'default-with-decl-contexts' dump style that dumps the dect context
hierarchy in addition to the AST
* Support `-dump-parse` with `-dump-ast-format json`
Instead, use the `%target-swift-5.1-abi-triple` substitution to compile the tests
for deployment to the minimum OS versions required for use of _Concurrency APIs.
This PR refactors the ASTDumper to make it more structured, less mistake-prone, and more amenable to future changes. For example:
```cpp
// Before:
void visitUnresolvedDotExpr(UnresolvedDotExpr *E) {
printCommon(E, "unresolved_dot_expr")
<< " field '" << E->getName() << "'";
PrintWithColorRAII(OS, ExprModifierColor)
<< " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
if (E->getBase()) {
OS << '\n';
printRec(E->getBase());
}
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
// After:
void visitUnresolvedDotExpr(UnresolvedDotExpr *E, StringRef label) {
printCommon(E, "unresolved_dot_expr", label);
printFieldQuoted(E->getName(), "field");
printField(E->getFunctionRefKind(), "function_ref", ExprModifierColor);
if (E->getBase()) {
printRec(E->getBase());
}
printFoot();
}
```
* Values are printed through calls to base class methods, rather than direct access to the underlying `raw_ostream`.
* These methods tend to reduce the chances of bugs like missing/extra spaces or newlines, too much/too little indentation, etc.
* More values are quoted, and unprintable/non-ASCII characters in quoted values are escaped before printing.
* Infrastructure to label child nodes now exists.
* Some weird breaks from the normal "style", like `PatternBindingDecl`'s original and processed initializers, have been brought into line.
* Some types that previously used ad-hoc dumping functions, like conformances and substitution maps, are now structured similarly to the dumper classes.
* I've fixed the odd dumping bug along the way. For example, distributed actors were only marked `actor`, not `distributed actor`.
This PR doesn't change the overall style of AST dumps; they're still pseudo-S-expressions. But the logic that implements this style is now isolated into a relatively small base class, making it feasible to introduce e.g. JSON dumping in the future.
This patch contains the updates for the tests. The merge removes the
`-async-main` flag, so the tests using that flag fail on that.
Additionally, the tests reflect the newer behavior of the main
resolution. `async_main_resolution` verifies that we're not preferring
an async function over a synchronous function, and vice versa.
This is also verified in `where_clause_main_resolution`, where we select
a main function using various configuration typealiases.
Finally, we only select a valid, usable main function. The old machinery
could select one sort of at random (technically it selected the first
overload declared in the source file) if an error occurred. Errors that
resulted in this behavior included a missing valid function, or an
ambiguous overload. In the case of the missing valid function, the
function returned would be from an invalid location if one existed,
which was called from `$main`. `$main` had sufficient context to realize
that the main function being called was not valid, and would emit an
error saying why. It would be better to realize that we're not getting a
valid main function earlier, and later we can emit notes saying why each
function called main could not be selected.
The async main resolution has dropped the custom availability checking,
so I am able to collapse the resolution checking into a single test
(deleting the macos-specific one).
Selection of an asynchronous main vs a synchronous main is dependent on
an `-async-main` flag. Due to the scoring mechanism, and that the
specificity of a given resolution doesn't affect the score, a more
general synchronous main will be selected over a more specific
asynchronous main when the `-async-main` flag is not passed.
If the flag is not passed and the program only contains an asynchronous
main, or the asynchronous main is the only main function that is
available given the constraints, then it will be selected.
Conversely, if the flag is set and no valid asynchronous main functions
exist, the main function will resolve to a synchronous main.
This is the same behavior that is used to resolve an synchronous and
asynchronous static function.
Fixing testing for different platforms. MacOS and iOS have
backdeployment and availability to consider. Other platforms don't need
to worry about that because they need to include the swift runtime in
the installation package anyway, so the concurrency bits can ship with
the installation.
The typesystem was avoiding the async main function if any synchronous
main was available. This is because the decl contexts where the main
function is looked up from aren't async contexts (extension contexts,
generic type contexts), so if a synchronous main function exists
anywhere, it will be a better "fit" for the context.
Since we're the main function, we decide on whether or not we want to be
async, so looking at the decl-context's asyncness is really the wrong
thing to do. Plumbing this info through the constraint system seems
risky at best, catastrophic at worst, so instead, I'm just grabbing the
buffer of resolved decls and doing my own scoring and selection.
We want to ensure that we are picking the main function that is closest
to the decl marked with `@main` in the protocol conformance chain. This
means that if your `@main` struct directly conforms to a protocol that
implements a main function, you should probably use it. If that protocol
implements two main functions, one sync and one async, we look at
whether we support async before selecting it.
Things get a little bit weird if you have implemented an async main in
the closest protocol, but are targeting something that doesn't support
concurrency. The `@available` checking should handle this with a nice
error saying you're doing bad things, but if you circumvent that
checking for bad reasons, it will still fall back on a synchronous main
function if one is available.