mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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.
75 lines
5.1 KiB
Swift
75 lines
5.1 KiB
Swift
// This test aims to show that no preference is given to either the async or
|
|
// sync main function. The most specific, valid, main function will be
|
|
// selected if one exists. If two main functions could exist, the usage is
|
|
// ambiguous.
|
|
|
|
// async main is nested deeper in protocols than sync, use sync
|
|
// sync main is nested deeper in protocols than async, use async
|
|
// async and sync are same level, error
|
|
|
|
// REQUIRES: concurrency
|
|
|
|
// ASYNC_NESTED: async is nested more deeply than sync main in protocol chain
|
|
// NO_ASYNC: no async main function
|
|
// NO_SYNC: no sync main function
|
|
// BOTH: MainProtocol has both sync and async main
|
|
// INHERIT_SYNC: main type directly conforms to synchronous main protocol
|
|
|
|
// | has async main | has sync main | both | inherits sync | nested async | Result | | Run |
|
|
// | | | | | | Error | No main | RUN: not %target-swift-frontend -disable-availability-checking -DNO_SYNC -DNO_ASYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR1
|
|
// | x | x | x | x | | Error | Ambiguous main in MainP | RUN: not %target-swift-frontend -disable-availability-checking -DBOTH -DINHERIT_SYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR2
|
|
// | | x | x | x | | Error | Ambiguous main in MainP | RUN: not %target-swift-frontend -disable-availability-checking -DBOTH -DINHERIT_SYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR2
|
|
// | x | x | x | | | Async | Directly selected | RUN: %target-swift-frontend -disable-availability-checking -DBOTH -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
|
|
// | x | x | | | | Async | Directly selected | RUN: %target-swift-frontend -disable-availability-checking -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
|
|
// | | x | | | | Sync | Indirectly selected | RUN: %target-swift-frontend -disable-availability-checking -DNO_ASYNC -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
|
|
// | x | x | | x | x | Sync | Directly selected | RUN: %target-swift-frontend -disable-availability-checking -DINHERIT_SYNC -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-SYNC
|
|
// | x | | | x | x | Async | Indirectly selected | RUN: %target-swift-frontend -disable-availability-checking -DNO_SYNC -DINHERIT_SYNC -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s | %FileCheck %s --check-prefix=CHECK-IS-ASYNC
|
|
// | x | | | x | | Error | Unrelated async main | RUN: not %target-swift-frontend -disable-availability-checking -DNO_SYNC -DINHERIT_SYNC -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR1
|
|
// | | x | | | x | Error | Unrelated sync main | RUN: not %target-swift-frontend -disable-availability-checking -DNO_ASYNC -DASYNC_NESTED -parse-as-library -typecheck -dump-ast %s 2>&1 | %FileCheck %s --check-prefix=CHECK-IS-ERROR1
|
|
|
|
#if ASYNC_NESTED
|
|
protocol AsyncMainProtocol { }
|
|
protocol MainProtocol : AsyncMainProtocol { }
|
|
#else
|
|
protocol MainProtocol { }
|
|
protocol AsyncMainProtocol : MainProtocol { }
|
|
#endif
|
|
|
|
#if NO_SYNC
|
|
#else
|
|
extension MainProtocol {
|
|
static func main() { }
|
|
}
|
|
#endif
|
|
|
|
#if NO_ASYNC
|
|
#else
|
|
extension AsyncMainProtocol {
|
|
static func main() async { }
|
|
}
|
|
#endif
|
|
|
|
#if BOTH
|
|
extension MainProtocol {
|
|
static func main() async { }
|
|
}
|
|
#endif
|
|
|
|
|
|
#if INHERIT_SYNC
|
|
@main struct MyMain : MainProtocol {}
|
|
#else
|
|
@main struct MyMain : AsyncMainProtocol {}
|
|
#endif
|
|
|
|
// CHECK-IS-SYNC-LABEL: "MyMain" interface type="MyMain.Type"
|
|
// CHECK-IS-SYNC: (func_decl implicit "$main()" interface type="(MyMain.Type) -> () -> ()"
|
|
// CHECK-IS-SYNC: (declref_expr implicit type="(MyMain.Type) -> () -> ()"
|
|
|
|
// CHECK-IS-ASYNC-LABEL: "MyMain" interface type="MyMain.Type"
|
|
// CHECK-IS-ASYNC: (func_decl implicit "$main()" interface type="(MyMain.Type) -> () async -> ()"
|
|
// CHECK-IS-ASYNC: (declref_expr implicit type="(MyMain.Type) -> () async -> ()"
|
|
|
|
// CHECK-IS-ERROR1: error: 'MyMain' is annotated with @main and must provide a main static function of type {{\(\) -> Void or \(\) throws -> Void|\(\) -> Void, \(\) throws -> Void, \(\) async -> Void, or \(\) async throws -> Void}}
|
|
// CHECK-IS-ERROR2: error: ambiguous use of 'main'
|