Commit Graph

690 Commits

Author SHA1 Message Date
Kallen Tu 53bad058b1 [flow] Add unit test for postIncDec().
Add Flow Analysis unit tests for FlowAnalysis.postIncDec() which should be used for postfix increment and decrement operations.

Bug: https://github.com/dart-lang/language/issues/3658
Change-Id: If77b6fbb5fc80d5f5d014ec0516d77578446dced
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/393441
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
2024-11-05 18:54:02 +00:00
Johnni Winther bdacb7d034 [_fe_analyzer_shared] Add evaluateExpression
This adds a helper method that evaluates an [Expression] based on
the semantics that can be deduced from the syntax.

Change-Id: I1b54ee03c1380d337969671133179aa557702a9b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392440
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
2024-11-01 09:26:44 +00:00
Johnni Winther 58c336e22b [_fe_analyzer_shared] Avoid deconstruction of potentially nullable type variables
The exhaustiveness model relies on null being extracted from nullable, for instance modeling `int?` as `int|Null`. This failed on type variable that are potentially nullable but not explicitly nullable. For these `Null` should be extract from their bound and not from themselves.

The logic in the getStaticType method now uses `isNullable` to determine both when to extract and to combine, so to avoid extracting but not combining `Null` for type variables and also not combine but not extract for instance for `void`.

Closes #56998

Change-Id: I47c2d0d6535ca66fe00e6344b11550c4308a7388
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392944
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
2024-11-01 08:47:02 +00:00
Chloe Stefantsova 297c90b50b [analyzer][cfe] Share the constraint collecting procedures
Part of https://github.com/dart-lang/sdk/issues/54902

Change-Id: I98dae68a61536cc3292f2a4f05cab22a8014486d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392581
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
2024-11-01 07:38:15 +00:00
Johnni Winther b7aa0faa44 [_fe_analyzer_shared] Add test for named mixin application in macro metadata
Change-Id: Ia968e49f2663970496ba289c5098802e1794799a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391760
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
2024-10-25 08:31:35 +00:00
Johnni Winther d96cecb4ff [_fe_analyzer_shared] Support mixins in macro metadata
Change-Id: I1eec1feb0230fa938b727c8eff88a048a53794be
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391660
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
2024-10-25 08:31:35 +00:00
Paul Berry 6a5b3d0457 Flow analysis: don't capture type information in equalityOperand_end.
There are two pieces of information flow analysis needs to know about
an equality test operand (i.e., an operands of `==`, `!=`, or
`identical()`):

- Their static types. This is used for reachability (e.g., flow
  analysis knows that if `f()` has type `Null`, then the body of `if
  (f() != null)` is unreachable).

- Whether they take the form of a null literal or a reference to
  something promotable. This is used to determine when an `if` test
  should promote a something to a non-nullable type.

Previous to this change, both pieces of information were captured by
`FlowAnalysis.equalityOperand_end` into an `ExpressionInfo` object,
and then those objects were passed into
`FlowAnalysis.equalityOperation_end`.

With this change, the client is now responsible for passing the static
types of the operands as separate arguments to
`FlowAnalysis.equalityOperation_end`, and the only information
captured by `equalityOperand_end` is whether the operand is a null
literal or a reference to something promotable.

This has two advantages:

- It avoids unnecessary allocations when analyzing code that doesn't
  have flow analysis consequences, since flow analysis no longer needs
  to allocate an `ExpressionInfo` for every equality test operand; it
  only has to allocate them for null literals and references to things
  that are promotable (which is a much smaller number of allocations).

- It means that `FlowAnalysis.equalityOperation_end` no longer needs
  to use the `type` field of `ExpressionInfo`. This helps build toward
  an eventual goal I have of removing this field, so that
  `ExpressionInfo` will simply be a container for a pair of flow
  models (one representing the flow state if the expression is `true`,
  one representing the flow state if the expression is `false`). I
  believe this will make flow analysis easier to reason about, and
  will help build toward a long term goal of cleaning up bugs in the
  "why not promoted" logic.

Making this change required adding a little bit of plumbing to the
analyzer, so that when analyzing an invocation of `identical`, it
keeps track of both the `ExpressionInfo` and the static type of the
operands; previously it just had to keep track of an `ExpressionInfo`
for each operand. The performance impact of this additional tracking
should be negligible, since this tracking doesn't happen for
invocations of anything other than `identical`.

