Commit Graph

370 Commits

Author SHA1 Message Date
Kavon Farvardin
31aa2f77e3 polish noncopyable types diagnostic wordings
- replaces "move-only" terminology with "noncopyable"
- replaces compiler jargon like "guaranteed parameters"
  and "lvalue" with corresponding language-level notions
- simplifies diagnostics about closures.

and probably more.

rdar://109281444
2023-05-24 20:56:36 -07:00
Erik Eckstein
85052a1489 deprecate the -experimental-performance-annotations option
Performance annotations can now be used without specifying this option
2023-05-11 08:03:19 +02:00
Kavon Farvardin
3e4bc82aa8 rename _forget to discard; deprecate _forget
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
2023-05-08 21:42:19 -07:00
Kavon Farvardin
578da4949d disallow "non-trivial" stored properties when using forget
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
2023-05-05 19:05:04 -07:00
Michael Gottesman
7e992cef6c [move-only] When emitting exclusivity diagnostics for move only types, do not suggest to the user to make a local copy.
It doesn't make sense to give this note since one can't make a copy of a
noncopyable type.

rdar://108511627
2023-04-25 10:51:04 -07:00
Michael Gottesman
76e93828ef [move-only] Make it an error if we attempt to destructure/partially invalidate through a field with a deinit.
If one has a type with a deinit, if one were to partially invalidate the value,
the checker will clean up the remaining parts of the value but not the actual
underlying value. This then would cause the deinit of the actual type to be
called.

rdar://101651138
2023-04-12 15:18:56 -07:00
Michael Gottesman
f055bdc3aa [reference-bindings] Add initial prototype of the reference binding transform pass. 2023-03-03 17:14:41 -08:00
Andrew Trick
f1ff6958a3 Merge pull request #63825 from atrick/diagnose-implicit-raw-bitwise
Warn on implicit pointer conversion from nontrivial inout values.
2023-03-02 10:57:30 -08:00
Joe Groff
ecceb02e2a Implement consume x operator with the accepted SE-0366 syntax.
Implement it as a contextual operator that only parses as an operator when
followed by an identifier.
2023-03-01 17:37:54 -08:00
Andrew Trick
bdeb58d61f Warn on implicit pointer conversion from nontrivial inout values.
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)
2023-02-27 21:51:17 -08:00
Michael Gottesman
1dd896ded9 [move-only] Implement escaping closure semantics.
NOTE: A few of the test patterns need to be made better, but this patch series
is large enough, I want to get it into tree and iterate.
2023-02-20 11:04:21 -08:00
Michael Gottesman
2c137512b0 [move-only] Add an error that is emitted if the move checker misses a copy and asks to file a bug. 2023-02-17 16:04:46 -08:00
Michael Gottesman
e58c45fa1e [move-only] Add support for ref_element_addr with AssignableButNotConsumable semantics.
rdar://104874497
2023-02-12 17:39:27 -08:00
Michael Gottesman
85ea8b5d5b [move-only] Rename CheckKind::NoImplicitCopy -> CheckKind::ConsumableAndAssignable
This fits the name of the check better. The reason I am doing this renaming is
b/c I am going to add a nonconsumable but assignable check for
global_addr/ref_element_addr/captures with var semantics.
2023-02-10 13:46:19 -08:00
Michael Gottesman
9ae7ff30dd [move-only] Wire up emission of the location for non-consuming uses for objects and emit more precise errors for consuming use errors.
Specifically, previously if we emitted an error we just dumped all of the
consuming uses. Now instead for each consuming use that needs a copy, we perform
a search for a specific boundary use (consuming or non-consuming) that is
reachable from the former and emit a specialized error for it. Thus we emit for
the two consuming case the normal consumed twice error, and now for
non-consuming errors we emit the "use after consume" error.
2023-02-04 10:43:13 -08:00
Michael Gottesman
e6ac700d75 [move-only] QoI: Fix up error notes from "{non,}consuming use" -> "{non,}consuming use here".
rdar://104926091
2023-02-01 12:05:02 -08:00
Michael Gottesman
4e86268243 [move-only] Teach the borrow to destructure transform how to handle consuming/non-consuming uses on the same instruction.
NOTE: The additional errors that are occuring in the move only object checker is
b/c I tweaked checkDestructureUsesOnBoundary so that when it detects an error it
continues instead of returns. This ensures that we get more that we emit errors
for multiple violations instead of just the first one.

