Commit Graph

435 Commits

Author SHA1 Message Date
Slava Pestov
41df661160 AST: Use a builtin conformance for unconditional Copyable/Escapable
This generalizes what we were already doing for classes.
2024-03-07 15:07:47 -05:00
Slava Pestov
02c30d1c15 AST: Fix confusion when builtin conformance passed to registerProtocolConformance() 2024-03-07 12:24:33 -05:00
Slava Pestov
aa4a1b2b6e AST: The generic conformance of a specialized conformance is always normal 2024-03-07 12:22:33 -05:00
Slava Pestov
08ba88f71b Sema: Remove deriveConformanceForInvertible() 2024-03-07 12:20:17 -05: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
Pavel Yaskevich
6e0cfb5ac4 [AST] NonCopyableGenerics: Remove a few uses for getMarking(...).getPositive() 2024-02-16 17:55:52 -08:00
Kavon Farvardin
3a45393e17 NCGenerics: break cycle with SuperclassTypeRequest
With NoncopyableGenerics, we get a cycle involving
`SuperclassTypeRequest` with this program:

  public struct RawMarkupHeader {}
  final class RawMarkup: ManagedBuffer<RawMarkupHeader, RawMarkup> { }

Because we generally don't support the following kind of relationship:

  class Base<T: P>: P {}
  class Derived: Base<Derived> {}

This commit works around the root-cause, which is that Derived's
synthesized conformance to Copyable gets superceded by the inherited one
from Base. Instead of recording conformances in the ConformanceLookup
table at all, create builtin conformances on the fly, since classes
cannot be conditionally Copyable or Escapable.
2024-02-13 09:19:12 -08:00
Kavon Farvardin
1c2dbf4498 NCGenerics: avoid synthesizing Equatable, etc.
While certain kinds of enums synthesize Equatable, Hashable, and
RawRepresentable conformances, we can't yet permit noncopyable types to
synthesize those until we upgrade those protocols themselves to not
require `Copyable` conformers. For example, Equatable needs to be
changed in the stdlib to be `protocol Equatable: ~Copyable`, etc.

I'm deferring upgrade work until a bit later.
2024-02-07 11:05:08 -08:00
Slava Pestov
991a6de207 Merge pull request #71131 from slavapestov/conformance-checker-vs-type-witnesses-untangling
Sema: Decouple type witness resolution from the ConformanceChecker
2024-01-25 20:06:01 -05:00
Slava Pestov
979fc28461 AST: Remove ProtocolConformanceState::CheckingTypeWitnesses 2024-01-24 21:45:34 -05:00
Kavon Farvardin
c7c9d80520 [NCGenerics] fix Combine issue
The solution is to add the unconditional conformances when building the
conformance lookup table for each nominal, instead of waiting until
conformance lookup infers it.

At the moment, because the stdlib isn't being built with Copyable
conformances injected into it, we still end up needing to infer Copyable
conformances for nominals like `Int` from the stdlib when trying to test
the feature, since it loads those nominals, but they lack conformance.

That should go away once we do enable NoncopyableGenerics for the stdlib
by default, and we'll be left with only inferring the conditional
conformance in TypeCheckInvertible.
2024-01-23 22:42:38 -08:00
Kavon Farvardin
b4985f7fde [NFC] replace canBeNoncopyable
First, "can have an absence of Copyable" is a rather confusing notion,
so the query is flipped to "can be Copyable". Next, it's more robust to
ask if a conformance exists for the TypeDecl to answer that question,
rather than trying to replicate what happens within that conformance
lookup.

Also renames `TypeDecl::isEscapable` to match.
2024-01-23 22:42:38 -08:00
Doug Gregor
97ea19d191 Introduce a builtin and API for getting the local actor from a distributed one
When an actual instance of a distributed actor is on the local node, it is
has the capabilities of `Actor`. This isn't expressible directly in the type
system, because not all `DistributedActor`s are `Actor`s, nor is the
opposite true.

Instead, provide an API `DistributedActor.asLocalActor` that can only
be executed when the distributed actor is known to be local (because
this API is not itself `distributed`), and produces an existential
`any Actor` referencing that actor. The resulting existential value
carries with it a special witness table that adapts any type
conforming to the DistributedActor protocol into a type that conforms
to the Actor protocol. It is "as if" one had written something like this:

    extension DistributedActor: Actor { }