Change-Id: I3e5473af095f3c8a747e9f527d7e14a21269dc95
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/389361
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Kallen Tu <kallentu@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
2024-10-24 16:37:11 +00:00
Johnni Winther 4d552d19eb [_fe_analyzer_shared] Rename StringJuxtaposition to AdjacentStringLiterals
Change-Id: I2ed9172f51f9a9011ca9dff59c62c42ffb56f05e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391605
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
2024-10-24 09:40:25 +00:00
Johnni Winther 4b2b07bf20 [_fe_analyzer_shared] Test late resolution of macro metadata
This delays the resolution of the identifier in metadata, such the
parsed annotation expression is initially unresolved and
`Expression.resolve` must be called in order to resolve it.

This execises the support for references to identifiers declare via
macros, which will initially occur as unresolved identifiers.

Change-Id: I4863ce950ded0b9d2c1744421d9751cddea6e80c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391641
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
2024-10-24 09:40:25 +00:00
Johnni Winther c0381d06b9 [_fe_analyzer_shared] Support enums in macro metadata
Change-Id: Ic6534fcbd48881184d6cb64c556d638f3e1d97b5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391601
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
2024-10-24 08:13:21 +00:00
Johnni Winther 875a130a42 [_fe_analyzer_shared] Support extension types in macro metadata
Change-Id: I91d4a2837285583ec8c05f0f8f3c4c906f861411
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391402
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
2024-10-24 08:13:21 +00:00
Johnni Winther bf16a40a97 [_fe_analyzer_shared] Support extensions in macro metadata
Change-Id: I06d3eeab53d8f739ec75dc5795ce46b57ef6f05b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391400
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
2024-10-23 07:48:23 +00:00
Johnni Winther 35db90aef6 [cfe][analyzer] Add metadata parser
This adds a shared metadata parser to be used for macros. The parser
create a new AST which supports unresolved ASTs and delayed AST resolution.
An id-test is added for the generated AST from both CFE and analyzer.

Change-Id: Ie51817493fa6e668727a7af3a55cd22e2be722b3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391100
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
2024-10-23 07:48:15 +00:00
Chloe Stefantsova d75fe77231 [anlyzer][cfe] Use bounds to restrict choices during inference
Closes https://github.com/dart-lang/language/issues/1194

Change-Id: I6866b6ab6f29cddbb293122e09588f705aaea1c1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/387020
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
2024-10-23 07:35:37 +00:00
Paul Berry c3ce683cca [Breaking change] Account for field promotion to Null when computing reachability based on equality tests.
Fixes https://github.com/dart-lang/sdk/issues/56893.
Fixes https://github.com/dart-lang/language/issues/4127.

Bug: https://github.com/dart-lang/sdk/issues/56893
Bug: https://github.com/dart-lang/language/issues/4127
Change-Id: If8bb0144ebe7024a7f4f7c1733e24632b4549c7f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/389660
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Kallen Tu <kallentu@google.com>
2024-10-22 22:10:50 +00:00
Kallen Tu 47d550277d [flow] Issue 1721 - Allow better promotions for final variables.
Promotions should happen for final variables because they are assigned and won't be re-assigned by the time they're evaluated. In a conservative join, promotions should not be cancelled for final variables.

Language tests made in https://dart-review.googlesource.com/c/sdk/+/390340.

Bug: https://github.com/dart-lang/language/issues/1721
Change-Id: I7bb577a694ddb5572a28884de70bd8c5b68e3c25
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/390803
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
2024-10-22 20:05:50 +00:00
Kallen Tu b85c499b60 [flow] Part 1 Issue 3658 - Store variable information after a write.
Assignments in the condition of an if statements don't store the promoted information (for the write of that variable). This fix stores the promotion of that expression for when we use it to null check or otherwise.

Part 1 because there's still some holes with postfix operators and null asserts that need to be fixed, but this behaviour stands on its own at the moment.

Everything is behind the flag so we'll iterate.

Bug: https://github.com/dart-lang/language/issues/3658
Change-Id: I8663f089a451468651efccadeb3991b34a37d899
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388903
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
2024-10-17 17:51:54 +00:00
Paul Berry 4f01b048dd Add tests reproducing language issue 4127.
These tests exercise the current (unintended) behavior described
https://github.com/dart-lang/language/issues/4127, which was
previously not well tested.

Adding these tests acts as a safeguard to make sure that we don't
change the current behavior by accident.  If/when we decide to fix
https://github.com/dart-lang/language/issues/4127, the test
expectations will need to be updated.

