Add type inference for assignments to properties.

This covers explicit property accesses (using both `.` and `?.`) as
well as implicit properties of `this`.

R=scheglov@google.com

Review-Url: https://codereview.chromium.org/2931363003 .
This commit is contained in:
Paul Berry 2017-06-12 11:33:03 -07:00
parent 65d05524ce
commit cdb1e858d2
43 changed files with 1886 additions and 44 deletions

View file

@ -9,6 +9,7 @@ import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'
KernelArguments,
KernelComplexAssignment,
KernelIndexAssign,
KernelPropertyAssign,
KernelStaticAssignment,
KernelThisExpression,
KernelVariableAssignment;
@ -675,6 +676,10 @@ class PropertyAccessor extends kernel.PropertyAccessor with FastaAccessor {
helper, token, receiver, name, getter, setter);
}
}
@override
KernelComplexAssignment startComplexAssignment(Expression rhs) =>
new KernelPropertyAssign(receiver, rhs);
}
class StaticAccessor extends kernel.StaticAccessor with FastaAccessor {
@ -772,6 +777,10 @@ class SuperPropertyAccessor extends kernel.SuperPropertyAccessor
}
toString() => "SuperPropertyAccessor()";
@override
KernelComplexAssignment startComplexAssignment(Expression rhs) =>
new KernelPropertyAssign(null, rhs, isSuper: true);
}
class ThisIndexAccessor extends kernel.ThisIndexAccessor with FastaAccessor {
@ -834,6 +843,10 @@ class ThisPropertyAccessor extends kernel.ThisPropertyAccessor
}
toString() => "ThisPropertyAccessor()";
@override
KernelComplexAssignment startComplexAssignment(Expression rhs) =>
new KernelPropertyAssign(null, rhs);
}
class NullAwarePropertyAccessor extends kernel.NullAwarePropertyAccessor
@ -851,6 +864,10 @@ class NullAwarePropertyAccessor extends kernel.NullAwarePropertyAccessor
}
toString() => "NullAwarePropertyAccessor()";
@override
KernelComplexAssignment startComplexAssignment(Expression rhs) =>
new KernelPropertyAssign(receiverExpression, rhs);
}
int adjustForImplicitCall(String name, int offset) {

View file

@ -11,6 +11,7 @@ import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'
KernelComplexAssignment,
KernelConditionalExpression,
KernelMethodInvocation,
KernelPropertyAssign,
KernelPropertyGet,
KernelPropertySet,
KernelThisExpression,
@ -249,8 +250,10 @@ class PropertyAccessor extends Accessor {
Expression _makeSimpleWrite(Expression value, bool voidContext,
KernelComplexAssignment complexAssignment) {
return new KernelPropertySet(receiver, name, value, setter)
var write = new KernelPropertySet(receiver, name, value, setter)
..fileOffset = offsetForToken(token);
complexAssignment?.write = write;
return write;
}
receiverAccess() {
@ -259,19 +262,31 @@ class PropertyAccessor extends Accessor {
..fileOffset = offsetForToken(token);
}
Expression _makeRead(KernelComplexAssignment complexAssignment) =>
new KernelPropertyGet(receiverAccess(), name, getter)
..fileOffset = offsetForToken(token);
Expression _makeRead(KernelComplexAssignment complexAssignment) {
var read = new KernelPropertyGet(receiverAccess(), name, getter)
..fileOffset = offsetForToken(token);
complexAssignment?.read = read;
return read;
}
Expression _makeWrite(Expression value, bool voidContext,
KernelComplexAssignment complexAssignment) {
return new KernelPropertySet(receiverAccess(), name, value, setter)
var write = new KernelPropertySet(receiverAccess(), name, value, setter)
..fileOffset = offsetForToken(token);
complexAssignment?.write = write;
return write;
}
Expression _finish(
Expression body, KernelComplexAssignment complexAssignment) =>
makeLet(_receiverVariable, body);
Expression body, KernelComplexAssignment complexAssignment) {
body = makeLet(_receiverVariable, body);
if (complexAssignment != null) {
complexAssignment.desugared = body;
return complexAssignment;
} else {
return body;
}
}
}
/// Special case of [PropertyAccessor] to avoid creating an indirect access to
@ -284,45 +299,67 @@ class ThisPropertyAccessor extends Accessor {
BuilderHelper helper, this.name, this.getter, this.setter, Token token)
: super(helper, token);
Expression _makeRead(KernelComplexAssignment complexAssignment) =>
new KernelPropertyGet(new KernelThisExpression(), name, getter)
..fileOffset = offsetForToken(token);
Expression _makeRead(KernelComplexAssignment complexAssignment) {
var read = new KernelPropertyGet(new KernelThisExpression(), name, getter)
..fileOffset = offsetForToken(token);
complexAssignment?.read = read;
return read;
}
Expression _makeWrite(Expression value, bool voidContext,
KernelComplexAssignment complexAssignment) {
return new KernelPropertySet(
new KernelThisExpression(), name, value, setter)
..fileOffset = offsetForToken(token);
var write =
new KernelPropertySet(new KernelThisExpression(), name, value, setter)
..fileOffset = offsetForToken(token);
complexAssignment?.write = write;
return write;
}
}
class NullAwarePropertyAccessor extends Accessor {
VariableDeclaration receiver;
Expression receiverExpression;
Name name;
Member getter, setter;
DartType type;
NullAwarePropertyAccessor(BuilderHelper helper, Expression receiver,
NullAwarePropertyAccessor(BuilderHelper helper, this.receiverExpression,
this.name, this.getter, this.setter, this.type, Token token)
: this.receiver = makeOrReuseVariable(receiver),
: this.receiver = makeOrReuseVariable(receiverExpression),
super(helper, token);
receiverAccess() => new VariableGet(receiver);
Expression _makeRead(KernelComplexAssignment complexAssignment) =>
new KernelPropertyGet(receiverAccess(), name, getter);
Expression _makeRead(KernelComplexAssignment complexAssignment) {
var read = new KernelPropertyGet(receiverAccess(), name, getter)
..fileOffset = offsetForToken(token);
complexAssignment?.read = read;
return read;
}
Expression _makeWrite(Expression value, bool voidContext,
KernelComplexAssignment complexAssignment) {
return new KernelPropertySet(receiverAccess(), name, value, setter);
var write = new KernelPropertySet(receiverAccess(), name, value, setter)
..fileOffset = offsetForToken(token);
complexAssignment?.write = write;
return write;
}
Expression _finish(
Expression body, KernelComplexAssignment complexAssignment) =>
makeLet(
receiver,
new KernelConditionalExpression(
buildIsNull(receiverAccess()), new NullLiteral(), body));
Expression body, KernelComplexAssignment complexAssignment) {
var nullAwareGuard = new KernelConditionalExpression(
buildIsNull(receiverAccess()), new NullLiteral(), body)
..fileOffset = offsetForToken(token);
body = makeLet(receiver, nullAwareGuard);
if (complexAssignment != null) {
KernelPropertyAssign kernelPropertyAssign = complexAssignment;
kernelPropertyAssign.nullAwareGuard = nullAwareGuard;
kernelPropertyAssign.desugared = body;
return kernelPropertyAssign;
} else {
return body;
}
}
}
class SuperPropertyAccessor extends Accessor {
@ -336,16 +373,20 @@ class SuperPropertyAccessor extends Accessor {
Expression _makeRead(KernelComplexAssignment complexAssignment) {
if (getter == null) return makeInvalidRead();
// TODO(ahe): Use [DirectPropertyGet] when possible.
return new SuperPropertyGet(name, getter)
var read = new SuperPropertyGet(name, getter)
..fileOffset = offsetForToken(token);
complexAssignment?.read = read;
return read;
}
Expression _makeWrite(Expression value, bool voidContext,
KernelComplexAssignment complexAssignment) {
if (setter == null) return makeInvalidWrite(value);
// TODO(ahe): Use [DirectPropertySet] when possible.
return new SuperPropertySet(name, value, setter)
var write = new SuperPropertySet(name, value, setter)
..fileOffset = offsetForToken(token);
complexAssignment?.write = write;
return write;
}
}

View file

@ -912,12 +912,10 @@ class KernelIfStatement extends IfStatement implements KernelStatement {
/// Concrete shadow object representing an assignment to a target of the form
/// `a[b]`.
class KernelIndexAssign extends KernelComplexAssignment {
/// The receiver of the assignment target (e.g. `a` in `a[b] = c`), or `null`
/// if there is no receiver.
/// The receiver of the assignment target (e.g. `a` in `a[b] = c`).
Expression receiver;
/// In an assignment to an index expression, the index expression, or `null`
/// if this is not an assignment to an index expression.
/// In an assignment to an index expression, the index expression.
Expression index;
KernelIndexAssign(this.receiver, this.index, Expression rhs) : super(rhs);
@ -1299,6 +1297,64 @@ class KernelNullLiteral extends NullLiteral implements KernelExpression {
}
}
/// Concrete shadow object representing an assignment to a property.
class KernelPropertyAssign extends KernelComplexAssignment {
/// The receiver of the assignment target (e.g. `a` in `a.b = c`), or `null`
/// if there is no receiver (implicit `this`).
Expression receiver;
/// If this assignment uses null-aware access (`?.`), the conditional
/// expression that guards the access; otherwise `null`.
Expression nullAwareGuard;
/// Indicates whether this assignment uses `super`.
final bool isSuper;
KernelPropertyAssign(this.receiver, Expression rhs, {this.isSuper: false})
: super(rhs);
@override
List<String> _getToStringParts() {
var parts = super._getToStringParts();
if (receiver != null) parts.add('receiver=$receiver');
if (nullAwareGuard != null) parts.add('nullAwareGuard=$nullAwareGuard');
return parts;
}
@override
DartType _inferExpression(
KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
typeNeeded =
inferrer.listener.propertyAssignEnter(desugared, typeContext) ||
typeNeeded;
// TODO(paulberry): record the appropriate types on let variables and
// conditional expressions.
DartType receiverType;
if (receiver != null) {
receiverType = inferrer.inferExpression(receiver, null, true);
} else if (isSuper) {
receiverType = inferrer.classHierarchy.getTypeAsInstanceOf(
inferrer.thisType, inferrer.thisType.classNode.supertype.classNode);
} else {
receiverType = inferrer.thisType;
}
if (read != null) {
inferrer.findPropertyGetMember(receiverType, read, silent: true);
}
Member writeMember;
if (write != null) {
writeMember = inferrer.findPropertySetMember(receiverType, write);
}
// To replicate analyzer behavior, we base type inference on the write
// member. TODO(paulberry): would it be better to use the read member when
// doing compound assignment?
var writeContext = writeMember?.setterType;
var inferredType = _inferRhs(inferrer, writeContext);
inferrer.listener.propertyAssignExit(desugared, inferredType);
return inferredType;
}
}
/// Shadow object for [PropertyGet].
class KernelPropertyGet extends PropertyGet implements KernelExpression {
KernelPropertyGet(Expression receiver, Name name, [Member interfaceTarget])

View file

@ -206,6 +206,12 @@ class TypeInferenceListener
void nullLiteralExit(NullLiteral expression, DartType inferredType) =>
debugExpressionExit("nullLiteral", expression, inferredType);
bool propertyAssignEnter(Expression expression, DartType typeContext) =>
debugExpressionEnter("propertyAssign", expression, typeContext);
void propertyAssignExit(Expression expression, DartType inferredType) =>
debugExpressionExit("propertyAssign", expression, inferredType);
bool propertyGetEnter(PropertyGet expression, DartType typeContext) =>
debugExpressionEnter("propertyGet", expression, typeContext);

View file

@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE.md file.
import 'package:front_end/src/base/instrumentation.dart';
import 'package:front_end/src/fasta/errors.dart' show internalError;
import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
import 'package:front_end/src/fasta/names.dart' show callName;
import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
@ -29,7 +30,11 @@ import 'package:kernel/ast.dart'
Name,
Procedure,
ProcedureKind,
PropertyGet,
PropertySet,
Statement,
SuperPropertyGet,
SuperPropertySet,
TypeParameterType,
VoidType;
import 'package:kernel/class_hierarchy.dart';
@ -270,6 +275,50 @@ abstract class TypeInferrerImpl extends TypeInferrer {
return interfaceMember;
}
/// Finds a member of [receiverType] called [name], and if it is found,
/// reports it through instrumentation and records it in [propertyGet].
Member findPropertyGetMember(DartType receiverType, Expression propertyGet,
{bool silent: false}) {
if (propertyGet is PropertyGet) {
var interfaceMember = findInterfaceMember(
receiverType, propertyGet.name, propertyGet.fileOffset,
silent: silent);
propertyGet.interfaceTarget = interfaceMember;
return interfaceMember;
} else if (propertyGet is SuperPropertyGet) {
var interfaceMember = findInterfaceMember(
receiverType, propertyGet.name, propertyGet.fileOffset,
silent: silent);
propertyGet.interfaceTarget = interfaceMember;
return interfaceMember;
} else {
throw internalError(
'Unexpected propertyGet type: ${propertyGet.runtimeType}');
}
}
/// Finds a member of [receiverType] called [name], and if it is found,
/// reports it through instrumentation and records it in [propertySet].
Member findPropertySetMember(DartType receiverType, Expression propertySet,
{bool silent: false}) {
if (propertySet is PropertySet) {
var interfaceMember = findInterfaceMember(
receiverType, propertySet.name, propertySet.fileOffset,
setter: true, silent: silent);
propertySet.interfaceTarget = interfaceMember;
return interfaceMember;
} else if (propertySet is SuperPropertySet) {
var interfaceMember = findInterfaceMember(
receiverType, propertySet.name, propertySet.fileOffset,
setter: true, silent: silent);
propertySet.interfaceTarget = interfaceMember;
return interfaceMember;
} else {
throw internalError(
'Unexpected propertySet type: ${propertySet.runtimeType}');
}
}
FunctionType getCalleeFunctionType(Member interfaceMember,
DartType receiverType, Name methodName, bool followCall) {
var type = getCalleeType(interfaceMember, receiverType, methodName);

View file

@ -175,6 +175,8 @@ inference/generic_methods_inference_error: Crash
inference/generic_methods_iterable_and_future: Crash
inference/generic_methods_nested_generic_instantiation: Crash
inference/generic_methods_uses_greatest_lower_bound: Crash
inference/infer_assign_to_implicit_this: Crash
inference/infer_assign_to_implicit_this_upwards: Crash
inference/infer_assign_to_index: Crash
inference/infer_assign_to_index_full: Crash
inference/infer_assign_to_index_set_vs_get: Crash
@ -183,6 +185,12 @@ inference/infer_assign_to_local: Crash
inference/infer_assign_to_local_upwards: Crash
inference/infer_assign_to_property: Crash
inference/infer_assign_to_property_custom: Crash
inference/infer_assign_to_property_full: Crash
inference/infer_assign_to_property_null_aware: Crash
inference/infer_assign_to_property_null_aware_upwards: Crash
inference/infer_assign_to_property_super: Crash
inference/infer_assign_to_property_super_upwards: Crash
inference/infer_assign_to_property_upwards: Crash
inference/infer_assign_to_ref: Crash
inference/infer_assign_to_static: Crash
inference/infer_assign_to_static_upwards: Crash

View file

@ -61,8 +61,6 @@ inference/downwards_inference_on_function_of_t_using_the_t: Fail
inference/future_then_explicit_future: Fail
inference/generic_functions_return_typedef: Fail
inference/generic_methods_infer_js_builtin: Fail
inference/infer_assign_to_property: Fail
inference/infer_assign_to_property_custom: Fail
inference/infer_binary_double_double: Fail
inference/infer_binary_double_int: Fail
inference/infer_binary_int_double: Fail
@ -81,7 +79,6 @@ inference/infer_prefix_expression: Fail
inference/infer_statics_transitively: Fail
inference/infer_statics_transitively3: Fail
inference/infer_statics_transitively_a: Fail
inference/infer_type_on_var_from_field: Fail
inference/infer_types_on_loop_indices_for_each_loop: Fail
inference/infer_types_on_loop_indices_for_loop_with_inference: Fail
inference/inferred_type_cascade: Fail
@ -90,6 +87,8 @@ inference/list_literals_can_infer_null_top_level: Fail
inference/map_literals_can_infer_null_top_level: Fail
inference/null_coalescing_operator: Fail
inference/null_coalescing_operator_2: Fail
inference/property_set: Fail
inference/property_set_bad_setter: Crash
inference/reference_to_typedef: Fail
inference/refine_binary_expression_type_type_parameter_t_double: Fail
inference/refine_binary_expression_type_type_parameter_t_int: Fail

View file

@ -0,0 +1,42 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
class A {}
class B extends A {
A operator +(C v) => null;
B operator -(int i) => null;
B operator *(B v) => null;
C operator &(A v) => null;
}
class C extends B {}
T f<T>() => null;
class Test {
B member;
void test() {
/*@target=Test::member*/ member = /*@typeArgs=B*/ f();
/*@target=Test::member*/ member ??= /*@typeArgs=B*/ f();
/*@target=Test::member*/ member += /*@typeArgs=dynamic*/ f();
/*@target=Test::member*/ member *= /*@typeArgs=dynamic*/ f();
/*@target=Test::member*/ member &= /*@typeArgs=dynamic*/ f();
-- /*@target=Test::member*/ member;
/*@target=Test::member*/ member--;
var /*@type=B*/ v1 = /*@target=Test::member*/ member = /*@typeArgs=B*/ f();
var /*@type=B*/ v2 = /*@target=Test::member*/ member ??= /*@typeArgs=B*/ f();
var /*@type=A*/ v3 = /*@target=Test::member*/ member += /*@typeArgs=dynamic*/ f();
var /*@type=B*/ v4 = /*@target=Test::member*/ member *= /*@typeArgs=dynamic*/ f();
var /*@type=C*/ v5 = /*@target=Test::member*/ member &= /*@typeArgs=dynamic*/ f();
var /*@type=B*/ v6 = -- /*@target=Test::member*/ member;
var /*@type=B*/ v7 = /*@target=Test::member*/ member--;
}
}
main() {}

View file

@ -0,0 +1,52 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
operator +(self::C v) → self::A
return null;
operator -(core::int i) → self::B
return null;
operator *(self::B v) → self::B
return null;
operator &(self::A v) → self::C
return null;
}
class C extends self::B {
constructor •() → void
: super self::B::•()
;
}
class Test extends core::Object {
field self::B member = null;
constructor •() → void
: super core::Object::•()
;
method test() → void {
this.member = self::f();
this.member.==(null) ? this.member = self::f() : null;
this.member = this.member.+(self::f());
this.member = this.member.*(self::f());
this.member = this.member.&(self::f());
this.member = this.member.-(1);
this.member = this.member.-(1);
dynamic v1 = this.member = self::f();
dynamic v2 = let final dynamic #t1 = this.member in #t1.==(null) ? this.member = self::f() : #t1;
dynamic v3 = this.member = this.member.+(self::f());
dynamic v4 = this.member = this.member.*(self::f());
dynamic v5 = this.member = this.member.&(self::f());
dynamic v6 = this.member = this.member.-(1);
dynamic v7 = let final dynamic #t2 = this.member in let final dynamic #t3 = this.member = #t2.-(1) in #t2;
}
}
static method f() → dynamic
return null;
static method main() → dynamic {}

View file

@ -0,0 +1,35 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
;
}
class B extends self::A {
constructor •() → void
;
operator +(self::C v) → self::A
;
operator -(core::int i) → self::B
;
operator *(self::B v) → self::B
;
operator &(self::A v) → self::C
;
}
class C extends self::B {
constructor •() → void
;
}
class Test extends core::Object {
field self::B member;
constructor •() → void
;
method test() → void
;
}
static method f<T extends core::Object>() → self::f::T
;
static method main() → dynamic
;

View file

@ -0,0 +1,52 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
operator +(self::C v) → self::A
return null;
operator -(core::int i) → self::B
return null;
operator *(self::B v) → self::B
return null;
operator &(self::A v) → self::C
return null;
}
class C extends self::B {
constructor •() → void
: super self::B::•()
;
}
class Test extends core::Object {
field self::B member = null;
constructor •() → void
: super core::Object::•()
;
method test() → void {
this.{self::Test::member} = self::f<self::B>();
this.{self::Test::member}.{core::Object::==}(null) ? this.{self::Test::member} = self::f<self::B>() : null;
this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<dynamic>());
this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>());
this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>());
this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
self::B v1 = this.{self::Test::member} = self::f<self::B>();
self::B v2 = let final dynamic #t1 = this.{self::Test::member} in #t1.{core::Object::==}(null) ? this.{self::Test::member} = self::f<self::B>() : #t1;
self::A v3 = this.{self::Test::member} = this.{self::Test::member}.{self::B::+}(self::f<dynamic>());
self::B v4 = this.{self::Test::member} = this.{self::Test::member}.{self::B::*}(self::f<dynamic>());
self::C v5 = this.{self::Test::member} = this.{self::Test::member}.{self::B::&}(self::f<dynamic>());
self::B v6 = this.{self::Test::member} = this.{self::Test::member}.{self::B::-}(1);
self::B v7 = let final dynamic #t2 = this.{self::Test::member} in let final dynamic #t3 = this.{self::Test::member} = #t2.{self::B::-}(1) in #t2;
}
}
static method f<T extends core::Object>() → self::f::T
return null;
static method main() → dynamic {}

