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
We needed a way to describe an ABI-safe cast of an address
representing an LValue to implement `@preconcurrency` and
its injection of casts during accesses of members.
This new AST node, `ABISafeConversionExpr` models what is
essentially an `unchecked_addr_cast` in SIL when accessing
the LVAlue.
As of now I simply implemented it and the verification of
the node for the concurrency needs to ensure that it's not
misused by accident. If it finds use outside of that,
feel free to update the verifier.
We intended to introduce AST conversions that strip concurrency
attributes off of types associated with `@preconcurrency` decls.
But for VarDecl references, we stripped it too early, leading to
things like a MemberVarDecl that doesn't have `@Sendable` in its
result type, but the VarDecl it refers to does have it.
That caused crashes in SIL where types didn't match up. This patch
fixes things by delaying the stripping until the right point.
resolves rdar://98018067
Previously locator for value-to-value conversion would just drop
all the contextual information if the conversion occurred while
converting expression to a contextual type. This is incorrect for
i.e. `return` statements and other targets because because they
are solved separately and using the same locator would result in
a clash when solutions are merged.
`ExprRewriter::coerceToType` should canonicalize contextual type before
attempting to use it for value abstraction, because sugared type could
have typealias references that hide their underlying opaque result types.
Resolves: rdar://98577451
In some circumstances opened type might not have a fixed binding.
A good example could be dependent sub-component produced for
result builder transformed code (connected via one-way constraints),
in such a case `OpenedTypes` would have outer generic parameters
but they might not be bound yet, so they have to be printed as
type variables.
The outermost wrapper is the one at index `0` in the wrapper list
but it's easy for humans to make a reverse assumption since outermost
is the back of the list. Let's add a dedicated method to reduce error
probability of the property wrapper APIs.
If the type for such declaration could be completely inferred it
would be used during solution application. This is used to infer
types for result builder components.