mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
[dart2js] Implement Cell lowering for uninitialized locals.
Change-Id: I7233e1484cc19e5f24d215bfd2c1e34c8f12961b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193588 Commit-Queue: Mayank Patke <fishythefish@google.com> Reviewed-by: Stephen Adams <sra@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
c089922d2a
commit
8f832e2c6b
8 changed files with 346 additions and 216 deletions
|
@ -62,10 +62,6 @@ int _foldLateLowerings(List<int> lowerings) =>
|
|||
|
||||
/// Late lowerings which the frontend performs for dart2js.
|
||||
const List<int> _allEnabledLateLowerings = [
|
||||
LateLowering.nullableUninitializedNonFinalLocal,
|
||||
LateLowering.nonNullableUninitializedNonFinalLocal,
|
||||
LateLowering.nullableUninitializedFinalLocal,
|
||||
LateLowering.nonNullableUninitializedFinalLocal,
|
||||
LateLowering.nullableInitializedNonFinalLocal,
|
||||
LateLowering.nonNullableInitializedNonFinalLocal,
|
||||
LateLowering.nullableInitializedFinalLocal,
|
||||
|
@ -167,8 +163,7 @@ class Dart2jsTarget extends Target {
|
|||
_nativeClasses)
|
||||
.visitLibrary(library);
|
||||
}
|
||||
lowering.transformLibraries(
|
||||
libraries, coreTypes, hierarchy, flags.enableNullSafety);
|
||||
lowering.transformLibraries(libraries, coreTypes, hierarchy);
|
||||
logger?.call("Lowering transformations performed");
|
||||
}
|
||||
|
||||
|
|
112
pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
Normal file
112
pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/library_index.dart';
|
||||
import 'package:kernel/type_algebra.dart';
|
||||
|
||||
bool _shouldLowerVariable(VariableDeclaration node) =>
|
||||
node.initializer == null && node.isLate;
|
||||
|
||||
class LateLowering {
|
||||
final Class _cellClass;
|
||||
final Constructor _cellConstructor;
|
||||
|
||||
final Procedure _readLocal;
|
||||
List<TypeParameter> _readLocalTypeParameters;
|
||||
FunctionType _readLocalTypeWithoutTypeParameters;
|
||||
|
||||
final Procedure _setValue;
|
||||
final Procedure _setFinalLocalValue;
|
||||
|
||||
final Map<VariableDeclaration, VariableDeclaration> _cells = {};
|
||||
|
||||
Member _contextMember;
|
||||
|
||||
LateLowering(LibraryIndex index)
|
||||
: _cellClass = index.getClass('dart:_late_helper', '_Cell'),
|
||||
_cellConstructor = index.getMember('dart:_late_helper', '_Cell', ''),
|
||||
_readLocal = index.getMember('dart:_late_helper', '_Cell', 'readLocal'),
|
||||
_setValue = index.getMember('dart:_late_helper', '_Cell', 'set:value'),
|
||||
_setFinalLocalValue = index.getMember(
|
||||
'dart:_late_helper', '_Cell', 'set:finalLocalValue') {
|
||||
FunctionType _readLocalType = _readLocal.getterType;
|
||||
_readLocalTypeParameters = _readLocalType.typeParameters;
|
||||
_readLocalTypeWithoutTypeParameters = _readLocalType.withoutTypeParameters;
|
||||
}
|
||||
|
||||
VariableDeclaration _variableCell(VariableDeclaration variable) {
|
||||
assert(_shouldLowerVariable(variable));
|
||||
return _cells.putIfAbsent(variable, () {
|
||||
int fileOffset = variable.fileOffset;
|
||||
return VariableDeclaration(variable.name,
|
||||
initializer:
|
||||
ConstructorInvocation(_cellConstructor, Arguments.empty())
|
||||
..fileOffset = fileOffset,
|
||||
type: InterfaceType(
|
||||
_cellClass, _contextMember.enclosingLibrary.nonNullable),
|
||||
isFinal: true)
|
||||
..fileOffset = fileOffset;
|
||||
});
|
||||
}
|
||||
|
||||
VariableGet _variableCellAccess(
|
||||
VariableDeclaration variable, int fileOffset) =>
|
||||
VariableGet(_variableCell(variable))..fileOffset = fileOffset;
|
||||
|
||||
TreeNode transformVariableDeclaration(
|
||||
VariableDeclaration node, Member contextMember) {
|
||||
_contextMember = contextMember;
|
||||
|
||||
if (!_shouldLowerVariable(node)) return node;
|
||||
|
||||
// A [VariableDeclaration] being used as a statement must be a direct child
|
||||
// of a [Block].
|
||||
if (node.parent is! Block) return node;
|
||||
|
||||
return _variableCell(node);
|
||||
}
|
||||
|
||||
TreeNode transformVariableGet(VariableGet node, Member contextMember) {
|
||||
_contextMember = contextMember;
|
||||
|
||||
VariableDeclaration variable = node.variable;
|
||||
if (!_shouldLowerVariable(variable)) return node;
|
||||
|
||||
int fileOffset = node.fileOffset;
|
||||
VariableGet cell = _variableCellAccess(variable, fileOffset);
|
||||
List<DartType> typeArguments = [node.promotedType ?? variable.type];
|
||||
return InstanceInvocation(
|
||||
InstanceAccessKind.Instance,
|
||||
cell,
|
||||
_readLocal.name,
|
||||
Arguments(const [], types: typeArguments)..fileOffset = fileOffset,
|
||||
interfaceTarget: _readLocal,
|
||||
functionType:
|
||||
Substitution.fromPairs(_readLocalTypeParameters, typeArguments)
|
||||
.substituteType(_readLocalTypeWithoutTypeParameters))
|
||||
..fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
TreeNode transformVariableSet(VariableSet node, Member contextMember) {
|
||||
_contextMember = contextMember;
|
||||
|
||||
VariableDeclaration variable = node.variable;
|
||||
if (!_shouldLowerVariable(variable)) return node;
|
||||
|
||||
int fileOffset = node.fileOffset;
|
||||
VariableGet cell = _variableCellAccess(variable, fileOffset);
|
||||
if (variable.isFinal) {
|
||||
return InstanceSet(InstanceAccessKind.Instance, cell,
|
||||
_setFinalLocalValue.name, node.value,
|
||||
interfaceTarget: _setFinalLocalValue)
|
||||
..fileOffset = fileOffset;
|
||||
} else {
|
||||
return InstanceSet(
|
||||
InstanceAccessKind.Instance, cell, _setValue.name, node.value,
|
||||
interfaceTarget: _setValue)
|
||||
..fileOffset = fileOffset;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,52 +5,57 @@
|
|||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
|
||||
import 'package:kernel/core_types.dart' show CoreTypes;
|
||||
import 'package:kernel/type_environment.dart'
|
||||
show StaticTypeContext, TypeEnvironment;
|
||||
import 'factory_specializer.dart';
|
||||
import 'late_lowering.dart';
|
||||
|
||||
/// dart2js-specific lowering transformations and optimizations combined into a
|
||||
/// single transformation pass.
|
||||
///
|
||||
/// Each transformation is applied locally to AST nodes of certain types after
|
||||
/// transforming children nodes.
|
||||
void transformLibraries(List<Library> libraries, CoreTypes coreTypes,
|
||||
ClassHierarchy hierarchy, bool nullSafety) {
|
||||
final transformer = _Lowering(coreTypes, hierarchy, nullSafety);
|
||||
void transformLibraries(
|
||||
List<Library> libraries, CoreTypes coreTypes, ClassHierarchy hierarchy) {
|
||||
final transformer = _Lowering(coreTypes, hierarchy);
|
||||
libraries.forEach(transformer.visitLibrary);
|
||||
}
|
||||
|
||||
class _Lowering extends Transformer {
|
||||
final TypeEnvironment env;
|
||||
final bool nullSafety;
|
||||
final FactorySpecializer factorySpecializer;
|
||||
final LateLowering _lateLowering;
|
||||
|
||||
Member _currentMember;
|
||||
StaticTypeContext _cachedStaticTypeContext;
|
||||
|
||||
_Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy, this.nullSafety)
|
||||
: env = TypeEnvironment(coreTypes, hierarchy),
|
||||
factorySpecializer = FactorySpecializer(coreTypes, hierarchy);
|
||||
|
||||
// ignore: unused_element
|
||||
StaticTypeContext get _staticTypeContext =>
|
||||
_cachedStaticTypeContext ??= StaticTypeContext(_currentMember, env);
|
||||
_Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy)
|
||||
: factorySpecializer = FactorySpecializer(coreTypes, hierarchy),
|
||||
_lateLowering = LateLowering(coreTypes.index);
|
||||
|
||||
@override
|
||||
defaultMember(Member node) {
|
||||
TreeNode defaultMember(Member node) {
|
||||
_currentMember = node;
|
||||
_cachedStaticTypeContext = null;
|
||||
|
||||
final result = super.defaultMember(node);
|
||||
|
||||
_currentMember = null;
|
||||
_cachedStaticTypeContext = null;
|
||||
return result;
|
||||
return super.defaultMember(node);
|
||||
}
|
||||
|
||||
@override
|
||||
visitStaticInvocation(StaticInvocation node) {
|
||||
TreeNode visitStaticInvocation(StaticInvocation node) {
|
||||
node.transformChildren(this);
|
||||
return factorySpecializer.transformStaticInvocation(node, _currentMember);
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitVariableDeclaration(VariableDeclaration node) {
|
||||
node.transformChildren(this);
|
||||
return _lateLowering.transformVariableDeclaration(node, _currentMember);
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitVariableGet(VariableGet node) {
|
||||
node.transformChildren(this);
|
||||
return _lateLowering.transformVariableGet(node, _currentMember);
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitVariableSet(VariableSet node) {
|
||||
node.transformChildren(this);
|
||||
return _lateLowering.transformVariableSet(node, _currentMember);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,61 +14,39 @@ static method main() → void {
|
|||
self::testNonNullableInitializedFinalLocal();
|
||||
}
|
||||
static method testNullableUninitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
|
||||
function #x#set(core::int? #t2) → dynamic
|
||||
return #x = #t2;
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
late core::int? x;
|
||||
x = 42;
|
||||
core::print(x{core::int});
|
||||
}
|
||||
static method testNonNullableUninitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x;
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t3 = #x in #t3 == null ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
|
||||
function #x#set(core::int #t4) → dynamic
|
||||
return #x = #t4;
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
late core::int x;
|
||||
x = 42;
|
||||
core::print(x);
|
||||
}
|
||||
static method testNullableUninitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
|
||||
function #x#set(core::int? #t6) → dynamic
|
||||
if(_in::isSentinel(#x))
|
||||
return #x = #t6;
|
||||
else
|
||||
throw new _in::LateError::localAI("x");
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
late final core::int? x;
|
||||
x = 42;
|
||||
core::print(x{core::int});
|
||||
}
|
||||
static method testNonNullableUninitializedFinalLocal() → void {
|
||||
lowered final core::int? #x;
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t7 = #x in #t7 == null ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
|
||||
function #x#set(core::int #t8) → dynamic
|
||||
if(#x == null)
|
||||
return #x = #t8;
|
||||
else
|
||||
throw new _in::LateError::localAI("x");
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
late final core::int x;
|
||||
x = 42;
|
||||
core::print(x);
|
||||
}
|
||||
static method testNullableInitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
|
||||
function #x#set(core::int? #t10) → dynamic
|
||||
return #x = #t10;
|
||||
return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
|
||||
function #x#set(core::int? #t2) → dynamic
|
||||
return #x = #t2;
|
||||
core::print(#x#get(){() → core::int?});
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
lowered core::int? #y = _in::createSentinel<core::int?>();
|
||||
function #y#get() → core::int?
|
||||
return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
|
||||
function #y#set(core::int? #t12) → dynamic
|
||||
return #y = #t12;
|
||||
return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
|
||||
function #y#set(core::int? #t4) → dynamic
|
||||
return #y = #t4;
|
||||
core::print(#y#get(){() → core::int?});
|
||||
#y#set(42){(core::int?) → dynamic};
|
||||
core::print(#y#get(){() → core::int?});
|
||||
|
@ -76,9 +54,9 @@ static method testNullableInitializedNonFinalLocal() → void {
|
|||
static method testNonNullableInitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x;
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t13 = #x in #t13 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
|
||||
function #x#set(core::int #t14) → dynamic
|
||||
return #x = #t14;
|
||||
return let final core::int? #t5 = #x in #t5 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
|
||||
function #x#set(core::int #t6) → dynamic
|
||||
return #x = #t6;
|
||||
core::print(#x#get(){() → core::int});
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
|
@ -86,16 +64,16 @@ static method testNonNullableInitializedNonFinalLocal() → void {
|
|||
static method testNullableInitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
|
||||
return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
|
||||
core::print(#x#get(){() → core::int?});
|
||||
lowered final core::int? #y = _in::createSentinel<core::int?>();
|
||||
function #y#get() → core::int?
|
||||
return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
|
||||
return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
|
||||
core::print(#y#get(){() → core::int?});
|
||||
}
|
||||
static method testNonNullableInitializedFinalLocal() → void {
|
||||
lowered final core::int? #x;
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t19 = #x in #t19 == null ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19{core::int};
|
||||
return let final core::int? #t11 = #x in #t11 == null ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11{core::int};
|
||||
core::print(#x#get(){() → core::int});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:_late_helper" as _la;
|
||||
import "dart:core" as core;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
|
@ -14,61 +15,39 @@ static method main() → void {
|
|||
self::testNonNullableInitializedFinalLocal();
|
||||
}
|
||||
static method testNullableUninitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
|
||||
function #x#set(core::int? #t2) → dynamic
|
||||
return #x = #t2;
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
final _la::_Cell x = new _la::_Cell::•();
|
||||
x.{_la::_Cell::value} = 42;
|
||||
core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
|
||||
}
|
||||
static method testNonNullableUninitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x;
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t3 = #x in #t3 == null ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
|
||||
function #x#set(core::int #t4) → dynamic
|
||||
return #x = #t4;
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
final _la::_Cell x = new _la::_Cell::•();
|
||||
x.{_la::_Cell::value} = 42;
|
||||
core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
|
||||
}
|
||||
static method testNullableUninitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
|
||||
function #x#set(core::int? #t6) → dynamic
|
||||
if(_in::isSentinel(#x))
|
||||
return #x = #t6;
|
||||
else
|
||||
throw new _in::LateError::localAI("x");
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
final _la::_Cell x = new _la::_Cell::•();
|
||||
x.{_la::_Cell::finalLocalValue} = 42;
|
||||
core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
|
||||
}
|
||||
static method testNonNullableUninitializedFinalLocal() → void {
|
||||
lowered final core::int? #x;
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t7 = #x in #t7 == null ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
|
||||
function #x#set(core::int #t8) → dynamic
|
||||
if(#x == null)
|
||||
return #x = #t8;
|
||||
else
|
||||
throw new _in::LateError::localAI("x");
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
final _la::_Cell x = new _la::_Cell::•();
|
||||
x.{_la::_Cell::finalLocalValue} = 42;
|
||||
core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
|
||||
}
|
||||
static method testNullableInitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
|
||||
function #x#set(core::int? #t10) → dynamic
|
||||
return #x = #t10;
|
||||
return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
|
||||
function #x#set(core::int? #t2) → dynamic
|
||||
return #x = #t2;
|
||||
core::print(#x#get(){() → core::int?});
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
lowered core::int? #y = _in::createSentinel<core::int?>();
|
||||
function #y#get() → core::int?
|
||||
return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
|
||||
function #y#set(core::int? #t12) → dynamic
|
||||
return #y = #t12;
|
||||
return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
|
||||
function #y#set(core::int? #t4) → dynamic
|
||||
return #y = #t4;
|
||||
core::print(#y#get(){() → core::int?});
|
||||
#y#set(42){(core::int?) → dynamic};
|
||||
core::print(#y#get(){() → core::int?});
|
||||
|
@ -76,9 +55,9 @@ static method testNullableInitializedNonFinalLocal() → void {
|
|||
static method testNonNullableInitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x;
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t13 = #x in #t13 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
|
||||
function #x#set(core::int #t14) → dynamic
|
||||
return #x = #t14;
|
||||
return let final core::int? #t5 = #x in #t5 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
|
||||
function #x#set(core::int #t6) → dynamic
|
||||
return #x = #t6;
|
||||
core::print(#x#get(){() → core::int});
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
|
@ -86,17 +65,17 @@ static method testNonNullableInitializedNonFinalLocal() → void {
|
|||
static method testNullableInitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
|
||||
return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
|
||||
core::print(#x#get(){() → core::int?});
|
||||
lowered final core::int? #y = _in::createSentinel<core::int?>();
|
||||
function #y#get() → core::int?
|
||||
return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
|
||||
return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
|
||||
core::print(#y#get(){() → core::int?});
|
||||
}
|
||||
static method testNonNullableInitializedFinalLocal() → void {
|
||||
lowered final core::int? #x;
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t19 = #x in #t19 == null ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19{core::int};
|
||||
return let final core::int? #t11 = #x in #t11 == null ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11{core::int};
|
||||
core::print(#x#get(){() → core::int});
|
||||
}
|
||||
|
||||
|
@ -109,4 +88,4 @@ Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:60:19 -> Doub
|
|||
Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:63:19 -> NullConstant(null)
|
||||
Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:68:22 -> DoubleConstant(-1.0)
|
||||
Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:68:18 -> DoubleConstant(-1.0)
|
||||
Extra constant evaluation: evaluated: 168, effectively constant: 7
|
||||
Extra constant evaluation: evaluated: 130, effectively constant: 7
|
||||
|
|
|
@ -14,61 +14,39 @@ static method main() → void {
|
|||
self::testNonNullableInitializedFinalLocal();
|
||||
}
|
||||
static method testNullableUninitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
|
||||
function #x#set(core::int? #t2) → dynamic
|
||||
return #x = #t2;
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
late core::int? x;
|
||||
x = 42;
|
||||
core::print(x{core::int});
|
||||
}
|
||||
static method testNonNullableUninitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int>();
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t3 = #x in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
|
||||
function #x#set(core::int #t4) → dynamic
|
||||
return #x = #t4;
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
late core::int x;
|
||||
x = 42;
|
||||
core::print(x);
|
||||
}
|
||||
static method testNullableUninitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
|
||||
function #x#set(core::int? #t6) → dynamic
|
||||
if(_in::isSentinel(#x))
|
||||
return #x = #t6;
|
||||
else
|
||||
throw new _in::LateError::localAI("x");
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
late final core::int? x;
|
||||
x = 42;
|
||||
core::print(x{core::int});
|
||||
}
|
||||
static method testNonNullableUninitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int>();
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
|
||||
function #x#set(core::int #t8) → dynamic
|
||||
if(_in::isSentinel(#x))
|
||||
return #x = #t8;
|
||||
else
|
||||
throw new _in::LateError::localAI("x");
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
late final core::int x;
|
||||
x = 42;
|
||||
core::print(x);
|
||||
}
|
||||
static method testNullableInitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
|
||||
function #x#set(core::int? #t10) → dynamic
|
||||
return #x = #t10;
|
||||
return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
|
||||
function #x#set(core::int? #t2) → dynamic
|
||||
return #x = #t2;
|
||||
core::print(#x#get(){() → core::int?});
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
lowered core::int? #y = _in::createSentinel<core::int?>();
|
||||
function #y#get() → core::int?
|
||||
return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
|
||||
function #y#set(core::int? #t12) → dynamic
|
||||
return #y = #t12;
|
||||
return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
|
||||
function #y#set(core::int? #t4) → dynamic
|
||||
return #y = #t4;
|
||||
core::print(#y#get(){() → core::int?});
|
||||
#y#set(42){(core::int?) → dynamic};
|
||||
core::print(#y#get(){() → core::int?});
|
||||
|
@ -76,9 +54,9 @@ static method testNullableInitializedNonFinalLocal() → void {
|
|||
static method testNonNullableInitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int>();
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t13 = #x in _in::isSentinel(#t13) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
|
||||
function #x#set(core::int #t14) → dynamic
|
||||
return #x = #t14;
|
||||
return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
|
||||
function #x#set(core::int #t6) → dynamic
|
||||
return #x = #t6;
|
||||
core::print(#x#get(){() → core::int});
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
|
@ -86,16 +64,16 @@ static method testNonNullableInitializedNonFinalLocal() → void {
|
|||
static method testNullableInitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
|
||||
return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
|
||||
core::print(#x#get(){() → core::int?});
|
||||
lowered final core::int? #y = _in::createSentinel<core::int?>();
|
||||
function #y#get() → core::int?
|
||||
return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
|
||||
return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
|
||||
core::print(#y#get(){() → core::int?});
|
||||
}
|
||||
static method testNonNullableInitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int>();
|
||||
function #x#get() → core::int
|
||||
return let final core::int #t19 = #x in _in::isSentinel(#t19) ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19;
|
||||
return let final core::int #t11 = #x in _in::isSentinel(#t11) ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11;
|
||||
core::print(#x#get(){() → core::int});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:_late_helper" as _la;
|
||||
import "dart:core" as core;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
|
@ -14,61 +15,39 @@ static method main() → void {
|
|||
self::testNonNullableInitializedFinalLocal();
|
||||
}
|
||||
static method testNullableUninitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
|
||||
function #x#set(core::int? #t2) → dynamic
|
||||
return #x = #t2;
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
final _la::_Cell x = new _la::_Cell::•();
|
||||
x.{_la::_Cell::value} = 42;
|
||||
core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
|
||||
}
|
||||
static method testNonNullableUninitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int>();
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t3 = #x in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
|
||||
function #x#set(core::int #t4) → dynamic
|
||||
return #x = #t4;
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
final _la::_Cell x = new _la::_Cell::•();
|
||||
x.{_la::_Cell::value} = 42;
|
||||
core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
|
||||
}
|
||||
static method testNullableUninitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
|
||||
function #x#set(core::int? #t6) → dynamic
|
||||
if(_in::isSentinel(#x))
|
||||
return #x = #t6;
|
||||
else
|
||||
throw new _in::LateError::localAI("x");
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
final _la::_Cell x = new _la::_Cell::•();
|
||||
x.{_la::_Cell::finalLocalValue} = 42;
|
||||
core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
|
||||
}
|
||||
static method testNonNullableUninitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int>();
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
|
||||
function #x#set(core::int #t8) → dynamic
|
||||
if(_in::isSentinel(#x))
|
||||
return #x = #t8;
|
||||
else
|
||||
throw new _in::LateError::localAI("x");
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
final _la::_Cell x = new _la::_Cell::•();
|
||||
x.{_la::_Cell::finalLocalValue} = 42;
|
||||
core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
|
||||
}
|
||||
static method testNullableInitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
|
||||
function #x#set(core::int? #t10) → dynamic
|
||||
return #x = #t10;
|
||||
return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
|
||||
function #x#set(core::int? #t2) → dynamic
|
||||
return #x = #t2;
|
||||
core::print(#x#get(){() → core::int?});
|
||||
#x#set(42){(core::int?) → dynamic};
|
||||
core::print(#x#get(){() → core::int?});
|
||||
lowered core::int? #y = _in::createSentinel<core::int?>();
|
||||
function #y#get() → core::int?
|
||||
return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
|
||||
function #y#set(core::int? #t12) → dynamic
|
||||
return #y = #t12;
|
||||
return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
|
||||
function #y#set(core::int? #t4) → dynamic
|
||||
return #y = #t4;
|
||||
core::print(#y#get(){() → core::int?});
|
||||
#y#set(42){(core::int?) → dynamic};
|
||||
core::print(#y#get(){() → core::int?});
|
||||
|
@ -76,9 +55,9 @@ static method testNullableInitializedNonFinalLocal() → void {
|
|||
static method testNonNullableInitializedNonFinalLocal() → void {
|
||||
lowered core::int? #x = _in::createSentinel<core::int>();
|
||||
function #x#get() → core::int
|
||||
return let final core::int? #t13 = #x in _in::isSentinel(#t13) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
|
||||
function #x#set(core::int #t14) → dynamic
|
||||
return #x = #t14;
|
||||
return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
|
||||
function #x#set(core::int #t6) → dynamic
|
||||
return #x = #t6;
|
||||
core::print(#x#get(){() → core::int});
|
||||
#x#set(42){(core::int) → dynamic};
|
||||
core::print(#x#get(){() → core::int});
|
||||
|
@ -86,17 +65,17 @@ static method testNonNullableInitializedNonFinalLocal() → void {
|
|||
static method testNullableInitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int?>();
|
||||
function #x#get() → core::int?
|
||||
return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
|
||||
return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
|
||||
core::print(#x#get(){() → core::int?});
|
||||
lowered final core::int? #y = _in::createSentinel<core::int?>();
|
||||
function #y#get() → core::int?
|
||||
return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
|
||||
return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
|
||||
core::print(#y#get(){() → core::int?});
|
||||
}
|
||||
static method testNonNullableInitializedFinalLocal() → void {
|
||||
lowered final core::int? #x = _in::createSentinel<core::int>();
|
||||
function #x#get() → core::int
|
||||
return let final core::int #t19 = #x in _in::isSentinel(#t19) ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19;
|
||||
return let final core::int #t11 = #x in _in::isSentinel(#t11) ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11;
|
||||
core::print(#x#get(){() → core::int});
|
||||
}
|
||||
|
||||
|
@ -109,4 +88,4 @@ Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:60:19 -> Doub
|
|||
Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:63:19 -> NullConstant(null)
|
||||
Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:68:22 -> DoubleConstant(-1.0)
|
||||
Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:68:18 -> DoubleConstant(-1.0)
|
||||
Extra constant evaluation: evaluated: 172, effectively constant: 7
|
||||
Extra constant evaluation: evaluated: 132, effectively constant: 7
|
||||
|
|
104
tests/language/nnbd/late/chained_assignment_test.dart
Normal file
104
tests/language/nnbd/late/chained_assignment_test.dart
Normal file
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
class Foo {
|
||||
int x = 0;
|
||||
|
||||
int _y = 0;
|
||||
int get y => _y;
|
||||
void set y(int y) => _y = y;
|
||||
|
||||
static late int z;
|
||||
late int w;
|
||||
}
|
||||
|
||||
void main() {
|
||||
final foo = Foo();
|
||||
int a = 0;
|
||||
late int b;
|
||||
late int c;
|
||||
late int d;
|
||||
|
||||
b = a = 1;
|
||||
Expect.equals(a, 1);
|
||||
Expect.equals(b, 1);
|
||||
|
||||
a = b = 2;
|
||||
Expect.equals(a, 2);
|
||||
Expect.equals(b, 2);
|
||||
|
||||
b = foo.x = 3;
|
||||
Expect.equals(foo.x, 3);
|
||||
Expect.equals(b, 3);
|
||||
|
||||
foo.x = b = 4;
|
||||
Expect.equals(foo.x, 4);
|
||||
Expect.equals(b, 4);
|
||||
|
||||
b = foo.y = 5;
|
||||
Expect.equals(foo.y, 5);
|
||||
Expect.equals(b, 5);
|
||||
|
||||
foo.y = b = 6;
|
||||
Expect.equals(foo.y, 6);
|
||||
Expect.equals(b, 6);
|
||||
|
||||
b = c = 7;
|
||||
Expect.equals(b, 7);
|
||||
Expect.equals(c, 7);
|
||||
|
||||
d = b = 8;
|
||||
Expect.equals(b, 8);
|
||||
Expect.equals(d, 8);
|
||||
|
||||
Foo.z = a = 9;
|
||||
Expect.equals(a, 9);
|
||||
Expect.equals(Foo.z, 9);
|
||||
|
||||
a = Foo.z = 10;
|
||||
Expect.equals(a, 10);
|
||||
Expect.equals(Foo.z, 10);
|
||||
|
||||
Foo.z = foo.x = 11;
|
||||
Expect.equals(foo.x, 11);
|
||||
Expect.equals(Foo.z, 11);
|
||||
|
||||
foo.x = Foo.z = 12;
|
||||
Expect.equals(foo.x, 12);
|
||||
Expect.equals(Foo.z, 12);
|
||||
|
||||
Foo.z = foo.y = 13;
|
||||
Expect.equals(foo.y, 13);
|
||||
Expect.equals(Foo.z, 13);
|
||||
|
||||
foo.y = Foo.z = 14;
|
||||
Expect.equals(foo.y, 14);
|
||||
Expect.equals(Foo.z, 14);
|
||||
|
||||
foo.w = a = 15;
|
||||
Expect.equals(a, 15);
|
||||
Expect.equals(foo.w, 15);
|
||||
|
||||
a = foo.w = 16;
|
||||
Expect.equals(a, 16);
|
||||
Expect.equals(foo.w, 16);
|
||||
|
||||
foo.w = foo.x = 17;
|
||||
Expect.equals(foo.x, 17);
|
||||
Expect.equals(foo.w, 17);
|
||||
|
||||
foo.x = foo.w = 18;
|
||||
Expect.equals(foo.x, 18);
|
||||
Expect.equals(foo.w, 18);
|
||||
|
||||
foo.w = foo.y = 19;
|
||||
Expect.equals(foo.y, 19);
|
||||
Expect.equals(foo.w, 19);
|
||||
|
||||
foo.y = foo.w = 20;
|
||||
Expect.equals(foo.y, 20);
|
||||
Expect.equals(foo.w, 20);
|
||||
}
|
Loading…
Reference in a new issue