Sometimes the upwards inference phase of generic type inference is
capable of assigning a more specific type than the downwards inference
phase, but we don't want to use the more specific type due to Dart's
"runtime checked covariant generics" design. For example, in this
code:
List<num> x = [1, 2, 3];
x.add(4.0);
Downwards inference provisionally considers the list to be a
`List<num>`. Without this heuristic, upwards inference would refine
the type to `List<int>`, leading to a runtime failure. So what we do
is "fix" the type parameter to `num` after downwards inference,
preventing upwards inference from doing any further refinement.
(Note that the heuristic isn't needed for type parameters whose
variance is explicitly specified using the as-yet-unreleased
"variance" feature, since type parameters whose variance is explicitly
specified don't undergo implicit runtime checks).
Previously, this heuristic was implemented in a kludgy way: we would
go ahead and gather type constraints during both the upwards and
downwards inference phases, and then just prior to choosing the final
type, if the downward constaints were sufficient to lock down the
type, we would discard the constraints from the upwardsr inference
phase.
This change simplifies the logic so that we figure out which
parameters to fix after the downwards inference phase, and simply stop
accumulating constraints for them.
This is a preparatory step towards implementing
https://github.com/dart-lang/language/issues/731, which will require
splitting type inference into more phases.
Change-Id: I0cc5774e61a5ace589ea0f45a20fbc1a67c8b940
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/237381
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This logic allowed the analyzer to omit consideration of type
parameter bounds during execution of the `matchSupertypeConstraints`
method (which is used for mixin type parameter inference). I added it
back in 2018 (https://dart-review.googlesource.com/c/sdk/+/44220) in
an attempt to fix#32353, however after I made the fix, additional
work by the front end team made it seem like I had probably
misunderstood the issue. In any case, I've verified with both SDK
trybots and an internal presubmit that removing this logic doesn't
break anything, so I believe it's likely that the bug was later fixed
in a different (and presumably more correct) fashion.
I'm currently doing work on the analyzer's type inference logic, and
GenericInferrer.considerExtendsClause is complicating my efforts, so
it seems reasonable to remove it at this point.
Change-Id: Ia0a988c7297e1579c2e96f9fa886e280f47ab62e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/237003
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Documentation comments claim that if the match fails, the set of type
constraints is unchanged. From code inspection, I believe this is
correct, but it's non-trivial to verify, so I've added a line to
type_constraint_gatherer_test.dart to double check it.
Change-Id: I9587922ca90fe9bbd51217906a4f4bd76047c777
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/237002
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
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>
A consistency check is not necessary in the event of an exception,
because we aren't returning a value anyhow. And it's guaranteed to
fail, because the AnalysisDriver clears the context when an exception
occurs (see AnalysisDriver._clearLibraryContextAfterException). This
is harmful, because the InconsistentAnalysisException covers up the
original exception, making debugging much more difficult.
Change-Id: Iaab1bdf1a32c1e261cef97b8749a2c5057d9b11c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/236780
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
It had bit rotted slightly: we were not properly accounting for
variance when gathering type inference constraints from the comparison
of two interface types.
Also, some of the tests needed to be updated to account for follow-on
errors.
Change-Id: Ife9feae3e2180a179ebc8503751690789dc1483e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/235941
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This would be a breaking change, so for now it is disabled, but
the method `applyPendingFileChanges()` can be added, and the clients
will call it to be ready for the switching the flag.
Only clients that call methods like `changeFile` have to await applying
the file changes. Other clients can continue using synchronous
`currentSession`.
Change-Id: I0f8d4cc874f485776f611790f6c80fd7e07c8051
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/236041
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@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>