From 991753313f4400dc465b98ec302f2919dd14a67d Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Tue, 30 Jan 2018 18:11:11 +0000 Subject: [PATCH] Remove deep future flattening from analyzer and DDC Change-Id: Ic48f29adec3a46744b259ba5b2b8ad7d97caa6c2 Reviewed-on: https://dart-review.googlesource.com/37424 Reviewed-by: Jenny Messerly --- CHANGELOG.md | 13 +++++++++ pkg/analyzer/lib/src/dart/element/type.dart | 27 ------------------- .../src/task/strong/inferred_type_test.dart | 2 +- .../lib/src/analyzer/code_generator.dart | 4 --- pkg/dev_compiler/lib/src/kernel/compiler.dart | 4 --- .../private/ddc_runtime/classes.dart | 18 ------------- .../dart2js/old_frontend/mock_compiler.dart | 2 +- tests/language_2/language_2_analyzer.status | 2 -- tests/language_2/language_2_dartdevc.status | 2 +- 9 files changed, 16 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c96bf6917d..1e19f7322d8 100644 --- a/CHANGELOG.md +++ b/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 f; + var x = f.then>>((x) => []); + Future> y = x; + } + ``` + + ### Core library changes * `dart:async` diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart index 744a53d96d1..67fe7c13a46 100644 --- a/pkg/analyzer/lib/src/dart/element/type.dart +++ b/pkg/analyzer/lib/src/dart/element/type.dart @@ -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> will flatten to Future. - // - // In the Dart 3rd edition spec, this flatten operation is used for - // `async` and `await`. In strong mode, we extend it to all Future - // 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 { - // Future then(S onValue(T value), ...); - // } - // - // Given a call where S <: Future for some R, we will need to flatten - // the return type so it is Future< flatten(S) >, yielding Future. - // - 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; 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 1204587d8cc..fb326f88781 100644 --- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart +++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart @@ -1642,7 +1642,7 @@ m1() { Future f; var x = f.then>>(/*info:INFERRED_TYPE_CLOSURE*/ (x) => /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/[]); - Future> y = x; + Future> y = /*error:INVALID_ASSIGNMENT*/x; } m2() { Future f; diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart index 0259a5f4ec5..1fa4b1e1606 100644 --- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart +++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart @@ -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]); diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart index f1ff8d10e12..2e31a1faf82 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart @@ -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]); diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart index 43fc54366a0..1f510b9f08a 100644 --- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart +++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart @@ -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; diff --git a/tests/compiler/dart2js/old_frontend/mock_compiler.dart b/tests/compiler/dart2js/old_frontend/mock_compiler.dart index 239aceb9a1a..94ea07a6860 100644 --- a/tests/compiler/dart2js/old_frontend/mock_compiler.dart +++ b/tests/compiler/dart2js/old_frontend/mock_compiler.dart @@ -282,7 +282,7 @@ class MockCompiler extends Compiler { } /// Create a new [MockCompiler] and apply it asynchronously to [f]. - static Future create(T f(MockCompiler compiler)) { + static Future create(FutureOr f(MockCompiler compiler)) { MockCompiler compiler = new MockCompiler.internal(); return compiler.init().then((_) => f(compiler)); } diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status index 17886f5d442..bcd9e606a48 100644 --- a/tests/language_2/language_2_analyzer.status +++ b/tests/language_2/language_2_analyzer.status @@ -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. diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status index 34d106d4ff2..8ffc38499bc 100644 --- a/tests/language_2/language_2_dartdevc.status +++ b/tests/language_2/language_2_dartdevc.status @@ -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