Bug: https://github.com/dart-lang/language/issues/4127
Change-Id: I02fd1d393038a304401d11cf2c19e97755ba90a0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/389584
Reviewed-by: Kallen Tu <kallentu@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-10-15 13:11:36 +00:00
Paul Berry e8ff9efe9a Add _PropertyElement.toString.
This improves the debug experience when debugging flow analysis code.

Change-Id: I876dece6213b0495caae5a9e673376898198e709
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/389221
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Kallen Tu <kallentu@google.com>
2024-10-10 17:40:03 +00:00
Paul Berry a1c805431e [cfe][analyzer] Change performSubtypeConstraintGenerationForFunctionTypes to return a bool.
Previously, this method returned `bool?`, however the only two
possible return values were `true` and `null`.

Change-Id: Ib111d6b3da87f8d04de884635fbec9ec7046dd8d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388860
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Auto-Submit: Paul Berry <paulberry@google.com>
2024-10-09 05:37:22 +00:00
Kallen Tu c8ee0e78a5 [flow] Pipe the language feature flag inference-update-4 through flow analysis.
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>
2024-10-08 16:32:24 +00:00
Paul Berry 38c08f919d [flow analysis] Remove ExpressionInfo.after.
Previously, the base `ExpressionInfo` class contained four fields:

- `type`: the type of the expression.

- `ifTrue`: a flow model describing the state of the program after the
  expression is evaluated, assuming the expression evaluates to
  `true`.

- `ifFalse`: a flow model describing the state of the program after
  the expression is evaluated, assuming the expression evaluates to
  `false`.

- `after`: a flow model describing the state of the prorgam after the
  expression is evaluated, making no assumptions about what value the
  expression evaluates to.

The `after` field was largely redundant, since it tracked the same
information as `FlowAnalysisImpl._current`. In fact, flow analysis
contained a substantial amount of code to copy from
`ExpressionInfo.after` to `FlowAnalysisImpl._current`, or vice versa,
in order to keep the two in sync.

The one exception was in `FlowAnalysisImpl.conditional_end`, which is
called at the end of visiting a conditional expression (`e1 ? e2 :
e3`): it joined the `after` flow models from `e2` and `e3` in order to
determine the state of the program after the conditional expression
completes. To preserve this behavior, a small amount of extra
accounting logic had to be added to the handling of conditional
expressions, to keep track of these flow models. (`e2.after` is now
stored in `_ConditionalContext.thenModel`, and `e3.after` comes from
the state of `_current` at the time of entry into
`FlowAnalysisImpl.conditional_end`).

Change-Id: I46e771f8b029550d43a5fe50366177f189a6a91d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388081
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Kallen Tu <kallentu@google.com>
2024-10-04 13:44:40 +00:00
Paul Berry 7a40688209 Sort named fields in mini types record representation.
This brings the "mini types" representation of records (which is used
for _fe_analyzer_shared unit tests) into alignment with the behavior
of analyzer and CFE record types (which sort their fields), and makes
the representation more consistent with that of function types.

Since all implementations of record types now maintain named fields in
sorted order, documentation has been added to
SharedRecordTypeStructure to indicate that the fields returned by the
`namedTypes` getter are sorted.

This exposed a minor bug in the error recovery logic in the shared
pattern type analyzer: upon encountering a record pattern with
duplicate field names, after reporting the appropriate error, it would
nonetheless attempt to create a record type containing duplicate
fields (potentially breaking the assumptions made by other code that
handles record types). This bug was fixed by adjusting the record
pattern analysis logic so that it drops duplicate field names when
constructing record types.

Change-Id: Ib06b86df980afcf17896e10ac7856f994aeda86f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388041
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-10-03 21:26:50 +00:00
Paul Berry b452721942 Change "mini types" type parameters to match CFE and analyzer.
Previously, the "mini types" representation used in
`_fe_analyzer_shared` unit tests represented unpromoted type
parameters using the `PrimaryType` class (which was also used for
interface types and special built-in types like `void`) and
represented promoted type parameters using a separate
`PromotedTypeVariableType` class.

This CL changes the "mini types" representation to use a single
`TypeParameterType` class for both unpromoted and promoted type
parameters.  This parallels the representation used by the analyzer
and CFE, so it should help pave the way for sharing type system logic
between the analyzer and CFE.

