When setting the signature conformances in a NormalProtocolConformance,
do so progressively rather than waiting until all of them are computed.
This allows later requirements to refer to earlier conformances.
If an enum has a raw type, and a SynthesizedProtocolAttr, don't add
two duplicate conformances, since that triggers an assertion.
Instead, make sure to only add each conformance once. We cannot just
drop the SynthesizedProtocolAttr in this case, because we need to
pull the LazyConformanceLoader out of it.
In almost all other places, 'resolver' means the ASTContext's LazyResolver,
which is just an abstract base class for the TypeChecker instance to break
circularity.
But here it is something totally different, used to lazily populate
imported and deserialized conformances, not parsed conformances.
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
substitutions for calling a specialized declaration.
For full generality, this really ought to be a Witness, but the current
use cases where we're constructing calls to specialized witnesses never
need to call a generic requirement, and I'm not sure how to apply
substitutions to a Witness with a synthetic environment.
Extend SubstOptions, which controls how substitution is performed, to
allow the caller to subst() to provide a callback function that may
provide a type witness for a normal protocol conformance that is
undergoing type witness inference. In effect, it's allowing us to
provide tentative bindings for type witnesses so we can see the
effects of substitution.
SubstitutionMap::lookupConformance() would map archetypes out
of context to compute a conformance path. Do the same thing
in SubstitutionMap::lookupSubstitution().
The DenseMap of replacement types in a SubstitutionMap now
always has GenericTypeParamTypes as keys.
This simplifies some code and brings us one step closer to
a more efficient representation of SubstitutionMaps.
Enums with the ns_error_domain attribute represent codes for NSError,
which means Swift developers will expect to interact with them in
terms of Error. SE-0112 improved bridging for these enums to generate
a struct with the following form:
struct MyError: Error {
@objc enum Code: RawRepresentable {
case outOfMemory
case fileNotFound
}
var userInfo: [NSObject: AnyObject] { get }
static var outOfMemory: Code { get }
static var fileNotFound: Code { get }
}
where MyError.Code corresponds to the original MyError enum defined in
Objective-C. Until recently, both the enum and the synthesized struct
were marked as having the original enum as their "Clang node", but
that leads to problems: the struct isn't really ObjC-compatible, and
the two decls have the same USR. (The latter had already been worked
around.)
This commit changes the struct to be merely considered a synthesized
"external definition", with no associated Clang node. This meant
auditing everywhere that's looking for a Clang node and seeing which
ones applied to external definitions in general.
There is one regression in quality here: the generated struct is no
longer printed as part of the Swift interface for a header file, since
it's not actually a decl with a corresponding Clang node. The previous
change to AST printing mitigates this a little by at least indicating
that the enum has become a nested "Code" type.
Instead of just falling back to module lookup any time conformance
substitution fails, only do it in the case we know doesn't work.
This should shake out some more bugs, hopefully without causing
too much pain.
Looking up the conformance @dynamic_self C<T> : P simply returns
the normal conformance C<T> : P.
If we later apply a substitution map to the conformance to
specialize T, we would call isSpecialized() on the substituted
type, which would return false. We would then hit an assertion
because the type type @dynamic_self C<Int> is not equal to the
(erroneously unsubstituted) conformance type C<T>.
Tweak the logic slightly to avoid this.
NormalProtocolConformance has the only correct implementation of this
functionality. Instead, providing a safer getWitnessDecl() that
doesn't promise substitutions that are incorrect (and not actually
used by any clients).
A canonical conformance is defined as a conformance which:
- does not contain any non-canonical types.
- Its type and interface type should be canonical.
- Any referenced conformances should be canonical.
- Any used substitutions should be canonical as well.
A substitution is canonical if:
- its replacement type is canonical
- all of its conformances are canonical
There are a number of type witnesses that are introduced by the Clang
importer. Immediately resolve those witnesses *without* going through
the type checker, because there are cases (i.e., deserialized SIL)
where the conformance is created but there is no type checker around.
Fixes rdar://problem/30364905, rdar://problem/31053701,
rdar://problem/31565413 / SR-4565.
* Use the presence of an argument type to check for associated values
hasOnlyCasesWithoutAssociatedValues returns true for any serialized
enum declaration whether or not it has cases. This never really came
up because it's mostly relevant to Sema's proto-deriving mechanism. Fix
this by using the presence of the case's argument type instead.
* Separate checks for presence of cases and enum simplicity
Necessary because the old behavior was an artifact of the
implementation.
All of this information is recoverable from the more-general,
more-sane signature conformances, so stop
recording/serializing/deserializing all of this extra stuff.
When looking up a particular conformance in a SubstitutionMap, use the
associated generic signature to determine how to find that conformance
(via a conformance access path). Follow that conformance access path
to retrieve the desired conformance.
FIXME: There is still one failure, here
Constraints/generic_overload.swift
which appears to be because we either have the wrong generic signature
for the override case or we are looking in the wrong map.