Nested types with inverse requirements on generic parameters would
sometimes print incorrectly. We only print the inverses on outer generic
parameters for extensions.
fixes rdar://123281976
When a NoncopyableGenericsMismatch happens between the compiler and
stdlib, allow the compiler to rebuild the stdlib from its interface
instead of exiting with an error.
Requirement lowering only expects that it won't see two requirements
of the same kind (except for conformance requirements). So only mark
those as conflicting.
This addresses a crash-on-invalid and improves diagnostics for
move-only generics, because a conflict won't drop the copyability
of a generic parameter and expose a move-only-naive user to
confusing error messages.
Fixes#61031.
Fixes#63997.
Fixes rdar://problem/111991454.
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.
We weren't diagnosing conflicts in PCT's like `Copyable & ~Copyable`,
instead deferring until that PCT was constrained to something like the
existential Self or a generic parameter, which then we'd diagnose.
But we should canonicalize PCT's such as `Copyable & Copyable` into
`Any`, which represents the empty composition. That's what the assert in
PCT::build is about.
These tests were not updated in the transition to
`REQUIRES: noncopyable_generics` and thus running them with a
correctly-built stdlib that has the Copyable requirements.
We want extensions to introduce default Copyable/Escapable just like
other generic contexts, so that once Optional adopts ~Copyable,
an `extension Optional` actually adds `Wrapped: Copyable` by default.
This problem was introduced in 2017 by commit bbaa7f7163.
If a protocol requirement has multiple potential witnesses, and one
of those witnesses only introduces tautological type witness bindings,
we would be forced to choose among the remaining witnesses.
However, this did not account for the possibility that the
tautological witness is the correct choice; it's possible that we
will infer the same type witnesses via a different protocol
requirement.
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.
It should be the responsibility of callers to map the type to a
contextual type, as needed. When it's not possible or repetitive to do
so, there is a special-purpose function `isInterfaceTypeNoncopyable` for
Sema.
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.
Workaround for rdar://119950540 when dealing with invertible protocols.
This should be sound because "its an invariant that subst() on a
conformance returns the same thing as a global lookup with subst() of
the conforming type, assuming you don't have overlapping conformances."
Follow the feature flag convention for capitalization and be
consistent with the related NoncopyableGenerics feature.
This is a new feature that no wild Swift code has used it yet:
commit e99ce1cc5d
Author: Kavon Farvardin <kfarvardin@apple.com>
Date: Tue Dec 5 23:25:09 2023
[NCGenerics] add `~Escapable`
Basic implementation of `~Escapable` in the type system.
We already need to track the inverses separate from the members in a
ProtocolCompositionType, since inverses aren't real types. Thus, the
only purpose being served by InverseType is to be eliminated by
RequirementLowering when it appears in a conformance requirement.
Instead, we introduce separate type InverseRequirement just to keep
track of which inverses we encounter to facilitate cancelling-out
defaults and ensuring that the inverses are respected after running
the RequirementMachine.
Much like when the type defines a deinit, if the nominal's declaration
is marked with ~Copyable, that prevents conformance to Copyable.
This meant that when trying to auto-derive Copyable conformance, we'll
skip types marked with ~Copyable. But now, we'll also reject
explicitly-requested conformances to Copyable because of that marking
too.
In reality right now, all marker protocols have conformances that are
always trivally checked and marked "complete", so when I refer to
rejecting a conformance here, I mean raising a diagnostic while checking
for validity.
A value type like a struct or enum cannot conform to Copyable if it has
a deinit. When NoncopyableGenerics is enabled, we make that part of what
is required to verify that such a nominal type conforms to Copyable.
This change also does some refactoring to share common code to point out
how to make a type noncopyable.
For containment issues, where an unconditionally or conditionally
Copyable type contains a fixed noncopyable element, remind users about
the conditional conformance in addition to the fix-it to add ~Copyable