Once we have expanded an expression macro, parse and type-check the
result given a priori knowledge of the expanded type. Then, create an
implicit macro-expansion expression to capture the result of the
rewrite.
During prechecking, postfix '...' expressions are rewritten to pack
expansion expressions if the operand contains pack references. References
to packs are replaced with opaque values, and the pack expansion stores
the opaque value bindings to decl refs.
Introduce an experimental option `BuiltinMacros` that takes the magic
literals (`#file`, `#line`, `#function`, etc.) after type checking and
processes the original source for the expression using the build
syntactic macro system in the swift-syntax library. At present, the
result of expansion is printed to standard output, but it's enough to
verify that we're able to find the corresponding syntax node based on
the C++ AST.
Introduce `MacroExpansionExpr` and `MacroExpansionDecl` and plumb it through. Parse them in roughly the same way we parse `ObjectLiteralExpr`.
The syntax is gated under `-enable-experimental-feature Macros`.
Immutable properties cannot be re-assigned and don't have setters
which means that we cannot use `assign_by_wrapper` instruction to
handle `let` properties, but we can use a direct reference to
`_storage` property instead when immutable property appears as an
assignment destination and let read references go through a getter
still.
There was a special case here to type-check `T.init` as a single closure
`{ args.. in T.init(args..) }`, but really, we can do that for any static
member applied to a static metatype base, including operators.
Also fix SILGen's function conversion peephole so it looks through
`as (T...) -> U` coercions that don't involve bridging.
Remove the preallocated closure discriminator from KeyPathExpr and go back
to expanding them using an AutoClosureExpr inside of a CaptureListExpr now
that that's supported. This allows the discriminator to be assigned during
type checking without disturbing the indexing of explicit closure literals.
Previously, we would turn a key path literal like `\.foo` in function type
context into a double-wrapped closure like this:
```
foo(\.x) // before type checking
foo({ $kp$ in { $0[$kp$] } }(\.x)) // after type checking
```
in order to preserve the evaluation semantics of the key path literal. This
works but leads to some awkward raw SIL generated out of SILGen which misses
out on various SILGen peepholes and requires a fair number of passes to clean
up. The semantics can still be preserved with a single layer of closure, by
using a capture list:
```
foo({[$kp$ = \.x] in $0[$kp$] }) // after type checking
```
which generates better natural code out of SILGen, and is also (IMO) easier
to understand on human inspection.
Changing the AST representation did lead to a change in code generation that
interfered with the efficacy of CapturePropagation of key path literals; for
key path literals used as nonescaping closures, a mark_dependence of the
nonescaping function value on the key path was left behind, leaving the key
path object alive. The dependence is severed by the specialization done in
the pass, so update the pass to eliminate the dependence.
Compared to the previous patch, this version removes the attempt to have
the type-checked function expression carry the noescape-ness of its context,
and allows for coerceToType to introduce a function conversion instead, since
that FunctionConversionExpr is apparently load-bearing for default argument
generators.
Previously, we would turn a key path literal like `\.foo` in function type
context into a double-wrapped closure like this:
foo(\.x) // before type checking
foo({ $kp$ in { $0[$kp$] } }(\.x)) // after type checking
in order to preserve the evaluation semantics of the key path literal. This
works but leads to some awkward raw SIL generated out of SILGen which misses
out on various SILGen peepholes and requires a fair number of passes to clean
up. The semantics can still be preserved with a single layer of closure, by
using a capture list:
foo({[$kp$ = \.x] in $0[$kp$] }) // after type checking
which generates better natural code out of SILGen, and is also (IMO) easier
to understand on human inspection.
Changing the AST representation did lead to a change in code generation that
interfered with the efficacy of CapturePropagation of key path literals; for
key path literals used as nonescaping closures, a mark_dependence of the
nonescaping function value on the key path was left behind, leaving the key
path object alive. The dependence is severed by the specialization done in
the pass, so update the pass to eliminate the dependence.
Replace the use of bool and pointer returns for
`walkToXXXPre`/`walkToXXXPost`, and instead use
explicit actions such as `Action::Continue(E)`,
`Action::SkipChildren(E)`, and `Action::Stop()`.
There are also conditional variants, e.g
`Action::SkipChildrenIf`, `Action::VisitChildrenIf`,
and `Action::StopIf`.
There is still more work that can be done here, in
particular:
- SourceEntityWalker still needs to be migrated.
- Some uses of `return false` in pre-visitation
methods can likely now be replaced by
`Action::Stop`.
- We still use bool and pointer returns internally
within the ASTWalker traversal, which could likely
be improved.
But I'm leaving those as future work for now as
this patch is already large enough.
Introduce the compiler directive `#_hasSymbol` which will be used to detect whether weakly linked symbols are present at runtime. It is intended for use in combination with `@_weakLinked import` or `-weak-link-at-target`.
```
if #_hasSymbol(foo(_:)) {
foo(42)
}
```
Parsing only; SILGen is coming in a later commit.
Resolves rdar://99342017