Commit Graph

109 Commits

Author SHA1 Message Date
Holly Borla
393b4ceb95 [NameLookup] Move macro-related name lookup operations into the namelookup
namespace.

This moves the `isInMacroArgument` predicate and `lookupMacros` into `namelookup`.
ASTScope still encapsulates the scope tree and contains the operation to lookup
the enclosing macro scope, which then invokes a callback to determine whether a
potential macro scope is indeed a macro, because answering this question requires
name lookup.
2023-06-11 23:10:43 -07:00
Holly Borla
0b91f63349 [ASTScope] Don't consider freestanding macro expansions as being part of a
macro argument.
2023-06-11 23:10:43 -07:00
Holly Borla
cd79cf97d6 [ASTScope] Add APIs for determining whether a given source location is inside
a macro argument.
2023-06-11 23:09:47 -07:00
Adrian Prantl
158772c2ab Rebase SILScope generation on top of ASTScope.
This patch replaces the stateful generation of SILScope information in
SILGenFunction with data derived from the ASTScope hierarchy, which should be
100% in sync with the scopes needed for local variables. The goal is to
eliminate the surprising effects that the stack of cleanup operations can have
on the current state of SILBuilder leading to a fully deterministic (in the
sense of: predictible by a human) association of SILDebugScopes with
SILInstructions. The patch also eliminates the need to many workarounds. There
are still some accomodations for several Sema transformation passes such as
ResultBuilders, which don't correctly update the source locations when moving
around nodes. If these were implemented as macros, this problem would disappear.

This necessary rewrite of the macro scope handling included in this patch also
adds proper support nested macro expansions.

This fixes

rdar://88274783

and either fixes or at least partially addresses the following:

rdar://89252827
rdar://105186946
rdar://105757810
rdar://105997826
rdar://105102288
2023-04-04 15:20:11 -07:00
Doug Gregor
40b332189f [Macros] Fix name lookup of macro parameters in the definition.
This enables macros to be defined in terms of other macros.
2023-03-29 16:32:31 -07:00
Doug Gregor
7ea0e3f096 Switch GeneratedSourceInfo ranges over to CharSourceRange.
Macro expansion buffers, along with other generated source buffers,
need more precise "original source ranges" that can be had with the
token-based `SourceRange`. Switch over to `CharSourceRange` and provide
more thoughtfully-determined original source ranges.
2023-02-11 11:23:26 -08:00
Hamish Knight
a40f1abaff Introduce if/switch expressions
Introduce SingleValueStmtExpr, which allows the
embedding of a statement in an expression context.
This then allows us to parse and type-check `if`
and `switch` statements as expressions, gated
behind the `IfSwitchExpression` experimental
feature for now. In the future,
SingleValueStmtExpr could also be used for e.g
`do` expressions.

For now, only single expression branches are
supported for producing a value from an
`if`/`switch` expression, and each branch is
type-checked independently. A multi-statement
branch may only appear if it ends with a `throw`,
and it may not `break`, `continue`, or `return`.

The placement of `if`/`switch` expressions is also
currently limited by a syntactic use diagnostic.
Currently they're only allowed in bindings,
assignments, throws, and returns. But this could
be lifted in the future if desired.
2023-02-01 15:30:18 +00:00
Holly Borla
07319d0fdd [ASTScope] Teach ASTScope lookup to find source locations inside macro-expanded
scopes.

ASTScope lookup can no longer assume that all scopes are within the same source
file. Scope trees can now contain scopes that are in macro expansion buffers, which
live in different source files with independent source ranges from the root of a
given scope tree. To handle this when searching for a scope containing a given source
location, ASTScope lookup needs to walk up the chain of macro expansion buffers to find
the lowest common buffer in which to compare source locations.

