blob: cab022fd64d4f39bd87b5db466d500cb93d05afc [file] [log] [blame]
// 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.
// 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 {
final int? _i;
final int? Function() _f;
Base(this._i, this._f);
}
/// In this class, `_i` and `_f` override the declarations of `_i` and `_f` in
/// `super`, so their promotions should be tracked separately.
class DerivedClassThatOverridesBaseMembers extends Base {
final int? _i;
final int? Function() _f;
DerivedClassThatOverridesBaseMembers(
this._i, this._f, int? superI, int? Function() superF)
: super(superI, superF);
void ordinaryVariableGet() {
_i.expectStaticType<Exactly<int?>>();
this._i.expectStaticType<Exactly<int?>>();
super._i.expectStaticType<Exactly<int?>>();
if (_i != null) {
_i.expectStaticType<Exactly<int>>();
this._i.expectStaticType<Exactly<int>>();
super._i.expectStaticType<Exactly<int?>>();
}
if (this._i != null) {
_i.expectStaticType<Exactly<int>>();
this._i.expectStaticType<Exactly<int>>();
super._i.expectStaticType<Exactly<int?>>();
}
if (super._i != null) {
_i.expectStaticType<Exactly<int?>>();
this._i.expectStaticType<Exactly<int?>>();
super._i.expectStaticType<Exactly<int>>();
}
}
void invokedVariableGet() {
_f().expectStaticType<Exactly<int?>>();
this._f().expectStaticType<Exactly<int?>>();
super._f().expectStaticType<Exactly<int?>>();
if (_f is int Function()) {
_f().expectStaticType<Exactly<int>>();
this._f().expectStaticType<Exactly<int>>();
super._f().expectStaticType<Exactly<int?>>();
}
if (this._f is int Function()) {
_f().expectStaticType<Exactly<int>>();
this._f().expectStaticType<Exactly<int>>();
super._f().expectStaticType<Exactly<int?>>();
}
if (super._f is int Function()) {
_f().expectStaticType<Exactly<int?>>();
this._f().expectStaticType<Exactly<int?>>();
super._f().expectStaticType<Exactly<int>>();
}
}
}
/// 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 extends Base {
DerivedClassThatOverridesNothing(super._i, super.f);
void ordinaryVariableGet() {
_i.expectStaticType<Exactly<int?>>();
this._i.expectStaticType<Exactly<int?>>();
super._i.expectStaticType<Exactly<int?>>();
if (_i != null) {
_i.expectStaticType<Exactly<int>>();
this._i.expectStaticType<Exactly<int>>();
super._i.expectStaticType<Exactly<int?>>();
}
if (this._i != null) {
_i.expectStaticType<Exactly<int>>();
this._i.expectStaticType<Exactly<int>>();
super._i.expectStaticType<Exactly<int?>>();
}
if (super._i != null) {
_i.expectStaticType<Exactly<int?>>();
this._i.expectStaticType<Exactly<int?>>();
super._i.expectStaticType<Exactly<int>>();
}
}
void invokedVariableGet() {
_f().expectStaticType<Exactly<int?>>();
this._f().expectStaticType<Exactly<int?>>();
super._f().expectStaticType<Exactly<int?>>();
if (_f is int Function()) {
_f().expectStaticType<Exactly<int>>();
this._f().expectStaticType<Exactly<int>>();
super._f().expectStaticType<Exactly<int?>>();
}
if (this._f is int Function()) {
_f().expectStaticType<Exactly<int>>();
this._f().expectStaticType<Exactly<int>>();
super._f().expectStaticType<Exactly<int?>>();
}
if (super._f is int Function()) {
_f().expectStaticType<Exactly<int?>>();
this._f().expectStaticType<Exactly<int?>>();
super._f().expectStaticType<Exactly<int>>();
}
}
}
main() {
int f() => 0;
int? g() => null;
DerivedClassThatOverridesBaseMembers(0, f, null, g)
..ordinaryVariableGet()
..invokedVariableGet();
DerivedClassThatOverridesBaseMembers(null, g, 0, f)
..ordinaryVariableGet()
..invokedVariableGet();
DerivedClassThatOverridesNothing(0, f)
..ordinaryVariableGet()
..invokedVariableGet();
}