Expressed as `__swift_attr__("~Sendable")` this acts like `: ~Sendable`
on Swift type declarations and supersedes `@_nonSendable(_assumed)`.
Resolves: rdar://140928937
Forgetting to handle DistributedActor next to Actor strikes again:
Actors are special that their conformance is implicit and needs not be
printed in swift interface files.
an actor's Actor conformance was filtered out, however the same logic
needs to be applied to DistributedActor, as otherwise there can be
redundant conformance errors when validating module interface files.
Resolves rdar://160252579
Swift warns users when they conform an imported type to an imported
protocol, because such retroactive conformances are prone to producing
conflicting conformances in multiple modules.
When a user annotates a class as SWIFT_PRIVATE_FILEID, they are
explicitly conveying that extensions in the blessed file are part of
the class's private implementation (and thus privy to elevated access),
so we should also not treat conformances in that file as retroactive.
This patch fixes that and adds a test case.
rdar://148083096
There were two problems that have been there for years:
- SubstitutionMap::lookupConformance() assumes that every concrete conformance
in the path has a root normal conformance. But calling getRootNormalConformance()
on a self conformance would assert.
- SelfProtocolConformance::getAssociatedConformance() was not implemented. While
self-conforming protocols do not have associated types, they can inherit from
other protocols, and we model this with an associated conformance requirement
having a subject type of `Self`.
Both problems were hidden by the fact that ProtocolConformanceRef::subst()
directly handled self-conforming existentials without calling into the
substitution map. But that is the wrong place for other reasons. The refactoring
in a209ff8869 exposed both of the above issues.
Fixes rdar://problem/151162470.
When defaulting to main-actor isolation, types that have synthesized
conformances (e.g., for Equatable, Hashable, Codable) were getting
nonisolated members by default. That would cause compiler errors
because the conformances themselves defaulted to main-actor isolation
when their types were.
Be careful to only mark these members as 'nonisolated' when it makes
sense, and leave them to get the isolation of their enclosing type
when the conformance might have isolation. This ensures that one can
use synthesis of these protocols along with default main-actor mode.
There is a one-off trick here to force the synthesized CodingKeys to
be nonisolated, because the CodingKey protocol requires Sendable.
We'll separately consider whether to generalize this rule.
More of rdar://150691429.
While here, fix some issues around implied isolated conformances (we
could get into an inconsistent state). Also provide an educational
note discussing isolated conformances and the kinds of errors one can
see when they are used from outside of their isolation domain.
Switch over to split caching for the conformance isolation request,
which optimizes for the common case where the conformance is
nonisolated. Also put the explicit global actor TypeExpr* in an
ASTContext side table, so we don't take a pointer's worth of storage
in every conformance.
For that side table, introduce a new "ASTContext::GlobalCache" that's
there only for side tables, so we don't have to go add get/set
operations to ASTContext and recompile the world every time we want to
add a side table like this.
Thanks, Slava!
The NormalProtocolConformance APIs for checking for an explicitly-written
isolation on a conformance were easy to get to, and the real semantic
API was buried in the type checker, leading to some unprincipled
checking. Instead, create a central ProtocolConformance::getIsolation()
to get the (semantic) actor isolation, and let that be the only place
that will access the explicitly-written global actor isolation for a
conformance. Update all call sites appropriately.
Put AvailabilityRange into its own header with very few dependencies so that it
can be included freely in other headers that need to use it as a complete type.
NFC.
We checked the wrong condition when deciding if a conformance should
be substituted or not, so we would leave behind opaque return types
in builtin and inherited conformances. This is now flagged by
SubstitutionMap::verify().
* Relax @retroactive check to allow same-package declarations
* Add package decls to the test too
* Fix tests
* Import test libraries publicly so I can use their conformances in public retroactive extensions
A conditional conformance to a protocol does not usually imply
a conformance to the protocol's inherited protocols, because
we have no way to guess what the conditional requirements
should be.
A carveout was added for 'Sendable', so that protocols could
inherit from 'Sendable' retroactively. However, the 'Sendable'
conformance would become conditional, which causes us to
reject a _second_ conditional conformance to such a protocol:
struct G<T> {}
protocol P: Sendable {}
protocol Q: Sendable {}
extension G: P where T: P {}
extension G: Q where T: Q {}
To make this work, tweak the code so that an implied conformance
has the same generic signature as the conforming type, that is,
we force it to be unconditional.
Fixes rdar://122754849
Fixes https://github.com/swiftlang/swift/issues/71544
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)
Force resolution of value witnesses and check the conformance for validity
before proceeding to witness table emission in SILGen to avoid crashing because
of unexpected errors in the AST.
Resolves rdar://123027739
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.
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.
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.
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.
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.