Save two pointers of storage in IterableDeclContext (a base class of
nominal type and extension declarations) by storing the lazy member
loader + context data in an ASTContext side table. It also makes it
easier to add more lazy context information later on.
Extensions cannot capture generic parameters from outer contexts.
Their generic parameter list does not point to the outer
parameter list, the signature does not contain outer parameters
and they do not appear in the extension's generic environment.
Furthermore, the depth/index of the extension's parameters may
clash with outer parameters, which would break all kinds of
invariants.
This patch changes these DeclContext methods to return false or
nullptr even if an extension is contained in a generic context:
- isGenericContext()
- getGenericParamsOfContext()
- getGenericSignatureOfContext()
- getGenericEnvironmentOfContext()
This method gets the GenericTypeDecl for a typealias, nominal type, or
extension thereof. While the result is typed as GenericTypeDecl, it's
not always generic, so rename it accordingly.
An audit of the callers illustrated that they should be using
different entrypoints anyway, so fix all of the callers and make this
function private.
DeclContext's nomenclature around "type contexts" is confusing,
because it essentially means "nominal type contexts", e.g.,
struct/class/enum/protocol and extensions thereof. This implies the
presence of a 'Self' type, the ability to have members, etc.
However, typealiases are also currently classified as "type
contexts", despite not having a reasonable 'Self' type, which breaks
in various places. Stop classifying typealiases as "type contexts".
After recent changes, this asserts on all decls that are not VarDecls,
so we can just enforce that statically now. Interestingly, this turns
up some dead code which would have asserted immediately if called.
Also, replace AnyFunctionRef::getType() with
AnyFunctionRef::getInterfaceType(), since the old
AnyFunctionRef::getType() would just assert when called on
a Decl.
A pointless use of polymorphism -- the result values are not
interchangeable in any practical sense:
- For GenericTypeParamDecls, this returned getDeclaredInterfaceType(),
which is an interface type.
- For AssociatedTypeDecls, this returned the sugared AssociatedTypeType,
which desugars to an archetype.
- For TypeAliasDecls, this returned TypeAliasDecl::getAliasType(),
which desugars to a type containing archetypes.
- For NominalTypeDecls, this returned NominalTypeDecl::getDeclaredType(),
which is the unbound generic type, a special case used for inferring
generic arguments when they're not written in source.
Fixes rdar://problem/29413845, a bug where we would mistakenly flag `@inline(__always)` nested functions as "fragile" even if they appeared nested inside private, internal, or nonfragile public contexts.
1. Add new AccessScope type that just wraps a plain DeclContext.
2. Propagate it into all uses of "ValueDecl::getFormalAccessScope".
3. Turn all operations that combine access scopes into methods on AccessScope.
4. Add the "private" flag to distinguish "private" from "fileprivate"
scope for top-level DeclContext.
In most places where we were checking "is<ErrorType>()", we now mean
"any error occurred". The few exceptions are in associated type
inference, code completion, and expression diagnostics, where we might
still work with partial errors.
There's a bit of a hack to deal with generic typealiases, but
overall this makes things more logical.
This is the last big refactoring before we can allow constrained
extensions to make generic parameters concrete. All that remains
is a small set of changes to SIL type lowering, and retooling
some diagnostics in Sema.
A GenericEnvironment stores the mapping between GenericTypeParamTypes
and context archetypes (or eventually, concrete types, once we allow
extensions to constrain a generic parameter to a concrete type).
The goals here are two-fold:
- Eliminate the GenericTypeParamDecl::getArchetype() method, and
always use mapTypeIntoContext() instead
- Replace SILFunction::ContextGenericParams with a GenericEnvironment
This patch adds the new data type as well as serializer and AST
verifier support. but nothing else uses it yet.
Note that GenericSignature::get() now asserts if there are no
generic parameters, instead of returning null. This requires a
few tweaks here and there.
One minor revision: this lifts the proposed restriction against
overriding a non-open method with an open one. On reflection,
that was inconsistent with the existing rule permitting non-public
methods to be overridden with public ones. The restriction on
subclassing a non-open class with an open class remains, and is
in fact consistent with the existing access rule.
'fileprivate' is considered a broader level of access than 'private',
but for now both of them are still available to the entire file. This
is intended as a migration aid.
One interesting fallout of the "access scope" model described in
758cf64 is that something declared 'private' at file scope is actually
treated as 'fileprivate' for diagnostic purposes. This is something
we can fix later, once the full model is in place. (It's not really
/wrong/ in that they have identical behavior, but diagnostics still
shouldn't refer to a type explicitly declared 'private' as
'fileprivate'.)
As a note, ValueDecl::getEffectiveAccess will always return 'FilePrivate'
rather than 'Private'; for purposes of optimization and code generation,
we should never try to distinguish these two cases.
This should have essentially no effect on code that's /not/ using
'fileprivate' other than altered diagnostics.
Progress on SE-0025 ('fileprivate' and 'private')
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.
Now that ConstraintSystem::openGeneric() is the only remaining
caller of this function, inline it in there and open-code the
logic.
Also, add a hack for opening nominal types contained inside
protocol types. This is invalid, but we should not crash, so
bind the type variable for the protocol 'Self' type to the
'Self' archetype, since it will not be equated with anything
otherwise.
There was a weird corner case with nested generic functions that
would fail in the SIL verifier with some nonsense about archetypes
out of context.
Fix this the "right" way, by re-working Sema function declaration
validation to assign generic signatures in a more principled way.
Previously, nested functions did not get an interface type unless
they themselves had generic parameters.
This was inconsistent with methods nested inside generic types,
which did get an interface type even if they themselves did not
have a generic parameter list.
There's some spill-over in SILGen from this change. Mostly it
makes things more consistent and fixes some corner cases.
When attempting to compile Swift 2 code (or any Swift code using the
Swift 2 names) in Swift 3, the compiler diagnostics are often entirely
useless because the names have changed radically enough that one
generally gets "no member named 'foo'" errors rather than a helpful
"'foo' was renamed to 'bar'" error. This makes for a very poor user
experience when (e.g.) trying to move Swift 2 code forward to Swift 3.
To improve the experience, when the Swift 2 and Swift 3 names of an
API differ, the Clang importer will produce a "stub" declaration that
matches the Swift 2 API. That stub will be marked with a synthesized
attribute
@available(unavailable, renamed: "the-swift-3-name")
that enables better diagnostics (e.g., "'foo' is unavailable: renamed
to 'bar') along with Fix-Its (courtesy of @jrose-apple's recent work)
that fix the Swift 2 code to compile in Swift 3.
This change addresses much of rdar://problem/25309323 (concerning QoI
of Swift 2 code compiled with a Swift 3 compiler), but some cleanup
remains.
If a function is public, and either @_transparent or @inline(__always),
we need to make its body available for inlining in other resilience
domains. The more general concept here is an 'inlineable' function;
once the precise behaviors we want are nailed down, the set of AST
attributes for exposing this will likely change.
At the SIL level, inlineable functions are marked with the [fragile]
attribute. The SIL serializer only serializes [fragile] functions
unless -sil-serialize-all is passed in.
This patch fixes two problems in this area by consolidating some
duplicated logic:
1) Property accesses in Sema did not check for @inline(__always)
functions, or functions nested inside inlineable functions.
This manifested as IRGen crashes if an inlineable function
accessed a property of a resilient type.
2) In SILGen, functions nested inside [fragile] functions were
properly [fragile], but @inline(__always) was not taken into
account. This manifested as SIL serializer crashes where a
[fragile] function could reference a non-public, non-[fragile]
function.
This change is part of the series for building the standard library
without -sil-serialize-all.
There's a group of methods in `DeclContext` with names that start with *is*,
such as `isClassOrClassExtensionContext()`. These names suggests a boolean
return value, while the methods actually return a type declaration. This
patch replaces the *is* prefix with *getAs* to better reflect their interface.
Fills in Chris's placeholder in feace85d5. I'm not quite sure why a private
subscript doesn't produce a non-cascading dependency right now, but this is
at least conservatively correct.
(For more infomation on dependencies, check out "Dependency Analysis.rst".)
This is necessary for some other work I'm doing, which really wants
paramdecls to have reasonable declcontexts. It is also a small step
towards generic subscripts.
Rather than plumbing a "has missing required members" flag all the way
through the LazyResolver's loadAllMembers and its implementations,
just eagerly update the "has missing required members" flag in the
Clang importer when it happens. More NFC cleanup.
Previously, methods on DeclContext for getting generic parameters
and signatures did not walk up from type contexts to function
contexts, or function contexts to function contexts.
Presumably this is because SIL doesn't completely support nested
generics yet, instead only handling these two special cases:
- non-generic local function inside generic function
- generic method inside generic type
For local functions nested inside generic functions, SIL expects
the closure to not have an interface type or generic signature,
even if the contextual type signature contains archetypes.
This should probably be revisited some day.
Recall that these cases are explicitly rejected by Sema diagnostics
because they lack SIL support:
- generic function inside generic function
- generic type inside generic function
After the previous patches in this series, it becomes possible to
construct types that are the same as before for the supported uses of
nested generics, while introducing a more self-consistent conceptual
model for the unsupported cases.
Some new tests show we generate diagnotics in various cases that
used to crash.
The conceptual model might still not be completely right, and of
course SIL, IRGen and runtime support is still missing.
Now that generic signatures of types include generic parameters
introduced by outer generic functions, we need to know to skip
them when forming bound generic types or substitutions.
Add a function that computes the depth of the innermost generic
context that is not a generic type context.
Once nested generic parameter lists are properly chained, we need a
way of checking if we're inside a generic type context that's
distinct from just checking if we have a generic type signature
available.
This distinguishes between these two cases:
class A<T> {
// generic signature
func method() -> T { // <T> A<T> -> () -> T
}
}
func f<T>() {
class A {
// no generic signature
func method() -> T { // A -> () -> T
}
}
}
For better or worse, the type of a function can end up as ErrorType,
and the generic signature was not stored anywhere else, causing
crashes from orphaned generic type parameters.
This patch is the first in a series to make this more robust by
storing the generic signature before the interface type is computed.
This is more complex than it could be if ExtensionDecl and NominalTypeDecl
had a common ancestor in the Decl hierarchy, however this is not possible
right now because TypeDecl inherits from ValueDecl.
Fixes <rdar://problem/20981254>.
Swift SVN r28941