The order of operations for type inference of a generic invocation is
now:
1. Create some constraints on type parameters by trying to match the
return type of the invocation target as a subtype of the incoming
type context. (For a constructor invocation, the return type of
the invocation target is considered the raw uninstantiated type of
the class enclosing the constructor declaration.)
2. Downwards inference: partially solve the set of type constraints
accumulated in step 1, to produce a preliminary mapping of type
parameters to type schemas.
3. Recursively infer all arguments to the invocation, except that if
experimental feature `inference-update-1` is enabled, skip any
arguments that are function literals (a.k.a. "closures"). Obtain
the type contexts for the recursive inference by substituting the
preliminary mapping (from step 2) into the corresponding parameter
types of the invocation target. For each argument that is
recursively inferred, create additional constraints on type
parameters using the resulting static type.
4. If no arguments were skipped during step 3, go to step 7 (this
always happens if `inference-update-1` is disabled).
5. Horizontal inference: partially solve the set of type constraints
accumulated so far, to produce an updated preliminary mapping of
type parameters to type schemas.
6. Recursively infer all of the invocation arguments that were
previously skipped. As in step 3, obtain the type contexts for the
recursive inference by substituting the preliminary mapping (this
time from step 5) into the corresponding parameter types of the
invocation target. Again, for each argument that is recursively
inferred, create additional constraints on type parameters using
the resulting static type.
7. Upwards inference: solve the set of type constraints accumulated so
far, to produce a final mapping of type parameters to types. Check
that each type is a subtype of the bound of its corresponding type
parameter.
8. Check that the static type of each argument is assignable to the
type obtained by substituting the final mapping (from step 7) into
the corresponding parameter type of the invocation target.
9. Finally, obtain the static type of the invocation by substituting
the final mapping (from step 7) into the return type of the
invocation target.
This addresses simpler cases of
https://github.com/dart-lang/language/issues/731. Note that if
experimental flag `inference-update-1` is disabled, the behavior is
unchanged.
Note that steps 2 and 5 use the same algorithm as each other (they
only differ in how many type constraints have been accumulated so
far), so I've renamed the function that performs it from
`downwardsInfer` to `partialInfer`.
Change-Id: I10d3288d4f4ba9e2b6bc18409186ddc67ca2ee9d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/238881
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
In order to address https://github.com/dart-lang/language/issues/731
(improved type inference for `fold` etc.) we're going to need to
sometimes defer analysis of invocation arguments that are closures, so
that closure parameters can have their types inferred based on other
parameters. To avoid annoying the user with inconsistent behaviors,
we defer analysis of closures in all circumstances, even if it's not
necessary to do so for type inference purposes.
This has a minor user-visible effect: if an invocation contains some
closures and some non-closures, any demotions that happen due to write
captures in the closures are postponed until the end of the
invocation; this means that the write-captured variables remain
promoted for other invocation arguments, even if those arguments
appear after the closure. This is safe because there is no way for
the closure to be called until after all of the other invocation
arguments are evaluated. See the language tests in this CL for
details.
Note that this change only has an effect when the experimental feature
`inference-update-1` is enabled.
Change-Id: I283fc5eb07af2aeca0a06d523011d8c4617fbad7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/237720
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
In the process, I removed 'useFastaParser' from both the public API and
the implementation class. I also removed 'enableTiming' from the public
API.
The other getters were left because they seem like reasonable options
for plugins to want to query. If you disagree, we can address them in a
future CL.
Change-Id: Ia5630b71190dd68bcd66199baa0c05846fcc37b8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/238661
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
All of the changes here should be non-breaking; they should only result
in _fewer_ diagnostics.
New cases of "check the parent": parent is
* BinaryExpression
* ForElement
* IfElement
* IndexedExpression
* PostfixExpression
* SpreadElement
New cases of a "real use": parent is
* AssertInitializer
* AssertStatement
* ConstructorFieldInitializer
* ForEachParts
* ForEachPartsWithDeclaration
* ForLoopParts
* IfStatement
* ThrowExpression
* WhileStatement
* YieldStatement
Bug: https://github.com/dart-lang/sdk/issues/47685
Change-Id: Ib3fa216d45d01a728f73795b32b52f204eb140e5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/238264
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
* Make `MicroContextObjects` constructor private, which is not used
outside the library.
* Remove unused `analysisContext2` constructor parameter.
* Make `tryMatchSubtypeOf` private, which requires a parameter of
private type.
* Make `_FileStateFiles` public, as it is used outside the library.
* Return empty for void-typed functions.
Change-Id: If67a69effdbbaed2eb364788e52eeb60270a0c19
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/237855
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Samuel Rawlins <srawlins@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>
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>