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 85a1085bef0fc6b253a86b6854b5c9315a60e496..77368a28f9d4e14861c0d6098e6ae7135983a68b 100644 |
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart |
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart |
@@ -1862,8 +1862,10 @@ main() { |
void foo(int f(Object _)) {} |
main() { |
- var f = (x) => null; |
- f = (x) => 'hello'; |
+ var f = (Object x) => null; |
+ String y = /*info:DYNAMIC_CAST*/f(42); |
+ |
+ f = /*info:INFERRED_TYPE_CLOSURE*/(x) => 'hello'; |
var g = null; |
g = 'hello'; |
@@ -1919,4 +1921,233 @@ test2() { |
} |
'''); |
}); |
+ |
+ |
+ group('block bodied lambdas', () { |
+ // Original feature request: https://github.com/dart-lang/sdk/issues/25487 |
+ |
+ test('basic', () { |
+ checkFile(r''' |
+ test1() { |
+ List<int> o; |
+ var y = o.map(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) { return x + 1; }); |
+ Iterable<int> z = y; |
+ } |
+ '''); |
+ }); |
+ |
+ test('no return', () { |
+ var mainUnit = checkFile(r''' |
+ test1() { |
+ List<int> o; |
+ var y = o.map(/*info:INFERRED_TYPE_CLOSURE*/(x) { }); |
+ Iterable<int> z = /*warning:DOWN_CAST_COMPOSITE*/y; |
+ } |
+ '''); |
+ var f = mainUnit.element.functions[0].localVariables[1]; |
+ expect(f.type.toString(), 'Iterable<dynamic>'); |
+ }); |
+ |
+ test('LUB', () { |
+ checkFile(r''' |
+ import 'dart:math' show Random; |
+ test2() { |
+ List<num> o; |
+ var y = o.map(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) { |
+ if (new Random().nextBool()) { |
+ return x.toInt() + 1; |
+ } else { |
+ return x.toDouble(); |
+ } |
+ }); |
+ Iterable<num> w = y; |
+ Iterable<int> z = /*info:ASSIGNMENT_CAST*/y; |
+ } |
+ '''); |
+ }); |
+ |
+ group('does not infer bottom', () { |
+ test('sync', () { |
+ var mainUnit = checkFile(r''' |
+ var h = null; |
+ void foo(int f(Object _)) {} |
+ |
+ main() { |
+ var f = (Object x) { return null; }; |
+ String y = /*info:DYNAMIC_CAST*/f(42); |
+ |
+ f = /*info:INFERRED_TYPE_CLOSURE*/(x) => 'hello'; |
+ |
+ foo(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) { return null; }); |
+ foo(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/(x) { throw "not implemented"; }); |
+ } |
+ '''); |
+ |
+ var f = mainUnit.element.functions[1].localVariables[0]; |
+ expect(f.type.toString(), '(Object) → dynamic'); |
+ }); |
+ |
+ test('sync*', () { |
+ var mainUnit = checkFile(r''' |
+ main() { |
+ var f = () sync* { yield null; }; |
+ Iterable y = f(); |
+ Iterable<String> z = /*warning:DOWN_CAST_COMPOSITE*/f(); |
+ String s = /*info:DYNAMIC_CAST*/f().first; |
+ } |
+ '''); |
+ |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → Iterable<dynamic>'); |
+ }); |
+ |
+ test('async', () { |
+ var mainUnit = checkFile(r''' |
+ import 'dart:async'; |
+ main() async { |
+ var f = () async { return null; }; |
+ Future y = f(); |
+ Future<String> z = /*warning:DOWN_CAST_COMPOSITE*/f(); |
+ String s = /*info:DYNAMIC_CAST*/await f(); |
+ } |
+ '''); |
+ |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → Future<dynamic>'); |
+ }); |
+ |
+ test('async*', () { |
+ var mainUnit = checkFile(r''' |
+ import 'dart:async'; |
+ main() async { |
+ var f = () async* { yield null; }; |
+ Stream y = f(); |
+ Stream<String> z = /*warning:DOWN_CAST_COMPOSITE*/f(); |
+ String s = /*info:DYNAMIC_CAST*/await f().first; |
+ } |
+ '''); |
+ |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → Stream<dynamic>'); |
+ }); |
+ }); |
+ |
+ group('async', () { |
+ test('all returns are values', () { |
+ var mainUnit = checkFile(r''' |
+ import 'dart:async'; |
+ import 'dart:math' show Random; |
+ main() { |
+ var f = /*info:INFERRED_TYPE_CLOSURE*/() async { |
+ if (new Random().nextBool()) { |
+ return 1; |
+ } else { |
+ return 2.0; |
+ } |
+ }; |
+ Future<num> g = f(); |
+ Future<int> h = /*info:ASSIGNMENT_CAST*/f(); |
+ } |
+ '''); |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → Future<num>'); |
+ }); |
+ |
+ test('all returns are futures', () { |
+ var mainUnit = checkFile(r''' |
+ import 'dart:async'; |
+ import 'dart:math' show Random; |
+ main() { |
+ var f = /*info:INFERRED_TYPE_CLOSURE*/() async { |
+ if (new Random().nextBool()) { |
+ return new Future<int>.value(1); |
+ } else { |
+ return new Future<double>.value(2.0); |
+ } |
+ }; |
+ Future<num> g = f(); |
+ Future<int> h = /*info:ASSIGNMENT_CAST*/f(); |
+ } |
+ '''); |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → Future<num>'); |
+ }); |
+ |
+ test('mix of values and futures', () { |
+ var mainUnit = checkFile(r''' |
+ import 'dart:async'; |
+ import 'dart:math' show Random; |
+ main() { |
+ var f = /*info:INFERRED_TYPE_CLOSURE*/() async { |
+ if (new Random().nextBool()) { |
+ return new Future<int>.value(1); |
+ } else { |
+ return 2.0; |
+ } |
+ }; |
+ Future<num> g = f(); |
+ Future<int> h = /*info:ASSIGNMENT_CAST*/f(); |
+ } |
+ '''); |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → Future<num>'); |
+ }); |
+ }); |
+ |
+ test('sync*', () { |
+ var mainUnit = checkFile(r''' |
+ main() { |
+ var f = /*info:INFERRED_TYPE_CLOSURE*/() sync* { |
+ yield 1; |
+ yield* [3, 4.0]; |
+ }; |
+ Iterable<num> g = f(); |
+ Iterable<int> h = /*info:ASSIGNMENT_CAST*/f(); |
+ } |
+ '''); |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → Iterable<num>'); |
+ }); |
+ |
+ test('async*', () { |
+ var mainUnit = checkFile(r''' |
+ import 'dart:async'; |
+ main() { |
+ var f = /*info:INFERRED_TYPE_CLOSURE*/() async* { |
+ yield 1; |
+ Stream<double> s; |
+ yield* s; |
+ }; |
+ Stream<num> g = f(); |
+ Stream<int> h = /*info:ASSIGNMENT_CAST*/f(); |
+ } |
+ '''); |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → Stream<num>'); |
+ }); |
+ |
+ test('downwards incompatible with upwards inference', () { |
+ var mainUnit = checkFile(r''' |
+ main() { |
+ String f() => null; |
+ var g = f; |
+ g = /*info:INFERRED_TYPE_CLOSURE*/() { return /*severe:STATIC_TYPE_ERROR*/1; }; |
+ } |
+ '''); |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → String'); |
+ }); |
+ |
+ test('nested lambdas', () { |
+ var mainUnit = checkFile(r''' |
+ main() { |
+ var f = /*info:INFERRED_TYPE_CLOSURE*/() { |
+ return /*info:INFERRED_TYPE_CLOSURE*/(int x) { return 2.0 * x; }; |
+ }; |
+ } |
+ '''); |
+ var f = mainUnit.element.functions[0].localVariables[0]; |
+ expect(f.type.toString(), '() → (int) → num'); |
+ }); |
+ }); |
} |