View file

@ -0,0 +1,61 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
int getInt() => 0;
num getNum() => 0;
double getDouble() => 0.0;
class Test1 {
int t;
void test() {
var /*@type=int*/ v1 = /*@target=Test1::t*/ t = getInt();
var /*@type=num*/ v2 = /*@target=Test1::t*/ t = getNum();
var /*@type=int*/ v4 = /*@target=Test1::t*/ t ??= getInt();
var /*@type=num*/ v5 = /*@target=Test1::t*/ t ??= getNum();
var /*@type=int*/ v7 = /*@target=Test1::t*/ t += getInt();
var /*@type=num*/ v8 = /*@target=Test1::t*/ t += getNum();
var /*@type=int*/ v10 = ++ /*@target=Test1::t*/ t;
var /*@type=int*/ v11 = /*@target=Test1::t*/ t++;
}
}
class Test2 {
num t;
void test() {
var /*@type=int*/ v1 = /*@target=Test2::t*/ t = getInt();
var /*@type=num*/ v2 = /*@target=Test2::t*/ t = getNum();
var /*@type=double*/ v3 = /*@target=Test2::t*/ t = getDouble();
var /*@type=num*/ v4 = /*@target=Test2::t*/ t ??= getInt();
var /*@type=num*/ v5 = /*@target=Test2::t*/ t ??= getNum();
var /*@type=num*/ v6 = /*@target=Test2::t*/ t ??= getDouble();
var /*@type=num*/ v7 = /*@target=Test2::t*/ t += getInt();
var /*@type=num*/ v8 = /*@target=Test2::t*/ t += getNum();
var /*@type=num*/ v9 = /*@target=Test2::t*/ t += getDouble();
var /*@type=num*/ v10 = ++ /*@target=Test2::t*/ t;
var /*@type=num*/ v11 = /*@target=Test2::t*/ t++;
}
}
class Test3 {
double t;
void test3() {
var /*@type=num*/ v2 = /*@target=Test3::t*/ t = getNum();
var /*@type=double*/ v3 = /*@target=Test3::t*/ t = getDouble();
var /*@type=num*/ v5 = /*@target=Test3::t*/ t ??= getNum();
var /*@type=double*/ v6 = /*@target=Test3::t*/ t ??= getDouble();
var /*@type=double*/ v7 = /*@target=Test3::t*/ t += getInt();
var /*@type=double*/ v8 = /*@target=Test3::t*/ t += getNum();
var /*@type=double*/ v9 = /*@target=Test3::t*/ t += getDouble();
var /*@type=double*/ v10 = ++ /*@target=Test3::t*/ t;
var /*@type=double*/ v11 = /*@target=Test3::t*/ t++;
}
}
main() {}

