Commit Graph

384 Commits

Author SHA1 Message Date
Joe Groff
da813458a6 SILGen: Emit an addressable representation for immutable bindings on demand.
To ensure that dependent values have a persistent-enough memory representation
to point into, when an immutable binding is referenced as an addressable
argument to a call, have SILGen retroactively emit a stack allocation and
materialization that covers the binding's scope.
2025-03-12 18:35:42 -07:00
Michael Gottesman
f6349aaf1e Revert "SILGen: Emit an addressable representation for immutable bindings on demand."
This reverts commit 19a99ea42b.

rdar://146864906
2025-03-12 13:24:33 -07:00
Joe Groff
2df3211690 Merge pull request #79903 from jckarter/addressable-representation-silgen
SILGen: Emit an addressable representation for immutable bindings on demand.
2025-03-12 08:02:05 -07:00
Joe Groff
19a99ea42b SILGen: Emit an addressable representation for immutable bindings on demand.
To ensure that dependent values have a persistent-enough memory representation
to point into, when an immutable binding is referenced as an addressable
argument to a call, have SILGen retroactively emit a stack allocation and
materialization that covers the binding's scope.
2025-03-11 15:15:48 -07:00
Rintaro Ishizaki
5eac58e1e0 [AST] SwitchStmt only hold CaseStmt
Now that there is no way SwitchStmt to hold AST nodes other than
CaseStmt.
2025-03-08 09:14:40 -08:00
Doug Gregor
8bb5bbedbc Implement an unsafe expression to cover uses of unsafe constructs
Introduce an `unsafe` expression akin to `try` and `await` that notes
that there are unsafe constructs in the expression to the right-hand
side. Extend the effects checker to also check for unsafety along with
throwing and async operations. This will result in diagnostics like
the following:

    10 |   func sum() -> Int {
    11 |     withUnsafeBufferPointer { buffer in
    12 |       let value = buffer[0]
       |                   |     `- note: reference to unsafe subscript 'subscript(_:)'
       |                   |- warning: expression uses unsafe constructs but is not marked with 'unsafe'
       |                   `- note: reference to parameter 'buffer' involves unsafe type 'UnsafeBufferPointer<Int>'
    13 |       tryWithP(X())
    14 |       return fastAdd(buffer.baseAddress, buffer.count)

These will come with a Fix-It that inserts `unsafe` into the proper
place. There's also a warning that appears when `unsafe` doesn't cover
any unsafe code, making it easier to clean up extraneous `unsafe`.

This approach requires that `@unsafe` be present on any declaration
that involves unsafe constructs within its signature. Outside of the
signature, the `unsafe` expression is used to identify unsafe code.
2025-01-10 10:39:14 -08:00
Nate Chandler
da71271d8f [CoroutineAccessors] Synthesize default req impls.
When a protocol which has a read (or modify) requirement is built with
the CoroutineAccessors feature, it gains a read2 (or modify2,
respectively) requirement.  For this to be compatible with binaries
built without the feature, a default implementation for these new
requirements must be provided.  Cause these new accessor requirements to
have default implementations by returning `true` from
`doesAccessorHaveBody` when the context is a `ProtocolDecl` and the
relevant availability check passes.
2024-11-07 16:47:09 -08:00
nate-chandler
ba8f8ea282 Merge pull request #76526 from nate-chandler/general-coro/20240906/1
[CoroutineAccessors] Initial framing.
2024-09-30 07:04:04 -07:00
Hamish Knight
91ae5d6345 [AST] NFC: Rename getArgumentInterfaceType -> getPayloadInterfaceType
IMO this is a slightly clearer name, many of its
uses already use the term "payload".
2024-09-29 17:05:14 +01:00
Nate Chandler
091368ba21 [CoroutineAccessors] Added read.
The name is a placeholder for the mutating single-yield coroutine
accessor.
2024-09-26 18:10:39 -07:00
Nate Chandler
98a2e6a7df [CoroutineAccessors] Added modify.
The name is a placeholder for the mutating single-yield coroutine
accessor.
2024-09-26 18:10:39 -07:00
Slava Pestov
1901862afc AST: Remove LookUpConformanceInSignature 2024-07-06 12:05:46 -04:00
Slava Pestov
fae01d9776 AST: Remove ModuleDecl parameter from more places 2024-07-06 12:05:46 -04:00
Tim Kientzle
1098054291 Merge branch 'main' into tbkka-assertions2 2024-06-18 17:52:00 -07:00
Joe Groff
e3fef32a9b SILGen: Don't use diagnoseUnexpectedEnumCase intrinsic for noncopyable enums.
It should be impossible to reach an unexpected case statically while using
noncopyable enums, and the intrinsic has not been updated to remove its
`Copyable` requirement. Emit a plain trap in cases where this code emission
path might still occur, such as when a redundant but incomplete set of case
patterns follow a wildcard pattern. Fixes rdar://130037881.
2024-06-17 14:29:56 -10:00
Tim Kientzle
1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Joe Groff
44483be120 SILGen: Diagnose unsupported shared case blocks for noncopyable switch subjects.
This isn't fully implemented yet so it would crash eventually, so instead of
letting the compiler crash put up a proper diagnostic indicating this isn't
yet implemented. rdar://129034189
2024-05-31 09:50:26 -07:00
Joe Groff
91bd3e6b60 SILGen: Check whether return statement has expression before examining for compatibility.
Avoid an assertion failure when a `return` with no expression appears inside of a noncopyable
switch. Fixes rdar://127294417
2024-04-30 08:24:57 -07:00
Joe Groff
cb5f1e20ae SILGen: Provide compatibility with prior BorrowingSwitch behavior.
To avoid breaking early adopters of this feature, accept attempts to `return`
a `let` binding in a noncopyable `switch` when it would be treated as a
borrow normally, with a warning that this behavior will change soon.
rdar://126775241
2024-04-19 15:20:31 -07:00
Joe Groff
5ad260315b Use the BorrowingSwitch implementation for all noncopyable switches.
It works well enough now that it should be an acceptable replacement for both
borrowing and consuming switches that works in more correct situations than the
previous implementation. This does however expose a few known issues that I'll
try to fix in follow ups:

- overconsumes cause verifier errors instead of raising diagnostics (rdar://125381446)
- cases with multiple pattern labels aren't yet supported (rdar://125188955)
- copyable types with the `borrowing` or `consuming` modifiers should probably use
  noncopyable pattern matching.

The `BorrowingSwitch` flag is still necessary to enable the surface-level syntax
changes (switches without `consume` and the `_borrowing` modifier, for instance).
2024-04-09 16:31:01 -07:00
Joe Groff
ba3494802a Alternative noncopyable switch design based on expression kind.
If an expression refers to noncopyable storage, then default to performing
a borrowing switch, where `let` bindings in patterns borrow out of the
matched value. If an expression refers to a temporary value or explicitly
uses the `consume` keyword, then perform a consuming switch, where
`let` bindings take ownership of corresponding parts of the matched value.
Allow `_borrowing` to still be used to explicitly bind a pattern variable
as a borrow, with no-implicit-copy semantics for copyable values.
2024-03-28 08:32:48 -07:00
Adrian Prantl
9b0c4104ef Merge pull request #72397 from Snowy1803/verifier-conflicting-debug-value-types
[SILVerifier] Add detection of conflicting debug variables
2024-03-22 11:31:05 -07:00
Nate Chandler
12c91d8dc0 [SILGen] Load trivial in consuming switch.
When emitting a consuming switch, the load of a trivial payload must be
trivial.

rdar://125182396
2024-03-21 11:51:17 -07:00
Emil Pedersen
04ab38056a [DebugInfo] Remove conflicting debug info in switch
For address-only types, a temporary was emitted with the same debug variable
and same scope as the instruction it is moved to after entering a shared case,
but it would have a different type, which would create a conflict.
The better way to fix this would probably to use a different scope for both,
but the variable is moved immediately anyway.
2024-03-20 15:35:52 -07:00
Allan Shortlidge
c0c24c1c58 Merge pull request #72213 from tshortli/unknown-default-suppresses-unreachable-default-warning
SILGen/Sema: Avoid diagnosing @unknown default switch cases as unreachable
2024-03-11 10:38:33 -07:00
Allan Shortlidge
3acc0d6655 SILGen/Sema: Avoid diagnosing @unknown default switch cases as unreachable.
Suppose you have an exhaustive switch statement which matches all the cases of
a Swift enum defined in a different module named `External`:

```
import External

var e: External.SomeEnum = //...

switch e {
case .a: break
}
```

If `External` is compiled with library evolution and `SomeEnum` is not frozen,
then the compiler will warn:

```
warning: switch covers known cases, but 'SomeEnum' may have additional unknown values
```

You add an `@unknown default` to the switch to resolve this warning. Now
suppose in another build configuration, `External` is built _without_ library
evolution. The compiler will complain about the unreachability of the default
case:

```
warning: Default will never be executed
```

These contradictory compiler diagnostics encourage the developer to change the
code in a way that will cause a diagnostic in the other configuration.
Developers should have the tools to address all warning diagnostics in a
reasonable fashion and this is a case where the compiler makes that especially
difficult. Given that writing `@unknown default` instead of `default` is a very
intentional action that would be the result of addressing the library evolution
configuration, it seems reasonable to suppress the `Default will never be
executed` diagnostic.
2024-03-09 12:26:22 -08:00
Nate Chandler
7fecf6149c [NFC] SIL: Typed begin_borrow's isFixed. 2024-03-08 22:28:20 -08:00
Nate Chandler
9f6c30919b [NFC] SIL: Typed begin_borrow's isLexical. 2024-03-08 22:27:50 -08:00
Joe Groff
828abb3f75 SILGen: Forward move-only ownership through optional chains.
Allow noncopyable values to be consumed, borrowed, or mutated transitively
through optional chains.
2024-03-06 13:44:02 -08:00
Michael Gottesman
11f0ff6e32 [sil] Ensure that all SILValues have a parent function by making it so that SILUndef is uniqued at the function instead of module level.
For years, optimizer engineers have been hitting a common bug caused by passes
assuming all SILValues have a parent function only to be surprised by SILUndef.
Generally we see SILUndef not that often so we see this come up later in
testing. This patch eliminates that problem by making SILUndef uniqued at the
function level instead of the module level. This ensures that it makes sense for
SILUndef to have a parent function, eliminating this possibility since we can
define an API to get its parent function.

rdar://123484595
2024-02-27 13:14:47 -08:00
Joe Groff
161183cbc4 Merge pull request #71803 from jckarter/begin-borrow-fixed-switch-subject
SIL: Enclose switch subjects in a new begin_borrow [fixed] variant.
2024-02-22 14:45:17 -08:00
Joe Groff
d75a62ce64 SIL: Enclose switch subjects in a new begin_borrow [fixed] variant.
We want to preserve the borrow scope during switch dispatch so that move-only
checking doesn't try to analyze destructures or consumes out of it. SILGen
should mark anywhere that's a potential possibility with its own marker so that
it gets borrow checked independently.
2024-02-21 20:41:20 -08:00
Ben Barham
ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
Joe Groff
0491755de9 Consume switch subjects under an opaque sub-access.
This prevents the move-only checker from trying to analyze the bindings
as partial consumptions, which ought to be unnecessary since SILGen
will always fully consume the subject as part of forming the bindings.
2024-02-20 16:35:39 -08:00
Joe Groff
01405ba2e8 Fixes for compound payloads in borrowing switches.
Fill in a missing path for destructuring loadable elements from
address-only tuples in a borrowing context. Enclose projections in their
own separate accesses so that they are analyzed independently by the
move checker.
2024-02-19 17:37:34 -08:00
Joe Groff
0365c6abba MoveOnlyAddressUtils: Fixes for borrowing switch over address-only types.
Relax some existing pattern matches and add some unhandled instructions to the
walkers so that borrowing switches over address-only enums are properly analyzed
for incorrect consumption. Add a `[strict]` flag to `mark_unresolved_move_only_value`
to indicate a borrow access that should remain a borrow access even if the subject
is later stack-promoted from a box.
2024-02-12 20:20:50 -08:00
Joe Groff
e46168c626 SILGen: Improve handling of copyable subpatterns in borrowing switches.
A `let` binding of a copyable subpattern can create an independent variable
which should be copyable and consumable without affecting a borrowed
move-only base. In the same way that `borrowing` parameters are
no-implicit-copy, though, explicitly `_borrowing` subpatterns of
copyable type should be no-implicit-copy as well.
2024-02-07 07:21:11 -08:00
Joe Groff
2f519f42c6 SILGen: Emit borrowing switch subjects under a formal access.
Ensure that dependent accesses are properly nested when a subject isn't directly
a borrowed parameter binding.
2024-02-05 19:39:10 -08:00
Joe Groff
067f1d3f1c SILGen: Don't mark_unresolved copyable borrows from noncopyable switches 2024-01-31 20:46:01 -08:00
Joe Groff
03e2e8f476 BorrowToDestructureUtils: handle borrowing switches.
Instead of trying to convert all switches into consumes, allow a switch of a borrow
to remain as such.
2024-01-31 20:38:22 -08:00
Joe Groff
c4bdc97d9c SILGen: Separate borrow from consume phase for destructive pattern matches.
We don't want the dispatch phase of a pattern match to invalidate the subject,
because we don't define the order in which patterns are evaluated, and if a
particular match attempt fails, we need to still have an intact subject value
on hand to try a potentially arbitrary other pattern against it. For
noncopyable types, this means we have to always emit the match phase as a
borrow, including the variable bindings for a guard expression if any.
For a consuming pattern match, end the borrow scope and reproject the variable
bindings by using consuming destructuring operations on the subject in the
match block.

For now, this new code path only handles single-case-label-per-block switches
without fallthroughs.
2024-01-29 18:01:55 -08:00
Joe Groff
960938f87e SILGen: Always match noncopyable values by borrowing.
Even if the final pattern ends up consuming the value, the match itself
must be nondestructive, because any match condition could fail and cause
us to have to go back to the original aggregate. For copyable values,
we can always copy our way out of consuming operations, but we don't
have that luxury for noncopyable types, so the entire match operation
has to be done as a borrow.

For address-only enums, this requires codifying part of our tag layout
algorithm in SIL, namely that an address-only enum will never use
spare bits or other overlapping storage for the enum tag. This allows
us to assume that `unchecked_take_enum_data_addr` is safely non-side-
effecting and match an address-only noncopyable enum as a borrow.
I put TODOs to remove defensive copies from various parts of our
copyable enum codegen, as well as to have the instruction report
its memory behavior as `None` when the projection is nondestructive,
but this disturbs SILGen for existing code in ways SIL passes aren't
yet ready for, so I'll leave those as is for now.

This patch is enough to get simple examples of noncopyable enum switches
to SILGen correctly. Additional work is necessary to stage in the binding
step of the pattern match; for a consuming switch, we'll need to end
the borrow(s) and then reproject the matched components so we can
consume them moving them into the owned bindings. The move-only checker
also needs to be updated because it currently always tries to convert
a switch into a consuming operation.
2024-01-19 13:59:04 -08:00
Doug Gregor
c4e97bc783 Handle non-existential errors in do..catch blocks 2024-01-12 21:27:30 -08:00
Hamish Knight
d9f3047871 [Profiler] Fix DoCatchStmt coverage handling
The logic here previously worked by computing the
exit count by taking the parent count and
subtracting any control flow that jumped out of the
clauses. With `try` handling fixed, this no longer
works correctly, since a `try` shouldn't be
subtracted if the error is caught be one of the
catches, as that's not actually leaving the
statement. We could write the logic to determine
where a `try` is jumping to, but the logic here is
already pretty brittle, relying on being sprinkled
in various different places.

For now, let's take the more straightforward
approach and handle do-catches the same way we
handle switches, we initialize the exit counter to
0, and add on each exit count of each branch. This
lets us re-use the existing CaseStmt handling
logic. This doesn't necessarily produce the most
optimal counter expressions, but I want to replace
this all with a SILOptimizer pass anyway, which
will be able to much more easily compute optimal
counter expressions.

rdar://100470244
2023-11-16 17:28:57 +00:00
Michael Gottesman
543063ef0e [silgen] Make ManagedValue::forUnmanaged private and change users to use other more specific APIs.
I have been doing this over the past couple of days in preparation for changing
ManagedValue to specify the type of scope its cleanup is connected to.
2023-08-19 14:11:44 -07:00
Michael Gottesman
ff948f7309 [silgen] Convert even more cases of using trivial and values without ownership to use for*RValueWithoutOwnership APIs. 2023-08-15 11:04:01 -07:00
Slava Pestov
9ebb5f2e03 AST: Rename VarDecl::getType() to VarDecl::getTypeInContext()
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.
2023-08-04 14:19:25 -04:00
Evan Wilde
250082df25 [NFC] Reformat all the LLVMs
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
2023-06-27 09:03:52 -07:00
Evan Wilde
f3ff561c6f [NFC] add llvm namespace to Optional and None
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
                     bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".

I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
2023-06-27 09:03:52 -07:00
Andrew Trick
ea7b8055bc Rewrite some isPlusOne calls to isPlusOneOrTrivial.
Whenever we want to forward to a +1 value but don't need to destroy
the original memory, use isPlusOneOrTrivial.

This follows the existing naming scheme.

Fixes rdar://108001491 (SIL verification failed: Found mutating or
consuming use of an in_guaranteed parameter?!:
!ImmutableAddressUseVerifier().isMutatingOrConsuming(fArg))
2023-05-01 23:24:29 -07:00