Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(606)

Unified Diff: pkg/analyzer/test/src/task/strong/inferred_type_test.dart

Issue 2524463005: Add tests for the real generic method syntax (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 ae546d5bd34082ff52a9ca1b9438553695659c71..79798808ad6ae847a1a0e2906bf8fb5c657e042d 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -1067,6 +1067,28 @@ void main () {
checkFile('''
void main () {
{
+ T f<T>(T x) => null;
+ var v1 = f;
+ v1 = /*info:INFERRED_TYPE_CLOSURE*/<S>(x) => x;
+ }
+ {
+ List<T> f<T>(T x) => null;
+ var v2 = f;
+ v2 = /*info:INFERRED_TYPE_CLOSURE*/<S>(x) => /*info:INFERRED_TYPE_LITERAL*/[x];
+ Iterable<int> r = v2(42);
+ Iterable<String> s = v2('hello');
+ Iterable<List<int>> t = v2(<int>[]);
+ Iterable<num> u = v2(42);
+ Iterable<num> v = v2<num>(42);
+ }
+}
+''');
+ }
+
+ void test_downwardsInferenceOnFunctionOfTUsingTheT_comment() {
+ checkFile('''
+void main () {
+ {
/*=T*/ f/*<T>*/(/*=T*/ x) => null;
var v1 = f;
v1 = /*info:INFERRED_TYPE_CLOSURE*//*<S>*/(x) => x;
@@ -1150,6 +1172,53 @@ void main() {
checkFile('''
void main () {
{
+ String f<S>(int x) => null;
+ var v = f;
+ v = /*info:INFERRED_TYPE_CLOSURE*/<T>(int x) => null;
+ v = <T>(int x) => "hello";
+ v = /*error:INVALID_ASSIGNMENT*/<T>(String x) => "hello";
+ v = /*error:INVALID_ASSIGNMENT*/<T>(int x) => 3;
+ v = /*info:INFERRED_TYPE_CLOSURE*/<T>(int x) {return /*error:RETURN_OF_INVALID_TYPE*/3;};
+ }
+ {
+ String f<S>(int x) => null;
+ var v = f;
+ v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) => null;
+ v = /*info:INFERRED_TYPE_CLOSURE*/<T>(x) => "hello";
+ v = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/<T>(x) => 3;
+ v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) {return /*error:RETURN_OF_INVALID_TYPE*/3;};
+ v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) {return /*error:RETURN_OF_INVALID_TYPE*/x;};
+ }
+ {
+ List<String> f<S>(int x) => null;
+ var v = f;
+ v = /*info:INFERRED_TYPE_CLOSURE*/<T>(int x) => null;
+ v = <T>(int x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
+ v = /*error:INVALID_ASSIGNMENT*/<T>(String x) => /*info:INFERRED_TYPE_LITERAL*/["hello"];
+ v = <T>(int x) => /*info:INFERRED_TYPE_LITERAL,error:COULD_NOT_INFER*/[/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/3];
+ v = /*info:INFERRED_TYPE_CLOSURE*/<T>(int x) {return /*info:INFERRED_TYPE_LITERAL,error:COULD_NOT_INFER*/[/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/3];};
+ }
+ {
+ int int2int<S>(int x) => null;
+ String int2String<T>(int x) => null;
+ String string2String<T>(String x) => null;
+ var x = int2int;
+ x = /*info:INFERRED_TYPE_CLOSURE*/<T>(x) => x;
+ x = /*info:INFERRED_TYPE_CLOSURE*/<T>(x) => x+1;
+ var y = int2String;
+ y = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/<T>(x) => x;
+ y = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) => /*info:DYNAMIC_INVOKE, info:DYNAMIC_CAST*/x.substring(3);
+ var z = string2String;
+ z = /*info:INFERRED_TYPE_CLOSURE*/<T>(x) => x.substring(3);
+ }
+}
+''');
+ }
+
+ void test_downwardsInferenceOnGenericFunctionExpressions_comment() {
+ checkFile('''
+void main () {
+ {
String f/*<S>*/(int x) => null;
var v = f;
v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) => null;
@@ -1537,6 +1606,46 @@ 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;
+}
+
+void main() {
+ $declared f;
+ $downwards<int> t1 = f.then((_) async => await new $upwards<int>.value(3));
+ $downwards<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {
+ return await new $upwards<int>.value(3);});
+ $downwards<int> t3 = f.then((_) async => 3);
+ $downwards<int> t4 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {
+ return 3;});
+ $downwards<int> t5 = f.then((_) => new $upwards<int>.value(3));
+ $downwards<int> t6 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) {return new $upwards<int>.value(3);});
+ $downwards<int> t7 = f.then((_) async => new $upwards<int>.value(3));
+ $downwards<int> t8 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {
+ return new $upwards<int>.value(3);});
+}
+''';
+
+ checkFile(
+ build(declared: "MyFuture", downwards: "Future", upwards: "Future"));
+ checkFile(
+ build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture"));
+ checkFile(
+ build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future"));
+ checkFile(build(
+ declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"));
+ checkFile(
+ build(declared: "Future", downwards: "Future", upwards: "MyFuture"));
+ checkFile(
+ build(declared: "Future", downwards: "Future", upwards: "Future"));
+ }
+
+ void test_futureThen_comment() {
+ String build({String declared, String downwards, String upwards}) => '''
+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;
}
@@ -1577,6 +1686,42 @@ 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;
+}
+
+void main() {
+ $declared<bool> f;
+ $downwards<int> t1 = f.then(/*info:INFERRED_TYPE_CLOSURE*/
+ (x) async => x ? 2 : await new $upwards<int>.value(3));
+ $downwards<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) async { // TODO(leafp): Why the duplicate here?
+ return await x ? 2 : new $upwards<int>.value(3);});
+ $downwards<int> t5 = f.then(/*info:INFERRED_TYPE_CLOSURE*/
+ (x) => x ? 2 : new $upwards<int>.value(3));
+ $downwards<int> t6 = f.then(/*info:INFERRED_TYPE_CLOSURE*/
+ (x) {return x ? 2 : new $upwards<int>.value(3);});
+}
+''';
+ checkFile(
+ build(declared: "MyFuture", downwards: "Future", upwards: "Future"));
+ checkFile(
+ build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture"));
+ checkFile(
+ build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future"));
+ checkFile(build(
+ declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"));
+ checkFile(
+ build(declared: "Future", downwards: "Future", upwards: "MyFuture"));
+ checkFile(
+ build(declared: "Future", downwards: "Future", upwards: "Future"));
+ }
+
+ void test_futureThen_conditional_comment() {
+ String build({String declared, String downwards, String upwards}) => '''
+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;
}
@@ -1625,6 +1770,17 @@ main() {
import "dart:async";
main() {
Future<int> f;
+ var x = f.then<Future<List<int>>>(/*info:INFERRED_TYPE_CLOSURE*/(x) => /*info:INFERRED_TYPE_LITERAL*/[]);
+ Future<List<int>> y = x;
+}
+ ''');
+ }
+
+ void test_futureThen_explicitFuture_comment() {
+ checkFile(r'''
+import "dart:async";
+main() {
+ Future<int> f;
var x = f.then/*<Future<List<int>>>*/(/*info:INFERRED_TYPE_CLOSURE*/(x) => /*info:INFERRED_TYPE_LITERAL*/[]);
Future<List<int>> y = x;
}
@@ -1639,6 +1795,36 @@ 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;
+}
+
+void main() {
+ var f = foo().then((_) => 2.3);
+ $downwards<int> f2 = /*error:INVALID_ASSIGNMENT*/f;
+
+ // The unnecessary cast is to illustrate that we inferred <double> for
+ // the generic type args, even though we had a return type context.
+ $downwards<num> f3 = /*info:UNNECESSARY_CAST*/foo().then(
+ (_) => 2.3) as $upwards<double>;
+}
+$declared foo() => new $declared<int>.value(1);
+ ''';
+ checkFile(
+ build(declared: "MyFuture", downwards: "Future", upwards: "Future"));
+ checkFile(build(
+ declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"));
+ checkFile(
+ build(declared: "Future", downwards: "Future", upwards: "Future"));
+ }
+
+ void test_futureThen_upwards_comment() {
+ // Regression test for https://github.com/dart-lang/sdk/issues/27088.
+ String build({String declared, String downwards, String upwards}) => '''
+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;
}
@@ -1682,6 +1868,29 @@ 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;
+}
+
+$downwards<int> g1(bool x) async {
+ return x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value(42); }
+$downwards<int> g2(bool x) async =>
+ x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value(42);
+$downwards<int> g3(bool x) async {
+ var y = x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new $upwards.value(42);
+ return y;
+}
+ ''';
+ checkFile(build(downwards: "Future", upwards: "Future"));
+ checkFile(build(downwards: "Future", upwards: "MyFuture"));
+ }
+
+ void test_futureUnion_asyncConditional_comment() {
+ String build({String declared, String downwards, String upwards}) => '''
+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;
}
@@ -1711,6 +1920,48 @@ 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(
+ /*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;
}
@@ -1763,6 +2014,20 @@ class A {}
checkFile(r'''
import 'dart:async';
+T id<T>(T x) => x;
+
+main() async {
+ Future<String> f;
+ String s = await id(f);
+}
+ ''');
+ }
+
+ 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 {
@@ -1798,6 +2063,20 @@ class C extends A {}
typedef void ToValue<T>(T value);
main() {
+ ToValue<T> f<T>(T x) => null;
+ var x = f<int>(42);
+ var y = f(42);
+ ToValue<int> takesInt = x;
+ takesInt = y;
+}
+ ''');
+ }
+
+ void test_genericFunctions_returnTypedef_comment() {
+ checkFile(r'''
+typedef void ToValue<T>(T value);
+
+main() {
ToValue/*<T>*/ f/*<T>*/(dynamic /*=T*/ x) => null;
var x = f/*<int>*/(42);
var y = f(42);
@@ -1809,6 +2088,16 @@ main() {
void test_genericMethods_basicDownwardInference() {
checkFile(r'''
+T f<S, T>(S s) => null;
+main() {
+ String x = f(42);
+ String y = (f)(42);
+}
+''');
+ }
+
+ void test_genericMethods_basicDownwardInference_comment() {
+ checkFile(r'''
/*=T*/ f/*<S, T>*/(/*=S*/ s) => null;
main() {
String x = f(42);
@@ -1821,6 +2110,28 @@ main() {
// 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);
+}
+''');
+ }
+
+ 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() {
@@ -1877,6 +2188,21 @@ main() {
void test_genericMethods_doNotInferInvalidOverrideOfGenericMethod() {
checkFile('''
class C {
+T m<T>(T x) => x;
+}
+class D extends C {
+/*error:INVALID_METHOD_OVERRIDE*/m(x) => x;
+}
+main() {
+ int y = /*info:DYNAMIC_CAST*/new D()./*error:WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD*/m<int>(42);
+ print(y);
+}
+''');
+ }
+
+ void test_genericMethods_doNotInferInvalidOverrideOfGenericMethod_comment() {
+ checkFile('''
+class C {
/*=T*/ m/*<T>*/(/*=T*/ x) => x;
}
class D extends C {
@@ -1891,6 +2217,16 @@ main() {
void test_genericMethods_downwardsInferenceAffectsArguments() {
checkFile(r'''
+T f<T>(List<T> s) => null;
+main() {
+ String x = f(/*info:INFERRED_TYPE_LITERAL*/['hi']);
+ String y = f(/*info:INFERRED_TYPE_LITERAL,error:COULD_NOT_INFER*/[/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/42]);
+}
+''');
+ }
+
+ void test_genericMethods_downwardsInferenceAffectsArguments_comment() {
+ checkFile(r'''
/*=T*/ f/*<T>*/(List/*<T>*/ s) => null;
main() {
String x = f(/*info:INFERRED_TYPE_LITERAL*/['hi']);
@@ -1927,6 +2263,24 @@ class C {
dynamic g(int x) => x;
}
class D extends C {
+ T m<T>(T x) => x;
+ T g<T>(T x) => x;
+}
+main() {
+ int y = /*info:DYNAMIC_CAST*/(/*info:UNNECESSARY_CAST*/new D() as C).m(42);
+ print(y);
+}
+ ''');
+ }
+
+ void test_genericMethods_handleOverrideOfNonGenericWithGeneric_comment() {
+ // Regression test for crash when adding genericity
+ checkFile('''
+class C {
+ m(x) => x;
+ dynamic g(int x) => x;
+}
+class D extends C {
/*=T*/ m/*<T>*/(/*=T*/ x) => x;
/*=T*/ g/*<T>*/(/*=T*/ x) => x;
}
@@ -1949,10 +2303,10 @@ main() {
void test_genericMethods_inferGenericFunctionParameterType() {
var mainUnit = checkFile('''
class C<T> extends D<T> {
- f/*<U>*/(x) {}
+ f<U>(x) {}
}
class D<T> {
- F/*<U>*/ f/*<U>*/(/*=U*/ u) => null;
+ F<U> f<U>(U u) => null;
}
typedef void F<V>(V v);
''');
@@ -1963,6 +2317,20 @@ typedef void F<V>(V v);
void test_genericMethods_inferGenericFunctionParameterType2() {
var mainUnit = checkFile('''
class C<T> extends D<T> {
+ f<U>(g) => null;
+}
+abstract class D<T> {
+ void f<U>(G<U> g);
+}
+typedef List<V> G<V>();
+''');
+ var f = mainUnit.getType('C').methods[0];
+ expect(f.type.toString(), '<U>(() → List<U>) → void');
+ }
+
+ void test_genericMethods_inferGenericFunctionParameterType2_comment() {
+ var mainUnit = checkFile('''
+class C<T> extends D<T> {
f/*<U>*/(g) => null;
}
abstract class D<T> {
@@ -1974,21 +2342,139 @@ typedef List<V> G<V>();
expect(f.type.toString(), '<U>(() → List<U>) → void');
}
+ void test_genericMethods_inferGenericFunctionParameterType_comment() {
+ var mainUnit = checkFile('''
+class C<T> extends D<T> {
+ f/*<U>*/(x) {}
+}
+class D<T> {
+ F/*<U>*/ f/*<U>*/(/*=U*/ u) => null;
+}
+typedef void F<V>(V v);
+''');
+ var f = mainUnit.getType('C').methods[0];
+ expect(f.type.toString(), '<U>(U) → (U) → void');
+ }
+
void test_genericMethods_inferGenericFunctionReturnType() {
var mainUnit = checkFile('''
class C<T> extends D<T> {
+ f<U>(x) {}
+}
+class D<T> {
+ F<U> f<U>(U u) => null;
+}
+typedef V F<V>();
+''');
+ var f = mainUnit.getType('C').methods[0];
+ expect(f.type.toString(), '<U>(U) → () → U');
+ }
+
+ void test_genericMethods_inferGenericFunctionReturnType_comment() {
+ var mainUnit = checkFile('''
+class C<T> extends D<T> {
f/*<U>*/(x) {}
}
class D<T> {
F/*<U>*/ f/*<U>*/(/*=U*/ u) => null;
}
-typedef V F<V>();
+typedef V F<V>();
+''');
+ var f = mainUnit.getType('C').methods[0];
+ expect(f.type.toString(), '<U>(U) → () → U');
+ }
+
+ void test_genericMethods_inferGenericInstantiation() {
+ 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);
+
+// 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)) {}
''');
- var f = mainUnit.getType('C').methods[0];
- expect(f.type.toString(), '<U>(U) → () → U');
}
- void test_genericMethods_inferGenericInstantiation() {
+ void test_genericMethods_inferGenericInstantiation_comment() {
checkFile('''
import 'dart:math' as math;
import 'dart:math' show min;
@@ -2082,6 +2568,22 @@ void takeDDO(Object fn(double a, double b)) {}
// Regression test for https://github.com/dart-lang/sdk/issues/25668
checkFile('''
class C {
+ T m<T>(T x) => x;
+}
+class D extends C {
+ m<S>(x) => x;
+}
+main() {
+ int y = new D().m<int>(42);
+ print(y);
+}
+ ''');
+ }
+
+ void test_genericMethods_inferGenericMethodType_comment() {
+ // Regression test for https://github.com/dart-lang/sdk/issues/25668
+ checkFile('''
+class C {
/*=T*/ m/*<T>*/(/*=T*/ x) => x;
}
class D extends C {
@@ -2128,6 +2630,19 @@ main() {
typedef Iterable<num> F(int x);
typedef List<int> G(double x);
+T generic<T>(a(T _), b(T _)) => null;
+
+var v = generic((F f) => null, (G g) => null);
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.type.toString(), '(num) → List<int>');
+ }
+
+ void test_genericMethods_usesGreatestLowerBound_comment() {
+ var mainUnit = checkFile(r'''
+typedef Iterable<num> F(int x);
+typedef List<int> G(double x);
+
/*=T*/ generic/*<T>*/(a(/*=T*/ _), b(/*=T*/ _)) => null;
var v = generic((F f) => null, (G g) => null);
@@ -2712,6 +3227,16 @@ test1() {
void test_inferGenericMethodType_named() {
var unit = checkFile('''
class C {
+ T m<T>(int a, {String b, T c}) => null;
+}
+var y = new C().m(1, b: 'bbb', c: 2.0);
+ ''');
+ expect(unit.topLevelVariables[0].type.toString(), 'double');
+ }
+
+ void test_inferGenericMethodType_named_comment() {
+ var unit = checkFile('''
+class C {
/*=T*/ m/*<T>*/(int a, {String b, /*=T*/ c}) => null;
}
var y = new C().m(1, b: 'bbb', c: 2.0);
@@ -2722,7 +3247,7 @@ var y = new C().m(1, b: 'bbb', c: 2.0);
void test_inferGenericMethodType_positional() {
var unit = checkFile('''
class C {
- /*=T*/ m/*<T>*/(int a, [/*=T*/ b]) => null;
+ T m<T>(int a, [T b]) => null;
}
var y = new C().m(1, 2.0);
''');
@@ -2732,6 +3257,16 @@ var y = new C().m(1, 2.0);
void test_inferGenericMethodType_positional2() {
var unit = checkFile('''
class C {
+ T m<T>(int a, [String b, T c]) => null;
+}
+var y = new C().m(1, 'bbb', 2.0);
+ ''');
+ expect(unit.topLevelVariables[0].type.toString(), 'double');
+ }
+
+ void test_inferGenericMethodType_positional2_comment() {
+ var unit = checkFile('''
+class C {
/*=T*/ m/*<T>*/(int a, [String b, /*=T*/ c]) => null;
}
var y = new C().m(1, 'bbb', 2.0);
@@ -2739,9 +3274,29 @@ var y = new C().m(1, 'bbb', 2.0);
expect(unit.topLevelVariables[0].type.toString(), 'double');
}
+ void test_inferGenericMethodType_positional_comment() {
+ var unit = checkFile('''
+class C {
+ /*=T*/ m/*<T>*/(int a, [/*=T*/ b]) => null;
+}
+var y = new C().m(1, 2.0);
+ ''');
+ expect(unit.topLevelVariables[0].type.toString(), 'double');
+ }
+
void test_inferGenericMethodType_required() {
var unit = checkFile('''
class C {
+ T m<T>(T x) => x;
+}
+var y = new C().m(42);
+ ''');
+ expect(unit.topLevelVariables[0].type.toString(), 'int');
+ }
+
+ void test_inferGenericMethodType_required_comment() {
+ var unit = checkFile('''
+class C {
/*=T*/ m/*<T>*/(/*=T*/ x) => x;
}
var y = new C().m(42);
@@ -3958,6 +4513,18 @@ var x = { null: null };
void test_methodCall_withTypeArguments_instanceMethod() {
var mainUnit = checkFile('''
class C {
+ D<T> f<T>() => null;
+}
+class D<T> {}
+var f = new C().f<int>();
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.type.toString(), 'D<int>');
+ }
+
+ void test_methodCall_withTypeArguments_instanceMethod_comment() {
+ var mainUnit = checkFile('''
+class C {
D/*<T>*/ f/*<T>*/() => null;
}
class D<T> {}
@@ -3970,6 +4537,21 @@ var f = new C().f/*<int>*/();
void test_methodCall_withTypeArguments_instanceMethod_identifierSequence() {
var mainUnit = checkFile('''
class C {
+ D<T> f<T>() => null;
+}
+class D<T> {}
+C c;
+var f = c.f<int>();
+''');
+ var v = mainUnit.topLevelVariables[1];
+ expect(v.name, 'f');
+ expect(v.type.toString(), 'D<int>');
+ }
+
+ void
+ test_methodCall_withTypeArguments_instanceMethod_identifierSequence_comment() {
+ var mainUnit = checkFile('''
+class C {
D/*<T>*/ f/*<T>*/() => null;
}
class D<T> {}
@@ -3984,6 +4566,18 @@ var f = c.f/*<int>*/();
void test_methodCall_withTypeArguments_staticMethod() {
var mainUnit = checkFile('''
class C {
+ static D<T> f<T>() => null;
+}
+class D<T> {}
+var f = C.f<int>();
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.type.toString(), 'D<int>');
+ }
+
+ void test_methodCall_withTypeArguments_staticMethod_comment() {
+ var mainUnit = checkFile('''
+class C {
static D/*<T>*/ f/*<T>*/() => null;
}
class D<T> {}
@@ -3995,6 +4589,16 @@ var f = C.f/*<int>*/();
void test_methodCall_withTypeArguments_topLevelFunction() {
var mainUnit = checkFile('''
+D<T> f<T>() => null;
+class D<T> {}
+var g = f<int>();
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.type.toString(), 'D<int>');
+ }
+
+ void test_methodCall_withTypeArguments_topLevelFunction_comment() {
+ var mainUnit = checkFile('''
D/*<T>*/ f/*<T>*/() => null;
class D<T> {}
var g = f/*<int>*/();
@@ -4381,6 +4985,17 @@ var v = new C(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
void test_unsafeBlockClosureInference_functionCall_explicitDynamicParam() {
var mainUnit = checkFile('''
+List<T> f<T>(T g()) => <T>[g()];
+var v = f<dynamic>(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<dynamic>');
+ }
+
+ void
+ test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_comment() {
+ var mainUnit = checkFile('''
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
var v = f/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
''');
@@ -4395,6 +5010,20 @@ var v = f/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
// Note: (f/*<dynamic>*/) is nort properly resulting in an instantiated
// function type due to dartbug.com/25824.
var mainUnit = checkFile('''
+List<T> f<T>(T g()) => <T>[g()];
+var v = (f<dynamic>)(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<dynamic>');
+ }
+
+ @failingTest
+ void
+ test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1_comment() {
+ // Note: (f/*<dynamic>*/) is nort properly resulting in an instantiated
+ // function type due to dartbug.com/25824.
+ var mainUnit = checkFile('''
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
var v = (f/*<dynamic>*/)(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
''');
@@ -4406,6 +5035,17 @@ var v = (f/*<dynamic>*/)(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
void
test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2() {
var mainUnit = checkFile('''
+List<T> f<T>(T g()) => <T>[g()];
+var v = (f)<dynamic>(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<dynamic>');
+ }
+
+ void
+ test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr2_comment() {
+ var mainUnit = checkFile('''
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
var v = (f)/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
''');
@@ -4416,6 +5056,17 @@ var v = (f)/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
void test_unsafeBlockClosureInference_functionCall_explicitTypeParam() {
var mainUnit = checkFile('''
+List<T> f<T>(T g()) => <T>[g()];
+var v = f<int>(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<int>');
+ }
+
+ void
+ test_unsafeBlockClosureInference_functionCall_explicitTypeParam_comment() {
+ var mainUnit = checkFile('''
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
var v = f/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
''');
@@ -4430,6 +5081,20 @@ var v = f/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
// TODO(paulberry): for some reason (f/*<int>) is nort properly resulting
// in an instantiated function type.
var mainUnit = checkFile('''
+List<T> f<T>(T g()) => <T>[g()];
+var v = (f/int>)(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<int>');
+ }
+
+ @failingTest
+ void
+ test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1_comment() {
+ // TODO(paulberry): for some reason (f/*<int>) is nort properly resulting
+ // in an instantiated function type.
+ var mainUnit = checkFile('''
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
var v = (f/*<int>*/)(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
''');
@@ -4441,6 +5106,17 @@ var v = (f/*<int>*/)(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
void
test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2() {
var mainUnit = checkFile('''
+List<T> f<T>(T g()) => <T>[g()];
+var v = (f)<int>(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<int>');
+ }
+
+ void
+ test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr2_comment() {
+ var mainUnit = checkFile('''
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
var v = (f)/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
''');
@@ -4451,6 +5127,20 @@ var v = (f)/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
void test_unsafeBlockClosureInference_functionCall_implicitTypeParam() {
var mainUnit = checkFile('''
+List<T> f<T>(T g()) => <T>[g()];
+var v = f(
+ /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+ return 1;
+ });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<int>');
+ }
+
+ void
+ test_unsafeBlockClosureInference_functionCall_implicitTypeParam_comment() {
+ var mainUnit = checkFile('''
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
var v = f(
/*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
@@ -4465,6 +5155,20 @@ var v = f(
void
test_unsafeBlockClosureInference_functionCall_implicitTypeParam_viaExpr() {
var mainUnit = checkFile('''
+List<T> f<T>(T g()) => <T>[g()];
+var v = (f)(
+ /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+ return 1;
+ });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<int>');
+ }
+
+ void
+ test_unsafeBlockClosureInference_functionCall_implicitTypeParam_viaExpr_comment() {
+ var mainUnit = checkFile('''
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
var v = (f)(
/*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
@@ -4561,6 +5265,19 @@ var v = /*info:INFERRED_TYPE_LITERAL*/{
void test_unsafeBlockClosureInference_methodCall_explicitDynamicParam() {
var mainUnit = checkFile('''
class C {
+ List<T> f<T>(T g()) => <T>[g()];
+}
+var v = new C().f<dynamic>(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<dynamic>');
+ }
+
+ void
+ test_unsafeBlockClosureInference_methodCall_explicitDynamicParam_comment() {
+ var mainUnit = checkFile('''
+class C {
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
}
var v = new C().f/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
@@ -4573,6 +5290,18 @@ var v = new C().f/*<dynamic>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
void test_unsafeBlockClosureInference_methodCall_explicitTypeParam() {
var mainUnit = checkFile('''
class C {
+ List<T> f<T>(T g()) => <T>[g()];
+}
+var v = new C().f<int>(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<int>');
+ }
+
+ void test_unsafeBlockClosureInference_methodCall_explicitTypeParam_comment() {
+ var mainUnit = checkFile('''
+class C {
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
}
var v = new C().f/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
@@ -4585,6 +5314,21 @@ var v = new C().f/*<int>*/(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
void test_unsafeBlockClosureInference_methodCall_implicitTypeParam() {
var mainUnit = checkFile('''
class C {
+ List<T> f<T>(T g()) => <T>[g()];
+}
+var v = new C().f(
+ /*info:INFERRED_TYPE_CLOSURE,warning:UNSAFE_BLOCK_CLOSURE_INFERENCE*/() {
+ return 1;
+ });
+''');
+ var v = mainUnit.topLevelVariables[0];
+ expect(v.name, 'v');
+ expect(v.type.toString(), 'List<int>');
+ }
+
+ void test_unsafeBlockClosureInference_methodCall_implicitTypeParam_comment() {
+ var mainUnit = checkFile('''
+class C {
dynamic /*=List<T>*/ f/*<T>*/(dynamic/*=T*/ g()) => <T>[g()];
}
var v = new C().f(
@@ -4611,6 +5355,37 @@ var v = new C().f(/*info:INFERRED_TYPE_CLOSURE*/() { return 1; });
void test_voidReturnTypeSubtypesDynamic() {
var unit = checkFile(r'''
+T run<T>(T f()) {
+ print("running");
+ var t = f();
+ print("done running");
+ return t;
+}
+
+
+void printRunning() { print("running"); }
+var x = run<dynamic>(printRunning);
+var y = run(printRunning);
+
+main() {
+ void printRunning() { print("running"); }
+ var x = run<dynamic>(printRunning);
+ var y = run(printRunning);
+ x = 123;
+ x = 'hi';
+ y = 123;
+ y = 'hi';
+}
+ ''');
+
+ var x = unit.topLevelVariables[0];
+ var y = unit.topLevelVariables[1];
+ expect(x.type.toString(), 'dynamic');
+ expect(y.type.toString(), 'dynamic');
+ }
+
+ void test_voidReturnTypeSubtypesDynamic_comment() {
+ var unit = checkFile(r'''
/*=T*/ run/*<T>*/(/*=T*/ f()) {
print("running");
var t = f();
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698