which, of course, is not permitted in the language. Nonetheless, we
lovingly craft such a witness table:

* The "type" being extended is represented as an extension context,
rather than as a type context. This hasn't been done before, all Swift
runtimes support it uniformly.

* A special witness is provided in the Distributed library to implement
the `Actor.unownedExecutor` operation. This witness back-deploys to the
Swift version were distributed actors were introduced (5.7). On Swift
5.9 runtimes (and newer), it will use
`DistributedActor.unownedExecutor` to support custom executors.

* The conformance of `Self: DistributedActor` is represented as a
conditional requirement, which gets satisfied by the witness table
that makes the type a `DistributedActor`. This makes the special
witness work.

* The witness table is *not* visible via any of the normal runtime
lookup tables, because doing so would allow any
`DistributedActor`-conforming type to conform to `Actor`, which would
break the safety model.

* The witness table is emitted on demand in any client that needs it.
In back-deployment configurations, there may be several witness tables
for the same concrete distributed actor conforming to `Actor`.
However, this duplication can only be observed under fairly extreme
circumstances (where one is opening the returned existential and
instantiating generic types with the distributed actor type as an
`Actor`, then performing dynamic type equivalence checks), and will
not be present with a new Swift runtime.

All of these tricks together mean that we need no runtime changes, and
`asLocalActor` back-deploys as far as distributed actors, allowing it's
use in `#isolation` and the async for...in loop.
2024-01-22 17:27:31 -08:00
Slava Pestov
18b34e55a9 Sema: Remove obsolete circularity break 2024-01-20 17:43:01 -05:00
Pavel Yaskevich
60badd6de3 [AST] Convert BuiltinProtocolConformance to use bitfield for its kind 2024-01-18 15:00:23 -08:00
Pavel Yaskevich
89b69930fc [AST] Convert NormalProtocolConformance to use bitfields for its aux information (state, flags etc.) 2024-01-18 15:00:12 -08:00
Pavel Yaskevich
e8b7a26eac [AST] Add a flag to indicate that the conformance is @preconcurrency 2024-01-16 11:51:42 -08:00
Nate Chandler
bac9e94a1d [BitwiseCopyable] Infer and check constraint.
When the BitwiseCopyable experimental feature is enabled, infer types to
conform to `_BitwiseCopyable`.  The `_BitwiseCopyable` inference broadly
follows the approach taken to infer `Sendable`.

(1) Special types are conformed:
- function types if trivial
- metatypes
- builtin types if trivial

(2) TheTupleType is conditionally conformed.

(3) Nominal types are conformed if:
- non-public or public+fixed-layout
- enum or struct (non-class)
- every field conforms to _BitwiseCopyable

Additionally, check that nominal types which are explicitly conformed to
`_BitwiseCopyable` satisfy the latter two conditions of (3).

For a public, non-fixed-layout type to conform to `_BitwiseCopyable`,
the user must conform the type explicitly.

Finally, verify that conformances correspond to TypeLowering's notion of
triviality to the appropriate extent:
- if a type isn't trivial, it doesn't conform to `_BitwiseCopyable`
  unless it's an archetype
- if a type is trivial, it conforms to `_BitwiseCopyable` unless some
  field in its layout doesn't conform to `_BitwiseCopyable`, which is
  only permitted under certain circumstances (the type has generic
  parameters, the type is public non-fixed-layout, the type is a
  reference but has ReferenceStorage::Unmanaged, the type is a
  ModuleType, etc.)
2024-01-15 17:08:32 -08:00
Slava Pestov
f96ab368e6 AST: Use dumpRef() instead of print() in Witness::dump() to avoid request cycles 2024-01-02 15:41:13 -05:00
Slava Pestov
026d3f0078 Merge pull request #70311 from slavapestov/type-witness-system-inference-stdlib
Get the standard library to build with -enable-experimental-associated-type-inference
2023-12-10 17:50:33 -05:00
Kavon Farvardin
e99ce1cc5d [NCGenerics] add ~Escapable
Basic implementation of `~Escapable` in the type system.

