During the review of SE-0413, typed throws, the notion of a `do throws`
syntax for `do..catch` blocks came up. Implement that syntax and
semantics, as a way to explicitly specify the type of error that is
thrown from the `do` body in `do..catch` statement.
This peephole optimization in SILGen requires us to use the thrown
error for the context of a closure type rather than the thrown error
for the closure AST node itself.
Introduce SILGen support for reabstractions thunks that change the
error, between indirect and direct errors as well as conversions
amongst error types (e.g., from concrete to `any Error`).
The type that is caught by the `catch` clauses in a `do..catch` block is
determined by the union of the thrown error types in the `do`
statement. Compute this type and use it for the catch clauses. This
does several things at once:
* Makes the type of the implicit `error` be a more-specific concrete
type when all throwing sites throw that same type
* When there's a concrete type for the error, one can use patterns
like `.cancelled`
* Check that this error type can be rethrown in the current context
* Verify that SIL generation involving do..catch with typed errors
doesn't require any existentials.
Lower the thrown error type into the SIL function type. This requires
very little code because the thrown error type was already modeled as
a SILResultInfo, which carries type information. Note that this
lowering does not yet account for error types that need to passed
indirectly, but we will need to do so for (e.g.) using resilient error
types.
Teach a few places in SIL generation not to assume that thrown types
are always the existential error type, which primarily comes down to
ensuring that rethrow epilogues have the thrown type of the
corresponding function or closure.
Teach throw emission to implicitly box concrete thrown errors in the
error existential when needed to satisfy the throw destination. This
is a temporary solution that helps translate typed throws into untyped
throws, but it should be replaced by a better modeling within the AST
of the points at which thrown errors are converted.
If we have an uninhabited branch, emit it as an
ignored expr followed by an unreachable.
Previously we would omit the unreachable and rely
on the SILOptimizer to infer it, but we ought to
just emit it here. Also check `isUninhabited()`
instead of `isStructurallyUninhabited` since this
better matches what we allow in Sema. For tuples
of uninhabited values, we can do a regular
initialization without issue.
These allow multi-statement `if`/`switch` expression
branches that can produce a value at the end by
saying `then <expr>`. This is gated behind
`-enable-experimental-feature ThenStatements`
pending evolution discussion.
This is a futile attempt to discourage future use of getType() by
giving it a "scary" name.
We want people to use getInterfaceType() like with the other decl kinds.
`Initialization` is stateful and not meant to be emitted into multiple times across different contexts.
If emitting into an initialization causes it to be split or aborted, that will carry over into
further uses of the initialization. This was happening during `if` and `switch` expression
emission, leading to miscompiles or compiler crashes. Fix this by saving only the buffer when
we prepare emission for a statement expression, and creating the initialization in the scope
where the expression for a branch actually gets emitted. Fixes rdar://112213253.
variadic-tuple results. There are three parts to this.
First, fix the emission of indirect result parameters to do a
proper abstraction-pattern-aware traversal of tuple patterns.
There was a FIXME here and everything.
Second, fix the computation of substituted abstraction
patterns to properly handle vanishing tuples. The previous code
was recursively destructuring tuples, but only when it saw a
tuple as the substituted type, which of course breaks on vanishing
tuples.
Finally, fix the emission of returns into vanishing tuple
patterns by allowing the code to not produce a TupleInitialization
when the tuple pattern vanishes. We should always get a singleton
element initializer in this case.
Fixes rdar://109843932, plus a closely-related test case for
vanishing tuples that I added myself.
drop_deinit ultimately only affects the semantics of its
destroy_value. Avoid generating releases for destroys in which the
deinit has been dropped. Instead, individually release the members.
SE-390 concluded with choosing the keyword discard rather than forget for
the statement that disables the deinit of a noncopyable type. This commit
adds parsing support for `discard self` and adds a deprecation warning for
`_forget self`.
rdar://108859077
We haven't quite got the semantics we want implemented
for `discard` aka `_forget` statements. Allowing people
to use `_forget` in noncopyable types that have stored
properties that require destruction will not let us
implement it the way we'd like in the future without
source break. But, if the type only has "trivial" stored
properties with a no-op destruction, like `Int`, then we
can still provide utility for users like FileDescriptor
who just want to disable the deinit and have nothing
fancy stored in the type itself.
rdar://108877261
This patch replaces the stateful generation of SILScope information in
SILGenFunction with data derived from the ASTScope hierarchy, which should be
100% in sync with the scopes needed for local variables. The goal is to
eliminate the surprising effects that the stack of cleanup operations can have
on the current state of SILBuilder leading to a fully deterministic (in the
sense of: predictible by a human) association of SILDebugScopes with
SILInstructions. The patch also eliminates the need to many workarounds. There
are still some accomodations for several Sema transformation passes such as
ResultBuilders, which don't correctly update the source locations when moving
around nodes. If these were implemented as macros, this problem would disappear.
This necessary rewrite of the macro scope handling included in this patch also
adds proper support nested macro expansions.
This fixes
rdar://88274783
and either fixes or at least partially addresses the following:
rdar://89252827
rdar://105186946
rdar://105757810
rdar://105997826
rdar://105102288
As I've been iterating on this work, I've been gradually mulling these
over, and I think this is the way to go for now. These should make it
a lot less cumbersome to write these kinds of traversals correctly.
The intent is to the sunset the existing expanded-components stuff
after I do a similar pass for function parameters.
More missing infrastructure. In this case, it's really *existing*
missing infrastructure, though; we should have been imploding tuples
this way all along, given that we're doing it in the first place.
I don't like that we're doing all these extra tuple copies. I'm not
sure yet if they're just coming out of SILGen and eliminated immediately
after in practice; maybe so. Still, it should be obvious that they're
unnecessary.
This required quite a bit of infrastructure for emitting this kind of
tuple expression, although I'm not going to claim they really work yet;
in particular, I know the RValue constructor is going to try to explode
them, which it really shouldn't.
It also doesn't include the caller side of returns, for which I'll need
to teach ResultPlan to do the new abstraction-pattern walk. But that's
next.
Currently, this is staged in as `_forget`,
as part of SE-390. It can only be used on
`self` for a move-only type within a consuming
method or accessor. There are other rules, see
Sema for the details.
A `forget self` really just consumes self and
performs memberwise destruction of its data.
Thus, the current expansion of this statement
just reuses what we inject into the end of a
deinit.
Parsing of `forget` is "contextual".
By contextual I mean that we do lookahead to
the next token and see if it's identifier-like.
If so, then we parse it as the `forget` statement.
Otherwise, we parse it as though "forget" is an
identifier as part of some expression.
This way, we won't introduce a source break for
people who wrote code that calls a forget
function.
This should make it seamless to change it from
`_forget` to `forget` in the future.
resolves rdar://105795731
Introduce SingleValueStmtExpr, which allows the
embedding of a statement in an expression context.
This then allows us to parse and type-check `if`
and `switch` statements as expressions, gated
behind the `IfSwitchExpression` experimental
feature for now. In the future,
SingleValueStmtExpr could also be used for e.g
`do` expressions.
For now, only single expression branches are
supported for producing a value from an
`if`/`switch` expression, and each branch is
type-checked independently. A multi-statement
branch may only appear if it ends with a `throw`,
and it may not `break`, `continue`, or `return`.
The placement of `if`/`switch` expressions is also
currently limited by a syntactic use diagnostic.
Currently they're only allowed in bindings,
assignments, throws, and returns. But this could
be lifted in the future if desired.
Instead of asking SILGen to build calls to `makeIterator` and
`$generator.next()`, let's synthesize and type-check them
together with the rest of for-in preamble. This greatly simplifies
interaction between Sema and SILGen for for-in statements.
Instead of short-circuiting out of emitBlockStmt if the SIL insertion point
has become unreachable (because, for instance, all paths through the function
have returned), iterate through the remaining elements and process
non-PatternBindingDecl declarations, to ensure that local functions and types
get emitted. Fixes rdar://87039628.
The use of the term 'uninhabited' does not make sense outside of formal type theoretic contexts. In Swift, we also do not use this term in a standard way - hence the term "structurally uninhabited" since we only consider products and sums eligible for the check. (Aside: We do not do exponentials because... well, Swift's type system implements Harper's "typerec" operator and as a consequence parametricity is just _not a thing_). I digress...
So, improve upon the old diagnostic in two ways:
1) Do away with 'uninhabited' - instead, mention that it's either an enum or a tuple with an enum in it that 'has no cases'
2) Since the SIL parameter convention flattens all tuples, point directly at the offending uninhabited element type
rdar://83600669
This fixes an ambiguity (that leads to a crash further down the pipeline) when
compiling optional unwrap bindings that bind the same variable name.
rdar://73490741
(cherry picked from commit 173c0b4657)
Literal closures are only ever directly referenced in the context of the expression they're written in,
so it's wasteful to emit them at their fully-substituted calling convention and then reabstract them if
they're passed directly to a generic function. Avoid this by saving the abstraction pattern of the context
before emitting the closure, and then lowering its main entry point's calling convention at that
level of abstraction. Generalize some of the prolog/epilog code to handle converting arguments and returns
to the correct representation for a different abstraction level.
Literal closures are only ever directly referenced in the context of the expression they're written in,
so it's wasteful to emit them at their fully-substituted calling convention and then reabstract them if
they're passed directly to a generic function. Avoid this by saving the abstraction pattern of the context
before emitting the closure, and then lowering its main entry point's calling convention at that
level of abstraction. Generalize some of the prolog/epilog code to handle converting arguments and returns
to the correct representation for a different abstraction level.
Literal closures are only ever directly referenced in the context of the expression they're written in,
so it's wasteful to emit them at their fully-substituted calling convention and then reabstract them if
they're passed directly to a generic function. Avoid this by saving the abstraction pattern of the context
before emitting the closure, and then lowering its main entry point's calling convention at that
level of abstraction. Generalize some of the prolog/epilog code to handle converting arguments and returns
to the correct representation for a different abstraction level.
emit those auxiliary decls inside the function body brace statement.
This generalizes the old code to work for parameters to any kind of
function (e.g. initializers).
We were just ignoring types here, but local functions don't matter. In
fact, if a local decl survives to SILGen, we only really care if it
carries some expression or statement itself - so pattern bindings are
the real stars here.
Re-resolves rdar://76269551 and SR-14449
Tasks shouldn't normally hog the actor context indefinitely after making a call that's bound to
that actor, since that prevents the actor from potentially taking on other jobs it needs to
be able to address. Set up SILGen so that it saves the current executor (using a new runtime
entry point) and hops back to it after every actor call, not only ones where the caller context
is also actor-bound.
The added executor hopping here also exposed a bug in the runtime implementation while processing
DefaultActor jobs, where if an actor job returned to the processing loop having already yielded
the thread back to a generic executor, we would still attempt to make the actor give up the thread
again, corrupting its state.
rdar://71905765