This fixes a number of issues with unqualified lookup into and from within macro-expanded
code.
2023-01-25 23:19:33 -08:00
Doug Gregor
b29fcb4e58 [Macros] Parse macro declarations fully, and treat them as normal declarations 2022-11-28 18:32:43 -08:00
Angela Laar
c3d4b3d985 [AST] Namelookup should only look at parsed generic parameters
We want to make sure not to cause a circular reference
by fetching the full generic parameter list when we are
creating opaque paramters and result types.
2022-09-20 15:25:09 -07:00
Doug Gregor
55067ba028 Support named opaque result types for properties.
Add lookup scopes for the generic parameters of a named opaque result
type and clean up the code that finds the opaque substitutions.
2022-01-04 21:14:39 -08:00
Rintaro Ishizaki
7c92a8e555 [SourceKit] Add a request to generate object files in SourceKit
Add 'request.compile'
2021-12-21 14:35:38 -08:00
Robert Widmann
c23a617da2 [NFC] Clean Up Unused Fields in Unqualified Lookup
* Drop some unused fields
* const-qualify a consumption method that is logically const - though it
  isn't physically const given the mutating use in
  ASTScopeDeclConsumerForUnqualifiedLookup::lookInMembers
* Privatize some internal fields
2021-11-05 11:25:15 -07:00
Hamish Knight
c1b1feb8e7 [AST] Clean up CaptureListEntry
Don't store a VarDecl separately, expose a `getVar`
accessor that forwards onto `getSingleVar`, and
rename `Init` to `PBD`.
2021-06-08 22:56:06 +01:00
Slava Pestov
0fa84c14a0 ASTScope: Remove the ExpandASTScopeRequest
This doesn't really fit the request evaluator model since the
result of evaluating the request is the new insertion point,
but we don't have a way to get the insertion point of an
already-expanded scope.

Instead, let's change the callers of the now-removed
expandAndBeCurrentDetectingRecursion() to instead call
expandAndBeCurrent(), while checking first if the scope was
already expanded.

Also, set the expanded flag before calling expandSpecifically()
from inside expandAndBeCurrent(), to ensure that re-entrant
calls to expandAndBeCurrent() are flagged by the existing
assertion there.

Finally, replace a couple of existing counters, and the
now-gone request counter with a single ASTScopeExpansions
counter to track expansions.
2020-12-18 15:43:33 -05:00
Slava Pestov
996100cfd1 ASTScope: Remove old SourceRange machinery 2020-10-07 12:33:58 -04:00
Slava Pestov
e52413f913 ASTScope: Use CharSourceRanges for lookup 2020-10-07 12:33:58 -04:00
Slava Pestov
2e67c135fd ASTScope: Rework ConditionalClauseScopes
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.
2020-10-07 12:33:29 -04:00
Slava Pestov
3ec4ced57d ASTScope: Don't handle top-level bindings in a SourceFile for now 2020-10-01 23:50:16 -04:00
Slava Pestov
f738a57040 ASTScope: Remove DeclVisibilityKind parameter from AbstractASTScopeDeclConsumer::consume()
It wasn't used for anything, and it was always set based on whether
the declaration in question was a GenericTypeParamDecl, a ParamDecl,
or something else.
2020-10-01 23:50:16 -04:00
Slava Pestov
28388384f2 AST: UnqualifiedLookup only finds forward references to outer local bindings when IncludeOuterResults is set
The old behavior was that ASTScope would introduce all VarDecls
defined in a BraceStmt at the beginning of the BraceStmt.

I recently enabled the use of PatternEntryDeclScopes, which
introduce the binding at its actual source location instead of
at the beginning of the parent statement.

This patch now makes use of the new information by having
UnqualifiedLookupFlags::IncludeOuterResults toggle between
the two behaviors. When searching for outer results, we also
consider all VarDecls in a BraceStmt, not just those in scope.

This is implemented by giving AbstractASTScopeDeclConsumer a
new entry point, consumePossiblyNotInScope(). When looking up
into a BraceStmt, all VarDecls are passed in to this entry
point.

The default implementation does nothing, which means that
ASTScope::lookupSingleLocalDecl() now respects source locations
when searching for bindings, just like parse-time lookup.