To allow the `Type` constructor to distinguish whether a given
identifier represents an interface type or a type variable, tests must
register all type names they will need, using either the static method
`TypeRegistry.addTypeParameter` or the static method
`TypeRegistry.addInterfaceTypeName`.

To prevent the type names registered by one unit test from interfering
with those registered by another, tests should call
`TypeRegistry.init` in a `setUp` callback and `TypeRegistry.uninit` in
a `tearDown` callback. Methods in `TypeRegistry` contain error checks
to help make sure these calls aren't forgotten.

Change-Id: I701842ad94899c819f1a059e660510a616d00456
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/387822
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-10-02 12:53:10 +00:00
Paul Berry e9e761644d [analyzer][cfe] Share constraint generation for non-generic function types
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>
2024-10-01 16:08:52 +00:00
Paul Berry 2a6d9cbb98 Introduce a shared base class for type parameters.
Change-Id: I341097643b6d6cec3c83c398a84aebbdf7500d09
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386736
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-09-30 14:40:36 +00:00
Paul Berry defce40d9d Expand mini-ast function type representation.
Mini-ast function types now support optional positional parameters and
named parameters (both required and optional).

This will allow more _fe_analyzer_shared functionality to be unit
tested.

Change-Id: I3425e0742de2bee511f2f3d303dd3ed6f26c289c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386729
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-09-30 12:21:36 +00:00
Chloe Stefantsova bc8104f3b2 [analyzer][cfe] Implement flow analysis for null-aware map entries
Closes https://github.com/dart-lang/sdk/issues/56786

Change-Id: I738c98b6f4e632cfbbe51221bbc3547edbc718fe
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386800
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
2024-09-30 09:48:27 +00:00
Paul Berry 6e249578f6 Add unit tests for _fe_analyzer_shared subtype functionality.
These tests cover just the portion of the subtype constraint
generation mechanism that's currently shared between the analyzer and
the CFE. I plan to add more unit tests as more functionality becomes
shared.

Note that as part of this change, I've eliminated the methods
`performSubtypeConstraintGenerationForFutureOrRightSchema` and
`performSubtypeConstraintGenerationForFutureOrLeftSchema`, and instead
made `_performSubtypeConstraintGenerationForFutureOrInternal` public
(renaming it to `performSubtypeConstraintGenerationForFutureOr`). My
rationale for this change is as follows:

- It makes testing easier, since only one method needs to be tested
  rather than two.

- Removing these two methods simplifies the call sites in the analyzer
  and CFE, since instead of having to use an `if` test to decide which
  method to call, they can simply pass in the appropriate boolean
  switch for the `leftSchema` argument.

Change-Id: I0911c80fc8e9a4fbdd3dd0063dd203066006c218
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386861
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
2024-09-26 13:38:13 +00:00
Paul Berry 72c2e73f0b Fill out return type of TypeAnalyzerOperations.matchTypeDeclarationType
The return type of this method was previously
`TypeDeclarationMatchResult?` (with no explicit type arguments),
meaning that the generic type parameters of
`TypeDeclarationMatchResult` would be filled in by
instantiate-to-bounds as `Object, Object, Object`. But the
implementations always return the more precise type
`TypeDeclarationMatchResult<TypeDeclarationType, TypeDeclaration,
TypeStructure>?`, and the use sites all expect this type. Adding
explicit type arguments improves type safety and probably allows the
compiler to elide some of the type casts involved in pattern matching.

Also, the "mini_ast" implementation of this method contained a subtle

bug: instead of using `unwrappedType.type` for the `typeDeclaration`
Change-Id: Ic7bffc1b0b3e9bfc86c0168d4e6bdf442af8ae39
argument, it should use `unwrappedType.name`. This ensures that if the
type being matched is generic, the generic arguments don't show up in
the `typeDeclaration`.
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386681
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-09-26 13:32:20 +00:00
Paul Berry 13d4eaf99a Implement matchInferableParameter in MiniAstOperations.
Previously the implementation of this method was a stub.

It turns out that all the necessary infrastructure was in place
already, however the type arguments supplied by MiniAstOperations to
TypeAnalyzerOperationsMixin and TypeAnalyzerOperations needed to be
changed: in the "mini_ast" representation of types, an
InferableParameter is represented by a String, not a
PromotedTypeVariableType. This is because InferableParameter is meant
to represent the declaration of the type parameter
(StructuralParameter for the CFE, TypeParameterElement for the
analyzer), not the type itself. The types used for unit testing in
_fe_analyzer_shared don't have a separate notion of the declaration of
a type parameter, so we just use its name.

