mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 14:32:24 +00:00
9a3420f1d4
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> |
||
---|---|---|
.. | ||
constants | ||
exhaustiveness | ||
flow_analysis | ||
inference | ||
inheritance/data | ||
macros | ||
sdk | ||
type_inference | ||
util | ||
annotated_code_helper_test.dart | ||
deferred_function_literal_heuristic_test.dart | ||
field_promotability_test.dart | ||
id_generation_test.dart | ||
mini_ast.dart | ||
mini_ir.dart | ||
mini_types.dart | ||
mini_types_test.dart | ||
resolve_input_uri_test.dart | ||
template_replacement_test.dart |