dart-sdk/pkg/_fe_analyzer_shared/test
Paul Berry 9a3420f1d4 Flow analysis: fix field promotion within cascades of non-promotable targets.
Previously, flow analysis used a hack to make it easy to generate "why
not promoted" messages when the user tried to promote a non-promotable
field: it treated all field accesses as stable for the purpose of
assigning SSA nodes, but avoided promoting non-promotable fields by
setting the `_Reference.isPromotable` flag to `false`. So, for
instance, in the following code, both subexpressions `c.i` got
assigned the same SSA node, even though there's no guarantee that
`C.x` will return the same value each time it's invoked.

    class C {
      int? get i => ...;
    }
    f(C c) {
      if (c.i != null) {
        var i = c.i; // Inferred type `int?`
      }
    }

This mostly worked, since the SSA node assigned by flow analysis is
only used for promotion, and promotion is disabled for non-promotable
fields. However, it broke when the field in question was used as the
target of a cascade, because fields within cascades always had their
`_Reference.isPromotable` flag set to `true` regardless of whether the
corresponding cascade target is promotable. For example:

    class C {
      D? get d => ...;
    }
    class D {
      final E? _e;
      ...
    }
    class E {
      m() { ... }
    }
    f(C c) {
      (c.d)
        .._e!.m() // OK; promotes _e
        .._e.m(); // OK; _e is promoted now
      (c.d)
        .._e.m(); // OOPS, _e is still promoted; it shouldn't be
    }

See
`tests/language/inference_update_2/cascaded_field_promotion_unstable_target_test.dart`
for a more detailed example.

This CL removes the hack; now, when a non-promotable property is
accessed more than once, flow analysis assignes a different SSA node
for each access. As a result, the `_Reference.isPromotable` is not
needed, because non-promotable fields simply never have the chance to
be promoted (since every field access gets a separate SSA node, so
type checking one field access has no effect on others).

To preserve the ability to generate "why not promoted" messages, the
`_PropertySsaNode` class now contains a `previousSsaNode` pointer,
which links together the separate SSA nodes allocated for
non-promotable properties, so that they form a linked list. The "why
not promoted" logic traverses this list to figure out which promotions
*would* have occurred if the property had been promotable.

In order to make it efficient to create this linked list, the
`SsaNode` class also had to acquire a `_nonPromotableProperties` map,
which records the SSA node that was allocated the last time each
property was accessed.

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

Change-Id: I16a7b27f77c309bdccce86195a53398e32e8f75d
Bug: https://github.com/dart-lang/sdk/issues/52728
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/318745
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
2023-08-08 17:26:09 +00:00
..
constants [analyzer] Refactor visitMethodInvocation in the const evaluator. 2023-06-30 18:32:27 +00:00
exhaustiveness [_fe_analyzer_shared] Add test for issue 52908 2023-07-19 13:54:10 +00:00
flow_analysis Flow analysis: fix field promotion within cascades of non-promotable targets. 2023-08-08 17:26:09 +00:00
inference
inheritance/data [cfe] Disallow implementing a legacy library subclass of a final/base class in the core libraries. 2023-05-10 14:31:50 +00:00
macros add hasBody getter to FunctionDeclaration 2023-08-01 16:00:29 +00:00
sdk
type_inference Unify "mini-ast" constructs for rest pattern elements. 2023-07-25 16:36:28 +00:00
util
annotated_code_helper_test.dart
deferred_function_literal_heuristic_test.dart
field_promotability_test.dart Field promotion: make the core promotability algorithm sharable; fix bugs 2023-07-18 18:54:26 +00:00
id_generation_test.dart [cfe] Remove unnecessary_null_comparison code 2023-06-08 08:46:47 +00:00
mini_ast.dart Unify "mini-ast" constructs for rest pattern elements. 2023-07-25 16:36:28 +00:00
mini_ir.dart Rename Ir to IR, per dart style conventions 2023-06-19 08:47:00 +00:00
mini_types.dart Use errorType for element type when an error in for-in. 2023-05-03 21:17:08 +00:00
mini_types_test.dart
resolve_input_uri_test.dart
template_replacement_test.dart