More groundwork for protocols with superclass constraints.
In several places we need to distinguish between existential
types that have a superclass term (MyClass & Proto) and
existential types containing a protocol with a superclass
constraint.
This is similar to how I can write 'AnyObject & Proto', or
write 'Proto1 & Proto2' where Proto1 has an ': AnyObject'
in its inheritance clause.
Note that some of the usages will be revisited later as
I do more refactoring and testing. This is just a first pass.
Several kinds of declarations can override other declarations, but the
computation and storage for these “overridden” declarations was scattered in
at least 3 different places, with different resolution paths. Pull them
all together into two bits of LazySemanticInfo in ValueDecl (“have we computed
overrides?” and “are there any overrides?”), with a side table for the
actual list of overrides.
One side effect here is that the AST can now represent multiple overridden
declarations, although only associated type declarations track this
information.
Start using LazyResolver::resolveOverriddenDecl() more consistently, unifying
it with the separate path we had for associated type overrides. All of this
is staging for a move to the request-evaluator for overridden declaration
computation.
As a debugging aid, introduce a new frontend flag `-debug-cycles` that
will emit a debug dump whenever the request-evaluator encounters a cyclic
dependency, while otherwise allowing compilation to continue.
The type checker has *lots* cycles, and producing diagnostics for them
at this point in the development of the request-evaluator is not
productive because it breaks currently-working code. Disable cycle
diagnostics for now when using the request-evaluator in the type
checker. We'll enable it later as things improve, or as a separate
logging mode in the interim.
Wire up the request-evaluator with an instance in ASTContext, and
introduce two request kinds: one to retrieve the superclass of a class
declaration, and one to compute the type of an entry in the
inheritance clause.
Teach ClassDecl::getSuperclass() to go through the request-evaluator,
centralizing the logic to compute and extract the superclass
type.
Fixes the crasher from rdar://problem/26498438.
Introduce some metaprogramming of accessors and generally prepare
for storing less-structured accessor lists.
NFC except for a change to the serialization format.
- De-templatize the intrinsic candidate search functions.
- Allow callback predicates access to the candidate's function type so they can evalute its parameters/return value themselves.
SubstitutionMaps are now just a trivial pointer-sized value, so
pass them by value instead.
I did have to move a couple of functors from Type.h to SubstitutionMap.h
to resolve some issues with forward declarations.
That is, if there's a problem with a witness, and the witness comes
from a different extension from the conformance (or the original type,
when the conformance is on an extension), put the main diagnostic on
the conformance, with a note on the witness. This involves some
shuffling and rephrasing of existing diagnostics too.
There's a few reasons for this change:
- More context. It may not be obvious why a declaration in file
A.swift needs to be marked 'public' if you can't see the conformance
in B.swift.
- Better locations for imported declarations. If you're checking a
conformance in a source file but the witness came from an imported
module, it's better to put the diagnostic on the part you have
control over. (This is especially true in Xcode, which can't display
diagnostics on imported declarations in the source editor.)
- Plays better with batch mode. Without this change, you can have
diagnostics being reported in file A.swift that are tied to a
conformance declared in file B.swift. Of course the contents of
A.swift also affect the diagnostic, but compiling A.swift on its
own wouldn't produce the diagnostic, and so putting it there is
problematic.
The change does in some cases make for a worse user experience,
though; if you just want to apply the changes and move on, the main
diagnostic isn't in the "right place". It's the note that has the info
and possible fix-it. It's also a slightly more complicated
implementation.
When building a substitution map, the client is only responsible for filling
in the replacement types for canonical generic parameters; the others
(e.g., those for generic parameters for which there is a same-type
constraint) can be filled in lazily. Profiling them leads to incorrect
uniquing of SubstitutionMap.
Fixes the rest of rdar://problem/39949332.
Now that SubstitutionMap is used in so many places, reduce it's header
dependencies by moving SubstitutionMap::Storage into its own separate
implementation header. Use forward declarations of other entities
(GenericSignature, Substitution) instead.
Good for build times and general sanity.
This can't arise from a clean build, but it can happen if you have
products lingering in a search path and then either rebuild one of
the modules in the cycle, or change the search paths.
The way this is implemented is for each module to track whether its
imports have all been resolved. If, when loading a module, one of its
dependencies hasn't resolved all of its imports yet, then we know
there's a cycle.
This doesn't produce the best diagnostics, but it's hard to get into
this state in the first place, so that's probably okay.
https://bugs.swift.org/browse/SR-7483
Convert NameAliasType’s internal representation from tail-allocating an
array of Substitutions (to be treated as a SubstitutionList) to store a
single SubstitutionMap. Serialize using that SubstitutionMap.
Prepare for SubstitutionMaps to be stored in other AST nodes by making
them ASTContext-allocated and uniqued (via a FoldingSet). They are now
cheap to copy and have trivial destructors.
This removes the default implementation of hash(into:), and replaces it with automatic synthesis built into the compiler. Hashable can now be implemented by defining either hashValue or hash(into:) -- the compiler supplies the missing half automatically, in all cases.
To determine which hash(into:) implementation to generate, the synthesizer resolves hashValue -- if it finds a synthesized definition for it, then the generated hash(into:) body implements hashing from scratch, feeding components into the hasher. Otherwise, the body implements hash(into:) in terms of hashValue.
With the previous changes, validating a property while
type checking its initializer is no longer a fatal error.
This means we don't have to do anything special when
validating typo correction candidates, so we can get rid
of the TypoCorrectionResolver. This means there is now
only one subclass of LazyResolver, the TypeChecker itself.