View file

@ -0,0 +1,63 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int t = null;
constructor •() → void
: super core::Object::•()
;
method test() → void {
dynamic v1 = this.t = self::getInt();
dynamic v2 = this.t = self::getNum();
dynamic v4 = let final dynamic #t1 = this.t in #t1.==(null) ? this.t = self::getInt() : #t1;
dynamic v5 = let final dynamic #t2 = this.t in #t2.==(null) ? this.t = self::getNum() : #t2;
dynamic v7 = this.t = this.t.+(self::getInt());
dynamic v8 = this.t = this.t.+(self::getNum());
dynamic v10 = this.t = this.t.+(1);
dynamic v11 = let final dynamic #t3 = this.t in let final dynamic #t4 = this.t = #t3.+(1) in #t3;
}
}
class Test2 extends core::Object {
field core::num t = null;
constructor •() → void
: super core::Object::•()
;
method test() → void {
dynamic v1 = this.t = self::getInt();
dynamic v2 = this.t = self::getNum();
dynamic v3 = this.t = self::getDouble();
dynamic v4 = let final dynamic #t5 = this.t in #t5.==(null) ? this.t = self::getInt() : #t5;
dynamic v5 = let final dynamic #t6 = this.t in #t6.==(null) ? this.t = self::getNum() : #t6;
dynamic v6 = let final dynamic #t7 = this.t in #t7.==(null) ? this.t = self::getDouble() : #t7;
dynamic v7 = this.t = this.t.+(self::getInt());
dynamic v8 = this.t = this.t.+(self::getNum());
dynamic v9 = this.t = this.t.+(self::getDouble());
dynamic v10 = this.t = this.t.+(1);
dynamic v11 = let final dynamic #t8 = this.t in let final dynamic #t9 = this.t = #t8.+(1) in #t8;
}
}
class Test3 extends core::Object {
field core::double t = null;
constructor •() → void
: super core::Object::•()
;
method test3() → void {
dynamic v2 = this.t = self::getNum();
dynamic v3 = this.t = self::getDouble();
dynamic v5 = let final dynamic #t10 = this.t in #t10.==(null) ? this.t = self::getNum() : #t10;
dynamic v6 = let final dynamic #t11 = this.t in #t11.==(null) ? this.t = self::getDouble() : #t11;
dynamic v7 = this.t = this.t.+(self::getInt());
dynamic v8 = this.t = this.t.+(self::getNum());
dynamic v9 = this.t = this.t.+(self::getDouble());
dynamic v10 = this.t = this.t.+(1);
dynamic v11 = let final dynamic #t12 = this.t in let final dynamic #t13 = this.t = #t12.+(1) in #t12;
}
}
static method getInt() → core::int
return 0;
static method getNum() → core::num
return 0;
static method getDouble() → core::double
return 0.0;
static method main() → dynamic {}

View file

@ -0,0 +1,33 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int t;
constructor •() → void
;
method test() → void
;
}
class Test2 extends core::Object {
field core::num t;
constructor •() → void
;
method test() → void
;
}
class Test3 extends core::Object {
field core::double t;
constructor •() → void
;
method test3() → void
;
}
static method getInt() → core::int
;
static method getNum() → core::num
;
static method getDouble() → core::double
;
static method main() → dynamic
;

View file

@ -0,0 +1,63 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int t = null;
constructor •() → void
: super core::Object::•()
;
method test() → void {
core::int v1 = this.{self::Test1::t} = self::getInt();
core::num v2 = this.{self::Test1::t} = self::getNum();
core::int v4 = let final dynamic #t1 = this.{self::Test1::t} in #t1.{core::num::==}(null) ? this.{self::Test1::t} = self::getInt() : #t1;
core::num v5 = let final dynamic #t2 = this.{self::Test1::t} in #t2.{core::num::==}(null) ? this.{self::Test1::t} = self::getNum() : #t2;
core::int v7 = this.{self::Test1::t} = this.{self::Test1::t}.{core::num::+}(self::getInt());
core::num v8 = this.{self::Test1::t} = this.{self::Test1::t}.{core::num::+}(self::getNum());
core::int v10 = this.{self::Test1::t} = this.{self::Test1::t}.{core::num::+}(1);
core::int v11 = let final dynamic #t3 = this.{self::Test1::t} in let final dynamic #t4 = this.{self::Test1::t} = #t3.{core::num::+}(1) in #t3;
}
}
class Test2 extends core::Object {
field core::num t = null;
constructor •() → void
: super core::Object::•()
;
method test() → void {
core::int v1 = this.{self::Test2::t} = self::getInt();
core::num v2 = this.{self::Test2::t} = self::getNum();
core::double v3 = this.{self::Test2::t} = self::getDouble();
core::num v4 = let final dynamic #t5 = this.{self::Test2::t} in #t5.{core::num::==}(null) ? this.{self::Test2::t} = self::getInt() : #t5;
core::num v5 = let final dynamic #t6 = this.{self::Test2::t} in #t6.{core::num::==}(null) ? this.{self::Test2::t} = self::getNum() : #t6;
core::num v6 = let final dynamic #t7 = this.{self::Test2::t} in #t7.{core::num::==}(null) ? this.{self::Test2::t} = self::getDouble() : #t7;
core::num v7 = this.{self::Test2::t} = this.{self::Test2::t}.{core::num::+}(self::getInt());
core::num v8 = this.{self::Test2::t} = this.{self::Test2::t}.{core::num::+}(self::getNum());
core::num v9 = this.{self::Test2::t} = this.{self::Test2::t}.{core::num::+}(self::getDouble());
core::num v10 = this.{self::Test2::t} = this.{self::Test2::t}.{core::num::+}(1);
core::num v11 = let final dynamic #t8 = this.{self::Test2::t} in let final dynamic #t9 = this.{self::Test2::t} = #t8.{core::num::+}(1) in #t8;
}
}
class Test3 extends core::Object {
field core::double t = null;
constructor •() → void
: super core::Object::•()
;
method test3() → void {
core::num v2 = this.{self::Test3::t} = self::getNum();
core::double v3 = this.{self::Test3::t} = self::getDouble();
core::num v5 = let final dynamic #t10 = this.{self::Test3::t} in #t10.{core::num::==}(null) ? this.{self::Test3::t} = self::getNum() : #t10;
core::double v6 = let final dynamic #t11 = this.{self::Test3::t} in #t11.{core::num::==}(null) ? this.{self::Test3::t} = self::getDouble() : #t11;
core::double v7 = this.{self::Test3::t} = this.{self::Test3::t}.{core::double::+}(self::getInt());
core::double v8 = this.{self::Test3::t} = this.{self::Test3::t}.{core::double::+}(self::getNum());
core::double v9 = this.{self::Test3::t} = this.{self::Test3::t}.{core::double::+}(self::getDouble());
core::double v10 = this.{self::Test3::t} = this.{self::Test3::t}.{core::double::+}(1);
core::double v11 = let final dynamic #t12 = this.{self::Test3::t} in let final dynamic #t13 = this.{self::Test3::t} = #t12.{core::double::+}(1) in #t12;
}
}
static method getInt() → core::int
return 0;
static method getNum() → core::num
return 0;
static method getDouble() → core::double
return 0.0;
static method main() → dynamic {}

View file

@ -8,12 +8,12 @@ class A extends core::Object {
: super core::Object::•()
;
}
static field dynamic v_assign = new self::A::•().f = 1;
static field dynamic v_plus = let final dynamic #t1 = new self::A::•() in #t1.f = #t1.f.+(1);
static field dynamic v_minus = let final dynamic #t2 = new self::A::•() in #t2.f = #t2.f.-(1);
static field dynamic v_multiply = let final dynamic #t3 = new self::A::•() in #t3.f = #t3.f.*(1);
static field dynamic v_prefix_pp = let final dynamic #t4 = new self::A::•() in #t4.f = #t4.f.+(1);
static field dynamic v_prefix_mm = let final dynamic #t5 = new self::A::•() in #t5.f = #t5.f.-(1);
static field dynamic v_postfix_pp = let final dynamic #t6 = new self::A::•() in let final dynamic #t7 = #t6.f in let final dynamic #t8 = #t6.f = #t7.+(1) in #t7;
static field dynamic v_postfix_mm = let final dynamic #t9 = new self::A::•() in let final dynamic #t10 = #t9.f in let final dynamic #t11 = #t9.f = #t10.-(1) in #t10;
static field dynamic v_assign = new self::A::•().{self::A::f} = 1;
static field dynamic v_plus = let final dynamic #t1 = new self::A::•() in #t1.{self::A::f} = #t1.{self::A::f}.{core::num::+}(1);
static field dynamic v_minus = let final dynamic #t2 = new self::A::•() in #t2.{self::A::f} = #t2.{self::A::f}.{core::num::-}(1);
static field dynamic v_multiply = let final dynamic #t3 = new self::A::•() in #t3.{self::A::f} = #t3.{self::A::f}.{core::num::*}(1);
static field dynamic v_prefix_pp = let final dynamic #t4 = new self::A::•() in #t4.{self::A::f} = #t4.{self::A::f}.{core::num::+}(1);
static field dynamic v_prefix_mm = let final dynamic #t5 = new self::A::•() in #t5.{self::A::f} = #t5.{self::A::f}.{core::num::-}(1);
static field dynamic v_postfix_pp = let final dynamic #t6 = new self::A::•() in let final dynamic #t7 = #t6.{self::A::f} in let final dynamic #t8 = #t6.{self::A::f} = #t7.{core::num::+}(1) in #t7;
static field dynamic v_postfix_mm = let final dynamic #t9 = new self::A::•() in let final dynamic #t10 = #t9.{self::A::f} in let final dynamic #t11 = #t9.{self::A::f} = #t10.{core::num::-}(1) in #t10;
static method main() → dynamic {}

View file

@ -17,8 +17,8 @@ class B extends core::Object {
: super core::Object::•()
;
}
static field dynamic v_prefix_pp = let final dynamic #t1 = new self::B::•() in #t1.a = #t1.a.+(1);
static field dynamic v_prefix_mm = let final dynamic #t2 = new self::B::•() in #t2.a = #t2.a.-(1);
static field dynamic v_postfix_pp = let final dynamic #t3 = new self::B::•() in let final dynamic #t4 = #t3.a in let final dynamic #t5 = #t3.a = #t4.+(1) in #t4;
static field dynamic v_postfix_mm = let final dynamic #t6 = new self::B::•() in let final dynamic #t7 = #t6.a in let final dynamic #t8 = #t6.a = #t7.-(1) in #t7;
static field dynamic v_prefix_pp = let final dynamic #t1 = new self::B::•() in #t1.{self::B::a} = #t1.{self::B::a}.{self::A::+}(1);
static field dynamic v_prefix_mm = let final dynamic #t2 = new self::B::•() in #t2.{self::B::a} = #t2.{self::B::a}.{self::A::-}(1);
static field dynamic v_postfix_pp = let final dynamic #t3 = new self::B::•() in let final dynamic #t4 = #t3.{self::B::a} in let final dynamic #t5 = #t3.{self::B::a} = #t4.{self::A::+}(1) in #t4;
static field dynamic v_postfix_mm = let final dynamic #t6 = new self::B::•() in let final dynamic #t7 = #t6.{self::B::a} in let final dynamic #t8 = #t6.{self::B::a} = #t7.{self::A::-}(1) in #t7;
static method main() → dynamic {}