Implementing this logic required adding a method
`TypeSystem.matchTypeParameterType`, which checks if a Type is a type
parameter type, and returns the name of the type parameter if so. I
based this on the previously existing `TypeSystem._isTypeVar` method
(which performed the same job but did not return the type parameter
name).

I also took the liberty of fixing a flow analysis test that treated
`T` as a type variable but failed to mark it as a type variable by
calling `addTypeVariable`.

This should help pave the way for unit testing more of the shared
infrastructure for types.

Change-Id: Ia7a9777ec3d90a5886567dcb9f831e388e372f32
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386607
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-09-25 12:23:01 +00:00
Jens Johansen 3dce89fbe0 [scanner] Don't give the Utf8 scanner a 0-terminated byte sequence
Not having to do the read-allocate-copy dance for files to add a 0-byte
at the end results in these changes when using the CFE to compile
(a fixed version of) the CFE:

```
msec task-clock:u: -1.7356% +/- 0.2164% (-73.16 +/- 9.12)
page-faults:u: -2.6957% +/- 0.0111% (-2914.83 +/- 12.00)
cycles:u: -1.7128% +/- 0.2223% (-297927979.70 +/- 38660477.01)
instructions:u: -1.6814% +/- 0.0002% (-361315766.86 +/- 36853.71)
branch-misses:u: -3.3289% +/- 0.9669% (-2153126.00 +/- 625370.97)
seconds time elapsed: -1.7372% +/- 0.2154% (-0.07 +/- 0.01)
seconds user: -1.5998% +/- 0.2740% (-0.06 +/- 0.01)
seconds sys: -4.1451% +/- 2.9801% (-0.01 +/- 0.01)
Scavenge(   new space) goes from 62 to 61
```

TEST=Existing test coverage.

Change-Id: I8e182bcee39839f6ed1e658c30c85c40ecf0b259
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385722
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Morgan :) <davidmorgan@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
2024-09-25 08:33:48 +00:00
Jens Johansen 3f24e57422 [scanner] Add scanner benchmark
E.g. we might do this

```
$ out/ReleaseX64/dart-sdk/bin/dart compile aot-snapshot pkg/_fe_analyzer_shared/test/scanner_benchmark.dart
Generated: /usr/local/google/home/jensj/code/dart-sdk/sdk/pkg/_fe_analyzer_shared/test/scanner_benchmark.aot

$ for type in --bytes --bytes0 --string --stringtobytes --count ; do out/ReleaseX64/dart-sdk/bin/dartaotruntime pkg/_fe_analyzer_shared/test/scanner_benchmark.aot pkg/kernel/lib/ast.dart $type; done
Scanned 466534 bytes 1000 times in 0:00:04.413011
Found errors 0 times
That's 105.71784208106438 bytes per microsecond

Scanned 466534 bytes 1000 times in 0:00:04.911947
Found errors 0 times
That's 94.97944501437007 bytes per microsecond

Scanned 466532 string characters 1000 times in 0:00:05.413169
Found errors 0 times
That's 86.18463602374136 string characters per microsecond

Scanned 466532 string characters as bytes 1000 times in 0:00:06.722731
Found errors 0 times
That's 69.39620222793386 string characters as bytes per microsecond

Scanned 466534 bytes 1000 times in 0:00:00.641854
Found errors 0 times
That's 726.8537704836302 bytes per microsecond
```

to see that scanning pre-0-at-the-end'ed bytes scan at ~105 bytes/µs,
doing a copy to add the 0 at then end, then parse bytes scan at ~95,
scanning strings runs at ~86, converting strings to bytes, then scanning
the bytes at ~69 and - for comparision - just running through the bytes
counting linebreaks runs at ~726.

The benchmark is also useful for comparing optimizations.

Change-Id: I67c12850505e7f712660fd353575e8c7a455f112
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385920
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
2024-09-25 06:47:14 +00:00
Chloe Stefantsova 3e85a29951 [cfe] Use the type of the coerced expression in inference
Closes https://github.com/dart-lang/sdk/issues/56666
Closes https://github.com/dart-lang/sdk/issues/33298

Change-Id: I4873247d89aad858df78795c031a4fb65b9a0e2a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385560
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
2024-09-20 08:02:50 +00:00
Paul Berry a3c696fa58 Properly report unreachable switch cases containing when clauses.
When determining whether a switch statement is exhaustive, it's
important for the exhaustiveness algorithm to ignore cases containing
`when` clauses, since a `when` clause creates the possiblity that the
case won't match.

