Commit Graph

115 Commits

Author SHA1 Message Date
Doug Gregor
79e31a87b3 Re-implement ASTScope's child-insertion assertions
ASTScope assertions that a new child node inserted into its parent list
is after all other child nodes in the source, which included some bespoke
code for dealing with macro expansions. Replace this bespoke code with
uses of the newer SourceManager operations that check ordering of
source locations in a manner that respects macro expansions.
2023-11-30 10:54:42 -08:00
Doug Gregor
37ed49e0bd Implement ordering of source locations that accounts for macro expansion
SourceManager's `isBeforeInBuffer` in buffer takes two source locations
that are assumed to be within the same source buffer and determines
whether the first precedes the second. However, due to macro
expansion, there can be source locations in different source buffers
that are nonetheless conceptually part of the same source file. For
such cases, `isBeforeInBuffer` will silently produce wrong results.

Extend `SourceManager` with a new `isBefore` operation that determines
whether one source location precedes another in the same conceptual
source file, even if they are in different source buffers that (e.g.)
represent macro expansions within that source file. Also introduce
`isAtOrBefore` to cover the case where the source locations might be
equivalent, which was previously handled via a separate equality check
on the source locations that won't work with macro expansions.

Add caching for the list of accessors of a buffer, so we aren't doing
a full walk up the source-buffer chain ever time we do a comparison of
source locations. LCA is still linear-time, but this eliminates
extraneous hash table lookups along the way.

Over time, we should both move more clients over to these new variants
and introduce more assertions into the old (in-buffer) versions to
catch improper uses of them.
2023-11-30 09:55:56 -08:00
Doug Gregor
c060a90fe0 Generalize the LCA implementation in ASTScope for arbitrary macro nesting
The prior Least Common Ancestor (LCA) implementation in ASTScope, which
is used to search child scopes to find a particular location, assumed
that the source range it was given was contained within a single
buffer and was specific to the child-scope search task. Generalize
this to a more fundamental "is before" operation on source locations
that respects macro expansions, simplifying the code in the process.
2023-11-30 08:28:44 -08:00
Doug Gregor
3dd4df2351 [Typed throws] Location based lookup for the thrown error type
Introduce a new API to find the AST node that catches or rethrows an
error thrown from the given source location. Use it to determine the
thrown error type to use for type checking a `throw` statement, which
begins as `any Error` within a `do..catch` and is later refined.
2023-10-15 22:59:48 -07:00
Karl Wagner
ab4f80ed95 [SE-0404] Allow protocols to be nested in non-generic contexts 2023-10-06 21:04:03 +02:00
Pavel Yaskevich
955e1166d3 [AST] ASTScope: Pass parent module to all search methods
Addresses recently discovered performance regression.
`findChildContaining` has to handle macros and for that
it needs a parent module, looking it up every time is
expensive because it involves walking up back to a source
file scope.

Resolves: rdar://114667408
Resolves: rdar://114667496
2023-08-31 10:08:23 -07:00
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