View file

@ -0,0 +1,47 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
class A {}
class B extends A {
A operator +(C v) => null;
B operator -(int i) => null;
B operator *(B v) => null;
C operator &(A v) => null;
}
class C extends B {}
T f<T>() => null;
class Test {
B member;
static void test(Test t) {
t. /*@target=Test::member*/ member = /*@typeArgs=B*/ f();
t. /*@target=Test::member*/ member ??= /*@typeArgs=B*/ f();
t. /*@target=Test::member*/ member += /*@typeArgs=dynamic*/ f();
t. /*@target=Test::member*/ member *= /*@typeArgs=dynamic*/ f();
t. /*@target=Test::member*/ member &= /*@typeArgs=dynamic*/ f();
--t. /*@target=Test::member*/ member;
t. /*@target=Test::member*/ member--;
var /*@type=B*/ v1 =
t. /*@target=Test::member*/ member = /*@typeArgs=B*/ f();
var /*@type=B*/ v2 =
t. /*@target=Test::member*/ member ??= /*@typeArgs=B*/ f();
var /*@type=A*/ v3 =
t. /*@target=Test::member*/ member += /*@typeArgs=dynamic*/ f();
var /*@type=B*/ v4 =
t. /*@target=Test::member*/ member *= /*@typeArgs=dynamic*/ f();
var /*@type=C*/ v5 =
t. /*@target=Test::member*/ member &= /*@typeArgs=dynamic*/ f();
var /*@type=B*/ v6 = --t. /*@target=Test::member*/ member;
var /*@type=B*/ v7 = t. /*@target=Test::member*/ member--;
}
}
main() {}

View file

@ -0,0 +1,52 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
operator +(self::C v) → self::A
return null;
operator -(core::int i) → self::B
return null;
operator *(self::B v) → self::B
return null;
operator &(self::A v) → self::C
return null;
}
class C extends self::B {
constructor •() → void
: super self::B::•()
;
}
class Test extends core::Object {
field self::B member = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test t) → void {
t.member = self::f();
let final dynamic #t1 = t in #t1.member.==(null) ? #t1.member = self::f() : null;
let final dynamic #t2 = t in #t2.member = #t2.member.+(self::f());
let final dynamic #t3 = t in #t3.member = #t3.member.*(self::f());
let final dynamic #t4 = t in #t4.member = #t4.member.&(self::f());
let final dynamic #t5 = t in #t5.member = #t5.member.-(1);
let final dynamic #t6 = t in #t6.member = #t6.member.-(1);
dynamic v1 = t.member = self::f();
dynamic v2 = let final dynamic #t7 = t in let final dynamic #t8 = #t7.member in #t8.==(null) ? #t7.member = self::f() : #t8;
dynamic v3 = let final dynamic #t9 = t in #t9.member = #t9.member.+(self::f());
dynamic v4 = let final dynamic #t10 = t in #t10.member = #t10.member.*(self::f());
dynamic v5 = let final dynamic #t11 = t in #t11.member = #t11.member.&(self::f());
dynamic v6 = let final dynamic #t12 = t in #t12.member = #t12.member.-(1);
dynamic v7 = let final dynamic #t13 = t in let final dynamic #t14 = #t13.member in let final dynamic #t15 = #t13.member = #t14.-(1) in #t14;
}
}
static method f() → dynamic
return null;
static method main() → dynamic {}

View file

@ -0,0 +1,35 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
;
}
class B extends self::A {
constructor •() → void
;
operator +(self::C v) → self::A
;
operator -(core::int i) → self::B
;
operator *(self::B v) → self::B
;
operator &(self::A v) → self::C
;
}
class C extends self::B {
constructor •() → void
;
}
class Test extends core::Object {
field self::B member;
constructor •() → void
;
static method test(self::Test t) → void
;
}
static method f<T extends core::Object>() → self::f::T
;
static method main() → dynamic
;

View file

@ -0,0 +1,52 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
operator +(self::C v) → self::A
return null;
operator -(core::int i) → self::B
return null;
operator *(self::B v) → self::B
return null;
operator &(self::A v) → self::C
return null;
}
class C extends self::B {
constructor •() → void
: super self::B::•()
;
}
class Test extends core::Object {
field self::B member = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test t) → void {
t.{self::Test::member} = self::f<self::B>();
let final dynamic #t1 = t in #t1.{self::Test::member}.{core::Object::==}(null) ? #t1.{self::Test::member} = self::f<self::B>() : null;
let final dynamic #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<dynamic>());
let final dynamic #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<dynamic>());
let final dynamic #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<dynamic>());
let final dynamic #t5 = t in #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::-}(1);
let final dynamic #t6 = t in #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
self::B v1 = t.{self::Test::member} = self::f<self::B>();
self::B v2 = let final dynamic #t7 = t in let final dynamic #t8 = #t7.{self::Test::member} in #t8.{core::Object::==}(null) ? #t7.{self::Test::member} = self::f<self::B>() : #t8;
self::A v3 = let final dynamic #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::+}(self::f<dynamic>());
self::B v4 = let final dynamic #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::*}(self::f<dynamic>());
self::C v5 = let final dynamic #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::&}(self::f<dynamic>());
self::B v6 = let final dynamic #t12 = t in #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::-}(1);
self::B v7 = let final dynamic #t13 = t in let final dynamic #t14 = #t13.{self::Test::member} in let final dynamic #t15 = #t13.{self::Test::member} = #t14.{self::B::-}(1) in #t14;
}
}
static method f<T extends core::Object>() → self::f::T
return null;
static method main() → dynamic {}

View file

@ -0,0 +1,47 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
class A {}
class B extends A {
A operator +(C v) => null;
B operator -(int i) => null;
B operator *(B v) => null;
C operator &(A v) => null;
}
class C extends B {}
T f<T>() => null;
class Test {
B member;
static void test(Test t) {
t?. /*@target=Test::member*/ member = /*@typeArgs=B*/ f();
t?. /*@target=Test::member*/ member ??= /*@typeArgs=B*/ f();
t?. /*@target=Test::member*/ member += /*@typeArgs=dynamic*/ f();
t?. /*@target=Test::member*/ member *= /*@typeArgs=dynamic*/ f();
t?. /*@target=Test::member*/ member &= /*@typeArgs=dynamic*/ f();
--t?. /*@target=Test::member*/ member;
t?. /*@target=Test::member*/ member--;
var /*@type=B*/ v1 =
t?. /*@target=Test::member*/ member = /*@typeArgs=B*/ f();
var /*@type=B*/ v2 =
t?. /*@target=Test::member*/ member ??= /*@typeArgs=B*/ f();
var /*@type=A*/ v3 =
t?. /*@target=Test::member*/ member += /*@typeArgs=dynamic*/ f();
var /*@type=B*/ v4 =
t?. /*@target=Test::member*/ member *= /*@typeArgs=dynamic*/ f();
var /*@type=C*/ v5 =
t?. /*@target=Test::member*/ member &= /*@typeArgs=dynamic*/ f();
var /*@type=B*/ v6 = --t?. /*@target=Test::member*/ member;
var /*@type=B*/ v7 = t?. /*@target=Test::member*/ member--;
}
}
main() {}

View file

@ -0,0 +1,52 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
operator +(self::C v) → self::A
return null;
operator -(core::int i) → self::B
return null;
operator *(self::B v) → self::B
return null;
operator &(self::A v) → self::C
return null;
}
class C extends self::B {
constructor •() → void
: super self::B::•()
;
}
class Test extends core::Object {
field self::B member = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test t) → void {
let final dynamic #t1 = t in #t1.==(null) ? null : #t1.member = self::f();
let final dynamic #t2 = t in #t2.==(null) ? null : #t2.member.==(null) ? #t2.member = self::f() : null;
let final dynamic #t3 = t in #t3.==(null) ? null : #t3.member = #t3.member.+(self::f());
let final dynamic #t4 = t in #t4.==(null) ? null : #t4.member = #t4.member.*(self::f());
let final dynamic #t5 = t in #t5.==(null) ? null : #t5.member = #t5.member.&(self::f());
let final dynamic #t6 = t in #t6.==(null) ? null : #t6.member = #t6.member.-(1);
let final dynamic #t7 = t in #t7.==(null) ? null : #t7.member = #t7.member.-(1);
dynamic v1 = let final dynamic #t8 = t in #t8.==(null) ? null : #t8.member = self::f();
dynamic v2 = let final dynamic #t9 = t in #t9.==(null) ? null : let final dynamic #t10 = #t9.member in #t10.==(null) ? #t9.member = self::f() : #t10;
dynamic v3 = let final dynamic #t11 = t in #t11.==(null) ? null : #t11.member = #t11.member.+(self::f());
dynamic v4 = let final dynamic #t12 = t in #t12.==(null) ? null : #t12.member = #t12.member.*(self::f());
dynamic v5 = let final dynamic #t13 = t in #t13.==(null) ? null : #t13.member = #t13.member.&(self::f());
dynamic v6 = let final dynamic #t14 = t in #t14.==(null) ? null : #t14.member = #t14.member.-(1);
dynamic v7 = let final dynamic #t15 = t in #t15.==(null) ? null : let final dynamic #t16 = #t15.member in let final dynamic #t17 = #t15.member = #t16.-(1) in #t16;
}
}
static method f() → dynamic
return null;
static method main() → dynamic {}

View file

@ -0,0 +1,35 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
;
}
class B extends self::A {
constructor •() → void
;
operator +(self::C v) → self::A
;
operator -(core::int i) → self::B
;
operator *(self::B v) → self::B
;
operator &(self::A v) → self::C
;
}
class C extends self::B {
constructor •() → void
;
}
class Test extends core::Object {
field self::B member;
constructor •() → void
;
static method test(self::Test t) → void
;
}
static method f<T extends core::Object>() → self::f::T
;
static method main() → dynamic
;

View file

@ -0,0 +1,52 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
operator +(self::C v) → self::A
return null;
operator -(core::int i) → self::B
return null;
operator *(self::B v) → self::B
return null;
operator &(self::A v) → self::C
return null;
}
class C extends self::B {
constructor •() → void
: super self::B::•()
;
}
class Test extends core::Object {
field self::B member = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test t) → void {
let final dynamic #t1 = t in #t1.==(null) ? null : #t1.{self::Test::member} = self::f<self::B>();
let final dynamic #t2 = t in #t2.==(null) ? null : #t2.{self::Test::member}.{core::Object::==}(null) ? #t2.{self::Test::member} = self::f<self::B>() : null;
let final dynamic #t3 = t in #t3.==(null) ? null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<dynamic>());
let final dynamic #t4 = t in #t4.==(null) ? null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<dynamic>());
let final dynamic #t5 = t in #t5.==(null) ? null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<dynamic>());
let final dynamic #t6 = t in #t6.==(null) ? null : #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
let final dynamic #t7 = t in #t7.==(null) ? null : #t7.{self::Test::member} = #t7.{self::Test::member}.{self::B::-}(1);
self::B v1 = let final dynamic #t8 = t in #t8.==(null) ? null : #t8.{self::Test::member} = self::f<self::B>();
self::B v2 = let final dynamic #t9 = t in #t9.==(null) ? null : let final dynamic #t10 = #t9.{self::Test::member} in #t10.{core::Object::==}(null) ? #t9.{self::Test::member} = self::f<self::B>() : #t10;
self::A v3 = let final dynamic #t11 = t in #t11.==(null) ? null : #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::+}(self::f<dynamic>());
self::B v4 = let final dynamic #t12 = t in #t12.==(null) ? null : #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::*}(self::f<dynamic>());
self::C v5 = let final dynamic #t13 = t in #t13.==(null) ? null : #t13.{self::Test::member} = #t13.{self::Test::member}.{self::B::&}(self::f<dynamic>());
self::B v6 = let final dynamic #t14 = t in #t14.==(null) ? null : #t14.{self::Test::member} = #t14.{self::Test::member}.{self::B::-}(1);
self::B v7 = let final dynamic #t15 = t in #t15.==(null) ? null : let final dynamic #t16 = #t15.{self::Test::member} in let final dynamic #t17 = #t15.{self::Test::member} = #t16.{self::B::-}(1) in #t16;
}
}
static method f<T extends core::Object>() → self::f::T
return null;
static method main() → dynamic {}