However, Sema's preCheckExpression() pass, which sets
Flags::IgnoreOuterResults, will continue to find
forward-referenced VarDecls, just as it did with the old
context-based DeclContext lookup.
2020-10-01 23:46:26 -04:00
Slava Pestov
01c434ca13 Merge pull request #34125 from slavapestov/local-redeclaration-checking
Implement re-declaration checking for declarations in local context
2020-10-01 17:07:39 -04:00
Slava Pestov
c56ab07c77 ASTScope: Add finishLookupInBraceStmt parameter to ASTScope::lookupLocalDecls()
This will be used to implement re-declaration checking for local
declarations. Currently this is handled by parse-time lookup.

To make it work with ASTScope, we need to perform lookups that
look into the innermost local scope only; for example, this is
an invalid redeclaration:

do {
  let x = 321
  let x = 123
}

But the following is fine, even though both VarDecls are in the same
*DeclContext*:

do {
  let x = 321
  do {
    let x = 123
  }
}
2020-09-29 23:38:24 -04:00
Slava Pestov
445d747622 AST: Move GenericParamList and friends to GenericParamList.{h,cpp} 2020-09-29 19:51:03 -04:00
Slava Pestov
f8fb071f0f ASTScope: Remove ASTScopeImpl::getDeclContext() 2020-09-25 02:40:13 -04:00
Slava Pestov
bbd79a2db2 ASTScope: unqualifiedLookup() entry point does not need the name
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).
2020-09-25 02:40:13 -04:00
Slava Pestov
cecbf212d3 ASTScope: PatternEntryInitializerScope needs a custom lookup parent
Bindings are not visible from inside their own initializer, eg this
is invalid:

  var (x, y) = (y, x)

The PatternEntryDeclScope which starts after the 'var' introduces x
and y, and it contains the PatternEntryInitializerScope which starts
after the '='.

To model this properly in ASTScope, the PatternEntryInitializerScope
overrides getLookupParent() to skip the PatternEntryDeclScope that
contains it.

I believe this is simpler than having PatternEntryDeclScope begin
at the source location following the initializer, because it is hard
to compute this source location in a way that works with invalid
code, for example the 'var' might be nested inside of a BraceStmt
with the closing '}' missing.
2020-09-23 22:28:01 -04:00
Slava Pestov
81fc342852 ASTScope: Ignore PatternEntryDeclScope when searching for statement labels 2020-09-23 22:28:01 -04:00
Slava Pestov
87593fc0be ASTScope: Fold AbstractFunctionBodyScope into FunctionBodyScope 2020-09-23 13:09:00 -04:00
Slava Pestov
b7bd4fb8b3 ASTScope: Remove 'history' vector 2020-09-22 13:42:48 -04:00
Slava Pestov
c662c10d1e ASTScope: Use visitParsedAccessors() instead of getAllAccessors() 2020-09-22 02:06:32 -04:00
Robert Widmann
d93c6d8b12 Remove Cascading Computations from ASTScope 2020-09-21 10:42:33 -06:00
Robert Widmann
7fb448071c Remove DependencyScope 2020-09-21 10:37:41 -06:00
Robert Widmann
934f994b46 Remove DeclContext::isCascadingContextForLookup 2020-09-21 10:37:41 -06:00
Slava Pestov
7cb809bf1d ASTScope: Remove old implementation of 'selfDC' computation 2020-09-18 16:11:06 -04:00
Slava Pestov
9b851bf8cb ASTScope: Collapse PureFunctionBodyScope and MethodBodyScope
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.
2020-09-18 15:05:48 -04:00
Slava Pestov
3801d16d6f ASTScope: Simplify representation of closures
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.
2020-09-17 14:46:47 -04:00
Slava Pestov
09bb3c0d30 ASTScope: Don't need to pass in a DeclContext
This was used to validate against the old lookup code, but should no
longer be needed.
2020-09-16 20:07:58 -04:00
Slava Pestov
d260fbb9b1 ASTScope: More accurate modeling of 'case' statements
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.
2020-09-16 00:21:13 -04:00
Slava Pestov
5e3ef645e6 AST: Fix ASTScopeLookup crash if a PatternBindingEntry's context is not a PatternBindingInitializer
The function builder transform creates pattern bindings parented
in other DeclContexts. If those pattern binding initializer
expressions in turn contain multi-statement closures, we will
try to perform unqualified lookups from those contexts when we
get around to type checking the closure body.

