8de8a1c226
They are all errors now. Change-Id: If48d38e38e845fd5b5a950dd5514bf1cbbce03d8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155880 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
147 lines
4.1 KiB
Dart
147 lines
4.1 KiB
Dart
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
// This test verifies that for an unnamed async closure, the following three
|
|
// types are all appropriately matched:
|
|
// - The static return type
|
|
// - The return type of reified runtime type of a tearoff of the function or
|
|
// method
|
|
// - The reified type of the future returned by the function or method
|
|
//
|
|
// Specific attention is paid to the following conditions:
|
|
// - The static return type is determined by type inference
|
|
// - The static return type is `dynamic`
|
|
// - The function or method immediately returns a value or future with a
|
|
// different type (possibly using `=>` syntax)
|
|
|
|
import 'dart:async';
|
|
|
|
import 'package:expect/expect.dart';
|
|
|
|
class A {}
|
|
|
|
class B extends A {}
|
|
|
|
Future quick() async {}
|
|
|
|
Future<A> futureA() => new Future<A>.value(new A());
|
|
|
|
Future<B> futureB() => new Future<B>.value(new B());
|
|
|
|
void checkFutureObject(dynamic tearoff) {
|
|
Expect.isTrue(tearoff is Future<Object> Function());
|
|
Expect.isFalse(tearoff is Future<A> Function());
|
|
dynamic f = tearoff();
|
|
Expect.isTrue(f is Future<Object>);
|
|
Expect.isFalse(f is Future<A>);
|
|
}
|
|
|
|
void checkFutureDynamic(dynamic tearoff) {
|
|
Expect.isTrue(tearoff is Future<dynamic> Function());
|
|
Expect.isFalse(tearoff is Future<A> Function());
|
|
dynamic f = tearoff();
|
|
Expect.isTrue(f is Future<dynamic>);
|
|
Expect.isFalse(f is Future<A>);
|
|
}
|
|
|
|
void checkFutureA(dynamic tearoff) {
|
|
Expect.isTrue(tearoff is Future<A> Function());
|
|
Expect.isFalse(tearoff is Future<B> Function());
|
|
dynamic f = tearoff();
|
|
Expect.isTrue(f is Future<A>);
|
|
Expect.isFalse(f is Future<B>);
|
|
}
|
|
|
|
main() {
|
|
var f_inferred_futureObject = () async {
|
|
await quick();
|
|
if (false) {
|
|
return 0;
|
|
} else {
|
|
return new A();
|
|
}
|
|
};
|
|
|
|
var f_inferred_A = () async {
|
|
await quick();
|
|
if (false) {
|
|
return new A();
|
|
} else {
|
|
return new B();
|
|
}
|
|
};
|
|
|
|
Future<dynamic> Function() f_futureDynamic = () async {
|
|
await quick();
|
|
if (false) {
|
|
return 0;
|
|
} else {
|
|
return new B();
|
|
}
|
|
};
|
|
|
|
Future<A> Function() f_A = () async {
|
|
await quick();
|
|
if (false) {
|
|
return new A();
|
|
} else {
|
|
return new B();
|
|
}
|
|
};
|
|
|
|
Future<A> Function() f_immediateReturn_B = () async {
|
|
if (false) {
|
|
return new A();
|
|
} else {
|
|
return new B();
|
|
}
|
|
};
|
|
|
|
Future<A> Function() f_immediateReturn_FutureB = () async {
|
|
if (false) {
|
|
return new A();
|
|
} else {
|
|
return futureB();
|
|
}
|
|
};
|
|
|
|
Future<A> Function() f_expressionSyntax_B =
|
|
() async => false ? new A() : new B();
|
|
|
|
Future<A> Function() f_expressionSyntax_FutureB =
|
|
() async => false ? futureA() : futureB();
|
|
|
|
// Not executed
|
|
void checkStaticTypes() {
|
|
// Check that f_inferred_futureObject's static return type is
|
|
// `Future<Object>`, by verifying that its return value can be assigned to
|
|
// `Future<Object>` but not `Future<int>`.
|
|
Future<Object> v1 = f_inferred_futureObject();
|
|
Future<int> v2 = f_inferred_futureObject();
|
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
|
|
// ^
|
|
// [cfe] A value of type 'Future<Object>' can't be assigned to a variable of type 'Future<int>'.
|
|
|
|
// Check that f_inferred_A's static return type is `Future<A>`, by verifying
|
|
// that its return value can be assigned to `Future<A>` but not
|
|
// `Future<B>`.
|
|
Future<A> v3 = f_inferred_A();
|
|
Future<B> v4 = f_inferred_A();
|
|
// ^^^^^^^^^^^^^^
|
|
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
|
|
// ^
|
|
// [cfe] A value of type 'Future<A>' can't be assigned to a variable of type 'Future<B>'.
|
|
}
|
|
|
|
checkFutureObject(f_inferred_futureObject);
|
|
checkFutureA(f_inferred_A);
|
|
checkFutureDynamic(f_futureDynamic);
|
|
checkFutureA(f_A);
|
|
checkFutureA(f_immediateReturn_B);
|
|
checkFutureA(f_immediateReturn_FutureB);
|
|
checkFutureA(f_expressionSyntax_B);
|
|
checkFutureA(f_expressionSyntax_FutureB);
|
|
}
|