From c3dfe51295378d1ac919dea6374b75eca7b0de4f Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Wed, 8 Jun 2016 10:50:33 +0200 Subject: [PATCH] Adds status entries for initializing_formal tests. This CL should fix the problem that arose with commit 543a51ff3eb1488e2c1938bfcd8779f0d634900c. Here's the description from that CL: This CL adds tests for previously uncovered elements of the semantics and includes fixes such that the desired behavior is obtained. In particular, an `isInitializingFormal` element may now occur in contexts where it wasn't expected until now, and changes were made to handle it. It is also checked that a capture of an initializing formal (in a function literal) captures the parameter, not the field. R=johnniwinther@google.com Review URL: https://codereview.chromium.org/2042293002 . --- .../lib/src/cps_ir/cps_ir_builder_task.dart | 6 ++-- pkg/compiler/lib/src/resolution/members.dart | 5 ++++ pkg/compiler/lib/src/typechecker.dart | 21 ++++++++++--- pkg/dart_messages/lib/shared_messages.dart | 2 ++ .../initializing_formal_capture_test.dart | 19 ++++++++++++ .../initializing_formal_final_test.dart | 20 +++++++++++++ .../initializing_formal_promotion_test.dart | 30 +++++++++++++++++++ .../initializing_formal_type_test.dart | 19 ++++++++++++ tests/language/language.status | 6 ++++ tests/language/language_analyzer2.status | 4 +++ tests/language/language_dart2js.status | 3 ++ 11 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 tests/language/initializing_formal_capture_test.dart create mode 100644 tests/language/initializing_formal_final_test.dart create mode 100644 tests/language/initializing_formal_promotion_test.dart create mode 100644 tests/language/initializing_formal_type_test.dart diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart index 18eeb525aae..28cc94a8420 100644 --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart @@ -3859,7 +3859,7 @@ class TryBoxedVariables extends ast.Visitor { if (Elements.isLocal(element)) { LocalElement local = element; if (insideInitializer && - local.isParameter && + (local.isParameter || local.isInitializingFormal) && local.enclosingElement == currentFunction) { assert(local.enclosingElement.isConstructor); // Initializers in an initializer-list can communicate via parameters. @@ -3871,7 +3871,9 @@ class TryBoxedVariables extends ast.Visitor { // outlive the activation of the function). markAsCaptured(local); } else if (inTryStatement) { - assert(local.isParameter || local.isVariable); + assert(local.isParameter || + local.isVariable || + local.isInitializingFormal); // Search for the position of the try block containing the variable // declaration, or -1 if it is declared outside the outermost try. int i = tryNestingStack.length - 1; diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart index 3658a7d8b8c..871f6afcae0 100644 --- a/pkg/compiler/lib/src/resolution/members.dart +++ b/pkg/compiler/lib/src/resolution/members.dart @@ -2573,6 +2573,11 @@ class ResolverVisitor extends MappingVisitor { } else { semantics = new StaticAccess.parameter(element); } + } else if (element.isInitializingFormal && + compiler.options.enableInitializingFormalAccess) { + error = reportAndCreateErroneousElement(node.selector, name.text, + MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER, {'name': name}); + semantics = new StaticAccess.finalParameter(element); } else if (element.isVariable) { if (element.isFinal || element.isConst) { error = reportAndCreateErroneousElement(node.selector, name.text, diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart index 2a8ab08ccdc..56f1326d024 100644 --- a/pkg/compiler/lib/src/typechecker.dart +++ b/pkg/compiler/lib/src/typechecker.dart @@ -681,7 +681,12 @@ class TypeCheckerVisitor extends Visitor { assert(invariant(node, element != null, message: 'Missing element for identifier')); assert(invariant( - node, element.isVariable || element.isParameter || element.isField, + node, + element.isVariable || + element.isParameter || + element.isField || + (element.isInitializingFormal && + compiler.options.enableInitializingFormalAccess), message: 'Unexpected context element ${element}')); return element.computeType(resolution); } @@ -766,7 +771,9 @@ class TypeCheckerVisitor extends Visitor { return access; } if (receiverElement != null && - (receiverElement.isVariable || receiverElement.isParameter)) { + (receiverElement.isVariable || receiverElement.isParameter || + (receiverElement.isInitializingFormal && + compiler.options.enableInitializingFormalAccess))) { Link typePromotions = typePromotionsMap[receiverElement]; if (typePromotions != null) { while (!typePromotions.isEmpty) { @@ -1082,7 +1089,9 @@ class TypeCheckerVisitor extends Visitor { } ElementAccess createPromotedAccess(Element element) { - if (element.isVariable || element.isParameter) { + if (element.isVariable || element.isParameter || + (element.isInitializingFormal && + compiler.options.enableInitializingFormalAccess)) { TypePromotion typePromotion = getKnownTypePromotion(element); if (typePromotion != null) { return new PromotedAccess(element, typePromotion.type); @@ -1217,7 +1226,11 @@ class TypeCheckerVisitor extends Visitor { } } - if (variable != null && (variable.isVariable || variable.isParameter)) { + if (variable != null && + (variable.isVariable || + variable.isParameter || + (variable.isInitializingFormal && + compiler.options.enableInitializingFormalAccess))) { DartType knownType = getKnownType(variable); if (!knownType.isDynamic) { DartType shownType = elements.getType(node.arguments.head); diff --git a/pkg/dart_messages/lib/shared_messages.dart b/pkg/dart_messages/lib/shared_messages.dart index c2e73c74f6c..ae917115c2a 100644 --- a/pkg/dart_messages/lib/shared_messages.dart +++ b/pkg/dart_messages/lib/shared_messages.dart @@ -682,6 +682,8 @@ final Map MESSAGES = { template: "The setter '#{memberName}' is not defined for the " "class '#{className}'.", usedBy: [dart2js, analyzer], + // TODO(eernst): When this.x access is available, add examples here, + // e.g., "class A { var x; A(this.x) : x = 3; } main() => new A(2);" examples: const ["class A {} main() { new A().x = 499; }",]), 'NO_SUCH_SUPER_MEMBER': new Message( diff --git a/tests/language/initializing_formal_capture_test.dart b/tests/language/initializing_formal_capture_test.dart new file mode 100644 index 00000000000..7ad3f083cc1 --- /dev/null +++ b/tests/language/initializing_formal_capture_test.dart @@ -0,0 +1,19 @@ +// Copyright (c) 2016, 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. +// +// DartOptions=--initializing-formal-access + +import "package:expect/expect.dart"; + +class A { + var x, y; + A(this.x) : y = (() => x); +} + +main() { + A a = new A(2); + a.x = 3; + Expect.equals(a.x, 3); + Expect.equals(a.y(), 2); +} diff --git a/tests/language/initializing_formal_final_test.dart b/tests/language/initializing_formal_final_test.dart new file mode 100644 index 00000000000..0832ce02d99 --- /dev/null +++ b/tests/language/initializing_formal_final_test.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2016, 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. +// +// DartOptions=--initializing-formal-access + +import "package:expect/expect.dart"; + +class A { + var x, y; + // This should cause a warning because `x` is final when + // accessed as an initializing formal. + A(this.x) : y = (() { x = 3; }); +} + +main() { + A a = new A(2); + Expect.equals(a.x, 2); + Expect.throws(() => a.y(), (e) => e is NoSuchMethodError); +} diff --git a/tests/language/initializing_formal_promotion_test.dart b/tests/language/initializing_formal_promotion_test.dart new file mode 100644 index 00000000000..b0314e822a9 --- /dev/null +++ b/tests/language/initializing_formal_promotion_test.dart @@ -0,0 +1,30 @@ +// Copyright (c) 2016, 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. +// +// DartOptions=--initializing-formal-access + +import "package:expect/expect.dart"; + +class B {} + +class A { + B x, y; + A(this.x) { + // Promote to subtype. + if (x is C) y = x.x; + // Promotion fails, not a subtype. + if (x is A) y = x; + } +} + +class C extends A implements B { + C(B x) : super(x); +} + +main() { + C c2 = new C(null); + C cc = new C(c2); + Expect.equals(c2.y, null); + Expect.equals(cc.y, c2); +} diff --git a/tests/language/initializing_formal_type_test.dart b/tests/language/initializing_formal_type_test.dart new file mode 100644 index 00000000000..352eecf6872 --- /dev/null +++ b/tests/language/initializing_formal_type_test.dart @@ -0,0 +1,19 @@ +// Copyright (c) 2016, 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. +// +// DartOptions=--initializing-formal-access + +import "package:expect/expect.dart"; + +class A { + int x; + String y; + A(this.x) : y = x { y = x; } +} + +main() { + A a = new A(null); + Expect.equals(a.x, null); + Expect.equals(a.y, null); +} diff --git a/tests/language/language.status b/tests/language/language.status index 9657b5493eb..77da565ac8f 100644 --- a/tests/language/language.status +++ b/tests/language/language.status @@ -55,6 +55,9 @@ generic_methods_type_expression_test: CompiletimeError # Issue 25869 # Experimental feature: Use initializing formals in initializers and constructor body. initializing_formal_access_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue. +initializing_formal_capture_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue. +initializing_formal_final_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue. +initializing_formal_type_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue. [ ($compiler == none || $compiler == precompiler || $compiler == dart2app || $compiler == dart2appjit) && ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_app) ] @@ -107,6 +110,9 @@ generic_methods_type_expression_test: RuntimeError # Issue 25869 # Experimental feature: Use initializing formals in initializers and constructor body. initializing_formal_access_test: RuntimeError # TODO(eernst): create a suitable sdk issue. +initializing_formal_capture_test: RuntimeError # TODO(eernst): create a suitable sdk issue. +initializing_formal_final_test: RuntimeError # TODO(eernst): create a suitable sdk issue. +initializing_formal_type_test: RuntimeError # TODO(eernst): create a suitable sdk issue. config_import_test: Skip # Issue 26250 diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status index 8525e336c92..e8adc717bab 100644 --- a/tests/language/language_analyzer2.status +++ b/tests/language/language_analyzer2.status @@ -512,3 +512,7 @@ generic_methods_type_expression_test: CompiletimeError # Issue 25868 # Experimental feature: Use initializing formals in initializers and constructor body. initializing_formal_access_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue. +initializing_formal_capture_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue. +initializing_formal_final_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue. +initializing_formal_promotion_test: StaticWarning # TODO(eernst): Create a suitable sdk issue. +initializing_formal_type_test: CompiletimeError # TODO(eernst): Create a suitable sdk issue. diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status index bb54e5c6be6..d80aae421c6 100644 --- a/tests/language/language_dart2js.status +++ b/tests/language/language_dart2js.status @@ -56,6 +56,9 @@ generic_methods_type_expression_test: CompiletimeError # DartOptions not passed # Experimental feature: Use initializing formals in initializers and constructor body. initializing_formal_access_test: CompiletimeError # DartOptions not passed to compiler. +initializing_formal_capture_test: CompiletimeError # DartOptions not passed to compiler. +initializing_formal_final_test: CompiletimeError # DartOptions not passed to compiler. +initializing_formal_type_test: CompiletimeError # DartOptions not passed to compiler. [ $compiler == dart2js ] invocation_mirror_empty_arguments_test: Fail # Issue 24331