| Index: pkg/analyzer/test/src/task/strong/inferred_type_test.dart
|
| diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
|
| index db3982841f56db273edf3fb623de64a379bc1fd9..364e124ce23e00f0e4e14a481a26b4999c399deb 100644
|
| --- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
|
| +++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
|
| @@ -630,9 +630,9 @@ num y;
|
| C<int> c_int = /*info:INFERRED_TYPE_ALLOCATION*/new /*error:COULD_NOT_INFER*/C(/*info:DOWN_CAST_IMPLICIT*/y);
|
|
|
| // These hints are not reported because we resolve with a null error listener.
|
| -C<num> c_num = /*pass should be info:INFERRED_TYPE_ALLOCATION*/new C(123);
|
| -C<num> c_num2 = (/*pass should be info:INFERRED_TYPE_ALLOCATION*/new C(456))
|
| - ..t = /*error:INVALID_ASSIGNMENT*/1.0;
|
| +C<num> c_num = /*info:INFERRED_TYPE_ALLOCATION*/new C(123);
|
| +C<num> c_num2 = (/*info:INFERRED_TYPE_ALLOCATION*/new C(456))
|
| + ..t = 1.0;
|
|
|
| // Down't infer from explicit dynamic.
|
| var c_dynamic = new C<dynamic>(42);
|
| @@ -649,6 +649,19 @@ main() {
|
| 'C<dynamic>');
|
| }
|
|
|
| + void test_constructors_inferFromArguments_downwardsFromConstructor() {
|
| + checkFile(r'''
|
| +class C<T> { C(List<T> list); }
|
| +
|
| +var x = /*info:INFERRED_TYPE_ALLOCATION*/new C(/*info:INFERRED_TYPE_LITERAL*/[123]);
|
| +C<int> y = x;
|
| +
|
| +var a = new C<dynamic>([123]);
|
| +// This one however works.
|
| +var b = new C<Object>(/*info:INFERRED_TYPE_LITERAL*/[123]);
|
| + ''');
|
| + }
|
| +
|
| void test_constructors_inferFromArguments_const() {
|
| var unit = checkFile('''
|
| class C<T> {
|
| @@ -673,6 +686,7 @@ class D<T extends num> {
|
| }
|
| void f() {
|
| const c = /*info:INFERRED_TYPE_ALLOCATION*/const C(0);
|
| + C<int> c2 = c;
|
| const D<int> d = /*info:INFERRED_TYPE_ALLOCATION*/const D();
|
| }
|
| ''');
|
| @@ -1154,9 +1168,9 @@ void main() {
|
| /*info:INFERRED_TYPE_LITERAL*/[3]]);
|
|
|
| new F3(/*info:INFERRED_TYPE_LITERAL*/[]);
|
| - /*info:INFERRED_TYPE_ALLOCATION*/new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/[3]]);
|
| - /*info:INFERRED_TYPE_ALLOCATION*/new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/["hello"]]);
|
| - /*info:INFERRED_TYPE_ALLOCATION*/new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/["hello"],
|
| + var f31 = /*info:INFERRED_TYPE_ALLOCATION*/new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/[3]]);
|
| + var f32 = /*info:INFERRED_TYPE_ALLOCATION*/new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/["hello"]]);
|
| + var f33 = /*info:INFERRED_TYPE_ALLOCATION*/new F3(/*info:INFERRED_TYPE_LITERAL*/[/*info:INFERRED_TYPE_LITERAL*/["hello"],
|
| /*info:INFERRED_TYPE_LITERAL*/[3]]);
|
|
|
| new F4(a: /*info:INFERRED_TYPE_LITERAL*/[]);
|
| @@ -1392,9 +1406,9 @@ void main() {
|
| }
|
| {
|
| List<dynamic> l0 = [];
|
| - List<dynamic> l1 = /*info:INFERRED_TYPE_LITERAL*/[3];
|
| - List<dynamic> l2 = /*info:INFERRED_TYPE_LITERAL*/["hello"];
|
| - List<dynamic> l3 = /*info:INFERRED_TYPE_LITERAL*/["hello", 3];
|
| + List<dynamic> l1 = [3];
|
| + List<dynamic> l2 = ["hello"];
|
| + List<dynamic> l3 = ["hello", 3];
|
| }
|
| {
|
| List<int> l0 = /*error:INVALID_CAST_LITERAL_LIST*/<num>[];
|
| @@ -1504,10 +1518,10 @@ void main() {
|
| }
|
| {
|
| Map<dynamic, dynamic> l0 = {};
|
| - Map<dynamic, dynamic> l1 = /*info:INFERRED_TYPE_LITERAL*/{3: "hello"};
|
| - Map<dynamic, dynamic> l2 = /*info:INFERRED_TYPE_LITERAL*/{"hello": "hello"};
|
| - Map<dynamic, dynamic> l3 = /*info:INFERRED_TYPE_LITERAL*/{3: 3};
|
| - Map<dynamic, dynamic> l4 = /*info:INFERRED_TYPE_LITERAL*/{3:"hello", "hello": 3};
|
| + Map<dynamic, dynamic> l1 = {3: "hello"};
|
| + Map<dynamic, dynamic> l2 = {"hello": "hello"};
|
| + Map<dynamic, dynamic> l3 = {3: 3};
|
| + Map<dynamic, dynamic> l4 = {3:"hello", "hello": 3};
|
| }
|
| {
|
| Map<dynamic, String> l0 = /*info:INFERRED_TYPE_LITERAL*/{};
|
| @@ -1909,11 +1923,6 @@ $downwards<int> g3(bool x) async {
|
|
|
| void test_futureUnion_downwards() {
|
| String build({String declared, String downwards, String upwards}) {
|
| - // TODO(leafp): The use of matchTypes in visitInstanceCreationExpression
|
| - // in the resolver visitor isn't powerful enough to catch this for the
|
| - // subclass. See the TODO there.
|
| - var allocInfo =
|
| - (upwards == "Future") ? "/*info:INFERRED_TYPE_ALLOCATION*/" : "";
|
| return '''
|
| import 'dart:async';
|
| class MyFuture<T> implements Future<T> {
|
| @@ -1926,49 +1935,7 @@ class MyFuture<T> implements Future<T> {
|
| $declared f;
|
| // Instantiates Future<int>
|
| $downwards<int> t1 = f.then((_) =>
|
| - ${allocInfo}new /*error:COULD_NOT_INFER*/$upwards.value(
|
| - /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'));
|
| -
|
| -// Instantiates List<int>
|
| -$downwards<List<int>> t2 = f.then((_) => /*info:INFERRED_TYPE_LITERAL*/[3]);
|
| -$downwards<List<int>> g2() async { return /*info:INFERRED_TYPE_LITERAL*/[3]; }
|
| -$downwards<List<int>> g3() async {
|
| - return /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value(
|
| - /*info:INFERRED_TYPE_LITERAL*/[3]); }
|
| -''';
|
| - }
|
| -
|
| - ;
|
| - checkFile(
|
| - build(declared: "MyFuture", downwards: "Future", upwards: "Future"));
|
| - checkFile(
|
| - build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture"));
|
| - checkFile(
|
| - build(declared: "Future", downwards: "Future", upwards: "Future"));
|
| - checkFile(
|
| - build(declared: "Future", downwards: "Future", upwards: "MyFuture"));
|
| - }
|
| -
|
| - void test_futureUnion_downwards_comment() {
|
| - String build({String declared, String downwards, String upwards}) {
|
| - // TODO(leafp): The use of matchTypes in visitInstanceCreationExpression
|
| - // in the resolver visitor isn't powerful enough to catch this for the
|
| - // subclass. See the TODO there.
|
| - var allocInfo =
|
| - (upwards == "Future") ? "/*info:INFERRED_TYPE_ALLOCATION*/" : "";
|
| - return '''
|
| -import 'dart:async';
|
| -class MyFuture<T> implements Future<T> {
|
| - MyFuture() {}
|
| - MyFuture.value([T x]) {}
|
| - dynamic noSuchMethod(invocation);
|
| - MyFuture/*<S>*/ then/*<S>*/(dynamic f(T x), {Function onError}) => null;
|
| -}
|
| -
|
| -$declared f;
|
| -// Instantiates Future<int>
|
| -$downwards<int> t1 = f.then((_) =>
|
| - ${allocInfo}new /*error:COULD_NOT_INFER*/$upwards.value(
|
| + /*info:INFERRED_TYPE_ALLOCATION*/new /*error:COULD_NOT_INFER*/$upwards.value(
|
| /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'));
|
|
|
| // Instantiates List<int>
|
| @@ -2023,20 +1990,6 @@ main() async {
|
| ''');
|
| }
|
|
|
| - void test_futureUnion_downwardsGenericMethodWithGenericReturn_comment() {
|
| - // Regression test for https://github.com/dart-lang/sdk/issues/27284
|
| - checkFile(r'''
|
| -import 'dart:async';
|
| -
|
| -/*=T*/ id/*<T>*/(/*=T*/ x) => x;
|
| -
|
| -main() async {
|
| - Future<String> f;
|
| - String s = await id(f);
|
| -}
|
| - ''');
|
| - }
|
| -
|
| void test_futureUnion_upwardsGenericMethods() {
|
| // Regression test for https://github.com/dart-lang/sdk/issues/27151
|
| checkFile(r'''
|
| @@ -2123,29 +2076,7 @@ main() {
|
| var c = new Foo().method("str");
|
| s = c;
|
|
|
| - new Foo<String>()./*error:COULD_NOT_INFER*/method(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/42);
|
| -}
|
| -''');
|
| - }
|
| -
|
| - void test_genericMethods_correctlyRecognizeGenericUpperBound_comment() {
|
| - // Regression test for https://github.com/dart-lang/sdk/issues/25740.
|
| - checkFile(r'''
|
| -class Foo<T extends Pattern> {
|
| - /*=U*/ method/*<U extends T>*/(/*=U*/ u) => u;
|
| -}
|
| -main() {
|
| - String s;
|
| - var a = new Foo().method/*<String>*/("str");
|
| - s = a;
|
| - new Foo();
|
| -
|
| - var b = new Foo<String>().method("str");
|
| - s = b;
|
| - var c = new Foo().method("str");
|
| - s = c;
|
| -
|
| - new Foo<String>()./*error:COULD_NOT_INFER*/method(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/42);
|
| + new Foo<String>()./*error:COULD_NOT_INFER*/method(42);
|
| }
|
| ''');
|
| }
|
| @@ -2386,11 +2317,11 @@ takeDDN(math.max);
|
| takeIIO(math.max);
|
| takeDDO(math.max);
|
|
|
| -takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| +takeOOI(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/math.max);
|
| +takeIDI(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| +takeDID(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| +takeOON(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/math.max);
|
| +takeOOO(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/math.max);
|
|
|
| // Also test SimpleIdentifier
|
| takeIII(min);
|
| @@ -2403,11 +2334,11 @@ takeDDN(min);
|
| takeIIO(min);
|
| takeDDO(min);
|
|
|
| -takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| +takeOOI(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/min);
|
| +takeIDI(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| +takeDID(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| +takeOON(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/min);
|
| +takeOOO(/*error:COULD_NOT_INFER,error:INVALID_CAST_FUNCTION*/min);
|
|
|
| // Also PropertyAccess
|
| takeIII(new C().m);
|
| @@ -2429,104 +2360,18 @@ takeDDO(new C().m);
|
| //
|
| // That's legal because we're loosening parameter types.
|
| //
|
| -takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| -takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| +// We do issue the inference error though, similar to generic function calls.
|
| +takeOON(/*error:COULD_NOT_INFER,warning:DOWN_CAST_COMPOSITE*/new C().m);
|
| +takeOOO(/*error:COULD_NOT_INFER,warning:DOWN_CAST_COMPOSITE*/new C().m);
|
|
|
| // Note: this is a warning because a downcast of a method tear-off could work
|
| // in "normal" Dart, due to bivariance.
|
| -takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| -takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| -takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| -}
|
| -
|
| -void takeIII(int fn(int a, int b)) {}
|
| -void takeDDD(double fn(double a, double b)) {}
|
| -void takeIDI(int fn(double a, int b)) {}
|
| -void takeDID(double fn(int a, double b)) {}
|
| -void takeIDN(num fn(double a, int b)) {}
|
| -void takeDIN(num fn(int a, double b)) {}
|
| -void takeIIN(num fn(int a, int b)) {}
|
| -void takeDDN(num fn(double a, double b)) {}
|
| -void takeNNN(num fn(num a, num b)) {}
|
| -void takeOON(num fn(Object a, Object b)) {}
|
| -void takeOOO(num fn(Object a, Object b)) {}
|
| -void takeOOI(int fn(Object a, Object b)) {}
|
| -void takeIIO(Object fn(int a, int b)) {}
|
| -void takeDDO(Object fn(double a, double b)) {}
|
| -''');
|
| - }
|
| -
|
| - void test_genericMethods_inferGenericInstantiation_comment() {
|
| - checkFile('''
|
| -import 'dart:math' as math;
|
| -import 'dart:math' show min;
|
| -
|
| -class C {
|
| -/*=T*/ m/*<T extends num>*/(/*=T*/ x, /*=T*/ y) => null;
|
| -}
|
| -
|
| -main() {
|
| -takeIII(math.max);
|
| -takeDDD(math.max);
|
| -takeNNN(math.max);
|
| -takeIDN(math.max);
|
| -takeDIN(math.max);
|
| -takeIIN(math.max);
|
| -takeDDN(math.max);
|
| -takeIIO(math.max);
|
| -takeDDO(math.max);
|
| -
|
| -takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/math.max);
|
| -
|
| -// Also test SimpleIdentifier
|
| -takeIII(min);
|
| -takeDDD(min);
|
| -takeNNN(min);
|
| -takeIDN(min);
|
| -takeDIN(min);
|
| -takeIIN(min);
|
| -takeDDN(min);
|
| -takeIIO(min);
|
| -takeDDO(min);
|
| -
|
| -takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/min);
|
| -
|
| -// Also PropertyAccess
|
| -takeIII(new C().m);
|
| -takeDDD(new C().m);
|
| -takeNNN(new C().m);
|
| -takeIDN(new C().m);
|
| -takeDIN(new C().m);
|
| -takeIIN(new C().m);
|
| -takeDDN(new C().m);
|
| -takeIIO(new C().m);
|
| -takeDDO(new C().m);
|
| -
|
| -// Note: this is a warning because a downcast of a method tear-off could work
|
| -// (derived method can be a subtype):
|
| //
|
| -// class D extends C {
|
| -// S m<S extends num>(Object x, Object y);
|
| -// }
|
| -//
|
| -// That's legal because we're loosening parameter types.
|
| -//
|
| -takeOON(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| -takeOOO(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| +// We do issue the inference error though, similar to generic function calls.
|
| +takeOOI(/*error:COULD_NOT_INFER,warning:DOWN_CAST_COMPOSITE*/new C().m);
|
|
|
| -// Note: this is a warning because a downcast of a method tear-off could work
|
| -// in "normal" Dart, due to bivariance.
|
| -takeOOI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| -takeIDI(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| -takeDID(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| +takeIDI(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| +takeDID(/*error:COULD_NOT_INFER,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/new C().m);
|
| }
|
|
|
| void takeIII(int fn(int a, int b)) {}
|
| @@ -2593,7 +2438,7 @@ main() {
|
| }
|
|
|
| void test_genericMethods_IterableAndFuture() {
|
| - checkFile('''
|
| + checkFile(r'''
|
| import 'dart:async';
|
|
|
| Future<int> make(int x) => (/*info:INFERRED_TYPE_ALLOCATION*/new Future(() => x));
|
| @@ -2607,6 +2452,25 @@ main() {
|
| ''');
|
| }
|
|
|
| + void test_genericMethods_nestedGenericInstantiation() {
|
| + checkFile(r'''
|
| +import 'dart:math' as math;
|
| +class Trace {
|
| + List<Frame> frames = /*info:INFERRED_TYPE_LITERAL*/[];
|
| +}
|
| +class Frame {
|
| + String location = '';
|
| +}
|
| +main() {
|
| + List<Trace> traces = /*info:INFERRED_TYPE_LITERAL*/[];
|
| + var longest = traces.map(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(trace) {
|
| + return trace.frames.map(/*info:INFERRED_TYPE_CLOSURE*/(frame) => frame.location.length)
|
| + .fold(0, math.max);
|
| + }).fold(0, math.max);
|
| +}
|
| + ''');
|
| + }
|
| +
|
| void test_genericMethods_usesGreatestLowerBound() {
|
| var mainUnit = checkFile(r'''
|
| typedef Iterable<num> F(int x);
|
| @@ -4321,7 +4185,7 @@ A v = null;
|
| void test_instantiateToBounds_invokeConstructor_noBound() {
|
| var unit = checkFile('''
|
| class C<T> {}
|
| -var x = new C();
|
| +var x = /*info:INFERRED_TYPE_ALLOCATION*/new C();
|
| ''');
|
| expect(unit.topLevelVariables[0].type.toString(), 'C<dynamic>');
|
| }
|
|
|