rdar://104900171
2023-02-01 12:04:41 -08:00
Michael Gottesman
6f940b4c4f [move-only] Implement the borrow-gep to destructure transform.
This enables us to emit the appropriate error for consuming uses of fields and
also causes us to eliminate copies exposed by using fields of a move only type
in a non-consuming way.

rdar://103271138
2023-01-24 16:56:11 -08:00
Michael Gottesman
4901529a72 [move-only-addr] Teach move only address checker that captured vars should be treated like inout arguments.
rdar://103313357
2022-12-15 09:59:36 -08:00
Michael Gottesman
3d53d73e0a [move-only-object] Use closureCapture to emit more informative diagnostic on lets being captured in a closure.
Specifically, previously we said something along the lines of...

'x' has guaranteed ownership but was consumed

even for lets. This is pretty misleading. Using @closureCapture, we can now emit
a much better diagnostic:

'x' consumed in closure. This is illegal since if the closure is invoked more than once the binding will be uninitialized on later invocations.

I am also going to use this technique to emit a similar diagnostic for vars that
are captured by a closure. It will be slightly different since vars will behave
like inout parameters.
2022-12-15 09:59:35 -08:00
Michael Gottesman
0735f9f0bb [move-only] Teach SILGen that lets captured by a closure must be no copy.
The current diagnostic that we are emitting is not perfect, but at least this
prevents us from saying that an error is not occuring here. I am going to file a
bug to track the QoI work of improving the diagnostic.

rdar://103313305
2022-12-14 10:57:34 -08:00
Michael Gottesman
361aa81d6d [move-only-address] Now that we borrow move only types when we call functions, enable the main move only address transform.
The main constraint that we needed to fight here is that we are not allowed in
the move only address checker to expand exclusivity scopes since we run after
the main exclusivity passes. This means that to enable this transformation I
needed to add a new error diagnostic that is emitted if we are unable to convert
a loadCopyOrTake operation to a borrow like operation due to an exclusivity
scope that is too tight. Example:

```
%0 = begin_access [read] %addr
%1 = load [copy] %0
end_access %0
...
destroy_value %1
```

Luckily this does not actually happen for move only structs/move only enums
after 525ba8c07b which makes it so that we perform
a true borrow of those types when passing them to functions. If we pass a move
only class directly, we get the same behavior. Sadly if we pass a field from a
move only class, we still get a tight exclusivity scope and thus will emit an
error today. This is an issue that we can fight at a later time once we decide
to productize move only classes further. But at least structs/enums work
well. One can see this behavior by looking at all of the places that needed to
be updated as a result of this change.

rdar://102491093
2022-11-17 16:25:12 -08:00
Michael Gottesman
0a16cc362a [move-only] Implement an initial version of the move only address checker.
Some notes:

1. I added support for both loadable/address only types.

2. These tests are based off of porting the move only object tests for inout,
vars, mutating self, etc.

3. I did not include already written tests for address only types in this
specific merge since I need to change us to borrow move only var like types.
Without that, we get a lot of spurious error msgs and the burden of writing that
is not worth it. So instead in a forthcoming commit where I fix that issue in
SILGen, I will commit the corresponding address only tests for this work.