View file

@ -0,0 +1,61 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
int getInt() => 0;
num getNum() => 0;
double getDouble() => 0.0;
class Test1 {
int prop;
static void test(Test1 t) {
var /*@type=int*/ v1 = t?. /*@target=Test1::prop*/ prop = getInt();
var /*@type=num*/ v2 = t?. /*@target=Test1::prop*/ prop = getNum();
var /*@type=int*/ v4 = t?. /*@target=Test1::prop*/ prop ??= getInt();
var /*@type=num*/ v5 = t?. /*@target=Test1::prop*/ prop ??= getNum();
var /*@type=int*/ v7 = t?. /*@target=Test1::prop*/ prop += getInt();
var /*@type=num*/ v8 = t?. /*@target=Test1::prop*/ prop += getNum();
var /*@type=int*/ v10 = ++t?. /*@target=Test1::prop*/ prop;
var /*@type=int*/ v11 = t?. /*@target=Test1::prop*/ prop++;
}
}
class Test2 {
num prop;
static void test(Test2 t) {
var /*@type=int*/ v1 = t?. /*@target=Test2::prop*/ prop = getInt();
var /*@type=num*/ v2 = t?. /*@target=Test2::prop*/ prop = getNum();
var /*@type=double*/ v3 = t?. /*@target=Test2::prop*/ prop = getDouble();
var /*@type=num*/ v4 = t?. /*@target=Test2::prop*/ prop ??= getInt();
var /*@type=num*/ v5 = t?. /*@target=Test2::prop*/ prop ??= getNum();
var /*@type=num*/ v6 = t?. /*@target=Test2::prop*/ prop ??= getDouble();
var /*@type=num*/ v7 = t?. /*@target=Test2::prop*/ prop += getInt();
var /*@type=num*/ v8 = t?. /*@target=Test2::prop*/ prop += getNum();
var /*@type=num*/ v9 = t?. /*@target=Test2::prop*/ prop += getDouble();
var /*@type=num*/ v10 = ++t?. /*@target=Test2::prop*/ prop;
var /*@type=num*/ v11 = t?. /*@target=Test2::prop*/ prop++;
}
}
class Test3 {
double prop;
static void test3(Test3 t) {
var /*@type=num*/ v2 = t?. /*@target=Test3::prop*/ prop = getNum();
var /*@type=double*/ v3 = t?. /*@target=Test3::prop*/ prop = getDouble();
var /*@type=num*/ v5 = t?. /*@target=Test3::prop*/ prop ??= getNum();
var /*@type=double*/ v6 = t?. /*@target=Test3::prop*/ prop ??= getDouble();
var /*@type=double*/ v7 = t?. /*@target=Test3::prop*/ prop += getInt();
var /*@type=double*/ v8 = t?. /*@target=Test3::prop*/ prop += getNum();
var /*@type=double*/ v9 = t?. /*@target=Test3::prop*/ prop += getDouble();
var /*@type=double*/ v10 = ++t?. /*@target=Test3::prop*/ prop;
var /*@type=double*/ v11 = t?. /*@target=Test3::prop*/ prop++;
}
}
main() {}

View file

@ -0,0 +1,63 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int prop = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test1 t) → void {
dynamic v1 = let final dynamic #t1 = t in #t1.==(null) ? null : #t1.prop = self::getInt();
dynamic v2 = let final dynamic #t2 = t in #t2.==(null) ? null : #t2.prop = self::getNum();
dynamic v4 = let final dynamic #t3 = t in #t3.==(null) ? null : let final dynamic #t4 = #t3.prop in #t4.==(null) ? #t3.prop = self::getInt() : #t4;
dynamic v5 = let final dynamic #t5 = t in #t5.==(null) ? null : let final dynamic #t6 = #t5.prop in #t6.==(null) ? #t5.prop = self::getNum() : #t6;
dynamic v7 = let final dynamic #t7 = t in #t7.==(null) ? null : #t7.prop = #t7.prop.+(self::getInt());
dynamic v8 = let final dynamic #t8 = t in #t8.==(null) ? null : #t8.prop = #t8.prop.+(self::getNum());
dynamic v10 = let final dynamic #t9 = t in #t9.==(null) ? null : #t9.prop = #t9.prop.+(1);
dynamic v11 = let final dynamic #t10 = t in #t10.==(null) ? null : let final dynamic #t11 = #t10.prop in let final dynamic #t12 = #t10.prop = #t11.+(1) in #t11;
}
}
class Test2 extends core::Object {
field core::num prop = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test2 t) → void {
dynamic v1 = let final dynamic #t13 = t in #t13.==(null) ? null : #t13.prop = self::getInt();
dynamic v2 = let final dynamic #t14 = t in #t14.==(null) ? null : #t14.prop = self::getNum();
dynamic v3 = let final dynamic #t15 = t in #t15.==(null) ? null : #t15.prop = self::getDouble();
dynamic v4 = let final dynamic #t16 = t in #t16.==(null) ? null : let final dynamic #t17 = #t16.prop in #t17.==(null) ? #t16.prop = self::getInt() : #t17;
dynamic v5 = let final dynamic #t18 = t in #t18.==(null) ? null : let final dynamic #t19 = #t18.prop in #t19.==(null) ? #t18.prop = self::getNum() : #t19;
dynamic v6 = let final dynamic #t20 = t in #t20.==(null) ? null : let final dynamic #t21 = #t20.prop in #t21.==(null) ? #t20.prop = self::getDouble() : #t21;
dynamic v7 = let final dynamic #t22 = t in #t22.==(null) ? null : #t22.prop = #t22.prop.+(self::getInt());
dynamic v8 = let final dynamic #t23 = t in #t23.==(null) ? null : #t23.prop = #t23.prop.+(self::getNum());
dynamic v9 = let final dynamic #t24 = t in #t24.==(null) ? null : #t24.prop = #t24.prop.+(self::getDouble());
dynamic v10 = let final dynamic #t25 = t in #t25.==(null) ? null : #t25.prop = #t25.prop.+(1);
dynamic v11 = let final dynamic #t26 = t in #t26.==(null) ? null : let final dynamic #t27 = #t26.prop in let final dynamic #t28 = #t26.prop = #t27.+(1) in #t27;
}
}
class Test3 extends core::Object {
field core::double prop = null;
constructor •() → void
: super core::Object::•()
;
static method test3(self::Test3 t) → void {
dynamic v2 = let final dynamic #t29 = t in #t29.==(null) ? null : #t29.prop = self::getNum();
dynamic v3 = let final dynamic #t30 = t in #t30.==(null) ? null : #t30.prop = self::getDouble();
dynamic v5 = let final dynamic #t31 = t in #t31.==(null) ? null : let final dynamic #t32 = #t31.prop in #t32.==(null) ? #t31.prop = self::getNum() : #t32;
dynamic v6 = let final dynamic #t33 = t in #t33.==(null) ? null : let final dynamic #t34 = #t33.prop in #t34.==(null) ? #t33.prop = self::getDouble() : #t34;
dynamic v7 = let final dynamic #t35 = t in #t35.==(null) ? null : #t35.prop = #t35.prop.+(self::getInt());
dynamic v8 = let final dynamic #t36 = t in #t36.==(null) ? null : #t36.prop = #t36.prop.+(self::getNum());
dynamic v9 = let final dynamic #t37 = t in #t37.==(null) ? null : #t37.prop = #t37.prop.+(self::getDouble());
dynamic v10 = let final dynamic #t38 = t in #t38.==(null) ? null : #t38.prop = #t38.prop.+(1);
dynamic v11 = let final dynamic #t39 = t in #t39.==(null) ? null : let final dynamic #t40 = #t39.prop in let final dynamic #t41 = #t39.prop = #t40.+(1) in #t40;
}
}
static method getInt() → core::int
return 0;
static method getNum() → core::num
return 0;
static method getDouble() → core::double
return 0.0;
static method main() → dynamic {}

View file

@ -0,0 +1,33 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int prop;
constructor •() → void
;
static method test(self::Test1 t) → void
;
}
class Test2 extends core::Object {
field core::num prop;
constructor •() → void
;
static method test(self::Test2 t) → void
;
}
class Test3 extends core::Object {
field core::double prop;
constructor •() → void
;
static method test3(self::Test3 t) → void
;
}
static method getInt() → core::int
;
static method getNum() → core::num
;
static method getDouble() → core::double
;
static method main() → dynamic
;

View file

