Previously we prohibited unbound generics in the underlying
type of a typealias, but due to an oversight the check was
not performed when resolving a nested type.
So this worked:
struct Outer { struct Inner<T> {} }
typealias OuterInner = Outer.Inner
let _: OuterInner<Int> = Outer.Inner<Int>()
However it was easy to cause a crash this way by stating an
unbound generic type where one was not expected. Also,
unqualified types in a typealias did not get this treatment,
so the following did not work:
typealias MyOptional = Optional
Formalize the old behavior by allowing unbound generic types
in the underlying type of a typealias, while otherwise
prohibiting unbound references to nested types.
There's no need to walk up from a function or type context -- if
no generic signature (or environment) is set, the parent won't have
one, either, and if we're in the middle of validating the child
context, using the parent's signature or environment to resolve
dependent types is just wrong.
Consider this code:
struct A<T> {
struct B {}
struct C<U> {}
}
Previously:
- getDeclaredType() of 'A.B' would give 'A<T>.B'
- getDeclaredTypeInContext() of 'A.B' would give 'A<T>.B'
- getDeclaredType() of 'A.C' would give 'A<T>.C'
- getDeclaredTypeInContext() of 'A.C' would give 'A<T>.C<U>'
This was causing problems for nested generics. Now, with this change,
- getDeclaredType() of 'A.B' gives 'A.B' (*)
- getDeclaredTypeInContext() of 'A.B' gives 'A<T>.B'
- getDeclaredType() of 'A.C' gives 'A.C' (*)
- getDeclaredTypeInContext() of 'A.C' gives 'A<T>.C<U>'
(Differences marked with (*)).
Also, this change makes these accessors fully lazy. Previously,
only getDeclaredTypeInContext() and getDeclaredIterfaceType()
were lazy, whereas getDeclaredType() was built from validateDecl().
Fix a few spots where the return value wasn't being checked
properly.
These functions return ErrorType if a circularity was detected via
the generic parameter list, or if the extension did not resolve.
They return Type() if the extension cannot be resolved *yet*.
This is pretty subtle, and I'll need to do another pass over
callers of these functions at some point. Many of them should be
moved over to use getSelfInContext(), getSelfOfContext() and
getSelfInterfaceType() instead.
Finally, this patch consolidates logic for diagnosting invalid
nesting of types.
The parser had some code for protocols in bad places and bad things
inside protocols, and Sema had several different bail-outs for
bad things in protocols, nested generic types, and stuff nested
inside protocol extensions.
Combine all of these into a single set of checks in Sema. Note
that we no longer give up early if we find invalid nesting.
Leaving decls unvalidated and un-type-checked only leads to
further problems. Now that all the preliminary crap has been
fixed, we can go ahead and start validating these funny nested
decls, actually fixing some crashers in the process.