Previously, the way this was done in the analyzer was for the
`SpaceCreator.createRootSpace` method to create an unknown space for
cases containing `when` clauses. This approach produced the correct
behavior when determining whether the switch statement as a whole was
exhaustive, but since it discarded information about the pattern being
matched, it limited the ability to determine whether an individual
case was reachable, leading to
https://github.com/dart-lang/sdk/issues/56710.

To fix this, `SpaceCreator.createRootSpace` is changed so that it
always produces a space that describes the case pattern, regardless of
whether a `when` clause is present, and instead,
`computeExhaustiveness` is responsible for ensuring that the case is
properly excluded from the determination of whether the switch is
exhaustive. This allows `computeExhaustiveness` to properly computate
whether each individual case is reachable, even for cases that have
`when` clauses.

This change in approach produced some minor differences in the test
cases in `pkg/_fe_analyzer_shared/test/exhaustiveness/data`, but these
differences are not user-observable.

Fixes https://github.com/dart-lang/sdk/issues/56710.

Change-Id: I36629a77c4c1832fb1b8abb6ea7b109e0ca14373
Bug: https://github.com/dart-lang/sdk/issues/56710
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384326
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-09-12 16:30:22 +00:00
Paul Berry cda2815bb1 Add UNREACHABLE_SWITCH_DEFAULT warning to the analyzer.
This warning is similar to the existing `UNREACHABLE_SWITCH_CASE`
warning, except that it warns if the `default` clause of a switch
statement is unreachable due to all the `case` clasuses fully
exhausting the switched type.

To make the implementation easier, I changed the API for the
`reportExhaustiveness` method in `_fe_analyzer_shared` (which is the
primary entry point to the shared exhaustiveness checker). Previously,
this method returned a list of `ExhaustivenessError`, where each list
element was either an `UnreachableCaseError` (indicating that a
certain case was unreachable) or a `NonExhaustiveError` (indicating
that the entire switch statement was not exhaustive). If the caller
passed in `false` for `computeUnreachable`, `UnreachableCaseError`s
would not be returned, so the returned list would either be empty or
contain a single `NonExhaustiveError`.

The new API renames the types for clarity:

- `NonExhaustiveError` becomes `NonExhaustiveness`, to highlight the
  fact that it's not necessarily an error for the switch's cases to be
  non-exhaustive; it's only an error if the scrutinee's static type is
  an "always exhaustive" type and there is no `default` clause.

- `UnreachableCaseError` becomes `CaseUnreachability`, to highlight
  the fact that it's not an error for a case to be unreachable; it's a
  warning.

Also, the new API adds instances of `CaseUnreachability` to an
optional user-provided list instead of returning a newly created list;
this allows callers to communicate that they don't need to see
`CaseUnreachability` information by passing `null`. This frees up the
return type to simply be an instance of `NonExhaustiveness` (if the
cases are not exhaustive) or `null` (if they are exhaustive). This
makes it easier for the analyzer to decide whether to issue the new
warning, because it doesn't have to dig around the list looking for an
instance of `NonExhaustiveness`.

The new warning has an associated quick fix (remove the unreachable
`default` clause). This quick fix uses the same `RemoveDeadCode` logic
in the analysis server that the existing `UNREACHABLE_SWITCH_CASE`
warning uses.

Fixes https://github.com/dart-lang/sdk/issues/54575.

Bug: https://github.com/dart-lang/sdk/issues/54575
Change-Id: I18b6b7c5249d77d28ead7488b4aae4ea65c4b664
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/378960
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Erik Ernst <eernst@google.com>
2024-09-10 19:13:12 +00:00
Chloe Stefantsova 3acd125e44 [analyzer][cfe] Implement types and type schemas as extension types
This CL removes Type and TypeSchema type variables from the abstract
classes with shared code between the CFE and the analyzer. Extension
types SharedTypeView and SharedTypeSchemaView are declared to replace
the type variables.

The update propagates the discipline of distinguishing between types
and type schemas into the clients of the shared code. Now the code in
the CFE and the Analyzer that uses the shared code needs to statically
specify the interpretation of their type objects as either types or
type schemas.

Another benefit of the update is SharedTypeView and
SharedTypeSchemaView being less opaque than the Type and TypeSchema
type variables, which removes the necessity for some code duplication
in abstract methods for types and type schemas.

