Rather than hardcoding all of the substitution logic for requirements
in the RequirementEnvironment constructor, harden and re-use the
GenericSignatureBuilder's substitution logic instead.
When a requirement mentions a concrete type, that type might utter
other types (e.g., Set<T>) that infer requirements (here, T:
Hashable). Perform requirement inference for such types.
Part of rdar://problem/31520386.
There were various problems with layout constraints either
being ignored or handled incorrectly. Now that I've exercised
this support with an upcoming patch, there are some fixes
here.
Also, introduce a new ExistentialLayout::getLayoutConstriant()
which returns a value for existentials which are class-constrained
but don't have a superclass or any class-constrained protocols;
an example would be AnyObject, or AnyObject & P for some
non-class protocol P.
NFC for now, since these layout-constrained existentials cannot
be constructed yet.
Add a 'hasExplicitAnyObject()' bit to ProtocolCompositionType
to represent canonical composition types containing '& AnyObject'.
Serialize this bit and take it into account when building
ExistentialLayouts.
Rename ProtocolCompositionType::getProtocols() to getMembers()
since it can contain classes now, and update a few usages that
need further attention with FIXMEs or asserts.
For now, nothing actually constructs these types, and they will
trigger arounds asserts. Upcoming patches will introduce support
for this.
We were putting conformance requirements on the representative of the
equivalence class, rather than directly on the potential archetype on
which the conformance requirement was specified. This violates the
invariant used when forming protocol-requirement sources that we never
reseat a requirement onto the representative (which would
have become a problem when implementing recursive protocol
constreaints) as well as masking a GSB idempotency issue that comes
from same-type requirements where the right-hand side was not
guaranteed to refer to the archetype anchor *within* that subcomponent.
Rather than true (an error occurred) or false (the constraint was
resolved), introduce ConstraintResult to better model what
happened. NFC for now, but the intent here is to report unresolved
constraints through this mechanism.
The dependent type that is the subject of a ProtocolRequirement
source is independently computable based on the root potential
archetype of the source and the potential archetype to which the
requirement applies, i.e., it's just the dependent member type that
gets from the former to the later. Compute this directly, rather than
relying on the passed-down dependent type.
This is possible now because we no longer capriciously rebase
requirements onto the representatives of equivalence classes, nor
destroy any other structural information in the formation of potential
archetypes.
As we've done with layout requirements, introduce a new entry point
(addTypeRequirement) that handles unresolved type requirements of the
form `T: U`, resolves the types, and then can
1. Diagnose any immediate problems with the types,
2. Delay the type requirement if one of the types cannot be resolved,
or
3. Break it into one or more "direct" requirements.
This allows us to clean up and centralize a bunch of checking that was
scattered/duplicated across the GSB and type checker.
When we resolve() a type that is being used in a constraint, allow
that resolution to fail. If it does fail, then record the constraint
we were trying to address (via a stub that, currently, just drops it)
and continue on. NFC for now; this is intended to allow us to limit
the explosion of types in recursive systems.
We want to validate both type in same-type or conformance constraints,
even when the first type is ill-formed, so we don't leave null types
around for later phases to crash on.
Fixes rdar://problem/31093854.
When enumerating same-type-to-concrete requirements, don't emit a
same-type-to-concrete requirement for a nested archetype anchor when
it's parent also is equivalent to a concrete type, because the former
can always be derived from the latter.
Fixes SR-4456 / rdar://problem/31286125.
When a nested type is within the same equivalence class as its parent,
don't emit a redundant same-type-to-concrete constraint for the
corresponding potential archetype. The nested type's constraint will
be derived from the parent... which is technically a self-derived
constraint, yet needs to be suppressed.
Generic signature canonicalization/minimization never removes type
parameters, so we cannot suppress type-parameter-to-concrete
requirements even when they are derived.
Fixes the rest of the known cases of rdar://problem/30478915.
The general self-derived check doesn't really make sense for
conformance constraints, because we want to distinguish among
different protocol conformances.
This PR addresses TODOs from #8241.
- It supports merging for layout constraints, e.g., if both a _Trivial constraint and a _Trivial(64) constraint appear on a type parameter, we keep only _Trivial(64) as a more specific layout constraint. We do a similar thing for ref-counted/native-ref-counted. The overall idea is to keep the more specific of two compatible layout constraints.
- The presence of a superclass constraint implies a layout constraint, e.g., a superclass constraint implies _Class or _NativeClass
Diagnose redundant same-type constraints using most of the same
machinery for diagnosing other redundant constraints. However,
same-type constraints are particularly interesting because
redundancies can be spelled in a number of different ways. Address
this using the connected components of the subgraph involving only
derived requirements (which is already used for the minimized generic
signature). Then, separate all of the non-derived requirements into
the intracomponent requirements and intercomponent requirements:
* All of the intracomponent requirements are redundant by definition,
because the components are defined by derived constraints.
* For the intercomponent requirements, form a spanning tree among the
various components and diagnose as redundant any edges that do not
extend the spanning tree.
It's better to compute this information once while we're sorting
through all of the same-type constraints, so we can use it later when
performing queries (e.g., enumerating requirements).
We were emitting a superclass constraint for each connected component
of derived same-type constraints within an equivalence class, when in
fact we only need one superclass constraint for the entire equivalence
class.
We were emitting a superclass constraint for each connected component
of derived same-type constraints within an equivalence class, when in
fact we only need one superclass constraint for the entire equivalence
class.
As we've done with all of the other kinds of constraints, keep track
of all of the layout constraints on the equivalence class. Use the
normal mechanism to diagnose conflicts between different layout
constraints, warn about duplicate layout constraints, etc.
As we've been doing with other kinds of constraints, track *all* of
the requirement sources for deriving same-type constraints within the
equivalence class, then remove self-derived constraints at the end.
There is no checking for duplicated same-type constraints yet.