mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
Remove deep future flattening from analyzer and DDC
Change-Id: Ic48f29adec3a46744b259ba5b2b8ad7d97caa6c2 Reviewed-on: https://dart-review.googlesource.com/37424 Reviewed-by: Jenny Messerly <jmesserly@google.com>
This commit is contained in:
parent
ec6eb06d2f
commit
991753313f
9 changed files with 16 additions and 58 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -11,6 +11,19 @@
|
|||
|
||||
#### Strong Mode
|
||||
|
||||
* Future flattening is now done only as specified in the Dart 2.0 spec, rather
|
||||
than more broadly. This means that the following code will now have an error on
|
||||
the assignment to `y`.
|
||||
|
||||
```dart
|
||||
test() {
|
||||
Future<int> f;
|
||||
var x = f.then<Future<List<int>>>((x) => []);
|
||||
Future<List<int>> y = x;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Core library changes
|
||||
|
||||
* `dart:async`
|
||||
|
|
|
@ -2127,33 +2127,6 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
|
|||
return this;
|
||||
}
|
||||
|
||||
if (isDartAsyncFuture && newTypeArguments.isNotEmpty) {
|
||||
//
|
||||
// In strong mode interpret Future< T > as Future< flatten(T) >
|
||||
//
|
||||
// For example, Future<Future<T>> will flatten to Future<T>.
|
||||
//
|
||||
// In the Dart 3rd edition spec, this flatten operation is used for
|
||||
// `async` and `await`. In strong mode, we extend it to all Future<T>
|
||||
// instantiations. This allows typing of Future-related operations
|
||||
// in dart:async in a way that matches their runtime behavior and provides
|
||||
// precise return types for users of these APIs.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// abstract class Future<T> {
|
||||
// Future<S> then<S>(S onValue(T value), ...);
|
||||
// }
|
||||
//
|
||||
// Given a call where S <: Future<R> for some R, we will need to flatten
|
||||
// the return type so it is Future< flatten(S) >, yielding Future<R>.
|
||||
//
|
||||
if (element.library.context.analysisOptions.strongMode) {
|
||||
TypeImpl t = newTypeArguments[0];
|
||||
newTypeArguments[0] = t.flattenFutures(new StrongTypeSystemImpl(null));
|
||||
}
|
||||
}
|
||||
|
||||
InterfaceTypeImpl newType = new InterfaceTypeImpl(element, prune);
|
||||
newType.typeArguments = newTypeArguments;
|
||||
return newType;
|
||||
|
|
|
@ -1642,7 +1642,7 @@ m1() {
|
|||
Future<int> f;
|
||||
var x = f.then<Future<List<int>>>(/*info:INFERRED_TYPE_CLOSURE*/
|
||||
(x) => /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/[]);
|
||||
Future<List<int>> y = x;
|
||||
Future<List<int>> y = /*error:INVALID_ASSIGNMENT*/x;
|
||||
}
|
||||
m2() {
|
||||
Future<int> f;
|
||||
|
|
|
@ -1232,10 +1232,6 @@ class CodeGenerator extends Object
|
|||
|
||||
var genericCall = _callHelper('generic(#)', [genericArgs]);
|
||||
|
||||
if (element.library.isDartAsync &&
|
||||
(element.name == "Future" || element.name == "_Future")) {
|
||||
genericCall = _callHelper('flattenFutures(#)', [genericCall]);
|
||||
}
|
||||
var genericName = _emitTopLevelNameNoInterop(element, suffix: '\$');
|
||||
return js.statement('{ # = #; # = #(); }',
|
||||
[genericName, genericCall, _emitTopLevelName(element), genericName]);
|
||||
|
|
|
@ -579,10 +579,6 @@ class ProgramCompiler
|
|||
|
||||
var genericCall = _callHelper('generic(#)', [genericArgs]);
|
||||
|
||||
if (getLibrary(c) == coreTypes.asyncLibrary &&
|
||||
(name == "Future" || name == "_Future")) {
|
||||
genericCall = _callHelper('flattenFutures(#)', [genericCall]);
|
||||
}
|
||||
var genericName = _emitTopLevelNameNoInterop(c, suffix: '\$');
|
||||
return js.statement('{ # = #; # = #(); }',
|
||||
[genericName, genericCall, _emitTopLevelName(c), genericName]);
|
||||
|
|
|
@ -58,24 +58,6 @@ final _originalDeclaration = JS('', 'Symbol("originalDeclaration")');
|
|||
|
||||
final mixinNew = JS('', 'Symbol("dart.mixinNew")');
|
||||
|
||||
/// Wrap a generic class builder function with future flattening.
|
||||
flattenFutures(builder) => JS('', '''(() => {
|
||||
function flatten(T) {
|
||||
if (!T) return $builder($dynamic);
|
||||
let futureClass = $getGenericClass($Future);
|
||||
//TODO(leafp): This only handles the direct flattening case.
|
||||
// It would probably be good to at least search up the class
|
||||
// hierarchy. If we keep doing flattening long term, we may
|
||||
// want to implement the full future flattening per spec.
|
||||
if ($getGenericClass(T) == futureClass) {
|
||||
let args = $getGenericArgs(T);
|
||||
if (args) return $builder(args[0]);
|
||||
}
|
||||
return $builder(T);
|
||||
}
|
||||
return flatten;
|
||||
})()''');
|
||||
|
||||
/// Memoize a generic type constructor function.
|
||||
generic(typeConstructor, setBaseClass) => JS('', '''(() => {
|
||||
let length = $typeConstructor.length;
|
||||
|
|
|
@ -282,7 +282,7 @@ class MockCompiler extends Compiler {
|
|||
}
|
||||
|
||||
/// Create a new [MockCompiler] and apply it asynchronously to [f].
|
||||
static Future<T> create<T>(T f(MockCompiler compiler)) {
|
||||
static Future<T> create<T>(FutureOr<T> f(MockCompiler compiler)) {
|
||||
MockCompiler compiler = new MockCompiler.internal();
|
||||
return compiler.init().then((_) => f(compiler));
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ abstract_override_adds_optional_args_concrete_subclass_test: MissingCompileTimeE
|
|||
abstract_override_adds_optional_args_concrete_test: MissingCompileTimeError # Issue #30568
|
||||
abstract_override_adds_optional_args_supercall_test: MissingCompileTimeError # Issue #30568
|
||||
assertion_initializer_const_function_test/01: MissingCompileTimeError
|
||||
async_return_types_test/nestedFuture: MissingCompileTimeError
|
||||
bad_initializer2_negative_test: Fail # Issue 14880
|
||||
black_listed_test/none: Fail # Issue 14228
|
||||
built_in_identifier_prefix_test: CompileTimeError
|
||||
|
@ -1228,7 +1227,6 @@ accessor_conflict_import_test: CompileTimeError # Issue 25626
|
|||
additional_interface_adds_optional_args_test: CompileTimeError # Issue #30568
|
||||
assertion_initializer_const_function_test/01: MissingStaticWarning
|
||||
assertion_initializer_test: CompileTimeError
|
||||
async_return_types_test/nestedFuture: MissingCompileTimeError
|
||||
cascaded_forwarding_stubs_test: CompileTimeError
|
||||
config_import_corelib_test: CompileTimeError
|
||||
const_types_test/07: MissingCompileTimeError # Incorrectly allows using type parameter in const expression.
|
||||
|
|
|
@ -343,6 +343,7 @@ async_await_syntax_test/d10a: MissingCompileTimeError
|
|||
async_or_generator_return_type_stacktrace_test/01: MissingCompileTimeError
|
||||
async_or_generator_return_type_stacktrace_test/02: MissingCompileTimeError
|
||||
async_or_generator_return_type_stacktrace_test/03: MissingCompileTimeError
|
||||
async_return_types_test/nestedFuture: MissingCompileTimeError
|
||||
async_return_types_test/tooManyTypeParameters: MissingCompileTimeError
|
||||
async_return_types_test/wrongReturnType: MissingCompileTimeError
|
||||
bad_named_parameters2_test/01: MissingCompileTimeError
|
||||
|
@ -1030,7 +1031,6 @@ truncdiv_test: RuntimeError # Issue 29920; Expect.throws fails: Did not throw
|
|||
abstract_override_adds_optional_args_concrete_subclass_test: MissingCompileTimeError # Issue #30568
|
||||
abstract_override_adds_optional_args_concrete_test: MissingCompileTimeError # Issue #30568
|
||||
abstract_override_adds_optional_args_supercall_test: MissingCompileTimeError # Issue #30568
|
||||
async_return_types_test/nestedFuture: MissingCompileTimeError
|
||||
bit_operations_test/01: MissingCompileTimeError
|
||||
bit_operations_test/02: MissingCompileTimeError
|
||||
built_in_identifier_prefix_test: CompileTimeError
|
||||
|
|
Loading…
Reference in a new issue