Change some unconditional casts to conditional casts in ASTScope
lookup, to handle this case. The casts are only performed while
checking if the initializer context is part of a 'lazy'
property, which doesn't apply here.

Fixes <rdar://problem/67265731>.
2020-08-24 22:55:23 -04:00
Rintaro Ishizaki
b070e851f8 [ASTScope] Simplify binary search code in findChildContaining()
The comparision happens only by 'comp(element, value)' not
'comp(value, element)'. We only need
`operator()(const ASTScopeImpl *, SourceLoc)`.

Use llvm::lower_bound() instead of std::lower_bound().
2020-08-13 08:59:05 -07:00
Rintaro Ishizaki
513fed7d8c [CodeCompletion] Enable ASTScope in code completion
* Re-create `ASTScope` for each completion
* Add generic params and where clause scope even without missing body
* Use `getOriginalBodySourceRange()` for `AbstractFunctionBodyScope`
* Source range translations for replaced ranges when finding scopes
* Bypass source range checks when the completion happens in the replaced
  range
* Be lenient with ASTScope / DeclContext mismatch in code completion
2020-08-12 16:36:09 -07:00
Doug Gregor
190aeeaa6e Simplify ASTScopeImpl::lookupFallthroughSourceAndDest. 2020-08-03 21:46:55 -07:00
Doug Gregor
827ec9d28e [ASTScope] Use ASTScope to find fallthrough source/dest cases.
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).
2020-08-02 10:29:42 -07:00
Doug Gregor
97a8919ca0 guard statements aren't really labeled statements
`guard` statements are prohibited from having labels, and aren't
actually break/continue targets. Stop producing them as results from
ASTScope-based labeled statement lookup and don't add them as a
labeled statement in the recursive walk.
2020-07-31 22:33:45 -07:00
Doug Gregor
0d90adf1b5 [ASTScope] Implement lookup for visible labeled statements.
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.
2020-07-30 23:55:10 -07:00
Slava Pestov
daf65ce923 AST: Explicitly encode that only protocol and extension members are visible in a 'where' clause
Today, ASTScope only creates NominalTypeWhereScopes for the 'where'
clause of an extension or a protocol. All other generic declarations
model the 'where' clause as part of the declaration's scope itself
(but it's not part of the body scope).

Lookups into the NominalTypeWhereScope would look inside the type,
because this is how we want protocol and protocol extension scopes
to work -- you should be able to refer to associated types without
a 'Self' prefix.

Let's add a conditional check for protocols and extensions to the
implementation of NominalTypeWhereScope, so that we can use this
scope for all other 'where' clauses and keep the old behavior.

Note that today, even _concrete_ extensions have this behavior,
which is perhaps slightly unexpected:

class C<T> {
  typealias U = Int
}

extension C where T == U {}

It would be nice to tighten up the rule here but there's already a
test in the suite that depends on it.
2020-07-28 02:07:16 -04:00
Slava Pestov
14dd4eef2d AST: Add a way to distinguish a parsed generic parameter list from a synthesized one
Add a new GenericContext::getParsedGenericParams(). This produces
the same value as GenericContext::getGenericParams() if the generic
parameter list was written in source. For extensions and protocols,
this returns nullptr without synthesizing anything.
2020-07-28 02:07:16 -04:00
Varun Gandhi
65577940d0 [NFC] Get rid of -Wrange-loop-analysis warnings. (#31324) 2020-04-27 09:47:52 -07:00
Owen Voorhees
43e2d107e1 [SE-0276] Implement multi-pattern catch clauses
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
2020-04-04 09:28:26 -07:00