@ -0,0 +1,63 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int prop = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test1 t) → void {
core::int v1 = let final dynamic #t1 = t in #t1.==(null) ? null : #t1.{self::Test1::prop} = self::getInt();
core::num v2 = let final dynamic #t2 = t in #t2.==(null) ? null : #t2.{self::Test1::prop} = self::getNum();
core::int v4 = let final dynamic #t3 = t in #t3.==(null) ? null : let final dynamic #t4 = #t3.{self::Test1::prop} in #t4.{core::num::==}(null) ? #t3.{self::Test1::prop} = self::getInt() : #t4;
core::num v5 = let final dynamic #t5 = t in #t5.==(null) ? null : let final dynamic #t6 = #t5.{self::Test1::prop} in #t6.{core::num::==}(null) ? #t5.{self::Test1::prop} = self::getNum() : #t6;
core::int v7 = let final dynamic #t7 = t in #t7.==(null) ? null : #t7.{self::Test1::prop} = #t7.{self::Test1::prop}.{core::num::+}(self::getInt());
core::num v8 = let final dynamic #t8 = t in #t8.==(null) ? null : #t8.{self::Test1::prop} = #t8.{self::Test1::prop}.{core::num::+}(self::getNum());
core::int v10 = let final dynamic #t9 = t in #t9.==(null) ? null : #t9.{self::Test1::prop} = #t9.{self::Test1::prop}.{core::num::+}(1);
core::int v11 = let final dynamic #t10 = t in #t10.==(null) ? null : let final dynamic #t11 = #t10.{self::Test1::prop} in let final dynamic #t12 = #t10.{self::Test1::prop} = #t11.{core::num::+}(1) in #t11;
}
}
class Test2 extends core::Object {
field core::num prop = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test2 t) → void {
core::int v1 = let final dynamic #t13 = t in #t13.==(null) ? null : #t13.{self::Test2::prop} = self::getInt();
core::num v2 = let final dynamic #t14 = t in #t14.==(null) ? null : #t14.{self::Test2::prop} = self::getNum();
core::double v3 = let final dynamic #t15 = t in #t15.==(null) ? null : #t15.{self::Test2::prop} = self::getDouble();
core::num v4 = let final dynamic #t16 = t in #t16.==(null) ? null : let final dynamic #t17 = #t16.{self::Test2::prop} in #t17.{core::num::==}(null) ? #t16.{self::Test2::prop} = self::getInt() : #t17;
core::num v5 = let final dynamic #t18 = t in #t18.==(null) ? null : let final dynamic #t19 = #t18.{self::Test2::prop} in #t19.{core::num::==}(null) ? #t18.{self::Test2::prop} = self::getNum() : #t19;
core::num v6 = let final dynamic #t20 = t in #t20.==(null) ? null : let final dynamic #t21 = #t20.{self::Test2::prop} in #t21.{core::num::==}(null) ? #t20.{self::Test2::prop} = self::getDouble() : #t21;
core::num v7 = let final dynamic #t22 = t in #t22.==(null) ? null : #t22.{self::Test2::prop} = #t22.{self::Test2::prop}.{core::num::+}(self::getInt());
core::num v8 = let final dynamic #t23 = t in #t23.==(null) ? null : #t23.{self::Test2::prop} = #t23.{self::Test2::prop}.{core::num::+}(self::getNum());
core::num v9 = let final dynamic #t24 = t in #t24.==(null) ? null : #t24.{self::Test2::prop} = #t24.{self::Test2::prop}.{core::num::+}(self::getDouble());
core::num v10 = let final dynamic #t25 = t in #t25.==(null) ? null : #t25.{self::Test2::prop} = #t25.{self::Test2::prop}.{core::num::+}(1);
core::num v11 = let final dynamic #t26 = t in #t26.==(null) ? null : let final dynamic #t27 = #t26.{self::Test2::prop} in let final dynamic #t28 = #t26.{self::Test2::prop} = #t27.{core::num::+}(1) in #t27;
}
}
class Test3 extends core::Object {
field core::double prop = null;
constructor •() → void
: super core::Object::•()
;
static method test3(self::Test3 t) → void {
core::num v2 = let final dynamic #t29 = t in #t29.==(null) ? null : #t29.{self::Test3::prop} = self::getNum();
core::double v3 = let final dynamic #t30 = t in #t30.==(null) ? null : #t30.{self::Test3::prop} = self::getDouble();
core::num v5 = let final dynamic #t31 = t in #t31.==(null) ? null : let final dynamic #t32 = #t31.{self::Test3::prop} in #t32.{core::num::==}(null) ? #t31.{self::Test3::prop} = self::getNum() : #t32;
core::double v6 = let final dynamic #t33 = t in #t33.==(null) ? null : let final dynamic #t34 = #t33.{self::Test3::prop} in #t34.{core::num::==}(null) ? #t33.{self::Test3::prop} = self::getDouble() : #t34;
core::double v7 = let final dynamic #t35 = t in #t35.==(null) ? null : #t35.{self::Test3::prop} = #t35.{self::Test3::prop}.{core::double::+}(self::getInt());
core::double v8 = let final dynamic #t36 = t in #t36.==(null) ? null : #t36.{self::Test3::prop} = #t36.{self::Test3::prop}.{core::double::+}(self::getNum());
core::double v9 = let final dynamic #t37 = t in #t37.==(null) ? null : #t37.{self::Test3::prop} = #t37.{self::Test3::prop}.{core::double::+}(self::getDouble());
core::double v10 = let final dynamic #t38 = t in #t38.==(null) ? null : #t38.{self::Test3::prop} = #t38.{self::Test3::prop}.{core::double::+}(1);
core::double v11 = let final dynamic #t39 = t in #t39.==(null) ? null : let final dynamic #t40 = #t39.{self::Test3::prop} in let final dynamic #t41 = #t39.{self::Test3::prop} = #t40.{core::double::+}(1) in #t40;
}
}
static method getInt() → core::int
return 0;
static method getNum() → core::num
return 0;
static method getDouble() → core::double
return 0.0;
static method main() → dynamic {}

View file

@ -0,0 +1,49 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
class A {}
class B extends A {
A operator +(C v) => null;
B operator -(int i) => null;
B operator *(B v) => null;
C operator &(A v) => null;
}
class C extends B {}
T f<T>() => null;
class Base {
B member;
}
class Test extends Base {
void test() {
super. /*@target=Base::member*/ member = /*@typeArgs=B*/ f();
super. /*@target=Base::member*/ member ??= /*@typeArgs=B*/ f();
super. /*@target=Base::member*/ member += /*@typeArgs=dynamic*/ f();
super. /*@target=Base::member*/ member *= /*@typeArgs=dynamic*/ f();
super. /*@target=Base::member*/ member &= /*@typeArgs=dynamic*/ f();
--super. /*@target=Base::member*/ member;
super. /*@target=Base::member*/ member--;
var /*@type=B*/ v1 =
super. /*@target=Base::member*/ member = /*@typeArgs=B*/ f();
var /*@type=B*/ v2 =
super. /*@target=Base::member*/ member ??= /*@typeArgs=B*/ f();
var /*@type=A*/ v3 =
super. /*@target=Base::member*/ member += /*@typeArgs=dynamic*/ f();
var /*@type=B*/ v4 =
super. /*@target=Base::member*/ member *= /*@typeArgs=dynamic*/ f();
var /*@type=C*/ v5 =
super. /*@target=Base::member*/ member &= /*@typeArgs=dynamic*/ f();
var /*@type=B*/ v6 = --super. /*@target=Base::member*/ member;
var /*@type=B*/ v7 = super. /*@target=Base::member*/ member--;
}
}
main() {}

View file

@ -0,0 +1,57 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
operator +(self::C v) → self::A
return null;
operator -(core::int i) → self::B
return null;
operator *(self::B v) → self::B
return null;
operator &(self::A v) → self::C
return null;
}
class C extends self::B {
constructor •() → void
: super self::B::•()
;
}
class Base extends core::Object {
field self::B member = null;
constructor •() → void
: super core::Object::•()
;
}
class Test extends self::Base {
constructor •() → void
: super self::Base::•()
;
method test() → void {
this.{=self::Base::member} = self::f();
this.{=self::Base::member}.==(null) ? this.{=self::Base::member} = self::f() : null;
this.{=self::Base::member} = this.{=self::Base::member}.+(self::f());
this.{=self::Base::member} = this.{=self::Base::member}.*(self::f());
this.{=self::Base::member} = this.{=self::Base::member}.&(self::f());
this.{=self::Base::member} = this.{=self::Base::member}.-(1);
this.{=self::Base::member} = this.{=self::Base::member}.-(1);
dynamic v1 = this.{=self::Base::member} = self::f();
dynamic v2 = let final dynamic #t1 = this.{=self::Base::member} in #t1.==(null) ? this.{=self::Base::member} = self::f() : #t1;
dynamic v3 = this.{=self::Base::member} = this.{=self::Base::member}.+(self::f());
dynamic v4 = this.{=self::Base::member} = this.{=self::Base::member}.*(self::f());
dynamic v5 = this.{=self::Base::member} = this.{=self::Base::member}.&(self::f());
dynamic v6 = this.{=self::Base::member} = this.{=self::Base::member}.-(1);
dynamic v7 = let final dynamic #t2 = this.{=self::Base::member} in let final dynamic #t3 = this.{=self::Base::member} = #t2.-(1) in #t2;
}
}
static method f() → dynamic
return null;
static method main() → dynamic {}

View file

@ -0,0 +1,39 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
;
}
class B extends self::A {
constructor •() → void
;
operator +(self::C v) → self::A
;
operator -(core::int i) → self::B
;
operator *(self::B v) → self::B
;
operator &(self::A v) → self::C
;
}
class C extends self::B {
constructor •() → void
;
}
class Base extends core::Object {
field self::B member;
constructor •() → void
;
}
class Test extends self::Base {
constructor •() → void
;
method test() → void
;
}
static method f<T extends core::Object>() → self::f::T
;
static method main() → dynamic
;

View file

@ -0,0 +1,57 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
operator +(self::C v) → self::A
return null;
operator -(core::int i) → self::B
return null;
operator *(self::B v) → self::B
return null;
operator &(self::A v) → self::C
return null;
}
class C extends self::B {
constructor •() → void
: super self::B::•()
;
}
class Base extends core::Object {
field self::B member = null;
constructor •() → void
: super core::Object::•()
;
}
class Test extends self::Base {
constructor •() → void
: super self::Base::•()
;
method test() → void {
this.{=self::Base::member} = self::f<self::B>();
this.{=self::Base::member}.{core::Object::==}(null) ? this.{=self::Base::member} = self::f<self::B>() : null;
this.{=self::Base::member} = this.{=self::Base::member}.{self::B::+}(self::f<dynamic>());
this.{=self::Base::member} = this.{=self::Base::member}.{self::B::*}(self::f<dynamic>());
this.{=self::Base::member} = this.{=self::Base::member}.{self::B::&}(self::f<dynamic>());
this.{=self::Base::member} = this.{=self::Base::member}.{self::B::-}(1);
this.{=self::Base::member} = this.{=self::Base::member}.{self::B::-}(1);
self::B v1 = this.{=self::Base::member} = self::f<self::B>();
self::B v2 = let final dynamic #t1 = this.{=self::Base::member} in #t1.{core::Object::==}(null) ? this.{=self::Base::member} = self::f<self::B>() : #t1;
self::A v3 = this.{=self::Base::member} = this.{=self::Base::member}.{self::B::+}(self::f<dynamic>());
self::B v4 = this.{=self::Base::member} = this.{=self::Base::member}.{self::B::*}(self::f<dynamic>());
self::C v5 = this.{=self::Base::member} = this.{=self::Base::member}.{self::B::&}(self::f<dynamic>());
self::B v6 = this.{=self::Base::member} = this.{=self::Base::member}.{self::B::-}(1);
self::B v7 = let final dynamic #t2 = this.{=self::Base::member} in let final dynamic #t3 = this.{=self::Base::member} = #t2.{self::B::-}(1) in #t2;
}
}
static method f<T extends core::Object>() → self::f::T
return null;
static method main() → dynamic {}

View file

@ -0,0 +1,75 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
int getInt() => 0;
num getNum() => 0;
double getDouble() => 0.0;
class Base {
int intProp;
num numProp;
double doubleProp;
}
class Test1 extends Base {
void test() {
var /*@type=int*/ v1 = super. /*@target=Base::intProp*/ intProp = getInt();
var /*@type=num*/ v2 = super. /*@target=Base::intProp*/ intProp = getNum();
var /*@type=int*/ v4 =
super. /*@target=Base::intProp*/ intProp ??= getInt();
var /*@type=num*/ v5 =
super. /*@target=Base::intProp*/ intProp ??= getNum();
var /*@type=int*/ v7 = super. /*@target=Base::intProp*/ intProp += getInt();
var /*@type=num*/ v8 = super. /*@target=Base::intProp*/ intProp += getNum();
var /*@type=int*/ v10 = ++super. /*@target=Base::intProp*/ intProp;
var /*@type=int*/ v11 = super. /*@target=Base::intProp*/ intProp++;
}
}
class Test2 extends Base {
void test() {
var /*@type=int*/ v1 = super. /*@target=Base::numProp*/ numProp = getInt();
var /*@type=num*/ v2 = super. /*@target=Base::numProp*/ numProp = getNum();
var /*@type=double*/ v3 =
super. /*@target=Base::numProp*/ numProp = getDouble();
var /*@type=num*/ v4 =
super. /*@target=Base::numProp*/ numProp ??= getInt();
var /*@type=num*/ v5 =
super. /*@target=Base::numProp*/ numProp ??= getNum();
var /*@type=num*/ v6 =
super. /*@target=Base::numProp*/ numProp ??= getDouble();
var /*@type=num*/ v7 = super. /*@target=Base::numProp*/ numProp += getInt();
var /*@type=num*/ v8 = super. /*@target=Base::numProp*/ numProp += getNum();
var /*@type=num*/ v9 =
super. /*@target=Base::numProp*/ numProp += getDouble();
var /*@type=num*/ v10 = ++super. /*@target=Base::numProp*/ numProp;
var /*@type=num*/ v11 = super. /*@target=Base::numProp*/ numProp++;
}
}
class Test3 extends Base {
void test3() {
var /*@type=num*/ v2 =
super. /*@target=Base::doubleProp*/ doubleProp = getNum();
var /*@type=double*/ v3 =
super. /*@target=Base::doubleProp*/ doubleProp = getDouble();
var /*@type=num*/ v5 =
super. /*@target=Base::doubleProp*/ doubleProp ??= getNum();
var /*@type=double*/ v6 =
super. /*@target=Base::doubleProp*/ doubleProp ??= getDouble();
var /*@type=double*/ v7 =
super. /*@target=Base::doubleProp*/ doubleProp += getInt();
var /*@type=double*/ v8 =
super. /*@target=Base::doubleProp*/ doubleProp += getNum();
var /*@type=double*/ v9 =
super. /*@target=Base::doubleProp*/ doubleProp += getDouble();
var /*@type=double*/ v10 = ++super. /*@target=Base::doubleProp*/ doubleProp;
var /*@type=double*/ v11 = super. /*@target=Base::doubleProp*/ doubleProp++;
}
}
main() {}

