Queries through the GenericSignatureBuilder about a particular type
parameter only really need information about the equivalence class in which that type parameter resides. Introduce a new entry point
GenericSignatureBuilder::resolveEquivalenceClass() that only
For now, resolveEquivalanceClass() is a thin layer over
resolveArchetype().
Introduce support for writing a GraphViz graph describing the
same-type constraints within an equivalence class. This visualization
helps debugging the minimization algorithm.
LLVM's GraphWriter is actually kinda awful, so there is some hackery
here both to dodge an overzealous static assertion and to munge the
output into an undirected graph.
NFC except for debugging.
Reimplement isSelfDerivedSource() in terms of
getMinimalConformanceSource(), because they're fundamentally the same
thing. Also, replace the custom removeSelfDerived() implementation
within checkConformanceConstraints() by improving the common
checkConformanceConstraints() and teaching it to work on top of
getMinimalConformanceSource().
There is some hackery in here to make getMinimalConformanceSource()
behave like the now-removed isSelfDerivedSource(). It's all marked
with FIXMEs while I sort out the general form of "self-derived" for
same-type constraints. It's not as easy as I had hoped ;)
When we detect that a requirement source is self-derived, identify the
redundant subpath and remove it to produce a new, smaller requirement
source that computes the same result. We were doing this form the
limited case where the redundant subpath ended at the end of the
requirement source; generalize that notion.
Fixes SR-5601.
When a potential archetype refers to a concrete (non-associated) type
declaration, we bind to that concrete type. Add a new requirement
source kind for this case that is always derived, separating it from
the nested-type-name-match source.
One important aspect of this is that typealiases in protocols that
"override" an associated type an inherited protocol will generate the
same requirement signature as the equivalent protocol that uses a
same-type constraint, making the suppression of the "hey, this is
equivalent to a same-type constraint now!" warning an ABI-preserving
change.
With this, remove a now-unnecessary hack for nested-name-match
requirement sources.
Detect requirement sources that are internally self-derived for
(e.g.) handling of requirement sources for same-type constraints and
superclass constraints. This eliminates some incorrect warnings about
redundant same-type constraints involving recursive protocols, which
(more importantly) were a symptom of incorrect generic signature
minimization.
Fixes SR-5473.
More correctly fix SR-5485: we were retaining self-derived conformance
sources when we shouldn't, which led to spurious "redundant
conformance" diagnostics and (much worse) incorrect minimized generic
signatures. Now, when we detect a self-derived conformance source,
return the minimal source that will derive the same conformance... and
retain that one if it's new.
processDelayedRequirements() was putting reprocessed-but-still-unresolved
requirements directly into the global delayed-requirements queue,
which meant that they didn't benefit from the optimization of putting
delayed requirements into the appropriate equivalence class.
Revise the meaning of UnresolvedHandlingKind::ReturnUnresolved (and
change its name to GenerateUnresolved) to still generate the
unresolved constraint, but notify the caller that it remained
unresolved. That way, we can track what happens when reprocessing
requirements (the statistics are *really* useful), but we still get
the optimization from putting delayed requirements onto the
equivalence class that can resolve them.
With this change, type checking the standard library is now only 1%
slower with ``enable-recursive-constraints`.
When a requirement is delayed, we know the equivalence class that
would have to change to make the requirement potentially
resolvable. Record the delayed requirement on that equivalence class.
When an equivalence class is modified for any reason, move all of the
delayed requirements to the global delayed-requirements queue so
they'll be reprocessed. This cuts the number of
reprocessed-but-still-unresolved requirements in half when
type-checking the standard library, taking us from 4x slower to 3x
slower.
Replace the overly-general bumpGeneration() with a "modified()"
operation on EquivalenceClass, indicating that the given
EquivalenceClass has been modified in some way. There are no
modifications in the system that do not directly affect an equivalence
class.
When we fail to resolve a particular type to a potential archetype,
track which equivalence class would have to change for the resolution
of that type to succeed. For now, this is "just" more bookkeeping.
When determining whether a conformance requirement source is
self-derived, ignore the top-level "Self: P" requirement in a
requirement signature.
Fixes SR-5485 / rdar://problem/33360699.
Whenever we need a complete, well-formed potential archetype,
reprocess any delayed requirements, so that we pick up additional
requirements on that potential archetype.
This relies on us tracking a generation count for the GSB instance as
a whole, which gets bumped each time we add some new requirement or
create a new potential archetype, and only actually reprocessing
delayed requirements when the generation count exceeds the point at
which we last processed delayed requirements.
This gets the most basic recursive protocol constraint working
end-to-end and doesn't seem to break things.
Inheritance of a protocol from JavaScriptCore's JSExport protocol is
used to indicate that the methods and properties of that protocol
should be exported to JavaScript. The actual check to determine
whether a protocol (directly) inherits JSExport is performed via the
Objective-C runtime. Note that the presence of JSExport in the
protocol hierarchy is not sufficient; the protocol must directly
inherit JSExport.
Swift warns about redundant conformance requirements and eliminates
them from the requirement signature (and, therefore, the Objective-C
metadata). This behavior is incorrect for JSExport, because the
conformance is actually needed for this API to work properly.
Recognize a protocol's inheritance JSExport specifically (by
name) when computing the requirement signature of the protocol. When
we find such a redundancy, suppress the "redundant conformance
constraint" diagnostic and add a new (hidden) attribute
@_restatedObjCConformance(proto). The attribute is used only by Objective-C
protocol metadata emission to ensure that we get the expected metadata
in the Objective-C runtime.
Fixes rdar://problem/32674145.
This method returns an empty Type if the conformance is currently
being checked. The other caller of this method in the
GenericSignatureBuilder checked the return value and bailed out,
but one place did not.
This is probably not the right long-term fix, but it matches what
the other caller of getTypeWitness() does in this file.
I don't have a reduced test case either; the repro involves
building a specific revision of the standard library with a patch
applied. However, the fix can't really do any harm, since passing
an empty Type here quickly crashes.
Fixes <rdar://problem/32296747>, <https://bugs.swift.org/browse/SR-4945>.
This reverts commit afbdbae9d9.
Commit ded45a6e1c more than triples the
type checking time when building Swift.o, so I am going to revert that ,
and it looks like this needs to be reverted as well if that commit is
reverted.
Whenever we need a complete, well-formed potential archetype,
reprocess any delayed requirements, so that we pick up additional
requirements on that potential archetype.
This relies on us tracking a generation count for the GSB instance as
a whole, which gets bumped each time we add some new requirement or
create a new potential archetype, and only actually reprocessing
delayed requirements when the generation count exceeds the point at
which we last processed delayed requirements.
This gets the most basic recursive protocol constraint working
end-to-end and doesn't seem to break things.
Introduce `-enable-recursive-constraints` to disable the error about
direct recursion within a protocol definition. The implementation of
recursive protocol constraints is incomplete, but might be useful for
experimentation.
If we encounter an associated type reference within a concrete type, but
haven't seen a specific protocol requirement, add the protocol
conformance.
Fixes rdar://problem/33139928 and another crasher.
Use ArchetypeResolutionKind::CompleteWellFormed whenever we need to
ask questions about the potential archetype, and
ArchetypeResolutionKind::WellFormed when we need only evaluate whether
there is a legitimate type with that name (and possibly get a handle
to it).
All of this is dead code now that we don't use
ArchetypeResolutionKind::AlwaysPartial and, therefore, cannot ever
produce an unresolved potential archetype.
The small-but-significant change to the generic signature builder is
to refuse to create unresolved potential archetypes. Instead, delay
any requirement that depends on such type, to be reprocessed once
we've seen all of the other requirements. If the type can be resolved
later, it will be; Otherwise, the type checker will complain when it
sees an unresolvable type. By itself, this fixes the crash in SR-2796.
Doing this by itself regresses diagnostics because typo correction in
the generic signature builder no longer kicks in. Therefore, implement
typo correction for these cases in the type checker proper, using its
existing facilities for typo correction. The result is more consistent
code with a better result.
Fixes SR-2796 / rdar://problem/28544316.
Rather than pretend that the requirement signature of a protocol is a
full, well-formed generic signature that one can meaningfully query,
treat it as a flat set of requirements. Nearly all clients already did
this, but make it official. NFC
PotentiallArchetype::getNestedType(Identifier...) was using
ArchetypeResolutionKind::AlwaysPartial, even though only one client
(the code that itself handles AlwaysPartial) needed it. Add an
ArchetypeResolutionKind parameter to pass through, updating clients
accordingly.
Eliminates 5 effective uses of AlwaysPartial. Only two left!
We don't need to force the creation of potential archetypes when
finding anchors, because new potential archetypes will only be created
by this process in ill-formed generic signatures. Tolerate failure
whenever this happens (for now) and the failure paths will become dead
once AlwaysPartial is eliminated fully.
When we merge equivalence classes (by choosing a new representative),
we already prefer the potential archetype with the shorter nesting
depth. However, barring that, we were preferring the potential
archetype that is a better archetype anchor. At one point we depended
on this, but now it's an extra cost that has the side effect of
building more potential archetypes than we really need at this stage.
Eliminate the compareDependentTypes() check when merging equivalence
classes. The intent is that we only need to form archetype anchors
when enumerating requirements or canonicalizing---not during the
normal "solving" path of the GSB.
When a concrete requirement is invalid due to the concrete type
lacking a conformance to a particular, required protocol, don't emit
that incorrect requirement---it causes invalid states further down the
line.
Fixes SR-5014 / rdar://problem/32402482.
While here, fix a comment that Huon noticed trailed off into oblivion.
When we see two type(aliase)s with the same name in a protocol
hierarchy, make them equal with an implied same-type requirement. This
detects inconstencies in typealiases across different protocols, and
eliminates the need for ad hoc consistency checking. This is a step
toward simplifying away the need for direct-diagnosis operations
involving concrete type mismatches.
While here, warn when we see an associated type with the same as a
typealias from an inherited protocol; in this case, the associated
type is basically useless, because it's going to be equivalent to the
typealias.
When two potential archetypes are merged and only one of them was a
concrete type beforehand, concretize the nested types in the
equivalence class of the non-concrete potential archetype. Otherwise,
we're liable to miss redundancies.
This feels like an ad hoc extension to an ad hoc mechanism, but gets
us back to parity with this patch series.