Previously, the analyzer would perform downwards and upwards inference
using separate GenericInferrer objects. This meant that any
constraint gathering work performed during downwards inference had to
be repeated during upwards inference.
This change avoids the extra work by using a single GenericInferrer
object for both downwards and upwards inference. It also cleans up
the API for GenericInferrer a bit.
Change-Id: Idc5deed96c18ffc89aeb8ba4e5e95942843dae11
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/236660
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Moves all of the analyzer's type inference logic for invocations into
a single `resolveInvocation` method, defined on an abstract base class
`InvocationInferrer`. There are concrete derived classes to
specialize this logic for all of the types of AST nodes require this
sort of inference (Annotation, ExtensionOverride,
FunctionExpressionInvocation, InstanceCreationExpression,
MethodInvocation, RedirectingConstructorInvocation, and
SuperConstructorInvocation), and the special logic for each node type
is slotted into the core algorithm using virtual dispatch.
In addition to making the code more maintainable by reducing code
duplication, this change paves the way toward modifying the core
algorithm to allow inference information to flow between arguments in
a generic function call
(https://github.com/dart-lang/language/issues/731).
Also partially addresses #48500 (Expression.staticParameterElement
sometimes points to a synthetic element).
Change-Id: I82788d58a62b6555589da16163317b6bbddd53c1
Bug: https://github.com/dart-lang/language/issues/731, https://github.com/dart-lang/sdk/issues/48500
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/234864
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This change eliminates the methods `InferenceContext.setType`,
`InferenceContext.clearType`, and `InferenceContext.getContext`, in
favor of passing context types around on the stack.
This should improve performance (by avoiding map lookups in
`AstNodeImpl._propertyMap`) and should make it easier to understand
the behavior of context types in the debugger (by making them visible
in stack frames).
Change-Id: Idd672af60adbb7f32258ef5319761706485a0f63
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/234113
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
The migration engine resolves the ASTs for the code in question twice,
once with null safety features turned off, in order to build the
nullability graph, and then a second time with null safety features
turned off, in order to determine the precise type of every
subexpression and figure out where `!`s and casts need to be inserted.
The analyzer passes type inference contexts around by storing them on
AST nodes. As a result, if a context type is associated with an AST
node the first time the code is resolved, and no context is stored the
second time it is resolved, the leftover contextual information gets
erroneously used by the second resolution pass. Before this change,
this was happening for expressions that received `.call` tearoffs,
because during the second resolution pass, the expression was wrapped
inside an `ImplicitCallReference` node, and the logic for analyzing
such nodes didn't bother to clear the context when visiting the
subexpression.
This change fixes the problem by directly calling `analyzeExpression`
to visit the subexpression (allowing the correct context to be
explicitly provided).
Fixes#47848.
Bug: https://github.com/dart-lang/sdk/issues/47848
Change-Id: Ie22c2821a0e04c1fb685d2cad7f8675fa08ef986
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/234080
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This change moves all the call sites for `Inference.getContext` to the
top of `ResolverVisitor.visit` methods. Any other methods that need
access to the inference context receive it as a parameter.
This is part of a larger effort to elimiate the use of
InferenceContext.getContext and InferenceContext.setType entirely.
Change-Id: Ie5b9dd3adf827a5b17b0f5662c5a7ed9c8e98069
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233863
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This changes the way the 'augment' modifier is handled in the parser.
Instead of being special cased for class declarations, it is now a
built-in identifier recognized only when the scanner is configured to
support augmentation libraries.
The change supports the used of the 'augment' modifier on not only
class declarations but also mixin and member declarations, as needed
for supporting macros.
Change-Id: I2679d198dea360900cfc478fae9c1660702a8a02
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233887
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Previously, the job of determining whether a `.call` tearoff was
necessary for an expression fell to the expression that contained it.
This made things complicated for set, map, and list literals, because
it required the literal to be visited twice (once to resolve the
subexpressions, and another time to insert `.call` tearoffs). With
this change, insertion of a `.call` tearoff is handled by the visitor
for the expression itself.
(Note that there are a few cases where we don't insert a `.call`
tearoff, or we do so based on a special type, based on the parent
expression. The language team is considering removing these special
cases, but for now, we maintain the existing behavior. We handle
these special cases by looking at `expression.parent`).
Change-Id: I85c813f8c105e3b962dd89d5a7fa8467506078ba
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/232660
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Previously, we only inserted these nodes when the
`constructor-tearoffs` feature was active, as a way of reducing the
risk of breaking analyzer clients; however this behavioral
inconsistency is not something we want to keep for the long term.
Note: even though this is technically a breaking change, we haven't
found any analyzer clients that are affected by it, so we're going
ahead and landing it without an analyzer version number bump.
Change-Id: I71f0fb2862b644dd1a81245bd12f5b7b9ca45857
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233653
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Previously, when upon reaching the integer literal, we would check if
the parent was a PrefixExpression with an operator of `-`, and if so,
use the context type of the PrefixExpression to decide whether to do
an int->double conversion. This CL moves the logic to the
PrefixExpressionResolver; we now pass down the appropriate context
when visiting the integer literal.
This makes the context handling for negated integer literals less of
an odd exception.
This is part of a larger effort to elimiate the use of
InferenceContext.getContext and InferenceContext.setType entirely.
Change-Id: I6ca63df1adcb706011c146c80c2576814a73926d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231326
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Use `hasScheme` in place of comparing against the empty string, and
`isScheme` to compare against all other schemes.
TEST=No behavior changes.
Change-Id: Ifc9fd13c6cf37933ebd4a754c4b500dedbcb291b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231185
Reviewed-by: Kevin Moore <kevmoo@google.com>
Commit-Queue: Nate Bosch <nbosch@google.com>
I was thinking about unifying these two codes for documentation purposes,
but then I wondered whether we might not want to unify them for reporting
purposes too. The reason I think it might be better to unify them is
because (a) they really represent a single problem (missing required
arguments) and (b) we were previously reporting the same problem multiple
times.
Change-Id: Iecf2865e67d61b03a1e1f56781e94e283d2a08e2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/232022
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This was broken after
https://dart-review.googlesource.com/c/sdk/+/230948, the example would
be
```dart
class A {
m() sync* {
yield* [1];
}
}
```
Inferred type for expression in `yield*` statement is
`List<FutureOr<dynamic>>` after the above CL, while I'd expect it
to be `List<int>`.
The change modified the behaivor while passing the imposed
return type a bit: `InferenceContext.setType` resets the type to `null`
if it's `dynamic`, while the logic that passes the type down explicitly
doesn't do that. My change restores the behavior of resetting the
imposed type to `null` if it's `dynamic`.
Interestingly enough, this is not a problem for function declarations:
`FunctionExpressionResolver.resolve(FunctionExpressionImpl)`
has special clause that resets the imposed type to null. But
for reasons I don't understand `FunctionExpressionResolver` is
used for function declarations but not for method declaration.
Change-Id: I63cfde01f067c25442afed64843861d09c7474a1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231702
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Ilya Yanok <yanok@google.com>
Now that we only use InferenceContext.setType for expressions, this
change consolidates all the call sites to just two places:
- The method ResolverVisitor.analyzeExpression, which is used when
recursively analyzing subexpressions inside expressions and
statements.
- The method InferenceContext.setTypeFromNode, which is used during
AST rewrites to transfer context information from the original node
to the rewritten node.
This is part of a larger effort to elimiate the use of
InferenceContext.getContext and InferenceContext.setType entirely.
Change-Id: Id236bcb1247c09b740bbbad41cb74ecda301cc86
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231181
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Instead of using InferenceContext.getContext and
InferenceContext.setType to associate type inference information with
VariableDeclaration nodes, we pass the information on the stack using
a new FunctionBodyImpl.resolve method. This should be more efficient
for two reasons: it avoids a map lookup, and it avoids the double
dispatch traditionally associated with calling a visitor. It should
also make the code easier to reason about (since it makes the flow of
data in the type inference process more explicit).
This is part of a larger effort to elimiate the use of
InferenceContext.getContext and InferenceContext.setType entirely.
Change-Id: I8a3f3be940acdcd0a2c4ad8ec37b41bafe25c952
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/230948
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Instead of using InferenceContext.getContext and
InferenceContext.setType to associate type inference information with
VariableDeclaration nodes, we directly look up the variable type when
we need it. This should be more efficient (since it avoids a map
lookup), and it should make the code easier to reason about (since it
makes the flow of data in the type inference process more explicit).
This is part of a larger effort to elimiate the use of
InferenceContext.getContext and InferenceContext.setType entirely.
Change-Id: I01262fb3c3e6789ee9da924e731d86d99ce3f4de
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/230946
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Instead of using InferenceContext.getContext and
InferenceContext.setType to associate type inference information with
ArgumentList nodes, we pass the contextual information around on the
stack. This should be more efficient (since it avoids a map lookup),
and it should make the code easier to reason about (since it makes the
flow of data in the type inference process more explicit).
This is part of a larger effort to elimiate the use of
InferenceContext.getContext and InferenceContext.setType entirely.
Change-Id: I331792cf6d7289a27fc71edfc6af33cd1af5288c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/230942
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Rather than do two passes over each collection literal (one to push
contexts down and a second pass to resolve), we pass the contexts down
on the stack during a single resolve pass.
I decided to create an extra data structure to hold the context
information (so I only had one thing to pass around on the stack
rather than four). The extra allocation will carry a small
performance cost. However, I was able to reduce the number of passes
over the collection literal from two to one, replace a chain of
is-tests with a virtual dispatch, and eliminate a double-dispatch in
some cases, so hopefully the benefit of those improvements will more
than offset the cost.
This is part of a larger effort to elimiate the use of
InferenceContext.getContext and InferenceContext.setType entirely.
Change-Id: I949c2c5ef99fc3395de3d67eaa8f326b7af5b158
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231062
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>