and lowered pack types.
The "approximate" thing is kindof a representational/testing wart.
Really, all that we care about is that we have a formal pack type
with the right shape. (We don't *really* need a formal pack type ---
we could use anything that can represent the shape --- but we seem
to be standardizing on `PackType` for that.) We could just use the
reduced shape for that, but for some reason I've been resisting that.
Not sure I have a compelling reason, though, and if we decide to
use reduced shapes, we can eliminate the approximate formal packs
stuff.
Inducing packs from tuple slices is a more permanently-useful thing.
This is all relatively nicely abstracted, which is not to say that
it didn't take an awful lot of plumbing to get it to work. The basic
problem here is inherent: we need to do component-specific setup and
teardown, and unfortunately in the current representation we have to
do that with separate loops and without any dominance relationships.
(This is the same thing preventing us from doing borrows in the
general case.) The result is that the general case of result emission
is to emit every element of the expansion into a temporary tuple
(requiring a pack loop before the call to initialize the pack), then
process those elements in the body of a second pack loop after the
call. And that's terrible enough that we really have to do the work
to try to avoid it, which makes all the APIs more complicated.
Anyway, most of the way through the basic plumbing for variadic
generics now. Next is reabstraction, I think, which I hope will
mostly mean fixing bugs in the infrastructure I've already written.
I'm not really convinced that the existing implementation here is
correct in general; it might work for the type checker's use cases,
but I don't think we can rely on not seeing opened element archetypes
from other expansions in the type we're processing here. But we can
at least tread water while offering a more convenient API.
Allow freestanding macros to be used at top-level.
- Parse top-level `#…` as `MacroExpansionDecl` when we are not in scripting mode.
- Add macro expansion decls to the source lookup cache with name-driven lazy expansion. Not supporting arbitrary name yet.
- Experimental support for script mode and brace-level declaration macro expansions: When type-checking a `MacroExpansionExpr`, assign it a substitute `MacroExpansionDecl` if the macro reference resolves to a declaration macro. This doesn’t work quite fully yet and will be enabled in a future fix.
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.
Always use `Decl::visitAuxiliaryDecls` to visit decls produced by macros, including peer macros and declaration macros. Use name-driven expansion for peer macros. Remove `MacroExpansionDecl::getRewritten()`.
Also make `ExpandMacroExpansionDeclRequest` cache the buffer ID (similar to other macros) instead of an array of decls.
Always use `Decl::visitAuxiliaryDecls` to visit decls produced by macros, including peer macros and declaration macros. Use name-driven expansion for peer macros. Remove `MacroExpansionDecl::getRewritten()`.
Also make `ExpandMacroExpansionDeclRequest` cache the buffer ID (similar to other macros) instead of an array of decls.
When an expression accessing a move-only type through a `_read`
accessor, it can only be borrowed. While a simple access like
`someClass.moveOnlyField` would get recognized in SILGen and properly
borrowed, if you did any further access off of that then you'd get an
illegal sequence involving a copy that is hard to eliminate. In
particular, if you wrote `someClass.moveOnlyField.method()` then we
would emit something like:
```
(%borrowedMO, %coro) = begin_apply #SomeClass.moveOnlyField!.read(...)
%copiedMO = copy_value %borrowedMO
end_apply %coro
= apply #MoveOnlyType.method(%copiedMO) // param is just @guaranteed
```
That's wrong, since we need to use the borrow to call the method, but
that borrow's lifetime ends at the `end_apply`.
Turns out the fix is rather subtle. The reason the access above wouldn't
work is that it did _not_ have a `LoadExpr` around it, which is what the
code in the `ArgEmitter` was expecting when doing an ad-hoc check to see
if it needs to emit as a borrow.
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
And do a first pass of auditing existing uses of the parameter specifiers to
make sure that we look at the ValueOwnership mapping in most cases instead of
individual modifiers.
Fixes a usability problem with implicit inout conversion to raw pointers.
For example, supporting this conversion turns out to be bad:
void read_void(const void *input);
func foo(data: inout Data) {
read_void(&data)
}
People understandably expect Foundation.Data to have the same sort of
implicit conversion as Array. But it does something very wrong
instead.
We could have added an an attribute to Data and other copy-on-write
containers to selectively suppress implicit conversion. But there is
no good reason to allow implicit conversion from any non-trivial
type. It is extremely dangerous, and almost always accidental. Note
that this problem becomes worse now that the compiler views imported
`char *` arguments as raw pointers. For example:
void read_char(const char *input);
var object: AnyObject = ...
read_void(&object1)
This seems like a good time to correct this old Swift 3 behavior.
Plan: Add a warning now. Convert it to an error in Swift 6 language
mode based on feedback.
Fixes rdar://97963116 (It's really easy to accidentally corrupt a Data
object with the & operator)
Previously, typechecking and SILGen would treat a function body as fragile as long as the declaration had a `@backDeployed` attribute, regardless of the platform specified by the attribute. This was overly conservative since back deployed functions are only emitted into the client on specific platforms. Now a `@backDeployed` function can reference non-`public` declarations on the platforms it is resilient on:
```
@backDeployed(before: iOS 15)
public func foo() {
#if os(iOS)
// Fragile; this code may be emitted into the client.
#else
// Resilient; this code won't ever be exposed to clients.
#endif
}
```
Resolves rdar://105298520
Some notes:
1. This ensures that if we capture them, we just capture the box by reference.
2. We are still using the old incorrect semantics for captures. I am doing this
so I can bring this up in separate easy to understand patches all of which
pass all of the moveonly tests.
3. Most of the test edits are due to small differences in error messages in
between the object and address checker.
4. I had to add a little support to the move only address checker for a small
pattern that doesn't occur with vars but do es occur for lets when we codegen
like this, specifically around enums. The pattern is we perform a load_borrow
and then copy_value and then use the result of the copy_value. Rather than fight
SILGen pattern I introduced a small canonicalization into the address checker which
transforms that pattern into a load [copy] + begin_borrow to restore the codegen
to a pattern the checker expects.
5. I left noimplicitcopy alone for now. But we should come back around and fix
it in a similar way. I just did not have time to do so.
This is the first slice of bringing up escaping closure support. The support is
based around introducing a new type of SILGen VarLoc: a VarLoc with a box and
without a value. Because the VarLoc only has a box, we have to in SILGen always
eagerly reproject out the address from the box. The reason why I am doing this
is that it makes it easy for the move checker to distinguish in between
different accesses to the box that we want to check separately. As such every
time that we open the box, we insert a mark_must_check
[assignable_but_not_consumable] on that project. If allocbox_to_stack manages to
determine that the box can be stack allocated, we eliminate all of the
mark_must_check and place a new mark_must_check [consumable_and_assignable] on
the alloc_stack. The end result is that we get the old model that we had before
and also can support escaping closures.