Infer same-type requirements among same-named associated
types/typealiases within inherited protocols. This is more staging; it
doesn't really have teeth until we stop wiring together these types as
part of lookup.
Introduce a warning about redeclaring the associated types from an
inherited protocol in the protocol being checked:
* If the new declaration is an associated type, note that the
declaration could be replaced by requirements in the protocol's
where clause.
* If the new declaration is a typealias, note that it could be
replaced by a same-type constraint in the protocol's where clause.
There's a more pervasive issue here that needs further study;
essentially, we can end up with self-derived sources getting
reinjected later, and will either need to avoid that reinjection or
need to expand what this localized hack does, filtering out
self-derived constraints when we enumerate requirements.
This stops after 5 recurrences of the same associated type. It is a
gross hack and a terrible idea, here as a placeholder to prevent us
from running off the rails in ill-formed code. This will go away when
we get further along the path with recursive protocol constraints.
When we’re determining what type should be used to key a ProtocolRequirement based on the source’s potential archetype and the target’s potential archetype, use potential archetype identity (==) rather than equivalence-class membership to cover the basis case. This ensures that interesting identity relationships in the enclosing context (e.g., the current GenericSignatureBuilder) don’t cause us to compute incorrect stored types.
When computing the connected components of within an equivalence class (based on derived same-type requirements), we might need derived-via-concrete constraints to maintain connectedness of the larger graph. Therefore, delay their removal until after we’ve computed connected components.
Now that we detect recursion based on repetition within the potential
archetypes, we no longer rely on passing down "visited" sets to
detect/diagnose recursion. Remove them.
Recursive protocol conformances still aren't functional, so reinstate
some checking for recursive protocol conformances. It doesn't catch
everything that the previous version did---but we don't crash on such
cases anymore, either.
Rather than detecting recursion and bailing early, delay requirements
that would form recursive types. Note that we aren't actually
processing them later.
Teach addInheritedRequirements() to take an UnresolvedType, so the
requirements it adds can be delayed if needed. More importantly, teach
the primary caller (addConformanceRequirement) not to use
getNestedType directly; instead, form an appropriate Type and let the
type-resolution machinery handle it.
Apply the same logic used for self-derived conformance constraints,
where we drop constraints derived from concrete conformances, to the
remaining kinds of constraints covered by isSelfDerivedSource().
Reimplement isSelfDerivedSource() in terms of the new
visitPotentialArchetypesAlongPath(). Aside from being clearer and
shorter, this formulation eliminates some hackery (the direct
"NestedType" lookup) that was mostly masking a bug in
updateNestedTypeForConformance() where we created a
nested-type-name-match source with an incorrect source for the
purposes of concretizing the nested type.
Fixes SR-4458 / rdar://problem/31375569.
Factor out a core operation of RequirementSource that walks the
potential archetypes from the root to the end of the path, enumerating
each partial RequirementSource along with the potential archetype to
which it applies. Use it for getting the final archetype to which the
RequirementSource refers, as well as simplifying the self-derived
check for conformance requirements.
When an otherwise abstract conformance constraint is derived from a
concrete conformance, retain the abstract conformance by removing the
requirement source that involves the concrete conformance. This
eliminates our reliance on the concrete conformance, which is not
retained as part of the generic signature.
Fixes rdar://problem/31163470 and rdar://problem/31520386.
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.