Finally, the update enables some further changes in the shared code
between the Analyzer and the CFE.

Change-Id: I88e8cfcd47d4f721974b4f2612521e85bb54c30f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/379302
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
2024-08-23 08:10:09 +00:00
Chloe Stefantsova cf0e927a43 [analyzer][cfe] Make SharedType into a family of recursive types
SharedType and its subtypes now all declare one recursive type
variable Type with the bound SharedType<Type>. It allows to treate
SharedType and its subtypes as an abstract familty of types that has a
specific structure.

More specifically, the type variables Type and TypeSchema in the
abstract classes for shared algorithms between the Analyzer and the
CFE can now be defined recursively as extending SharedType<Type> and
SharedType<TypeSchema>, giving both types and type schemas the
structure of the family of types with the root at SharedType.

One of the benefits for that is that some abstract members become
unnecessary. For example, a type or type schema can now be tested for
having the shape of the type 'dynamic' with a direct is-check,
comparing them, correspondingly, with SharedType<Type> and
SharedType<TypeSchema>.

More importantly, having the family of recursive types lays the
foundation for further work on sharing the type structure between the
Analyzer and the CFE.

Change-Id: I67904f878668c035702092e8c21d3ce66f5ca469
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/378700
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
2024-08-09 07:10:42 +00:00
Chloe Stefantsova 2522063236 [analyzer][cfe] Introduce shared TypeConstraintGenerator class
The shared abstract class TypeConstraintGenerator is introduced and is
set as the parent for both the Analyzer's TypeConstraintGatherer and
the CFE's TypeConstraintGenerator. The interface of the shared
abstract class is minimal, to support the treatment of the discrepancy
between the Analyzer and the CFE around FutureOr types.

The discrepancy between the Analyzer and the CFE is seaprated out into
a smaller method and can be controlled via a boolean flag that
switches between the behaviors of the two frontends. The flag is
called requiredEmptyNullabilitySuffix and is passed as a named
parameter to
TypeConstraintGenerator.performSubtypeConstraintGenerationForFutureOr.

In response to https://github.com/dart-lang/sdk/issues/55344

Part of https://github.com/dart-lang/sdk/issues/54902

Change-Id: I272b57b573377a54977a516ce6e378953bd1c0e8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373480
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
2024-07-19 08:07:06 +00:00
Paul Berry 0c2d58eeac Fix comment references in type_inference and mini_*.dart.
Fix bracketed references in doc comments that previously pointed to
nowhere, in the following source code:

- Shared type inference logic
  (pkg/_fe_analyzer_shared/lib/src/type_inference/...).

- Testing infrastructure that exercises shared type inference logic
  and flow analysis (pkg/_fe_analyzer_shared/test/mini_*.dart).

This is part of a larger effort to clean up _fe_analyzer_shared to the
point where the `comment_references` lint can be enabled.

Change-Id: I15e6133dc7631c9a634131f0df3a3ff14f568e3b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/375201
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-07-10 23:20:18 +00:00
Sam Rawlins 5e8ee77772 Support digit separators
Work towards https://github.com/dart-lang/language/issues/2

The feature is well-specified at the issue, but I will also follow
up with a specification to check into the language repo.

This change implements the feature more-or-less from front to back
(because the back is very close to the front in this case :P; no
"backend" work in the VM, etc). Digit separators are made available
via a new experiment, `digit-separators`.

Care is taken to report a single error when an underscore appears in
an unexpected position (see new `separators_error_test.dart`).

Three test files are added:

* `separators_test.dart` is run with the experiment enabled, and has
  no compile-time errors.
* `separators_error_test.dart` is run with the experiment enabled, and
  has many compile-time errors.
* `separators_error_no_experiment_test.dart` is run with the
  experiment _disabled_.

Change-Id: I7f1b1305d28b708b5ddf83f26188cd6e9ce3dd58
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365181
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Reviewed-by: Kevin Moore <kevmoo@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
2024-07-09 14:50:59 +00:00
Johnni Winther 4692937341 [cfe] Support extension types in macro introspection
Change-Id: I946ba3461ca2ff897cf4c1071b3aa356bf835535
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/368102
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
2024-06-03 13:04:31 +00:00
Paul Berry 547307e554 Add SharedType.nullabilitySuffix getter.
This allows TypeAnalyzerOperations.getNullabilitySuffix to be removed,
and allows shared code to access nullability suffixes directly as
properties of a type, in the same way that the analyzer does.

