| Index: test/checker/inferred_type_test.dart
|
| diff --git a/test/checker/inferred_type_test.dart b/test/checker/inferred_type_test.dart
|
| index 27dc282937c6357a0f278fc119f59b949a04bca6..accbecb73f9db9dc985ed8d935178d464bb90121 100644
|
| --- a/test/checker/inferred_type_test.dart
|
| +++ b/test/checker/inferred_type_test.dart
|
| @@ -137,36 +137,32 @@ void main() {
|
| });
|
| });
|
|
|
| - test('do not infer from variables in same lib (order independence)', () {
|
| + test('do not infer field type when initializer is null', () {
|
| testChecker({
|
| '/main.dart': '''
|
| - var x = 2;
|
| - var y = x;
|
| -
|
| - test1() {
|
| - x = /*severe:StaticTypeError*/"hi";
|
| - y = "hi";
|
| - }
|
| - '''
|
| - });
|
| + var x = null;
|
| + var y = 3;
|
| + class A {
|
| + static var x = null;
|
| + static var y = 3;
|
|
|
| - testChecker({
|
| - '/main.dart': '''
|
| - class A {
|
| - static var x = 2;
|
| - static var y = A.x;
|
| - }
|
| + var x2 = null;
|
| + var y2 = 3;
|
| + }
|
|
|
| - test1() {
|
| - A.x = /*severe:StaticTypeError*/"hi";
|
| - A.y = "hi";
|
| - }
|
| + test() {
|
| + x = "hi";
|
| + y = /*severe:StaticTypeError*/"hi";
|
| + A.x = "hi";
|
| + A.y = /*severe:StaticTypeError*/"hi";
|
| + new A().x2 = "hi";
|
| + new A().y2 = /*severe:StaticTypeError*/"hi";
|
| + }
|
| '''
|
| });
|
| + });
|
|
|
| - // Allowed with special flag. Note, while the flag is generally not stable,
|
| - // we can use it in this test because it is stable within a library (order
|
| - // matches program order).
|
| + test('do not infer from variables in same lib (order independence)', () {
|
| testChecker({
|
| '/main.dart': '''
|
| var x = 2;
|
| @@ -174,10 +170,10 @@ void main() {
|
|
|
| test1() {
|
| x = /*severe:StaticTypeError*/"hi";
|
| - y = /*severe:StaticTypeError*/"hi";
|
| + y = "hi";
|
| }
|
| '''
|
| - }, inferInNonStableOrder: true);
|
| + });
|
|
|
| testChecker({
|
| '/main.dart': '''
|
| @@ -188,10 +184,10 @@ void main() {
|
|
|
| test1() {
|
| A.x = /*severe:StaticTypeError*/"hi";
|
| - A.y = /*severe:StaticTypeError*/"hi";
|
| + A.y = "hi";
|
| }
|
| '''
|
| - }, inferInNonStableOrder: true);
|
| + });
|
| });
|
|
|
| test('not ok to infer from variables in non-cycle libs', () {
|
| @@ -262,15 +258,15 @@ void main() {
|
| testChecker({
|
| '/a.dart': '''
|
| import 'main.dart';
|
| - var x = 2;
|
| + var x = 2; // ok to infer
|
| ''',
|
| '/main.dart': '''
|
| import 'a.dart';
|
| - var y = x;
|
| + var y = x; // not ok to infer yet
|
|
|
| test1() {
|
| int t = 3;
|
| - t = /*info:DownCast*/x;
|
| + t = x;
|
| t = /*info:DownCast*/y;
|
| }
|
| '''
|
| @@ -287,7 +283,7 @@ void main() {
|
|
|
| test1() {
|
| int t = 3;
|
| - t = /*info:DownCast*/A.x;
|
| + t = A.x;
|
| t = /*info:DownCast*/A.y;
|
| }
|
| '''
|
| @@ -350,7 +346,27 @@ void main() {
|
| }, inferStaticsFromIdentifiers: true);
|
| });
|
|
|
| - test('don\'t infer on cycles', () {
|
| + test('inference uses declared types', () {
|
| + testChecker({
|
| + '/main.dart': '''
|
| + int w = 0;
|
| + var x = 0;
|
| +
|
| + var y = w; // y can be inferred because w is typed int.
|
| + var z = x; // z cannot, because x would be inferred.
|
| +
|
| + test1() {
|
| + int a;
|
| + a = w;
|
| + a = x;
|
| + a = y;
|
| + a = /*info:DownCast*/z;
|
| + }
|
| + '''
|
| + }, inferStaticsFromIdentifiers: true);
|
| + });
|
| +
|
| + test('inference in cycles is deterministic', () {
|
| testChecker({
|
| '/a.dart': '''
|
| import 'b.dart';
|
| @@ -374,15 +390,20 @@ void main() {
|
| }
|
| ''',
|
| '/e.dart': '''
|
| - part "e2.dart";
|
| + import 'a.dart';
|
| + part 'e2.dart';
|
|
|
| class E {
|
| static final e1 = 1;
|
| - final e2 = 1;
|
| + static final e2 = F.f1;
|
| + static final e3 = A.a1;
|
| + final e4 = 1;
|
| + final e5 = new F().f2;
|
| + final e6 = new A().a2;
|
| }
|
| ''',
|
| '/f.dart': '''
|
| - part "f2.dart";
|
| + part 'f2.dart';
|
| ''',
|
| '/e2.dart': '''
|
| class F {
|
| @@ -408,21 +429,25 @@ void main() {
|
| x = A.a1;
|
| x = new A().a2;
|
|
|
| - // inference here or in c.dart is disabled because of the cycle
|
| - x = /*info:DownCast*/C.c1;
|
| - x = /*info:DownCast*/D.d1;
|
| + // Within a cycle we allow inference when the RHS is well known, but
|
| + // not when it depends on other fields within the cycle
|
| + x = C.c1;
|
| + x = D.d1;
|
| x = /*info:DownCast*/D.d2;
|
| - x = /*info:DownCast*/new C().c2;
|
| - x = /*info:DownCast*/new D().d3;
|
| + x = new C().c2;
|
| + x = new D().d3;
|
| x = /*info:DownCast*/new D().d4;
|
|
|
|
|
| - // inference in e.dart and f.dart is disabled because they contains
|
| - // parts
|
| - x = /*info:DownCast*/E.e1;
|
| - x = /*info:DownCast*/new E().e2;
|
| - x = /*info:DownCast*/F.f1;
|
| - x = /*info:DownCast*/new F().f2;
|
| + // Similarly if the library contains parts.
|
| + x = E.e1;
|
| + x = /*info:DownCast*/E.e2;
|
| + x = E.e3;
|
| + x = new E().e4;
|
| + x = /*info:DownCast*/new E().e5;
|
| + x = new E().e6;
|
| + x = F.f1;
|
| + x = new F().f2;
|
| }
|
| '''
|
| }, inferStaticsFromIdentifiers: true);
|
| @@ -446,6 +471,7 @@ void main() {
|
| var g = -3;
|
| var h = new A() + 3;
|
| var i = - new A();
|
| + var j = null as B;
|
|
|
| test1() {
|
| a = /*severe:StaticTypeError*/"hi";
|
| @@ -467,6 +493,9 @@ void main() {
|
| h = /*severe:StaticTypeError*/false;
|
| h = new B();
|
| i = false;
|
| + j = new B();
|
| + j = /*severe:StaticTypeError*/false;
|
| + j = /*severe:StaticTypeError*/[];
|
| }
|
| '''
|
| });
|
| @@ -814,8 +843,33 @@ void main() {
|
| }, inferFromOverrides: true);
|
| });
|
|
|
| - // TODO(sigmund): enable this test, it's currently flaky (see issue #48).
|
| - skip_test('infer types on generic instantiations in library cycle', () {
|
| + test('infer type regardless of declaration order or cycles', () {
|
| + testChecker({
|
| + '/b.dart': '''
|
| + import 'main.dart';
|
| +
|
| + class B extends A { }
|
| + ''',
|
| + '/main.dart': '''
|
| + import 'b.dart';
|
| + class C extends B {
|
| + get x;
|
| + }
|
| + class A {
|
| + int get x;
|
| + }
|
| + foo () {
|
| + int y = new C().x;
|
| + String y = /*severe:StaticTypeError*/new C().x;
|
| + }
|
| + '''
|
| + }, inferFromOverrides: true);
|
| + });
|
| +
|
| + // Note: this is a regression test for a non-deterministic behavior we used to
|
| + // have with inference in library cycles. If you see this test flake out,
|
| + // change `test` to `skip_test` and reopen bug #48.
|
| + test('infer types on generic instantiations in library cycle', () {
|
| testChecker({
|
| '/a.dart': '''
|
| import 'main.dart';
|
| @@ -933,4 +987,69 @@ void main() {
|
| '''
|
| }, inferFromOverrides: true);
|
| });
|
| +
|
| + test('infer from RHS only if it wont conflict with overridden fields', () {
|
| + testChecker({
|
| + '/main.dart': '''
|
| + class A {
|
| + var x;
|
| + }
|
| +
|
| + class B extends A {
|
| + var x = 2;
|
| + }
|
| +
|
| + foo() {
|
| + String y = /*info:DownCast*/new B().x;
|
| + int z = /*info:DownCast*/new B().x;
|
| + }
|
| + '''
|
| + }, inferFromOverrides: true);
|
| +
|
| + testChecker({
|
| + '/main.dart': '''
|
| + class A {
|
| + final x;
|
| + }
|
| +
|
| + class B extends A {
|
| + final x = 2;
|
| + }
|
| +
|
| + foo() {
|
| + String y = /*severe:StaticTypeError*/new B().x;
|
| + int z = new B().x;
|
| + }
|
| + '''
|
| + }, inferFromOverrides: true);
|
| + });
|
| +
|
| + test('infer correctly on multiple variables declared together', () {
|
| + testChecker({
|
| + '/main.dart': '''
|
| + class A {
|
| + var x, y = 2, z = "hi";
|
| + }
|
| +
|
| + class B extends A {
|
| + var x = 2, y = 3, z, w = 2;
|
| + }
|
| +
|
| + foo() {
|
| + String s;
|
| + int i;
|
| +
|
| + s = /*info:DownCast*/new B().x;
|
| + s = /*severe:StaticTypeError*/new B().y;
|
| + s = new B().z;
|
| + s = /*severe:StaticTypeError*/new B().w;
|
| +
|
| + i = /*info:DownCast*/new B().x;
|
| + i = new B().y;
|
| + i = /*severe:StaticTypeError*/new B().z;
|
| + i = new B().w;
|
| + }
|
| + '''
|
| + }, inferFromOverrides: true);
|
| + });
|
| }
|
|
|