From 3572482e77717d012e12b87a5fdd2c44b6b77374 Mon Sep 17 00:00:00 2001 From: Jens Johansen Date: Thu, 28 Nov 2024 14:32:00 +0000 Subject: [PATCH] [CFE] Fix crash when metadata references locals in extension type Having metadata on several variables means it has to be cloned which (used to) crash. Change-Id: I0ed1d4b51cec98adb23674d144d3970d3db9d69d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/398060 Reviewed-by: Johnni Winther Commit-Queue: Jens Johansen --- .../lib/src/kernel/body_builder.dart | 2 +- ...ion_type_metadata_references_variable.dart | 10 +++++ ...ata_references_variable.dart.strong.expect | 42 +++++++++++++++++++ ...rences_variable.dart.strong.modular.expect | 42 +++++++++++++++++++ ...rences_variable.dart.strong.outline.expect | 19 +++++++++ ...es_variable.dart.strong.transformed.expect | 42 +++++++++++++++++++ ...ences_variable.dart.textual_outline.expect | 3 ++ ...iable.dart.textual_outline_modelled.expect | 3 ++ 8 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart create mode 100644 pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.expect create mode 100644 pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.modular.expect create mode 100644 pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.outline.expect create mode 100644 pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.transformed.expect create mode 100644 pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.textual_outline.expect create mode 100644 pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.textual_outline_modelled.expect diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart index 603c3ea04dc3..1c1db8727ff8 100644 --- a/pkg/front_end/lib/src/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/kernel/body_builder.dart @@ -3288,7 +3288,7 @@ class BodyBuilder extends StackListenerImpl VariableBuilder variableBuilder = declaration as VariableBuilder; if (constantContext != ConstantContext.none && !variableBuilder.isConst && - !_context.isConstructor && + !(_context.isConstructor && inFieldInitializer) && !libraryFeatures.constFunctions.isEnabled) { return new IncompleteErrorGenerator( this, nameToken, cfe.messageNotAConstantExpression); diff --git a/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart new file mode 100644 index 000000000000..de52afa0570f --- /dev/null +++ b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart @@ -0,0 +1,10 @@ +// Copyright (c) 2024, 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. + +extension type Foo._(int _x) { + Foo(this._x, int bar){ + @bar + int a1, a2; + } +} diff --git a/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.expect b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.expect new file mode 100644 index 000000000000..0c2024fa02d2 --- /dev/null +++ b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.expect @@ -0,0 +1,42 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: Not a constant expression. +// @bar +// ^^^ +// +// pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. +// @bar +// ^ +// +import self as self; +import "dart:core" as core; + +extension type Foo(core::int _x) { + abstract extension-type-member representation-field get _x() → core::int; + constructor _ = self::Foo|constructor#_; + constructor tearoff _ = self::Foo|constructor#_#_#tearOff; + constructor • = self::Foo|constructor#; + constructor tearoff • = self::Foo|constructor#_#new#tearOff; +} +static extension-type-member method Foo|constructor#_(core::int _x) → self::Foo% /* erasure=core::int, declared=! */ { + lowered final self::Foo% /* erasure=core::int, declared=! */ #this = _x; + return #this; +} +static extension-type-member method Foo|constructor#_#_#tearOff(core::int _x) → self::Foo% /* erasure=core::int, declared=! */ + return self::Foo|constructor#_(_x); +static extension-type-member method Foo|constructor#(core::int _x, core::int bar) → self::Foo% /* erasure=core::int, declared=! */ { + lowered final self::Foo% /* erasure=core::int, declared=! */ #this = _x; + { + @invalid-expression "pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. + @bar + ^" core::int a1; + @invalid-expression "pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. + @bar + ^" core::int a2; + } + return #this; +} +static extension-type-member method Foo|constructor#_#new#tearOff(core::int _x, core::int bar) → self::Foo% /* erasure=core::int, declared=! */ + return self::Foo|constructor#(_x, bar); diff --git a/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.modular.expect b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.modular.expect new file mode 100644 index 000000000000..0c2024fa02d2 --- /dev/null +++ b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.modular.expect @@ -0,0 +1,42 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: Not a constant expression. +// @bar +// ^^^ +// +// pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. +// @bar +// ^ +// +import self as self; +import "dart:core" as core; + +extension type Foo(core::int _x) { + abstract extension-type-member representation-field get _x() → core::int; + constructor _ = self::Foo|constructor#_; + constructor tearoff _ = self::Foo|constructor#_#_#tearOff; + constructor • = self::Foo|constructor#; + constructor tearoff • = self::Foo|constructor#_#new#tearOff; +} +static extension-type-member method Foo|constructor#_(core::int _x) → self::Foo% /* erasure=core::int, declared=! */ { + lowered final self::Foo% /* erasure=core::int, declared=! */ #this = _x; + return #this; +} +static extension-type-member method Foo|constructor#_#_#tearOff(core::int _x) → self::Foo% /* erasure=core::int, declared=! */ + return self::Foo|constructor#_(_x); +static extension-type-member method Foo|constructor#(core::int _x, core::int bar) → self::Foo% /* erasure=core::int, declared=! */ { + lowered final self::Foo% /* erasure=core::int, declared=! */ #this = _x; + { + @invalid-expression "pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. + @bar + ^" core::int a1; + @invalid-expression "pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. + @bar + ^" core::int a2; + } + return #this; +} +static extension-type-member method Foo|constructor#_#new#tearOff(core::int _x, core::int bar) → self::Foo% /* erasure=core::int, declared=! */ + return self::Foo|constructor#(_x, bar); diff --git a/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.outline.expect b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.outline.expect new file mode 100644 index 000000000000..35cd20372de4 --- /dev/null +++ b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.outline.expect @@ -0,0 +1,19 @@ +library; +import self as self; +import "dart:core" as core; + +extension type Foo(core::int _x) { + abstract extension-type-member representation-field get _x() → core::int; + constructor _ = self::Foo|constructor#_; + constructor tearoff _ = self::Foo|constructor#_#_#tearOff; + constructor • = self::Foo|constructor#; + constructor tearoff • = self::Foo|constructor#_#new#tearOff; +} +static extension-type-member method Foo|constructor#_(core::int _x) → self::Foo% /* erasure=core::int, declared=! */ + ; +static extension-type-member method Foo|constructor#_#_#tearOff(core::int _x) → self::Foo% /* erasure=core::int, declared=! */ + return self::Foo|constructor#_(_x); +static extension-type-member method Foo|constructor#(core::int _x, core::int bar) → self::Foo% /* erasure=core::int, declared=! */ + ; +static extension-type-member method Foo|constructor#_#new#tearOff(core::int _x, core::int bar) → self::Foo% /* erasure=core::int, declared=! */ + return self::Foo|constructor#(_x, bar); diff --git a/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.transformed.expect new file mode 100644 index 000000000000..0c2024fa02d2 --- /dev/null +++ b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.strong.transformed.expect @@ -0,0 +1,42 @@ +library; +// +// Problems in library: +// +// pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: Not a constant expression. +// @bar +// ^^^ +// +// pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. +// @bar +// ^ +// +import self as self; +import "dart:core" as core; + +extension type Foo(core::int _x) { + abstract extension-type-member representation-field get _x() → core::int; + constructor _ = self::Foo|constructor#_; + constructor tearoff _ = self::Foo|constructor#_#_#tearOff; + constructor • = self::Foo|constructor#; + constructor tearoff • = self::Foo|constructor#_#new#tearOff; +} +static extension-type-member method Foo|constructor#_(core::int _x) → self::Foo% /* erasure=core::int, declared=! */ { + lowered final self::Foo% /* erasure=core::int, declared=! */ #this = _x; + return #this; +} +static extension-type-member method Foo|constructor#_#_#tearOff(core::int _x) → self::Foo% /* erasure=core::int, declared=! */ + return self::Foo|constructor#_(_x); +static extension-type-member method Foo|constructor#(core::int _x, core::int bar) → self::Foo% /* erasure=core::int, declared=! */ { + lowered final self::Foo% /* erasure=core::int, declared=! */ #this = _x; + { + @invalid-expression "pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. + @bar + ^" core::int a1; + @invalid-expression "pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart:7:6: Error: This can't be used as an annotation; an annotation should be a reference to a compile-time constant variable, or a call to a constant constructor. + @bar + ^" core::int a2; + } + return #this; +} +static extension-type-member method Foo|constructor#_#new#tearOff(core::int _x, core::int bar) → self::Foo% /* erasure=core::int, declared=! */ + return self::Foo|constructor#(_x, bar); diff --git a/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.textual_outline.expect b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.textual_outline.expect new file mode 100644 index 000000000000..05cec89e4fdf --- /dev/null +++ b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.textual_outline.expect @@ -0,0 +1,3 @@ +extension type Foo._(int _x) { + Foo(this._x, int bar) {} +} diff --git a/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.textual_outline_modelled.expect new file mode 100644 index 000000000000..05cec89e4fdf --- /dev/null +++ b/pkg/front_end/testcases/regress/extension_type_metadata_references_variable.dart.textual_outline_modelled.expect @@ -0,0 +1,3 @@ +extension type Foo._(int _x) { + Foo(this._x, int bar) {} +}