Change-Id: I33ab90798b779534b5b0b111ec5137845b32f23b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/368443
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-05-30 16:43:29 +00:00
Johnni Winther a59faa2636 [cfe] Remove nnbd annotation from id-tests
Change-Id: Ib63b80e19027389cec41adf705829b5d4201c0d8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366669
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
2024-05-24 10:44:54 +00:00
Johnni Winther eccaf152ee [cfe] Change more nnbd default modes to strong
Change-Id: Iab51c30024764ebd1c82991ad8687e7accf999f9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366661
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
2024-05-16 07:44:10 +00:00
Paul Berry 1b075fb407 Mini_types: rework representation of nullability to match analyzer.
The "mini_types" representation (used for unit testing of shared flow
analysis and type analysis code) is reworked so that it represents
nullabilities in the same way as the analyzer (and in a more similar
way to the CFE), namely: each type has a field `nullabilitySuffix`
indicating whether the type is followed by `?`, `*`, or neither.

This change ensures that `is` and `as` tests using the mini_types
representation (e.g. `is FunctionType`) will behave the same way as
they ehave in the analyzer and CFE; this in turn should lead to
additional opportunities to share code between the analyzer and CFE.

Change-Id: Ia5d963eb96e225e62df71a406d4024053311df88
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365700
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-05-10 15:42:51 +00:00
Paul Berry b64c9ee5e9 Mini_types: Improve toString logic.
The `toString` logic in `mini_types.dart` is improved in the following ways:

- The `toString` representation of the "unknown" type is changed from
  `?` to `_`, to match the behavior of the mini_types parser.

- Logic for applying parentheses is simplified and moved into the
  function `_parenthesizeIf`.

- The boolean `allowSuffixes` (which was not well documented, and
  poorly named) is replaced with a boolean `parenthesizeIfComplex`,
  and documentation is added to clarify its behavior.

- Unit tests of `toString` are added to `mini_types_test.dart`.

Change-Id: I251e137369b5880017022be2514f00975a511e72
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365660
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-05-08 20:38:30 +00:00
Johnni Winther 6bec589f00 [cfe] Add least supported version check of 2.12
Change-Id: Iff8a3ea624b7130cb09359fbc9787a98ba07c4e5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/364700
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
2024-05-08 09:28:45 +00:00
Paul Berry 0d8bb0e7e7 Share more analyzer/CFE code related to types.
This commit builds on the work done in
https://dart-review.googlesource.com/c/sdk/+/362481, which established
the framework for sharing a class hierarchy between the analyzer and
CFE to represent types.

This commit introduces the following new classes:

- `SharedDynamicType`, which represents the common interface between
  the `DynamicType` classes in the analyzer and the CFE.

- `SharedInvalidType`, which represents the common interface between
  the `InvalidType` classes in the analyzer and the CFE.

- `SharedVoidType`, which represents the common interface between the
  `VoidType` classes in the analyzer and the CFE.

This allows 3 methods to be removed from the
`FlowAnalysisTypeOperations` class:

- `isDynamic`, which is no longer needed becasue `is
  SharedDynamicType` can be used instead.

- `isError`, which is no longer needed because `is SharedInvalidType`
  can be used instead.

- `isVoid`, which is no longer needed because `is SharedVoidType` can
  be used instead.

In addition, `getDisplayString` is removed from the
`TypeAnalyzerOperations` class, and replaced with a `getDisplayString`
method in `SharedType`. This does not increase the API surface area of
the analyzer, because the analyzer already has a
`DartType.getDisplayString` method.

Change-Id: Ib8d9d3a7699f3d1e8b9612ca9c8f4134fa19de77
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365303
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-05-03 12:22:13 +00:00
Paul Berry 51d93de528 mini_types: introduce new classes for special built-in types.
New classes are introduced into the "mini_types" representation to
represent `dynamic`, `FutureOr<T>`, `Never`, `Null`, `void`, and the
"invalid" type. Previously, these were all represented simply using
`PrimaryType`.

Introducing new classes for these types makes the "mini_types"
representation more consistent with the representations used by the
analyzer and the front end. Since the "mini_types" representation is
used solely for unit testing the shared logic in the
`_fe_analyzer_shared` package, it's hard to justify unnecessary
differences between it and the analyzer and front end representations;
these differences just make it harder to effectively share code.

Change-Id: Ie633feef914c5ce4540b9da681a84b7f53fd8f38
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365340
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2024-05-03 12:17:37 +00:00