4. I did not include support for trivial types in this. I am going to do
object/address for that at the same time.
2022-09-11 18:57:32 -07:00
Michael Gottesman
f1182a73da [no-implicit-copy] Remove auto +1 param signature change called by noimplicit copy in favor of following normal convention.
I also added a bunch of tests for both the trivial/non-trivial case as well as
some docs to SIL.rst.
2022-07-19 16:39:03 -07:00
Michael Gottesman
79042f1cec [no-implicit-copy] Emit an error diagnostic if we find a mark_must_check [no_implicit_copy] we don't know how to check.
We do the same thing already with the move function. If someone is using this
functionality and the compiler fails, we don't want to succeed the compilation
since the user is relying on the compiler for safety!
2022-06-30 22:22:27 -07:00
Josh Soref
81d3ad76ac Spelling ast (#42463)
* spelling: accessor

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: accommodates

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: argument

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: associated

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: availability

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: available

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: belongs

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: bookkeeping

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: building

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: clazz

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: clonable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: closure

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: concatenated

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: conformance

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: context

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: conversion

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: correspondence

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: declarations

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: declared

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: defining

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: delayed

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: dependency

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: deployed

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: descendants

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: diagnose

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: diagnostic

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: equitable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: evaluation

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: exclusivity

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: existence

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: existential

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: explicit

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: expressed

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: for

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: foreign

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: function

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: identifier

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: implicit

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: indices

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: information

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: instance

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: interchangeable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: interface

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: introduced

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: invalid

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: kind-in

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: least

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: library

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: location

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: namespace

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: necessary

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: nonexistent

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: not

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: number

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: obtains

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: occurs

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: opaque

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: overridden

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: parameter

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: precede

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: preceding

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: property

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: protocol

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: qualified

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: recognized

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: recursively

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: references

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: relaxing

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: represented

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: request

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: requirement

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: requirements

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: retrieve

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: returned

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: satisfied

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: satisfy

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: scanner

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: siblings

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: simplified

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: something

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: source

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: specializations

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: specially

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: statement

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: stripped

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: structure

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: substitution

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: the

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: transform

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: transformed

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: transitively

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: transparent

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: typecheck

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: unknown

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: unlabeled

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: unqualified

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: whether

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: with

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: scanner

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
2022-04-21 12:57:16 -07:00
Kavon Farvardin
13cbe0dd15 adding the @_compilerInitialized attribute
This attribute is designed for let-bound variables whose initializing
assignment is synthesized by the compiler. This assignment is
expected to happen at some point before DefiniteInitialization has
run, which is the pass that verifies whether the compiler truly
initialized the variable.

I generally expect that this will never be a user-facing feature, and
that the synthesized assignment happens in SILGen.
2022-03-24 16:18:49 -07:00
Kavon Farvardin
4f28b87de9 basic implementation of flow-isolation for SE-327
Flow-isolation is a diagnostic SIL pass that finds
unsafe accesses to properties in initializers and
deinitializers that cannot gain isolation to otherwise
protect those accesses from concurrent modifications.
See SE-327 for more details about how and why it exists.

This commit includes changes and features like:

- The removal of the escaping-use restriction
- Flow-isolation that works properly with `defer` statements
- Flow-isolation with an emphasis on helpful diagnostics.

It also includes known issues like:

- Local / nonescaping functions are not analyzed by
  flow-isolation, despite it being technically possible.
  The main challenge in supporting it efficiently is that
  such functions do not have a single exit-point, like
  a `defer`. In particular, arbitrary functions can throw
  so there are points where nonisolation should _not_ flow
  out of the function at a call-site in the initializer, etc.

- The implementation of the flow-isolation pass is not
  particularly memory efficient; it relies on BitDataflow
  even though the particular flow problem is simple.
  So, a more efficient implementation would be specialized for
  this particular problem, etc.

There are also some changes to the Swift language itself: defer
will respect its context when deciding its property access kind.

Previously, a defer in an initializer would always access a stored
property through its accessor methods, instead of doing so directly
like its enclosing function might. This inconsistency is unfortunate,
so for Swift 6+ we make this consistent. For Swift 5, only a defer
in a function that is a member of the following kinds of types
will gain this consistency:

- an actor type
- any nominal type that is actor-isolated, excluding UnsafeGlobalActor.

These types are still rather new, so there is much less of a chance of
breaking expected behaviors around defer. In particular, the danger is
that users are relying on the behavior of defer triggering a property
observer within an init or deinit, when it would not be triggering it
without the defer.
2022-02-02 13:31:14 -07:00
Michael Gottesman
f3801c2453 Fix diagnostic to use proper grammar. 2021-12-06 12:47:31 -08:00
Michael Gottesman
b22d68a6dd [move-function] Tweak the we do not support using move error. 2021-12-03 12:12:13 -08:00
Michael Gottesman
97b19206e2 [moveOnly] Emit an error diagnostic if a user applies _move to a value that the compiler doesn't know how to check (non-let, non-param today).
The error diagnostic tells the user that the compiler can't check the value. It
then instructs the user to make a feature request and provide the test case if
they think it is reasonable. I also provided an option to disable the diagnostic
to unblock people.

The reason why I think this is the right thing to do is we want people to know
that _move means they do not need to worry about the given binding being used
later in the program in some way without having to reason. For now I am doing
this by banning _move on non-lets, non-params. This is implemented by noting
that:

1. _move inserts move_value [allows_diagnostics].
2. The checker always removes [allows_diagnostics] after checking a _move.

Thus we know after we check, any move_value that is still marked with
[allows_diagnostic], it was a _move that we never used in any checking.

I added some test cases where this known triggers. I am either going to
implement some sort of support for performing _move on them or give a more
specific diagnostic. This is just an initial incremental step.
2021-11-06 01:26:43 -07:00
swift-ci
65f09cce9d Merge pull request #39708 from kavon/actor-init-fixes 2021-11-05 15:52:33 -07:00
Kavon Farvardin
2d69bc8a39 respect nonisolated on an async actor initializer
Previously, we were ignoring the explicit `nonisolated`
attribute on an actor initializer. This only has a
noticable effect if the initializer is `async`: an actor
hop is being emitted even though isolation was explicitly
not requested.

While we internally treat the isolation of an unadorned
actor initializer as if it were `nonisolated`, if the
programmer explicitly requests it, then it should be honored
in an async init too. Thus, this patch tells definite initialization
to skip the insertion of the hop, instead treating a `nonisolated`
initializer as though it has the escaping-use restriction.

resolves rdar://84164173
2021-11-04 19:04:13 -07:00
Michael Gottesman
4aa4ac3027 [moveOnly] Add checker that validates that if a let/param copyable value has _move applied to it, the let doesn't have any later uses.
This is just an initial prototype for people to play with. It is as always
behind the -enable-experimental-move-only flag.

NOTE: In this PR I implemented this only for 'local let' like things (local
lets/params). I did not implement in this PR support for local var and haven't
done anything with class ivars or globals.

rdar://83957028
2021-11-04 17:13:29 -07:00
Michael Gottesman
f9122a79b7 [moveOnly] Implement a new _copy function that performs an explicit copy value.
The key thing is that the move checker will not consider the explicit copy value
to be a copy_value that can be rewritten, ensuring that any uses of the result
of the explicit copy_value (consuming or other wise) are not checked.

Similar to the _move operator I recently introduced, this is a transparent
function so we can perform one level of specialization and thus at least be
generic over all concrete types.
2021-10-29 15:37:46 -07:00
eeckstein
d5ae51130d Merge pull request #39902 from eeckstein/performance-annotations
First prototype of Performance Annotations
2021-10-29 07:39:41 +02:00
Michael Gottesman
e5d0f386e4 [moveOnly] Add a new experimental move only checker that checks noImplicitCopy variables.
NOTE: This is only available when the flag -enable-experimental-move-only. There
are no effects when the flag is disabled.

The way that this works is that it takes advantage of the following changes to
SILGen emission:

* When SILGen initializes a let with NoImplicitCopyAttribute, SILGen now emits
a begin_borrow [lexical] + copy + move_only. This is a pattern that we can check
and know that we are processing a move only value. When performing move
checking, we check move_only as a move only value and that it isn't consumed
multiple times.

* The first point works well for emitting all diagnostics except for
initializing an additional let var. To work around that I changed let
initialization to always bind to an owned value to a move of that owned
value. There is no semantic difference since that value is going to be consumed
by the binding operation anyways so we effectively just move the cleanup from
the original value we wanted to bind to the move. We still then actually borrow
the new let value with a begin_borrow [lexical] for the new let value. This
ensures that an initialization of a let value appears to be a consuming use to
the move only value checker while ensuring that the value has a proper
begin_borrow [lexical].

Some notes on functionality:

1. This attribute can only be applied to local 'let'.

2. "print" due to how we call it today with a vararg array is treated as a
   consuming use (unfortunately).

3. I have not added the builtin copy operator yet, but I recently added a _move
   skeleton attribute so one can end the lifetimes of these values early.

4. This supports all types that are not address only types (similar to
   _move). To support full on address only types we need opaque values.

rdar://83957088
2021-10-28 11:32:22 -07:00
Erik Eckstein
9f8b155c6c PerformanceDiagnostics: a pass to print errors for performance violations in annotated functions.
The PerformanceDiagnostics pass issues performance diagnostics for functions which are annotated with performance annotations, like @_noLocks, @_noAllocation.
This is done recursively for all functions which are called from performance-annotated functions.

rdar://83882635
2021-10-28 18:44:46 +02:00
Michael Gottesman
114789707c [moveOnly] Implement a semi-generic _move function that can be used on non-generic, non-existential values.
This patch introduces a new stdlib function called _move:

```Swift
  @_alwaysEmitIntoClient
  @_transparent
  @_semantics("lifetimemanagement.move")
  public func _move<T>(_ value: __owned T) -> T {
  #if $ExperimentalMoveOnly
    Builtin.move(value)
  #else
    value
  #endif
  }
```

It is a first attempt at creating a "move" function for Swift, albeit a skleton
one since we do not yet perform the "no use after move" analysis. But this at
leasts gets the skeleton into place so we can built the analysis on top of it
and churn tree in a manageable way. Thus in its current incarnation, all it does
is take in an __owned +1 parameter and returns it after moving it through
Builtin.move.

Given that we want to use an OSSA based analysis for our "no use after move"
analysis and we do not have opaque values yet, we can not supporting moving
generic values since they are address only. This has stymied us in the past from
creating this function. With the implementation in this PR via a bit of
cleverness, we are now able to support this as a generic function over all
concrete types by being a little clever.

The trick is that when we transparent inline _move (to get the builtin), we
perform one level of specialization causing the inlined Builtin.move to be of a
loadable type. If after transparent inlining, we inline builtin "move" into a
context where it is still address only, we emit a diagnostic telling the user
that they applied move to a generic or existential and that this is not yet
supported.

The reason why we are taking this approach is that we wish to use this to
implement a new (as yet unwritten) diagnostic pass that verifies that _move
(even for non-trivial copyable values) ends the lifetime of the value. This will
ensure that one can write the following code to reliably end the lifetime of a
let binding in Swift:

```Swift
  let x = Klass()
  let _ = _move(x)
  // hypotheticalUse(x)
```

Without the diagnostic pass, if one were to write another hypothetical use of x
after the _move, the compiler would copy x to at least hypotheticalUse(x)
meaning the lifetime of x would not end at the _move, =><=.

So to implement this diagnostic pass, we want to use the OSSA infrastructure and
that only works on objects! So how do we square this circle: by taking advantage
of the mandatory SIL optimzier pipeline! Specifically we take advantage of the
following:

1. Mandatory Inlining and Predictable Dead Allocation Elimination run before any
   of the move only diagnostic passes that we run.

2. Mandatory Inlining is able to specialize a callee a single level when it
   inlines code. One can take advantage of this to even at -Onone to
   monomorphosize code.

and then note that _move is such a simple function that predictable dead
allocation elimination is able to without issue eliminate the extra alloc_stack
that appear in the caller after inlining without issue. So we (as the tests
show) get SIL that for concrete types looks exactly like we just had run a
move_value for that specific type as an object since we promote away the
stores/loads in favor of object operations when we eliminate the allocation.

In order to prevent any issue with this being used in a context where multiple
specializations may occur, I made the inliner emit a diagnostic if it inlines
_move into a function that applies it to an address only value. The diagnostic
is emitted at the source location where the function call occurs so it is easy
to find, e.x.:

```
func addressOnlyMove<T>(t: T) -> T {
    _move(t) // expected-error {{move() used on a generic or existential value}}
}

moveonly_builtin_generic_failure.swift:12:5: error: move() used on a generic or existential value
    _move(t)
    ^
```

To eliminate any potential ABI impact, if someone calls _move in a way that
causes it to be used in a context where the transparent inliner will not inline
it, I taught IRGen that Builtin.move is equivalent to a take from src -> dst and
marked _move as always emit into client (AEIC). I also took advantage of the
feature flag I added in the previous commit in order to prevent any cond_fails
from exposing Builtin.move in the stdlib. If one does not pass in the flag
-enable-experimental-move-only then the function just returns the value without
calling Builtin.move, so we are safe.

rdar://83957028
2021-10-27 19:36:49 -07:00
Robert Widmann
5bbd126179 Redo The Notes For "Uninhabited" Parameter Types
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
2021-09-27 20:17:28 -07:00
Konrad `ktoso` Malawski
703595e396 [Concurrent] Warnings/errors should use "sendable" not "concurrent"
Resolves rdar://83416205
2021-09-23 12:45:07 +09:00
Doug Gregor
3d91fd1a6c Use a remark, rather than a disembodied note, for constant evaluator 2021-08-16 12:08:56 -07:00
Kavon Farvardin
3e4cad1d57 add a note about using actor convenience inits
This is a follow-up to the changes that restrict
uses of 'self' in certain actor initializers, to
guide people to using the convenience inits for
now.
2021-06-24 17:57:40 -07:00
Kavon Farvardin
f722ccdcdd restrict uses of 'self' in certain actor initializers
A uniqueness rule for 'self' is enforced throughout
the following types of actor initializers:

1. synchronous
2. global-actor isolated

This means that 'self' cannot be used for anything,
even after 'self' is fully initialized, other than
for access to stored properties. Method calls are
considered escaping uses of 'self', since it is passed
implicitly to the method of computed property when invoked.

Also, an actor's convenience init now treats self as
nonisolated.

This provides a way to perform follow-up work after
self is fully initialized, when creating the
actor from a synchronous context.

Resolves rdar://78790369
2021-06-23 14:17:00 -07:00
Luciano Almeida
ddeb1929c4 [DiagnosticQol][SR-14505] Use DeclDescriptive kind in missing return data flow diagnostics (#36952)
* [Diagnostics] Use DeclDescriptiveKind on data flow diagnostics to improve diagnostic message

* [tests] Add regression tests to SILOptimizer/return.swift

* [tests] Adapt other tests to changes of SR-14505

* [Diagnostics] Adapt message for missing return diagnostics, remove article

* [Diagnostics] Adapt message for missing return diagnostics to have a note with fix

* [tests] Adjust tests in validation suit
2021-04-20 08:16:32 -03:00
Erik Eckstein
dccaa8f01f diagnose duplicated @_cdecl and @_silgen_name function names
Prints a regular error instead of crashing.
The check is done in SILGen, because it's simple. We could also do it earlier, but I don't see a strong reason for this.

rdar://75950093
2021-03-31 13:30:22 +02:00
Slava Pestov
b6381d4549 Sema: Ban forward references of captured values from 'defer' body
While 'defer' is implemented as a local function, it doesn't
behave as one. In particular, since SILGen runs it after
destroying all local bindings that appear after the 'defer'
definition, the body of a 'defer' cannot forward reference
captured bindings the way that local functions can.

Note that I had to remove a SILGen test case for an older,
related issue. The new diagnostic in Sema catches these cases
earlier.

Fixes rdar://problem/75088379.
2021-03-15 17:17:30 -04:00
Erik Eckstein
a17f8c2f3f SILOptimizer: add a diagnostics pass to warn about lifetime issues with weak references.
The DiagnoseLifetimeIssuesPass pass prints a warning if an object is stored to a weak property (or is weakly captured) and destroyed before the property (or captured reference) is ever used again.
This can happen if the programmer relies on the lexical scope to keep an object alive, but copy-propagation can shrink the object's lifetime to its last use.
For example:

  func test() {
    let k = Klass()
      // k is deallocated immediately after the closure capture (a store_weak).
      functionWithClosure({ [weak k] in
                            // crash!
                            k!.foo()
                          })
    }

Unfortunately this pass can only catch simple cases, but it's better than nothing.

rdar://73910632
2021-02-15 11:11:35 +01:00
Richard Wei
18fe723543 Merge pull request #35811 from rxwei/69980056-differentiable-reverse
[AutoDiff] Add '@differentiable(reverse)'.
2021-02-08 04:32:27 -08:00
Richard Wei
af8942d940 [AutoDiff] Rename '@differentiable' to '@differentiable(reverse)'.
Compiler:
- Add `Forward` and `Reverse` to `DifferentiabilityKind`.
- Expand `DifferentiabilityMask` in `ExtInfo` to 3 bits so that it now holds all 4 cases of `DifferentiabilityKind`.
- Parse `@differentiable(reverse)` and `@differentiable(_forward)` declaration attributes and type attributes.
- Emit a warning for `@differentiable` without `reverse`.
- Emit an error for `@differentiable(_forward)`.
- Rename `@differentiable(linear)` to `@differentiable(_linear)`.
- Make `@differentiable(reverse)` type lowering go through today's `@differentiable` code path. We will specialize it to reverse-mode in a follow-up patch.

ABI:
- Add `Forward` and `Reverse` to `FunctionMetadataDifferentiabilityKind`.
- Extend `TargetFunctionTypeFlags` by 1 bit to store the highest bit of differentiability kind (linear). Note that there is a 2-bit gap in `DifferentiabilityMask` which is reserved for `AsyncMask` and `ConcurrentMask`; `AsyncMask` is ABI-stable so we cannot change that.

_Differentiation module:
- Replace all occurrences of `@differentiable` with `@differentiable(reverse)`.
- Delete `_transpose(of:)`.

Resolves rdar://69980056.
2021-02-07 14:09:46 -08:00