|  | // Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | // Tests that field promotion distinguishes `this` accesses from `super` | 
|  | // accesses when they resolve to different fields. | 
|  |  | 
|  | // In this test, the fields in question have generic types. This is an important | 
|  | // special case to test because the analyzer uses special "Member" data | 
|  | // structures to track accesses to fields with generic types. | 
|  |  | 
|  | // Since the analyzer has different logic for resolving ordinary variable gets | 
|  | // and variable gets that look like member invocations, both scenarios are | 
|  | // tested. | 
|  |  | 
|  | import '../static_type_helper.dart'; | 
|  |  | 
|  | class Base<T extends Object> { | 
|  | final T? _t; | 
|  | final T? Function() _f; | 
|  | Base(this._t, this._f); | 
|  | } | 
|  |  | 
|  | /// In this class, `_t` and `_f` override the declarations of `_t` and `_f` in | 
|  | /// `super`, so their promotions should be tracked separately. | 
|  | class DerivedClassThatOverridesBaseMembers<T extends Object> extends Base<T> { | 
|  | final T? _t; | 
|  | final T? Function() _f; | 
|  | DerivedClassThatOverridesBaseMembers( | 
|  | this._t, this._f, T? superI, T? Function() superF) | 
|  | : super(superI, superF); | 
|  |  | 
|  | void ordinaryVariableGet() { | 
|  | _t.expectStaticType<Exactly<T?>>(); | 
|  | this._t.expectStaticType<Exactly<T?>>(); | 
|  | super._t.expectStaticType<Exactly<T?>>(); | 
|  | if (_t != null) { | 
|  | _t.expectStaticType<Exactly<T>>(); | 
|  | this._t.expectStaticType<Exactly<T>>(); | 
|  | super._t.expectStaticType<Exactly<T?>>(); | 
|  | } | 
|  | if (this._t != null) { | 
|  | _t.expectStaticType<Exactly<T>>(); | 
|  | this._t.expectStaticType<Exactly<T>>(); | 
|  | super._t.expectStaticType<Exactly<T?>>(); | 
|  | } | 
|  | if (super._t != null) { | 
|  | _t.expectStaticType<Exactly<T?>>(); | 
|  | this._t.expectStaticType<Exactly<T?>>(); | 
|  | super._t.expectStaticType<Exactly<T>>(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void invokedVariableGet() { | 
|  | _f().expectStaticType<Exactly<T?>>(); | 
|  | this._f().expectStaticType<Exactly<T?>>(); | 
|  | super._f().expectStaticType<Exactly<T?>>(); | 
|  | if (_f is T Function()) { | 
|  | _f().expectStaticType<Exactly<T>>(); | 
|  | this._f().expectStaticType<Exactly<T>>(); | 
|  | super._f().expectStaticType<Exactly<T?>>(); | 
|  | } | 
|  | if (this._f is T Function()) { | 
|  | _f().expectStaticType<Exactly<T>>(); | 
|  | this._f().expectStaticType<Exactly<T>>(); | 
|  | super._f().expectStaticType<Exactly<T?>>(); | 
|  | } | 
|  | if (super._f is T Function()) { | 
|  | _f().expectStaticType<Exactly<T?>>(); | 
|  | this._f().expectStaticType<Exactly<T?>>(); | 
|  | super._f().expectStaticType<Exactly<T>>(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// In this class, `_i` and `_f` refer to the declarations of `_i` and `_f` in | 
|  | /// `super`. However, accesses made through `this` still promote independently | 
|  | /// from accesses made through `super`, since this is simpler to implement, has | 
|  | /// no soundness problems, and is unlikely to cause problems in real-world code. | 
|  | class DerivedClassThatOverridesNothing<T extends Object> extends Base<T> { | 
|  | DerivedClassThatOverridesNothing(super._t, super.f); | 
|  |  | 
|  | void ordinaryVariableGet() { | 
|  | _t.expectStaticType<Exactly<T?>>(); | 
|  | this._t.expectStaticType<Exactly<T?>>(); | 
|  | super._t.expectStaticType<Exactly<T?>>(); | 
|  | if (_t != null) { | 
|  | _t.expectStaticType<Exactly<T>>(); | 
|  | this._t.expectStaticType<Exactly<T>>(); | 
|  | super._t.expectStaticType<Exactly<T?>>(); | 
|  | } | 
|  | if (this._t != null) { | 
|  | _t.expectStaticType<Exactly<T>>(); | 
|  | this._t.expectStaticType<Exactly<T>>(); | 
|  | super._t.expectStaticType<Exactly<T?>>(); | 
|  | } | 
|  | if (super._t != null) { | 
|  | _t.expectStaticType<Exactly<T?>>(); | 
|  | this._t.expectStaticType<Exactly<T?>>(); | 
|  | super._t.expectStaticType<Exactly<T>>(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void invokedVariableGet() { | 
|  | _f().expectStaticType<Exactly<T?>>(); | 
|  | this._f().expectStaticType<Exactly<T?>>(); | 
|  | super._f().expectStaticType<Exactly<T?>>(); | 
|  | if (_f is T Function()) { | 
|  | _f().expectStaticType<Exactly<T>>(); | 
|  | this._f().expectStaticType<Exactly<T>>(); | 
|  | super._f().expectStaticType<Exactly<T?>>(); | 
|  | } | 
|  | if (this._f is T Function()) { | 
|  | _f().expectStaticType<Exactly<T>>(); | 
|  | this._f().expectStaticType<Exactly<T>>(); | 
|  | super._f().expectStaticType<Exactly<T?>>(); | 
|  | } | 
|  | if (super._f is T Function()) { | 
|  | _f().expectStaticType<Exactly<T?>>(); | 
|  | this._f().expectStaticType<Exactly<T?>>(); | 
|  | super._f().expectStaticType<Exactly<T>>(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | main() { | 
|  | int f() => 0; | 
|  | int? g() => null; | 
|  | DerivedClassThatOverridesBaseMembers<int>(0, f, null, g) | 
|  | ..ordinaryVariableGet() | 
|  | ..invokedVariableGet(); | 
|  | DerivedClassThatOverridesBaseMembers<int>(null, g, 0, f) | 
|  | ..ordinaryVariableGet() | 
|  | ..invokedVariableGet(); | 
|  | DerivedClassThatOverridesNothing<int>(0, f) | 
|  | ..ordinaryVariableGet() | 
|  | ..invokedVariableGet(); | 
|  | } |