Codable's deep magic currently forces conformance checks in the middle
of name lookup in order to inject CodingKeys into lookup results. This
is compounded by the fact that this lookup fixup is occuring
incrementally, meaning depending on order of requirements being looked
up, Decl::getMembers() will give you a different answer.
Compounding this, NameLookup relied on the LazyResolver to formalize
this layering violation, and relied on implicit laziness to guard
against re-entrancy.
The approach is multi-pronged:
1) Shift the layering violation into the request evaluator
2) Spell out the kinds of resolution we support explicitly (make them
easier to find and kill)
3) Remove the LazyResolver entrypoint this was relying on
4) Split off the property wrappers part into its own utility
By convention, most structs and classes in the Swift compiler include a `dump()` method which prints debugging information. This method is meant to be called only from the debugger, but this means they’re often unused and may be eliminated from optimized binaries. On the other hand, some parts of the compiler call `dump()` methods directly despite them being intended as a pure debugging aid. clang supports attributes which can be used to avoid these problems, but they’re used very inconsistently across the compiler.
This commit adds `SWIFT_DEBUG_DUMP` and `SWIFT_DEBUG_DUMPER(<name>(<params>))` macros to declare `dump()` methods with the appropriate set of attributes and adopts this macro throughout the frontend. It does not pervasively adopt this macro in SILGen, SILOptimizer, or IRGen; these components use `dump()` methods in a different way where they’re frequently called from debugging code. Nor does it adopt it in runtime components like swiftRuntime and swiftReflection, because I’m a bit worried about size.
Despite the large number of files and lines affected, this change is NFC.
Patch up all the places that are making a syntactic judgement about the
isInvalid() bit in a ValueDecl. They may continue to use that query,
but most guard themselves on whether the interface type has been set.
Swift 5.1's lookup for custom attributes skipped associated type
members, which allowed code like the given example to compile. To
maintain source compatibility, identify the narrow case that happens
in practice---the property wrapper is at module scope but is now
shadowed by an associated type---warn about it, and accept it.
Fixes rdar://problem/56213175.
Remove the early return in the case where one of our parent contexts was
being validated, and replace it with a simpler check that is only
performed in some callers related to associated type inference; we want
to bail out in one specific case only, which is that the declaration
is inside an extension whose generic signature is in the process of
being computed.
The existing rules sometimes behaved this way, because validateDecl()
bails out silently without error on circularity.
Let's make this explicit instead, and get it working in all cases.
Fixes <rdar://https://bugs.swift.org/browse/SR-3492> and
<rdar://problem/45889192>.
Like the last commit, SourceFile is used a lot by Parse and Sema, but
less so by the ClangImporter and (de)Serialization. Split it out to
cut down on recompilation times when something changes.
This commit does /not/ split the implementation of SourceFile out of
Module.cpp, which is where most of it lives. That might also be a
reasonable change, but the reason I was reluctant to is because a
number of SourceFile members correspond to the entry points in
ModuleDecl. Someone else can pick this up later if they decide it's a
good idea.
No functionality change.
Most of AST, Parse, and Sema deal with FileUnits regularly, but SIL
and IRGen certainly don't. Split FileUnit out into its own header to
cut down on recompilation times when something changes.
No functionality change.
Computing the interface type of a typealias used to push validation forward and recompute the interface type on the fly. This was fragile and inconsistent with the way interface types are computed in the rest of the decls. Separate these two notions, and plumb through explicit interface type computations with the same "computeType" idiom. This will better allow us to identify the places where we have to force an interface type computation.
Also remove access to the underlying type loc. It's now just a cache location the underlying type request will use. Push a type repr accessor to the places that need it, and push the underlying type accessor for everywhere else. Getting the structural type is still preferred for pre-validated computations.
This required the resetting of a number of places where we were - in many cases tacitly - asking the question "does the interface type exist". This enables the removal of validateDeclForNameLookup
My recent refactoring of top-level lookup replaced the old
shadowing done as part of top-level lookup with two separate
rules:
- If all paths from the current source file to a module 'B'
go through a module 'A', then declarations in 'A' shadow
declarations in 'B'.
- If a declaration in module 'A' was found via a scoped
import and a declaration with the same name in module 'B'
was found via an unscoped import, prefer the declaration
from module 'A'.
However this caused a source break when you have a scenario
like the following:
- A source file imports 'A', 'B', and 'B.Foo'.
- 'A' re-exports 'B'.
- Both 'A' and 'B' define a type named 'Foo'.
The problem is that the scoped import 'B.Foo' can actually
find both 'A.Foo' and 'B.Foo', since 'B' re-exports 'A'.
Furthermore, since the source file explicitly imports 'A',
'B' does not shadow 'A' in the import graph.
As a result neither shadowing rule would eliminate the
ambiguity.
The new rule combines the scoped import check and the
shadowing check by considering all access paths to 'A'
that are not shadowed by 'B'. Using this rule, 'A.Foo'
is only seen via the access path 'A', whereas 'B.Foo'
is seen under both 'B' and 'B.Foo'. Since 'B.Foo' is seen
via a scoped import and 'A.Foo' is only seen via an
unscoped import, we can conclude that 'B.Foo' shadows
'A.Foo'.
Fixes <rdar://problem/55205050>.
This should not start searching at the extension. Start looking one
level up. Breaks a potential cycle where an extension's generic
parameters were subject to lookup while computing the nominal type.
Since we started saving the nominal in the .swiftmodule, changing the other
call-sites in ClangImporter to save the value means that we can rely on
the typeRepr being non-null except when the syntax tree was ill-formed.
Instead of computing it from the extended type after deserialization --
which is tricky to do, due to potential presence of protocol
compositions -- we obtain the extended nominal directly.
Fixes SR-11227 and linked rdar://problem/53712389.
This avoids a re-entrant lookup while doing lazy member loading,
and eliminates a usage of LookupDirectFlags::IgnoreNewExtensions,
and the last usage of NominalTypeDecl::makeMemberVisible().
Ensure that lazy parsing of the members of nominal type definitions
and extensions is handled through a request. Most of the effort here
is in establishing a new request zone for parser requests.
This simulates the shadowing done by ModuleNameLookup, which is about to be
removed.
The basic idea is that top-level declarations found via scoped imports
take precedence over unscoped imports.
This simulates the shadowing done by ModuleNameLookup, which is about to be
removed.
The basic idea is that if a module A imports a module B, and B imports C,
then from A's point of view, top-level declarations from B will shadow
top-level declarations from C.
When performing unqualified lookup via directReferencesForUnqualifiedTypeLookup(), we should look into protocol members as well, as it's possible that the user has defined a typealias
Note that in all cases it was either nullptr or ctx.getLazyResolver().
While passing in nullptr might appear at first glance to mean something
("don't type check anything"), in practice we would check for a nullptr
value and pull out ctx.getLazyResolver() instead. Furthermore, with
the lazy resolver going away (at least for resolveDeclSignature() calls),
it won't make sense to do that anymore anyway.
There was a bit of a misunderstanding between the 'lazy member' code
and the 'delayed member parsing' code. We have to explicitly parse
extensions of a 'lazy member' type when incrementally building the
lookup table, otherwise we'll never revisit the parsed extension
members later.
No test case because this can't happen right now; we force all delayed
parsing before any qualified lookups are performed. However everything
breaks badly without this change once delayed member parsing actually
occurs.