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.
We don't need to serialize the protocol's superclass, we can compute it from the
generic signature. Previously, we would drop the superclass while
serializing because we didn't check the generic signature in
SuperclassTypeRequest, which would cause us to cache `NULL` when we
called `setSuperclass` for a protocol with a superclass constraint.
Fixes rdar://50526401
This commit adds a new type DynamicLookupInfo that provides information
about how a dynamic member lookup found a particular Decl. This is
needed to correctly handle KeyPath dynamic member lookups, but for now
just plumb it through everywhere.
Specifically the bad pattern was:
```
for (auto *vd : *caseStmt->getCaseBodyVariables()) { ... }
```
The problem is that the optional is not lifetime extended over the for loop. To
work around this, I changed the API of CaseStmt's getCaseBodyVariable methods to
never return the inner Optional<MutableArrayRef<T>>. Now we have the following 3
methods (ignoring const differences):
1. CaseStmt::hasCaseBodyVariables().
2. CaseStmt::getCaseBodyVariables(). Asserts if the case body variable array was
never specified.
3. CaseStmt::getCaseBodyVariablesOrEmptyArray(). Returns either the case body
variables array or an empty array if we were never given any case body
variable array.
This should prevent anyone else in the future from hitting this type of bug.
radar://49609717
There are multiple ways in which the Clang importer can produce an
initializer, and we have existing name shadowing rules to decide on
the best. Extend those rules to cover the case where a
Clang-importer-synthesized initializer collides with a C function
imported as an initializer. There's technically no reason to do the
latter because the former already exists, but some frameworks
currently depend on this.
Prior to this, the constraint solver was preferring the synthesized
initializer already (which is the right thing to do), for the wrong
reasons.