rdar://119216918
2023-12-10 01:25:43 -08:00
Slava Pestov
335d6ffea1 Frontend: Add -disable-experimental-associated-type-inference flag 2023-12-08 13:39:10 -05:00
Slava Pestov
e29c3a90aa AST: Lazily populate associated conformances with -enable-experimental-associated-type-inference 2023-12-07 19:27:59 -05:00
Kavon Farvardin
a9c64baaa3 [Sema] refactor TypeDecl::isNoncopyable
In preparation for reporting whether the inverse marking on a TypeDecl
was inferred instead of explicit.
2023-11-06 15:40:12 -08:00
Harlan Haskins
4ac34a40ea @retroactive conformance syntax and checking (#36068) 2023-10-20 14:27:03 -07:00
Kavon Farvardin
d5f2d54ca7 [Sema] initial overhaul of isNoncopyable
This implementation has the function execute a request to scan the
inheritance clause of non-protocol nominals for a `~Copyable`. For
protocols, we look in the requirement signature.

This isn't our final state, as the GenericEnvironment needs to be
queried in general to determine of a Type is noncopyable. So for now
checking for a `~Copyable` only makes sense for Decls.
2023-10-18 13:45:50 -07:00
Kavon Farvardin
148897ac1a [nfc] refactor ValueDecl::isMoveOnly
I've renamed the method to `TypeDecl::isNoncopyable`, because the query
doesn't make sense for many other kinds of `ValueDecl`'s beyond the
`TypeDecl`'s. In fact, it looks like no one was relying on that anyway.

Thus, we now have a distinction where in Sema, you ask whether
a `Type` or `TypeDecl` is "Noncopyable". But within SIL, we still
preserve the notion of "move-only" since there is additionally the
move-only type wrapper for types that otherwise support copying.
2023-10-18 13:45:50 -07:00
Slava Pestov
3b91173e71 AST: Factor out guts of finishSignatureConformances() into a new AssociatedConformanceRequest 2023-10-11 15:04:09 -04:00
Slava Pestov
28d1455373 AST: Re-implement associated conformance storage in preparation for AssociatedConformanceRequest 2023-10-11 15:04:09 -04:00
Slava Pestov
c0637b101b AST: Add NormalProtocolConformance::AssociatedConformances 2023-10-11 15:04:09 -04:00
Slava Pestov
d51442247a AST: Add HasComputedAssociatedConformancesFlag to NormalProtocolConformance 2023-10-11 15:04:09 -04:00
Slava Pestov
ab7c85387e AST: Re-implement getAssociatedConformance() using forEachAssociatedConformance() 2023-10-11 15:04:09 -04:00
Slava Pestov
c07d5b5609 AST: Fix caching policy in SpecializedProtocolConformance::getTypeWitnessAndDecl()
The substituted witness type may depend on a tentative type witness
indirectly. In this case, we would incorrectly cache the result.

The outcome was that associated type inference would fail because
the first attempted witness would "lock in" a cached substituted
witness in some other specialized conformance.
2023-10-11 15:03:03 -04:00
Slava Pestov
9c2557dcc3 AST: Unwrap one-element tuple conformances 2023-09-08 15:56:30 -04:00
Slava Pestov
eefa409656 AST: Change return type of ProtocolConformance::subst() to ProtocolConformanceRef 2023-09-08 15:56:30 -04:00
Doug Gregor
b7bfaf3522 [Macros] Fix handling of extension macro conformances and witnesses
Fix two inter-related issues with extension macros that provide
conformances to a protocol, the combined effect of which is that one
cannot meaningfully provide extension macros that implement
conformances to a protocol like Equatable or Hashable that also
supports auto-synthesis.

The first issue involves name lookup of operators provided by macro
expansions. The logic for performing qualified lookup in addition to
unqualified lookup (for operators) did not account for extension
macros in the same manner as it did for member macros, so we would not
find a macro-produced operator (such as operator==) in witness
matching.

The second issue is more fundamental, which is that the conformance
lookup table would create `NormalProtocolConformance` instances for
pre-macro-expansion conformance entries, even though these should
always have been superseded by explicit conformances within the macro
expansion buffers. The end result is that we could end up with two
`NormalProtocolConformance` records for the same conformance. Some
code was taught to ignore the pre-expansion placeholder conformances,
other code was not. Instead, we now refuse to create a
`NormalProtocolConformance` for the pre-expansion entries, and remove
all of the special-case checks for this, so we always using the
superseding explicit conformances produced by the macro expansions (or
error if the macros don't produce them).

Fixes rdar://113994346 / https://github.com/apple/swift/issues/66348
2023-08-16 19:18:36 -07:00
Slava Pestov
f219274e9b AST: Remove generic signature and conditional requirements from BuiltinProtocolConformance 2023-08-09 17:42:57 -04:00
Slava Pestov
1b8e9a2964 SIL: Fixes for tuple conformances 2023-08-09 17:42:25 -04:00
Holly Borla
0bd898eb12 [Macros] Allow extension macros to suppress conformances that are already
stated in the original source.

If an extension macro can introduce protocol conformances, macro expansion
will check which of those protocols already have a stated conformance in the
original source. The protocols that don't will be passed as arguments to
extension macro expansion, indicating to the macro that it should only add
conformances to those protocols.
2023-06-30 16:01:15 -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
John McCall
80551ce8ad [NFC] Thread a common type through all the AST substitution code.
There are a lot of problems caused by our highly-abstract substitution
subsystem.  Most of them would be solved by a more semantic / holistic
understanding of the active transformation, but that's difficult to do
because we just pass around function_refs.  The first step in fixing
that is to pass around a better currency type.  For now, it can just
hold the function_refs (and the SubstOptions).

I've set it up so that the places that just apply SubstitutionMaps
are constructing the IFS in a standard way; that should make it easy
to change those places in the future.
2023-03-25 18:54:14 -04:00
Slava Pestov
a355c38a34 AST: Rename ProtocolConformance::getSubstitutions() to getSubstitutionMap() and remove ModuleDecl parameter 2023-03-21 16:16:34 -04:00
Kavon Farvardin
091d63a5c8 revise how the Copyable constraint is added
The _Copyable constraint was implemented as a marker protocol.
That protocol is part of the KnownProtocol's in the compiler.
When `ASTContext::getProtocol(KnownProtocolKind kind)` tries
to find the ProtocolDecl for Copyable, it will look in the
stdlib module (i.e., Swift module), which is where I initially
planned to put it.

That created problems initially when some regression tests
use `-parse-stdlib` failed to do that protocol lookup, which is
essential for adding the constraint (given the current implementation).

That led to believe we need to pull Copyable out of the stdlib, but that's
wrong. In fact, when building the Swift module itself, we do `-parse-stdlib`
but we also include `-module-name Swift`. This causes the _Copyable protocol
defined in the Stdlib to be correctly discovered while building the stdlib
itself (see the test case in this commit). So, the only downside of
having the Copyable protocol in the Stdlib is that `-parse-stdlib` tests
in the compiler can't use move-only types correctly, as they'll be
allowed in generic contexts. No real program would build like this.

Until I have time to do a further refactoring, this is an acceptable trade-off.

fixes rdar://104898230
2023-03-04 11:42:09 -08:00
Kavon Farvardin
60d9e614f2 prevent more synthesized conformances for move-only types
enums with only cases that have no associated values
automatically get Equatable and Hashable synthesized.

That's not valid for move-only enums, so we were
just getting errors about broken conformances when
we hadn't specified any explicitly.

This PR just prevents the synthesis from the start
so we don't get any errors.

fixes rdar://104986597
2023-02-10 10:02:43 -08:00
Kavon Farvardin
66ac9bb592 slight tweak to how implicit conformance of nominals is generated
Also, only generate those conformances when the move-only feature is on,
for now.
2023-02-01 23:38:28 -08:00
Kavon Farvardin
18b1389542 [nfc] improve some comments 2023-02-01 23:38:28 -08:00
Kavon Farvardin
ab130883a3 Initial ban of move-only types from being used generically
Since values of generic type are currently assumed to always
support copying, we need to prevent move-only types from
being substituted for generic type parameters.

This approach leans on a `_Copyable` marker protocol to which
all generic type parameters implicitly must conform.

A few other changes in this initial implementation:

- Now every concrete type that can conform to Copyable will do so. This fixes issues with conforming to a protocol that requires Copyable.
- Narrowly ban writing a concrete type `[T]` when `T` is move-only.
2023-02-01 23:38:28 -08:00
zoecarver
1a0e1adee1 [cxx-interop] Don't synthesize conformance to invalid protocols. 2022-12-06 14:25:37 -08:00
zoecarver
665d3e1db4 [cxx-interop] Add diagnostics for explicit protocol conformance on the C++ side. 2022-12-02 10:04:48 -08:00
zoecarver
5eb7c7a6cf [cxx-interop] Add ability to specify protocol conformance on C++ side. 2022-11-30 17:26:15 -07:00