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 541e75f7ffebee02321c0689812d6c4efa11c630..544f6deddebf60fca1122eb63ed847d88b67f307 100644 |
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart |
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart |
@@ -676,9 +676,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); |
@@ -695,6 +695,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> { |
@@ -719,6 +732,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(); |
} |
'''); |
@@ -1205,9 +1219,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*/[]); |
@@ -1443,9 +1457,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>[]; |
@@ -1555,10 +1569,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*/{}; |
@@ -1934,11 +1948,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> { |
@@ -1951,7 +1960,7 @@ class MyFuture<T> implements Future<T> { |
$declared f; |
// Instantiates Future<int> |
$downwards<int> t1 = f.then((_) => |
- ${allocInfo}new $upwards.value('hi')); |
+ /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value('hi')); |
// Instantiates List<int> |
$downwards<List<int>> t2 = f.then((_) => /*info:INFERRED_TYPE_LITERAL*/[3]); |
@@ -2004,20 +2013,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''' |
@@ -2104,29 +2099,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); |
} |
'''); |
} |
@@ -2367,11 +2340,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); |
@@ -2384,11 +2357,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); |
@@ -2410,104 +2383,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)) {} |
@@ -2574,7 +2461,7 @@ main() { |
} |
void test_genericMethods_IterableAndFuture() { |
- checkFile(''' |
+ checkFile(r''' |
import 'dart:async'; |
Future<int> make(int x) => (/*info:INFERRED_TYPE_ALLOCATION*/new Future(() => x)); |
@@ -2586,11 +2473,33 @@ main() { |
=> list.fold('', /*info:INFERRED_TYPE_CLOSURE*/(x, y) => /*info:DYNAMIC_CAST,info:DYNAMIC_INVOKE*/x /*error:UNDEFINED_OPERATOR*/+ y.toString())); |
Future<String> results3 = results.then((List<int> list) |
- => list.fold('', /*info:INFERRED_TYPE_CLOSURE*/(String x, y) => x + y.toString())); |
+ => list./*error:COULD_NOT_INFER*/fold('', /*info:INFERRED_TYPE_CLOSURE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/(String x, y) => x + y.toString())); |
+ |
+ Future<String> results4 = results.then((List<int> list) |
+ => list.fold<String>('', /*info:INFERRED_TYPE_CLOSURE*/(x, y) => x + y.toString())); |
} |
'''); |
} |
+ 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); |
@@ -4315,7 +4224,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>'); |
} |