View file

@ -0,0 +1,68 @@
library test;
import self as self;
import "dart:core" as core;
class Base extends core::Object {
field core::int intProp = null;
field core::num numProp = null;
field core::double doubleProp = null;
constructor •() → void
: super core::Object::•()
;
}
class Test1 extends self::Base {
constructor •() → void
: super self::Base::•()
;
method test() → void {
dynamic v1 = this.{=self::Base::intProp} = self::getInt();
dynamic v2 = this.{=self::Base::intProp} = self::getNum();
dynamic v4 = let final dynamic #t1 = this.{=self::Base::intProp} in #t1.==(null) ? this.{=self::Base::intProp} = self::getInt() : #t1;
dynamic v5 = let final dynamic #t2 = this.{=self::Base::intProp} in #t2.==(null) ? this.{=self::Base::intProp} = self::getNum() : #t2;
dynamic v7 = this.{=self::Base::intProp} = this.{=self::Base::intProp}.+(self::getInt());
dynamic v8 = this.{=self::Base::intProp} = this.{=self::Base::intProp}.+(self::getNum());
dynamic v10 = this.{=self::Base::intProp} = this.{=self::Base::intProp}.+(1);
dynamic v11 = let final dynamic #t3 = this.{=self::Base::intProp} in let final dynamic #t4 = this.{=self::Base::intProp} = #t3.+(1) in #t3;
}
}
class Test2 extends self::Base {
constructor •() → void
: super self::Base::•()
;
method test() → void {
dynamic v1 = this.{=self::Base::numProp} = self::getInt();
dynamic v2 = this.{=self::Base::numProp} = self::getNum();
dynamic v3 = this.{=self::Base::numProp} = self::getDouble();
dynamic v4 = let final dynamic #t5 = this.{=self::Base::numProp} in #t5.==(null) ? this.{=self::Base::numProp} = self::getInt() : #t5;
dynamic v5 = let final dynamic #t6 = this.{=self::Base::numProp} in #t6.==(null) ? this.{=self::Base::numProp} = self::getNum() : #t6;
dynamic v6 = let final dynamic #t7 = this.{=self::Base::numProp} in #t7.==(null) ? this.{=self::Base::numProp} = self::getDouble() : #t7;
dynamic v7 = this.{=self::Base::numProp} = this.{=self::Base::numProp}.+(self::getInt());
dynamic v8 = this.{=self::Base::numProp} = this.{=self::Base::numProp}.+(self::getNum());
dynamic v9 = this.{=self::Base::numProp} = this.{=self::Base::numProp}.+(self::getDouble());
dynamic v10 = this.{=self::Base::numProp} = this.{=self::Base::numProp}.+(1);
dynamic v11 = let final dynamic #t8 = this.{=self::Base::numProp} in let final dynamic #t9 = this.{=self::Base::numProp} = #t8.+(1) in #t8;
}
}
class Test3 extends self::Base {
constructor •() → void
: super self::Base::•()
;
method test3() → void {
dynamic v2 = this.{=self::Base::doubleProp} = self::getNum();
dynamic v3 = this.{=self::Base::doubleProp} = self::getDouble();
dynamic v5 = let final dynamic #t10 = this.{=self::Base::doubleProp} in #t10.==(null) ? this.{=self::Base::doubleProp} = self::getNum() : #t10;
dynamic v6 = let final dynamic #t11 = this.{=self::Base::doubleProp} in #t11.==(null) ? this.{=self::Base::doubleProp} = self::getDouble() : #t11;
dynamic v7 = this.{=self::Base::doubleProp} = this.{=self::Base::doubleProp}.+(self::getInt());
dynamic v8 = this.{=self::Base::doubleProp} = this.{=self::Base::doubleProp}.+(self::getNum());
dynamic v9 = this.{=self::Base::doubleProp} = this.{=self::Base::doubleProp}.+(self::getDouble());
dynamic v10 = this.{=self::Base::doubleProp} = this.{=self::Base::doubleProp}.+(1);
dynamic v11 = let final dynamic #t12 = this.{=self::Base::doubleProp} in let final dynamic #t13 = this.{=self::Base::doubleProp} = #t12.+(1) in #t12;
}
}
static method getInt() → core::int
return 0;
static method getNum() → core::num
return 0;
static method getDouble() → core::double
return 0.0;
static method main() → dynamic {}

View file

@ -0,0 +1,37 @@
library test;
import self as self;
import "dart:core" as core;
class Base extends core::Object {
field core::int intProp;
field core::num numProp;
field core::double doubleProp;
constructor •() → void
;
}
class Test1 extends self::Base {
constructor •() → void
;
method test() → void
;
}
class Test2 extends self::Base {
constructor •() → void
;
method test() → void
;
}
class Test3 extends self::Base {
constructor •() → void
;
method test3() → void
;
}
static method getInt() → core::int
;
static method getNum() → core::num
;
static method getDouble() → core::double
;
static method main() → dynamic
;

View file

@ -0,0 +1,68 @@
library test;
import self as self;
import "dart:core" as core;
class Base extends core::Object {
field core::int intProp = null;
field core::num numProp = null;
field core::double doubleProp = null;
constructor •() → void
: super core::Object::•()
;
}
class Test1 extends self::Base {
constructor •() → void
: super self::Base::•()
;
method test() → void {
core::int v1 = this.{=self::Base::intProp} = self::getInt();
core::num v2 = this.{=self::Base::intProp} = self::getNum();
core::int v4 = let final dynamic #t1 = this.{=self::Base::intProp} in #t1.{core::num::==}(null) ? this.{=self::Base::intProp} = self::getInt() : #t1;
core::num v5 = let final dynamic #t2 = this.{=self::Base::intProp} in #t2.{core::num::==}(null) ? this.{=self::Base::intProp} = self::getNum() : #t2;
core::int v7 = this.{=self::Base::intProp} = this.{=self::Base::intProp}.{core::num::+}(self::getInt());
core::num v8 = this.{=self::Base::intProp} = this.{=self::Base::intProp}.{core::num::+}(self::getNum());
core::int v10 = this.{=self::Base::intProp} = this.{=self::Base::intProp}.{core::num::+}(1);
core::int v11 = let final dynamic #t3 = this.{=self::Base::intProp} in let final dynamic #t4 = this.{=self::Base::intProp} = #t3.{core::num::+}(1) in #t3;
}
}
class Test2 extends self::Base {
constructor •() → void
: super self::Base::•()
;
method test() → void {
core::int v1 = this.{=self::Base::numProp} = self::getInt();
core::num v2 = this.{=self::Base::numProp} = self::getNum();
core::double v3 = this.{=self::Base::numProp} = self::getDouble();
core::num v4 = let final dynamic #t5 = this.{=self::Base::numProp} in #t5.{core::num::==}(null) ? this.{=self::Base::numProp} = self::getInt() : #t5;
core::num v5 = let final dynamic #t6 = this.{=self::Base::numProp} in #t6.{core::num::==}(null) ? this.{=self::Base::numProp} = self::getNum() : #t6;
core::num v6 = let final dynamic #t7 = this.{=self::Base::numProp} in #t7.{core::num::==}(null) ? this.{=self::Base::numProp} = self::getDouble() : #t7;
core::num v7 = this.{=self::Base::numProp} = this.{=self::Base::numProp}.{core::num::+}(self::getInt());
core::num v8 = this.{=self::Base::numProp} = this.{=self::Base::numProp}.{core::num::+}(self::getNum());
core::num v9 = this.{=self::Base::numProp} = this.{=self::Base::numProp}.{core::num::+}(self::getDouble());
core::num v10 = this.{=self::Base::numProp} = this.{=self::Base::numProp}.{core::num::+}(1);
core::num v11 = let final dynamic #t8 = this.{=self::Base::numProp} in let final dynamic #t9 = this.{=self::Base::numProp} = #t8.{core::num::+}(1) in #t8;
}
}
class Test3 extends self::Base {
constructor •() → void
: super self::Base::•()
;
method test3() → void {
core::num v2 = this.{=self::Base::doubleProp} = self::getNum();
core::double v3 = this.{=self::Base::doubleProp} = self::getDouble();
core::num v5 = let final dynamic #t10 = this.{=self::Base::doubleProp} in #t10.{core::num::==}(null) ? this.{=self::Base::doubleProp} = self::getNum() : #t10;
core::double v6 = let final dynamic #t11 = this.{=self::Base::doubleProp} in #t11.{core::num::==}(null) ? this.{=self::Base::doubleProp} = self::getDouble() : #t11;
core::double v7 = this.{=self::Base::doubleProp} = this.{=self::Base::doubleProp}.{core::double::+}(self::getInt());
core::double v8 = this.{=self::Base::doubleProp} = this.{=self::Base::doubleProp}.{core::double::+}(self::getNum());
core::double v9 = this.{=self::Base::doubleProp} = this.{=self::Base::doubleProp}.{core::double::+}(self::getDouble());
core::double v10 = this.{=self::Base::doubleProp} = this.{=self::Base::doubleProp}.{core::double::+}(1);
core::double v11 = let final dynamic #t12 = this.{=self::Base::doubleProp} in let final dynamic #t13 = this.{=self::Base::doubleProp} = #t12.{core::double::+}(1) in #t12;
}
}
static method getInt() → core::int
return 0;
static method getNum() → core::num
return 0;
static method getDouble() → core::double
return 0.0;
static method main() → dynamic {}

View file

