Teach ASTScope how to reason about macro expansions. When we create an
ASTScope for a source file that represents a macro expansion, its
parent scope node is the macro expansion itself. When performing
unqualified lookup (of any form), find the starting source file based
on the location, not on the source file provided---this ensures that
we start lookups within the macro expansion (for example).
The effect of this is to enable macro expansions to work in nested
contexts, where they refer to names in the scope in which the macro is
expanded.
This is decidedly unhiegenic, but it fits with our syntactic model.
Semantically, the capture list binding behavior doesn't require the scope
to be an explicit closure, and forming new ClosureExprs during type-checking
is difficult because they have to have preassigned discriminators, unlike
AutoClosureExprs which get discriminators introduced by Sema itself. Allowing
CaptureListExpr to hold an AutoClosureExpr makes it easier to synthesize
CaptureListExprs during type checking, to represent expressions with closure
semantics that evaluate some parts of the expression eagerly in the surrounding
context.
The top-level scope for a conditional clause with a pattern is now
ConditionalClausePatternUseScope, which introduces the pattern's
bindings.
Since the patterns are not visible in their own initializer, a new
ConditionalClauseInitializerScope is used for the initializer.
While it is nested inside of the ConditionalClausePatternUseScope,
it's lookup parent skips one level, giving us the desired behavior.
If we're searching for a declaration with a given name, the name
should be entirely encapsulated inside the DeclConsumer.
Otherwise, there might not be a specific name at all, if we're
performing code completion for example (once LookupVisibleDecls
starts to use ASTScope, anyway).
DifferentiableAttr, SpecializeAttr and CustomAttr create scopes
because lookups can be performed from inside them. Previously
we would sort DifferentiableAttr and SpecializeAttr by source
order, but we consider that a declaration may also have more
than one _kind_ of attribute requiring special handling.
The case where this comes up is properties that have both a
DifferentiableAttr and CustomAttr. This fixes test failures in
AutoDiff tests with subsequent commits in this PR.
This centralizes some invariants around the 'self' parameter.
While all ConstructorDecls and DestructorDecls have a 'self',
even if they're invalid because they're not nested inside a type,
we don't want to consider this as the base 'self' for lookups.
Eg, consider this invalid code:
class C {
func f() {
init() {
x
}
}
}
The base for the lookup should be f.self, not f.init.self.
Let's use a ClosureParametersScope for all closures, even those
without an 'in' keyword. This eliminates the need for the
ClosureBodyScope and WholeClosureScope.
Also, let's move the lookup of capture list bindings from
CaptureParametersScope to CaptureListScope. This eliminates the
need for CaptureParametersScope to store a reference to the
capture list, which allows us to remove the AbstractClosureScope
base class entirely.
In a code snippet like the following,
static func ==(a: Foo, b: Foo) -> Bool {
switch (a, b) {
case (.x(let aa), .x(let bb)) where condition(aa, bb),
(.y(let aa), .y(let bb)) where condition(aa, bb):
return aa == bb
default:
return false
}
}
The CaseStmt defines two patterns, both of which bind
'aa' and 'bb'. The first 'aa'/'bb' are in scope inside the
first 'where' clause, and the second 'aa'/'bb' are in scope
inside the second 'where' clause.
Furthermore, the parser creates a "fake" VarDecl for
'aa' and 'bb' to represent the phi node merging the two
values along the two control flow paths; these are in scope
inside the body.
Model this situation by introducing a new CaseLabelItemScope
for the 'where' clauses, and a CaseStmtBodyScope for the
body.
Rather than depending on the tracking of state in switch cases to
remember the case statements that are the source and destination for a
`fallthrough` statement, compute them using ASTScope to find the
nearest enclosing case (the source) and then find the next case in the
same `switch` statement (the destination).
Use the scope map to implement lookup for the labeled statements that
are visible from a given source location, which is a lexical property
that is currently handled with stateful tracking in the type checker.
For now, merely assert that the results of this approach are identical
to the state tracked in the statement type checker.
Like switch cases, a catch clause may now include a comma-
separated list of patterns. The body will be executed if any
one of those patterns is matched.
This patch replaces `CatchStmt` with `CaseStmt` as the children
of `DoCatchStmt` in the AST. This necessitates a number of changes
throughout the compiler, including:
- Parser & libsyntax support for the new syntax and AST structure
- Typechecking of multi-pattern catches, including those which
contain bindings.
- SILGen support
- Code completion updates
- Profiler updates
- Name lookup changes
`@differentiable` attributes may contain `where` clauses referencing generic
parameters from some generic context, just like `@_specialize` attributes.
Without special ASTScope support for `@differentiable` attributes,
ASTScopeLookup.cpp logic tries to resolve the generic parameter `DeclName`s in
`where` clauses based on source location alone
(`ASTScopeImpl::findChildContaining`) and fails.
The fix is to add a special `DifferentiableAttributeScope`, mimicking
`SpecializeAttributeScope`. Every `@differentiable` attribute has its own scope,
derived from the declaration on which it is declared. Unlike `@_specialize`,
`@differentiable` may also be declared on `AbstractStorageDecl` declarations
(subscripts and variables).
Upstreams https://github.com/apple/swift/pull/27451.
Progress towards TF-828: upstream `@differentiable` attribute type-checking.
Switch most callers to explicit indices. The exceptions lie in things that needs to manipulate the parsed output directly including the Parser and components of the ASTScope. These are included as friend class exceptions.
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.