Weaves the flag `inference-update-4` through to `FlowAnalysis` and updating both the analyzer and CFE point-of-entry to include the flag.
This flag will be used in `flow_analysis.dart` to hide upcoming bug fixes to flow analysis.
Change-Id: Ib0004eb4bcf0b6e579116632b5973fe969e51e90
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388582
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
The `TypeConstraintGatherer` methods `trySubtypeMatch`,
`_functionType`, `_functionType0`, and `_recordType` have the
convention that if they do not find a match, they leave the set of
gathered constraints in the same state it was in at the time of the
call. The shared methods they invoke
(`performSubtypeConstraintGenerationForFutureOr`,
`performSubtypeConstraintGenerationForTypeDeclarationTypes`, and
`performSubtypeConstraintGenerationForFunctionTypes`) all follow the
same convention.
Because of this convention, much of the logic in `trySubtypeMatch` for
restoring the state of gathered constraints was actually redundant;
this CL removes the redundant logic. It also adds some comments to try
to clarify the calling conventions.
Change-Id: Ie11e4bc3edd3249191a09d9b93ae5844d5bf511c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388664
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
These if/else chains were selecting a behavior based on the type of a
collection element. Changing them to switch statements, and making use
of `CollectionElementImpl` (which is a sealed type), ensures that if
more kinds of collection elements are added in the future, we won't
forget to update the switches.
Change-Id: Iedd5d14aa22b7690902868ba15d9127d79bcad27
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388280
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This CL implements type inference for null-aware colletion elements
and map entires in the Analyzer. The new functionality is dependent on
the `null-aware-elements` feature flag, since only when the flag is
enable, can the `keyQuestion` and `valueQuestion` properties of the
MapEntryLiteralEntry class be not null and the objects of the
`NullAwareElement` be created.
Part of https://github.com/dart-lang/sdk/issues/56836
Change-Id: I9243b01d5de097ae0d2ca3376807c6209ef0f830
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/387980
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
With the changes to `FunctionTypeImpl` landed in
https://dart-review.googlesource.com/c/sdk/+/386322, it's now possible
to implement a few methods more efficiently:
- `namedParameterTypes` can be accomplished by simply iterating
through `sortedNamedParameters` once.
- `normalParameterTypes` and `optionalParameterTypes` can be
accomplished by calling `sublist` on `positionalParameterTypes`.
Change-Id: Ia4e6132fab3a9b5b6792ecad0cf893f9c3e74ad3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388022
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This change addresses several drawbacks that previously existed in
FunctionTypeImpl.hashCode:
- The hash computation was complex and not cached, potentially slowing
down performance.
- The hash computation failed to differentiate between optional
positional parameters and required positional parameters, leading to
a greater risk of hash collisions.
- The hash computation failed to differentiate between optional named
parameters and required named parameters, leading to a greater risk
of hash collisions.
- The hash computation failed to differentiate between named
parameters based on their names, leading to a greater risk of hash
collisions.
- The hash computation failed to account for the presence or absence
of a nullability suffix, leading to a greater risk of hash
collisions.
- The hash computation distinguished between equivalent types that had
different type formal names, leading to a situation where two
function types might compare equal but have different hash codes.
Of these drawbacks, only the last is a serious issue, since it
violates the implied contract of hash codes; the others are only
potential performance issues.
Change-Id: I9fbe4dd4751e7a070934e5d86de529765e135ac9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388100
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This change combines function-handling logic from the analyzer's
`TypeConstraintGatherer._functionType0` and the CFE's
`TypeConstraintGatherer._isNullabilityAwareSubtypeMatch` methods into
`TypeConstraintGenerator.performSubtypeConstraintGenerationForFunctionTypes`,
which is in `_fe_analyzer_shared`.
The CFE and the analyzer have some pretty significant differences in
how they represent function types:
- In the analyzer, all function parameters are in a single
`parameters` list; each element of this list (of type
`ParameterElement`) can be queried to find out if it is named or
unnamed, and if it is required or optional. A convention enforced
partially by the `FunctionType` constructor is that the `parameters`
list stores reqired unnamed parameters first, then either optional
unnamed parameters or named parameters; named parameters are sorted
by name. The analyzer provides additional getters
`namedParameterTypes`, `normalParameterNames`,
`normalParameterTypes`, `optionalParameterNames`, and
`optionalParameterTypes`, which provide other views of this
information (for example, `namedParameterTypes` contains just the
named parameters, as a map from name to `ParameterElement`).
- In the CFE, unnamed and named parameters are in two separate lists
(`positionalParameters`, of type `List<DartType>`, and
`namedParameters`, of type `List<NamedType>`); in
`positionalParameters`, required parameters come before optional
ones. A single integer (`requiredParameterCount`) indicates how many
elements of `positionalParameters` are required, and by convention,
`namedParameters` is sorted by name.
In order to share logic between these representations, I had to come
up with a common API that these two representations could be easily
adapted to. The analyzer's representation proved to be easier to
adapt, so I based the common API mostly on the CFE's representation,
but with some name changes for clarity. The shared API is:
- `positionalParameterTypes` gets a list of positional parameter types
- `requiredPositionalParameterCount` tells how many entries in
`positionalParameterTypes` are required.
- `returnType` gets the function type's return type.
- `sortedNamedParameters` gets a list of information about named
parameters. The list elements are sorted by name, and each element
of this list is of type `FunctionParameterStructure` (a common
interface implemented both by the analyzer's `ParameterElement` and
the CFE's `NamedType`).
- `typeFormals` gets a list of the function type's formal type
parameters.
To minimize the performance impact of adapting the analyzer to this
API, the analyzer computes `positionalParameterTypes`,
`requiredPositionalParameterCount`, and `sortedNamedParameters` at the
time a `FunctionType` is constructed. Hopefully this should not be too
much of a performance hit, since doing so does not take too much more
effort than checking that the named parameters are sorted (which the
`FunctionType` constructor was already doing).
This is based on previous work by Chloe Stefantsova in
https://dart-review.googlesource.com/c/sdk/+/386480.
Change-Id: Iefe18d72771146399d81747ceab9c929516b0523
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386322
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>