mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:09:49 +00:00
9d933d1281
Tested: No new tests. Change-Id: Idf19ce8b6743b221841e6cef6b2a80e8ab37860e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/354260 Auto-Submit: Lasse Nielsen <lrn@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com> Reviewed-by: Nate Bosch <nbosch@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com> Commit-Queue: Lasse Nielsen <lrn@google.com>
139 lines
4.7 KiB
Dart
139 lines
4.7 KiB
Dart
// 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();
|
|
}
|