This CL makes two fixes:
1. When a field is visited for the second time (to infer
subexpressions), don't use the inferred field type as the context;
this can change the inference results in a few rare circumstances,
making it different from what would be inferred inside a method body.
2. When doing extended top level type inference is enabled, only skip
subexpressions whose type is not needed.
Note that some tests had to be moved (either partially or completely)
into pkg/front_end/testcases/inference_new to reflect the fact that
front_end type inference now produces more correct results than
analyzer. Also, the annotation comments in
pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart
were completely bogus and needed to be changed.
R=ahe@google.com
Review-Url: https://codereview.chromium.org/2954063002 .
I'm about to start introducing usages of TypeParameterType.bound, and
nearly all of the usage sites will need to fall back on
TypeParameter.bound if there is no bound stored in the
TypeParameterType. This CL places the fallback behavior in the
TypeParameterType.bound getter so that we won't have to duplicate it
at every usage site (and risk making mistakes). The few call sites
that don't want the fallback behavior (such as the one in
ast_to_binary.dart) can avoid it by referring to
TypeParameterType.promotedBound directly.
R=ahe@google.com
Review-Url: https://codereview.chromium.org/2952883003 .
Also, fix a minor bug in variable declaration inference that was
preventing a local variable without an initializer from having its
type properly "inferred" as `dynamic`.
R=sigmund@google.com
Review-Url: https://codereview.chromium.org/2949093002 .
On a switch fall through error, Fasta currently generates
```
throw new core::FallThroughError::•();
```
which generates the error-message via the VM:
```
'null': Switch case fall-through at line null.
```
This introduces a new constructor taking a url and a linenumber,
which then can give a better error message.
BUG=
R=ahe@google.com
Review-Url: https://codereview.chromium.org/2951453002 .
In spec mode the types aren't meaningful anyway (due to the fact that
the spec mode type system is unsound), and they don't match the
behavior of Rasta (causing bot failures).
R=sigmund@google.com
Review-Url: https://codereview.chromium.org/2953503002 .
Normally getters and setters are considered distinct and unrelated by
the type inference algorithm. However, if a getter has no declared
type and doesn't override anything, then we fall back on inferring its
type from an inherited setter, and vice versa.
R=sigmund@google.com
Review-Url: https://codereview.chromium.org/2946733003 .
This mimics the behaviour of the source-based pipeline,
i.e. instead of "manually" calling _AssertionError._create and giving
the correct parameters (wrong parameters, actually), use the helper
method _AssertionError.ThrowNew.
BUG=
R=ahe@google.com, vegorov@google.com
Review-Url: https://codereview.chromium.org/2940283002 .
To facilitate experimentation, I've left the old code in place, but
disabled it using a const bool `fullTopLevelInference`. The old code
can be re-enabled by setting this bool to `false`. Once we are sure
that we want to proceed with this approach, we can remove the old
code.
I believe that with this change, all expressions that can be type
inferred inside a method body can now be type inferred at top level,
provided that there are no circular dependencies.
R=sigmund@google.com
Review-Url: https://codereview.chromium.org/2942153002 .
This CL combines the two parts of top level type inference
(determining dependencies and inferring a type) into a single
operation.
The technique is: instead of evaluating top level types in
topologically sorted order (which requires that we figure out the
dependencies first, so that we can do topological sorting), we simply
iterate over the fields requiring inference and begin inferring them
in whatever order they are encountered. If, while trying to infer the
type of one field, we discover a reference to field that hasn't been
type inferred yet, we make a recursive call to infer the second field.
If this recursion leads to a loop, then we mark all of the fields in
the loop as participating in a circularity (and set their types to
`dynamic` for error recovery purposes).
To facilitate experimentation, I've left the old code in place, but
disabled it using a const bool `fusedTopLevelInference`. The old code
can be re-enabled by setting this bool to `false`. Once we are sure
that we want to proceed with this approach, we can remove the old
code.
Note that there are some minor user-visible behavioral changes:
- When there is a circularity, we no longer consider the entire
strongly connected component to be part of the circularity; we only
consider the loop formed by following the first unresolved
dependency of each field. (I did this because of ease of
implementation, and because it made it easier to reassure myself
that the outcome of the algorithm is independent of the order in
which fields are visited). See
pkg/front_end/testcases/inference_new/strongly_connected_component.dart
for the user-visible consequence of this change.
- We no longer need to speculatively assume that method invocations
depend on the types of their parameters when not supplying generic
types; now they only depend on the types of their parameters when
the method being invoked is known to be generic. See
pkg/front_end/testcases/inference_new/dependency_only_if_generic_method.dart.
- We no longer need to speculatively assume that invocations of `+`,
`-`, `*`, and `%` depend on the types of their RHS; now they only
depend on the types of their RHS when the type of the LHS is
`int`. See
pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.
R=sigmund@google.com
Review-Url: https://codereview.chromium.org/2942623004 .
This CL lifts all of the restrictions on top level type inference
except for one: the restriction that expressions used for top level
type inference cannot depend on the types of instance getters,
instance setters, or instance fields. (That restriction will be
lifted in a later CL).
The technique is: to determine the dependencies of an expression,
rather than recurse through the expression applying the rules for what
constitutes an "immediately evident" expression, we simply do a dry
run of the inference algorithm and record what static fields were
accessed. To avoid recording bogus dependencies on fields whose type
doesn't matter, this dry run skips subexpressions whose type isn't
needed.
To facilitate experimentation, I've left the old code in place, but
disabled it using a const bool `extendedTopLevelInference`. The old
code can be re-enabled by setting this bool to `false`. Once we are
sure that we want to proceed with this approach, we can remove the old
code.
Note that this makes the behavior begin to diverge with analyzer
behavior, so I've created a new test directory:
pkg/front_end/testcases/inference_new/, to hold test cases which
aren't expected to match analyzer. Analyzer is only tested against
the test cases in pkg/front_end/testcases/inference/.
R=scheglov@google.com
Review-Url: https://codereview.chromium.org/2935323002 .