@ -0,0 +1,61 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
int getInt() => 0;
num getNum() => 0;
double getDouble() => 0.0;
class Test1 {
int prop;
static void test(Test1 t) {
var /*@type=int*/ v1 = t. /*@target=Test1::prop*/ prop = getInt();
var /*@type=num*/ v2 = t. /*@target=Test1::prop*/ prop = getNum();
var /*@type=int*/ v4 = t. /*@target=Test1::prop*/ prop ??= getInt();
var /*@type=num*/ v5 = t. /*@target=Test1::prop*/ prop ??= getNum();
var /*@type=int*/ v7 = t. /*@target=Test1::prop*/ prop += getInt();
var /*@type=num*/ v8 = t. /*@target=Test1::prop*/ prop += getNum();
var /*@type=int*/ v10 = ++t. /*@target=Test1::prop*/ prop;
var /*@type=int*/ v11 = t. /*@target=Test1::prop*/ prop++;
}
}
class Test2 {
num prop;
static void test(Test2 t) {
var /*@type=int*/ v1 = t. /*@target=Test2::prop*/ prop = getInt();
var /*@type=num*/ v2 = t. /*@target=Test2::prop*/ prop = getNum();
var /*@type=double*/ v3 = t. /*@target=Test2::prop*/ prop = getDouble();
var /*@type=num*/ v4 = t. /*@target=Test2::prop*/ prop ??= getInt();
var /*@type=num*/ v5 = t. /*@target=Test2::prop*/ prop ??= getNum();
var /*@type=num*/ v6 = t. /*@target=Test2::prop*/ prop ??= getDouble();
var /*@type=num*/ v7 = t. /*@target=Test2::prop*/ prop += getInt();
var /*@type=num*/ v8 = t. /*@target=Test2::prop*/ prop += getNum();
var /*@type=num*/ v9 = t. /*@target=Test2::prop*/ prop += getDouble();
var /*@type=num*/ v10 = ++t. /*@target=Test2::prop*/ prop;
var /*@type=num*/ v11 = t. /*@target=Test2::prop*/ prop++;
}
}
class Test3 {
double prop;
static void test3(Test3 t) {
var /*@type=num*/ v2 = t. /*@target=Test3::prop*/ prop = getNum();
var /*@type=double*/ v3 = t. /*@target=Test3::prop*/ prop = getDouble();
var /*@type=num*/ v5 = t. /*@target=Test3::prop*/ prop ??= getNum();
var /*@type=double*/ v6 = t. /*@target=Test3::prop*/ prop ??= getDouble();
var /*@type=double*/ v7 = t. /*@target=Test3::prop*/ prop += getInt();
var /*@type=double*/ v8 = t. /*@target=Test3::prop*/ prop += getNum();
var /*@type=double*/ v9 = t. /*@target=Test3::prop*/ prop += getDouble();
var /*@type=double*/ v10 = ++t. /*@target=Test3::prop*/ prop;
var /*@type=double*/ v11 = t. /*@target=Test3::prop*/ prop++;
}
}
main() {}

View file

@ -0,0 +1,63 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int prop = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test1 t) → void {
dynamic v1 = t.prop = self::getInt();
dynamic v2 = t.prop = self::getNum();
dynamic v4 = let final dynamic #t1 = t in let final dynamic #t2 = #t1.prop in #t2.==(null) ? #t1.prop = self::getInt() : #t2;
dynamic v5 = let final dynamic #t3 = t in let final dynamic #t4 = #t3.prop in #t4.==(null) ? #t3.prop = self::getNum() : #t4;
dynamic v7 = let final dynamic #t5 = t in #t5.prop = #t5.prop.+(self::getInt());
dynamic v8 = let final dynamic #t6 = t in #t6.prop = #t6.prop.+(self::getNum());
dynamic v10 = let final dynamic #t7 = t in #t7.prop = #t7.prop.+(1);
dynamic v11 = let final dynamic #t8 = t in let final dynamic #t9 = #t8.prop in let final dynamic #t10 = #t8.prop = #t9.+(1) in #t9;
}
}
class Test2 extends core::Object {
field core::num prop = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test2 t) → void {
dynamic v1 = t.prop = self::getInt();
dynamic v2 = t.prop = self::getNum();
dynamic v3 = t.prop = self::getDouble();
dynamic v4 = let final dynamic #t11 = t in let final dynamic #t12 = #t11.prop in #t12.==(null) ? #t11.prop = self::getInt() : #t12;
dynamic v5 = let final dynamic #t13 = t in let final dynamic #t14 = #t13.prop in #t14.==(null) ? #t13.prop = self::getNum() : #t14;
dynamic v6 = let final dynamic #t15 = t in let final dynamic #t16 = #t15.prop in #t16.==(null) ? #t15.prop = self::getDouble() : #t16;
dynamic v7 = let final dynamic #t17 = t in #t17.prop = #t17.prop.+(self::getInt());
dynamic v8 = let final dynamic #t18 = t in #t18.prop = #t18.prop.+(self::getNum());
dynamic v9 = let final dynamic #t19 = t in #t19.prop = #t19.prop.+(self::getDouble());
dynamic v10 = let final dynamic #t20 = t in #t20.prop = #t20.prop.+(1);
dynamic v11 = let final dynamic #t21 = t in let final dynamic #t22 = #t21.prop in let final dynamic #t23 = #t21.prop = #t22.+(1) in #t22;
}
}
class Test3 extends core::Object {
field core::double prop = null;
constructor •() → void
: super core::Object::•()
;
static method test3(self::Test3 t) → void {
dynamic v2 = t.prop = self::getNum();
dynamic v3 = t.prop = self::getDouble();
dynamic v5 = let final dynamic #t24 = t in let final dynamic #t25 = #t24.prop in #t25.==(null) ? #t24.prop = self::getNum() : #t25;
dynamic v6 = let final dynamic #t26 = t in let final dynamic #t27 = #t26.prop in #t27.==(null) ? #t26.prop = self::getDouble() : #t27;
dynamic v7 = let final dynamic #t28 = t in #t28.prop = #t28.prop.+(self::getInt());
dynamic v8 = let final dynamic #t29 = t in #t29.prop = #t29.prop.+(self::getNum());
dynamic v9 = let final dynamic #t30 = t in #t30.prop = #t30.prop.+(self::getDouble());
dynamic v10 = let final dynamic #t31 = t in #t31.prop = #t31.prop.+(1);
dynamic v11 = let final dynamic #t32 = t in let final dynamic #t33 = #t32.prop in let final dynamic #t34 = #t32.prop = #t33.+(1) in #t33;
}
}
static method getInt() → core::int
return 0;
static method getNum() → core::num
return 0;
static method getDouble() → core::double
return 0.0;
static method main() → dynamic {}

View file

@ -0,0 +1,33 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int prop;
constructor •() → void
;
static method test(self::Test1 t) → void
;
}
class Test2 extends core::Object {
field core::num prop;
constructor •() → void
;
static method test(self::Test2 t) → void
;
}
class Test3 extends core::Object {
field core::double prop;
constructor •() → void
;
static method test3(self::Test3 t) → void
;
}
static method getInt() → core::int
;
static method getNum() → core::num
;
static method getDouble() → core::double
;
static method main() → dynamic
;

View file

@ -0,0 +1,63 @@
library test;
import self as self;
import "dart:core" as core;
class Test1 extends core::Object {
field core::int prop = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test1 t) → void {
core::int v1 = t.{self::Test1::prop} = self::getInt();
core::num v2 = t.{self::Test1::prop} = self::getNum();
core::int v4 = let final dynamic #t1 = t in let final dynamic #t2 = #t1.{self::Test1::prop} in #t2.{core::num::==}(null) ? #t1.{self::Test1::prop} = self::getInt() : #t2;
core::num v5 = let final dynamic #t3 = t in let final dynamic #t4 = #t3.{self::Test1::prop} in #t4.{core::num::==}(null) ? #t3.{self::Test1::prop} = self::getNum() : #t4;
core::int v7 = let final dynamic #t5 = t in #t5.{self::Test1::prop} = #t5.{self::Test1::prop}.{core::num::+}(self::getInt());
core::num v8 = let final dynamic #t6 = t in #t6.{self::Test1::prop} = #t6.{self::Test1::prop}.{core::num::+}(self::getNum());
core::int v10 = let final dynamic #t7 = t in #t7.{self::Test1::prop} = #t7.{self::Test1::prop}.{core::num::+}(1);
core::int v11 = let final dynamic #t8 = t in let final dynamic #t9 = #t8.{self::Test1::prop} in let final dynamic #t10 = #t8.{self::Test1::prop} = #t9.{core::num::+}(1) in #t9;
}
}
class Test2 extends core::Object {
field core::num prop = null;
constructor •() → void
: super core::Object::•()
;
static method test(self::Test2 t) → void {
core::int v1 = t.{self::Test2::prop} = self::getInt();
core::num v2 = t.{self::Test2::prop} = self::getNum();
core::double v3 = t.{self::Test2::prop} = self::getDouble();
core::num v4 = let final dynamic #t11 = t in let final dynamic #t12 = #t11.{self::Test2::prop} in #t12.{core::num::==}(null) ? #t11.{self::Test2::prop} = self::getInt() : #t12;
core::num v5 = let final dynamic #t13 = t in let final dynamic #t14 = #t13.{self::Test2::prop} in #t14.{core::num::==}(null) ? #t13.{self::Test2::prop} = self::getNum() : #t14;
core::num v6 = let final dynamic #t15 = t in let final dynamic #t16 = #t15.{self::Test2::prop} in #t16.{core::num::==}(null) ? #t15.{self::Test2::prop} = self::getDouble() : #t16;
core::num v7 = let final dynamic #t17 = t in #t17.{self::Test2::prop} = #t17.{self::Test2::prop}.{core::num::+}(self::getInt());
core::num v8 = let final dynamic #t18 = t in #t18.{self::Test2::prop} = #t18.{self::Test2::prop}.{core::num::+}(self::getNum());
core::num v9 = let final dynamic #t19 = t in #t19.{self::Test2::prop} = #t19.{self::Test2::prop}.{core::num::+}(self::getDouble());
core::num v10 = let final dynamic #t20 = t in #t20.{self::Test2::prop} = #t20.{self::Test2::prop}.{core::num::+}(1);
core::num v11 = let final dynamic #t21 = t in let final dynamic #t22 = #t21.{self::Test2::prop} in let final dynamic #t23 = #t21.{self::Test2::prop} = #t22.{core::num::+}(1) in #t22;
}
}
class Test3 extends core::Object {
field core::double prop = null;
constructor •() → void
: super core::Object::•()
;
static method test3(self::Test3 t) → void {
core::num v2 = t.{self::Test3::prop} = self::getNum();
core::double v3 = t.{self::Test3::prop} = self::getDouble();
core::num v5 = let final dynamic #t24 = t in let final dynamic #t25 = #t24.{self::Test3::prop} in #t25.{core::num::==}(null) ? #t24.{self::Test3::prop} = self::getNum() : #t25;
core::double v6 = let final dynamic #t26 = t in let final dynamic #t27 = #t26.{self::Test3::prop} in #t27.{core::num::==}(null) ? #t26.{self::Test3::prop} = self::getDouble() : #t27;
core::double v7 = let final dynamic #t28 = t in #t28.{self::Test3::prop} = #t28.{self::Test3::prop}.{core::double::+}(self::getInt());
core::double v8 = let final dynamic #t29 = t in #t29.{self::Test3::prop} = #t29.{self::Test3::prop}.{core::double::+}(self::getNum());
core::double v9 = let final dynamic #t30 = t in #t30.{self::Test3::prop} = #t30.{self::Test3::prop}.{core::double::+}(self::getDouble());
core::double v10 = let final dynamic #t31 = t in #t31.{self::Test3::prop} = #t31.{self::Test3::prop}.{core::double::+}(1);
core::double v11 = let final dynamic #t32 = t in let final dynamic #t33 = #t32.{self::Test3::prop} in let final dynamic #t34 = #t32.{self::Test3::prop} = #t33.{core::double::+}(1) in #t33;
}
}
static method getInt() → core::int
return 0;
static method getNum() → core::num
return 0;
static method getDouble() → core::double
return 0.0;
static method main() → dynamic {}

View file

@ -23,3 +23,5 @@ class A {
int y; // field def after use
final /*@topType=int*/ z = 42; // should infer `int`
}
main() {}

View file

@ -21,3 +21,4 @@ class A extends core::Object {
c = 4;
}
}
static method main() → dynamic {}