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 663ee78c3cde942090a4776e3015e8d81a952595..46e44000f1a001a2e7eca8f4ed2d2447786bc8e7 100644 |
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart |
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart |
@@ -1491,6 +1491,75 @@ main() { |
'''); |
}); |
+ test('downwards inference on generic function expressions', () { |
+ 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 = /*severe:STATIC_TYPE_ERROR*//*<T>*/(String x) => "hello"; |
+ v = /*severe:STATIC_TYPE_ERROR*//*<T>*/(int x) => 3; |
+ v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*severe:STATIC_TYPE_ERROR*/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, severe:STATIC_TYPE_ERROR*//*<T>*/(x) => 3; |
+ v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*severe:STATIC_TYPE_ERROR*/3;}; |
+ v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) {return /*severe:STATIC_TYPE_ERROR*/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 = /*severe:STATIC_TYPE_ERROR*//*<T>*/(String x) => /*info:INFERRED_TYPE_LITERAL*/["hello"]; |
+ v = /*<T>*/(int x) => /*info:INFERRED_TYPE_LITERAL*/[/*severe:STATIC_TYPE_ERROR*/3]; |
+ v = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(int x) {return /*info:INFERRED_TYPE_LITERAL*/[/*severe:STATIC_TYPE_ERROR*/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, severe:STATIC_TYPE_ERROR*//*<T>*/(x) => x; |
+ y = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/x.substring(3); |
+ var z = string2String; |
+ z = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x.substring(3); |
+ } |
+ } |
+ '''); |
+ }); |
+ |
+ test('downwards inference on function<T> using the T', () { |
+ 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); |
+ } |
+ } |
+ '''); |
+ }); |
+ |
test('downwards inference initializing formal, default formal', () { |
checkFile(''' |
typedef T Function2<S, T>([S x]); |
@@ -1500,7 +1569,7 @@ main() { |
Foo.named([List<int> x = /*info:INFERRED_TYPE_LITERAL*/const [1]]); |
} |
void f([List<int> l = /*info:INFERRED_TYPE_LITERAL*/const [1]]) {} |
-// We do this inference in an early task but don't preserve the infos. |
+ // We do this inference in an early task but don't preserve the infos. |
Function2<List<int>, String> g = /*pass should be info:INFERRED_TYPE_CLOSURE*/([llll = /*info:INFERRED_TYPE_LITERAL*/const [1]]) => "hello"; |
'''); |
}); |
@@ -1696,14 +1765,23 @@ main() { |
takeIIO(new C().m); |
takeDDO(new C().m); |
- takeOOI(/*severe:STATIC_TYPE_ERROR*/new C().m); |
- takeIDI(/*severe:STATIC_TYPE_ERROR*/new C().m); |
- takeDID(/*severe:STATIC_TYPE_ERROR*/new C().m); |
- |
// Note: this is a warning because a downcast of a method tear-off could work |
- // (derived method can be a subtype). |
+ // (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(/*warning:DOWN_CAST_COMPOSITE*/new C().m); |
takeOOO(/*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(/*warning:DOWN_CAST_COMPOSITE*/new C().m); |
+ takeIDI(/*warning:DOWN_CAST_COMPOSITE*/new C().m); |
+ takeDID(/*warning:DOWN_CAST_COMPOSITE*/new C().m); |
} |
void takeIII(int fn(int a, int b)) {} |