From 7481d41941d4f5430c8a87398e2461c7957c0083 Mon Sep 17 00:00:00 2001 From: Kallen Tu Date: Mon, 23 Mar 2026 13:59:04 -0700 Subject: [PATCH] [tests] Primary constructors - Add const initializer and body tests. Tests for the spec change in https://github.com/dart-lang/language/pull/4655. - An identifier expression denoting a parameter of a constant primary constructor that occurs in the initializer list of the body part of the primary constructor, or in an initializing expression of a non-late instance variable declaration, is potentially constant. - A compile-time error occurs if a class, mixin class, enum, or extension type declaration has a constant generative constructor, and a non-late instance variable declaration in the body of the declaration has an initializing expression which is not potentially constant. - A compile-time error also occurs if the body of a declaration contains a body part for the primary constructor, and it has an initializer list, and the initializer list contains an expression which is not potentially constant. - A compile-time error occurs if the result of substituting actual arguments of the constructor invocation into one of the above mentioned initializing expressions or initializer list elements yields an expression which is not constant. Bug: https://github.com/dart-lang/sdk/issues/61687 Change-Id: I8f9d5d49ab48f6cd07ad005b9483e21ef190f324 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/489543 Commit-Queue: Kallen Tu Reviewed-by: Erik Ernst --- .../potentially_constant_error_test.dart | 71 +++++++++++++++++++ .../const/potentially_constant_test.dart | 56 +++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 tests/language/primary_constructors/const/potentially_constant_error_test.dart create mode 100644 tests/language/primary_constructors/const/potentially_constant_test.dart diff --git a/tests/language/primary_constructors/const/potentially_constant_error_test.dart b/tests/language/primary_constructors/const/potentially_constant_error_test.dart new file mode 100644 index 00000000000..96acfc33363 --- /dev/null +++ b/tests/language/primary_constructors/const/potentially_constant_error_test.dart @@ -0,0 +1,71 @@ +// Copyright (c) 2026, 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. + +// A compile-time error occurs if a class, mixin class, enum, or extension type +// declaration has a constant generative constructor, and a non-late instance +// variable declaration in the body of the declaration has an initializing +// expression which is not potentially constant. +// +// A compile-time error also occurs if the body of a declaration contains a +// body part for the primary constructor, and it has an initializer list, and +// the initializer list contains an expression which is not potentially +// constant. + +// SharedOptions=--enable-experiment=primary-constructors + +int fn(int x) => x; + +class const C(int p) { +// ^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST + // TODO(cfe): Avoid having multiple errors here and make sure the error + // message is accurate. i.e. "Not a potentially constant expression." + final int x = fn(p); + // ^ + // [cfe] unspecified +} + +class const C2(int p) { + final int y; + this : y = fn(p); + // ^^^^^ + // [analyzer] COMPILE_TIME_ERROR.INVALID_CONSTANT + // [cfe] Method invocation is not a constant expression. +} + +enum const E(int p) { +// ^^^^^ +// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST + e(1); + + final int x = fn(p); + // ^^^^^ + // [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_METHOD_INVOCATION + // [cfe] Static invocation is not a constant expression. +} + +extension type const Ext(int p) { + this : assert(fn(p) > 0); + // ^^^^^ + // [analyzer] COMPILE_TIME_ERROR.INVALID_CONSTANT + // [cfe] Method invocation is not a constant expression. +} + +// A compile-time error occurs if the result of substituting actual arguments of +// the constructor invocation into one of the above mentioned initializing +// expressions or initializer list elements yields an expression which is not +// constant. + +class const A(dynamic d) { + // TODO(cfe): Avoid having multiple errors here and make sure the error + // message is accurate. i.e. "Not a potentially constant expression." + final int i = d.length; + // ^^^^^^^^ + // [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_PROPERTY_ACCESS + // [cfe] unspecified +} + +void main() { + const A([]); // Error because `[].length` isn't constant. +} diff --git a/tests/language/primary_constructors/const/potentially_constant_test.dart b/tests/language/primary_constructors/const/potentially_constant_test.dart new file mode 100644 index 00000000000..17eab9e0540 --- /dev/null +++ b/tests/language/primary_constructors/const/potentially_constant_test.dart @@ -0,0 +1,56 @@ +// Copyright (c) 2026, 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. + +// An identifier expression denoting a parameter of a constant primary +// constructor that occurs in the initializer list of the body part of the +// primary constructor, or in an initializing expression of a non-late instance +// variable declaration, is potentially constant. + +// SharedOptions=--enable-experiment=primary-constructors + +import 'package:expect/expect.dart'; + +class const A(dynamic d) { + final int i = d.length; +} + +class const C(int p) { + final int x = p; + final int y; + this : y = p; +} + +enum const E(int p) { + e(1); + + final int x = p; + final int y; + this : y = p; +} + +extension type const Ext(int p) { + this : assert(p > 0); +} + +void main() { + const A(''); + + const c = C(1); + Expect.equals(1, c.x); + Expect.equals(1, c.y); + + var c2 = C(2); + Expect.equals(2, c2.x); + Expect.equals(2, c2.y); + + const e = E.e; + Expect.equals(1, e.x); + Expect.equals(1, e.y); + + const ext = Ext(1); + Expect.equals(1, ext.p); + + var ext2 = Ext(2); + Expect.equals(2, ext2.p); +}