From 7bf88af303409837dcd8aef3c9d67ef56178c605 Mon Sep 17 00:00:00 2001 From: "Sergey G. Grekhov" Date: Mon, 4 Sep 2023 14:54:49 +0300 Subject: [PATCH] #2145. Add more local variable declaration tests (#2254) Rename Local Variable declaration tests. Delete duplicates. --- .../declared_type_A01_t01.dart | 28 +++++++++ .../declared_type_A02_t01.dart | 27 ++++++-- .../declared_type_A02_t02.dart | 39 ++++++++++-- .../declared_type_A03_t01.dart | 59 +++++++++++++++++ .../declared_type_A03_t02.dart | 63 +++++++++++++++++++ .../declared_type_A04_t01.dart | 43 +++++++++++++ .../declared_type_A04_t02.dart | 30 +++++++++ .../late_await_A01_t01.dart | 41 ++++++++++++ .../late_await_A01_t02.dart | 33 ++++++++++ .../late_final_A01_t01.dart | 31 +++++++++ .../late_final_A01_t02.dart | 35 +++++++++++ .../reference_error_A01_t02.dart | 40 ++++++++++++ .../reference_error_A01_t03.dart | 35 +++++++++++ 13 files changed, 495 insertions(+), 9 deletions(-) create mode 100644 Language/Statements/Local_Variable_Declaration/declared_type_A01_t01.dart create mode 100644 Language/Statements/Local_Variable_Declaration/declared_type_A03_t01.dart create mode 100644 Language/Statements/Local_Variable_Declaration/declared_type_A03_t02.dart create mode 100644 Language/Statements/Local_Variable_Declaration/declared_type_A04_t01.dart create mode 100644 Language/Statements/Local_Variable_Declaration/declared_type_A04_t02.dart create mode 100644 Language/Statements/Local_Variable_Declaration/late_await_A01_t01.dart create mode 100644 Language/Statements/Local_Variable_Declaration/late_await_A01_t02.dart create mode 100644 Language/Statements/Local_Variable_Declaration/late_final_A01_t01.dart create mode 100644 Language/Statements/Local_Variable_Declaration/late_final_A01_t02.dart create mode 100644 Language/Statements/Local_Variable_Declaration/reference_error_A01_t02.dart create mode 100644 Language/Statements/Local_Variable_Declaration/reference_error_A01_t03.dart diff --git a/Language/Statements/Local_Variable_Declaration/declared_type_A01_t01.dart b/Language/Statements/Local_Variable_Declaration/declared_type_A01_t01.dart new file mode 100644 index 0000000000..6882688ed7 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/declared_type_A01_t01.dart @@ -0,0 +1,28 @@ +// Copyright (c) 2023, 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. + +/// @assertion The declared type of a local variable with a declaration of one +/// of the forms +/// late? T v = e; late? final T v = e; const T v = e; is T +/// +/// @description Checks that the declared type of a local variable with the +/// specified type `T` is `T` +/// @author sgrekhov22@gmail.com + +import '../../../Utils/static_type_helper.dart'; + +main() { + // We use `as dynamic` below to avoid a type promotion on an assignment + late num v1 = 1 as dynamic; + late final num v2 = 2 as dynamic; + num v3 = 3 as dynamic; + final num? v4 = 4 as dynamic; + const num v5 = 5 as dynamic; + + v1.expectStaticType>(); + v2.expectStaticType>(); + v3.expectStaticType>(); + v4.expectStaticType>(); + v5.expectStaticType>(); +} diff --git a/Language/Statements/Local_Variable_Declaration/declared_type_A02_t01.dart b/Language/Statements/Local_Variable_Declaration/declared_type_A02_t01.dart index f8f66dd17b..af5b60b832 100644 --- a/Language/Statements/Local_Variable_Declaration/declared_type_A02_t01.dart +++ b/Language/Statements/Local_Variable_Declaration/declared_type_A02_t01.dart @@ -7,16 +7,16 @@ /// as follows: /// • If the static type of e is Null then the declared type of v is dynamic. /// -/// @description Checks that a variable declaration statement `var id;` -/// introduces a new variable `id` with `dynamic` static type into the innermost -/// enclosing scope. +/// @description Checks that the variable declaration statements +/// `late? var v = e; late? final v = e; const v = e;` introduce a new variable +/// `v` with `dynamic` static type into the innermost enclosing scope. /// @author vasya import '../../../Utils/expect.dart'; class C {} -main() { +test1() { var id; Expect.throws(() { id.whatever; @@ -24,6 +24,23 @@ main() { id = false; id = ""; id = 2; - id = new C(); + id = C(); id = () {}; } + +test2() { + late var id; + Expect.throws(() { + id.whatever; + }); + id = false; + id = ""; + id = 2; + id = C(); + id = () {}; +} + +main() { + test1(); + test2(); +} diff --git a/Language/Statements/Local_Variable_Declaration/declared_type_A02_t02.dart b/Language/Statements/Local_Variable_Declaration/declared_type_A02_t02.dart index 39c6fccb1a..0524a77033 100644 --- a/Language/Statements/Local_Variable_Declaration/declared_type_A02_t02.dart +++ b/Language/Statements/Local_Variable_Declaration/declared_type_A02_t02.dart @@ -7,16 +7,16 @@ /// as follows: /// • If the static type of e is Null then the declared type of v is dynamic. /// -/// @description Checks that a variable declaration statement `var id = null;` -/// introduces a new variable `id` with `dynamic` static type into the innermost -/// enclosing scope. +/// @description Checks that the variable declaration statements +/// `late? var v = null; late? final v = null; const v = null;` introduce a new +/// variable `v` with `dynamic` static type into the innermost enclosing scope. /// @author vasya import '../../../Utils/expect.dart'; class C {} -main() { +test1() { var id = null; Expect.throws(() { id.whatever; @@ -27,3 +27,34 @@ main() { id = new C(); id = () {}; } + +test2() { + late var id = null; + Expect.throws(() { + id.whatever; + }); + id = false; + id = ""; + id = 2; + id = new C(); + id = () {}; +} + +main() { + late final v1 = null; + final v2 = null; + const v3 = null; + + Expect.throws(() { + v1.whatever; + }); + Expect.throws(() { + v2.whatever; + }); + Expect.throws(() { + v3.whatever; + }); + + test1(); + test2(); +} diff --git a/Language/Statements/Local_Variable_Declaration/declared_type_A03_t01.dart b/Language/Statements/Local_Variable_Declaration/declared_type_A03_t01.dart new file mode 100644 index 0000000000..b4fe8ca816 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/declared_type_A03_t01.dart @@ -0,0 +1,59 @@ +// Copyright (c) 2023, 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. + +/// @assertion The declared type of a local variable with a declaration of one +/// of the forms late? var v = e; late? final v = e; const v = e; is determined +/// as follows: +/// ... +/// • If the static type of e is of the form X & T where X is a type variable, +/// the declared type of v is X. In this case v is immediately promoted to X & T +/// +/// @description Checks that the static type of a variable declared by the +/// statements `late? var v = e; late? final v = e;` is `X` if the static type +/// of `e` is `X & T` where `X` is a type variable. Also test that `v` is +/// promoted to `X & T` +/// @author sgrekhov22@gmail.com + +import '../../../Utils/static_type_helper.dart'; + +test1(T t) { + if (t is int) { + var v = t; + v.isEven; + T x = v; + v = x; + } +} + +test2(T t) { + if (t is int) { + late var v = t; + v.isEven; + T x = v; + v = x; + } +} + +test3(T t) { + if (t is int) { + final v = t; + v.isEven; + T x = v; + } +} + +test4(T t) { + if (t is int) { + late final v = t; + v.isEven; + T x = v; + } +} + +main() { + test1(1); + test2(2); + test3(3); + test4(4); +} diff --git a/Language/Statements/Local_Variable_Declaration/declared_type_A03_t02.dart b/Language/Statements/Local_Variable_Declaration/declared_type_A03_t02.dart new file mode 100644 index 0000000000..d3f836c4e7 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/declared_type_A03_t02.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2023, 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. + +/// @assertion The declared type of a local variable with a declaration of one +/// of the forms late? var v = e; late? final v = e; const v = e; is determined +/// as follows: +/// ... +/// • If the static type of e is of the form X & T where X is a type variable, +/// the declared type of v is X. In this case v is immediately promoted to X & T +/// +/// @description Checks that the static type of a variable declared by the +/// statements `late? var v = e; late? final v = e;` is `X` if the static type +/// of `e` is where `X` is a type variable. Also check that `v` is not +/// erroneously promoted +/// @author sgrekhov22@gmail.com + +test1(T t) { + if (t is int) { + } + var v = t; + v.isEven; +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +test2(T t) { + if (t is int) { + } + late var v = t; + v.isEven; +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +test3(T t) { + if (t is int) { + } + final v = t; + v.isEven; +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +test4(T t) { + if (t is int) { + } + late final v = t; + v.isEven; +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + test1(1); + test2(2); + test3(3); + test4(4); +} diff --git a/Language/Statements/Local_Variable_Declaration/declared_type_A04_t01.dart b/Language/Statements/Local_Variable_Declaration/declared_type_A04_t01.dart new file mode 100644 index 0000000000..55959c33f0 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/declared_type_A04_t01.dart @@ -0,0 +1,43 @@ +// Copyright (c) 2023, 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. + +/// @assertion The declared type of a local variable with a declaration of one +/// of the forms late? var v = e; late? final v = e; const v = e; is determined +/// as follows: +/// ... +/// • Otherwise, the declared type of v is the static type of e. +/// +/// @description Checks that static type of a variable declared by the +/// statements `late? var v = e; late? final v = e; const v = e;` is the static +/// type of `e` +/// @author sgrekhov22@gmail.com + +import '../../../Utils/static_type_helper.dart'; + +test(T t) { + if (t is int) { + late final v = t; + v.isEven; + T x = v; + } +} + +main() { + late var v1 = "1"; + v1.expectStaticType>(); + + var v2 = 2; + v2.expectStaticType>(); + + late final v3 = 3 as num; + v3.expectStaticType>(); + + final v4 = 4 as int?; + v4.expectStaticType>(); + + const v5 = 5 as num?; + v5.expectStaticType>(); + + test(42); +} diff --git a/Language/Statements/Local_Variable_Declaration/declared_type_A04_t02.dart b/Language/Statements/Local_Variable_Declaration/declared_type_A04_t02.dart new file mode 100644 index 0000000000..1d97f58167 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/declared_type_A04_t02.dart @@ -0,0 +1,30 @@ +// Copyright (c) 2023, 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. + +/// @assertion The declared type of a local variable with a declaration of one +/// of the forms late? var v = e; late? final v = e; const v = e; is determined +/// as follows: +/// ... +/// • Otherwise, the declared type of v is the static type of e. +/// +/// @description Checks that the static type of a variable declared by the +/// statements `late? var v = e; late? final v = e; const v = e;` is the static +/// type of `e`. Check that `v` is not erroneously promoted +/// @author sgrekhov22@gmail.com + +import '../../../Utils/static_type_helper.dart'; + +test(T t) { + if (t is int) { + } + late final v = t; + v.isEven; +// ^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + test(3.14); +} diff --git a/Language/Statements/Local_Variable_Declaration/late_await_A01_t01.dart b/Language/Statements/Local_Variable_Declaration/late_await_A01_t01.dart new file mode 100644 index 0000000000..05fe8bc966 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/late_await_A01_t01.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2023, 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. + +/// @assertion Assume that D is a local variable declaration with the modifier +/// late that declares a variable v, which has an initializing expression e. It +/// is a compile-time error if e contains an await expression a, unless there is +/// a function f which is the immediately enclosing function for a, and f is not +/// the immediately enclosing function for D. +/// +/// @description Checks that it is a compile-time error if initializing +/// expression of a late local variable contains an `await` expression +/// @author sgrekhov22@gmail.com + +import 'dart:async'; + +Future foo(T t) => Future.value(t); + +main() async { + late var v1 = await Future.value(1); +// ^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + + late final v2 = await foo(2); +// ^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + + late String v3 = await foo("3"); +// ^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + + late final int v4 = await Future.value(4); +// ^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + + return 0; +} diff --git a/Language/Statements/Local_Variable_Declaration/late_await_A01_t02.dart b/Language/Statements/Local_Variable_Declaration/late_await_A01_t02.dart new file mode 100644 index 0000000000..aba2b34565 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/late_await_A01_t02.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2023, 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. + +/// @assertion Assume that D is a local variable declaration with the modifier +/// late that declares a variable v, which has an initializing expression e. It +/// is a compile-time error if e contains an await expression a, unless there is +/// a function f which is the immediately enclosing function for a, and f is not +/// the immediately enclosing function for D. +/// +/// @description Checks that it is not an error if there is a function `f` which +/// is the immediately enclosing function for `a`, and `f` is not the +/// immediately enclosing function for `D` +/// @author sgrekhov22@gmail.com + +import 'dart:async'; +import '../../../Utils/static_type_helper.dart'; + +Future foo(T t) => Future.value(t); + +main() { + late var v1 = () async => await Future.value(1); + v1.expectStaticType Function()>>(); + + late final v2 = () async {return await foo(2);}; + v2.expectStaticType Function()>>(); + + late Future v3 = () async {return await foo("3");}(); + print(v3); + + late final Future Function() v4 = () async => await Future.value(4); + print(v4); +} diff --git a/Language/Statements/Local_Variable_Declaration/late_final_A01_t01.dart b/Language/Statements/Local_Variable_Declaration/late_final_A01_t01.dart new file mode 100644 index 0000000000..06e4eeacd5 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/late_final_A01_t01.dart @@ -0,0 +1,31 @@ +// Copyright (c) 2023, 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. + +/// @assertion Let D be a late and final local variable declaration that +/// declares a variable v. If an object o is assigned to v in a situation where +/// v is unbound then v is bound to o. If an object o is assigned to v in a +/// situation where v is bound to an object o′ then a dynamic error occurs (it +/// does not matter whether o is the same object as o′). +/// +/// @description Checks that if an object `o` is assigned to a late final local +/// variable `v` in a situation where `v` is unbound then `v` is bound to `o` +/// @author sgrekhov22@gmail.com + +import '../../../Utils/expect.dart'; + +class C { + int id; + C(this.id); +} + +main() { + C c1 = C(1); + late final v1 = c1; + Expect.identical(c1, v1); + + C c2 = C(2); + late final v2; + v2 = c2; + Expect.identical(c2, v2); +} diff --git a/Language/Statements/Local_Variable_Declaration/late_final_A01_t02.dart b/Language/Statements/Local_Variable_Declaration/late_final_A01_t02.dart new file mode 100644 index 0000000000..fb760665f2 --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/late_final_A01_t02.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2023, 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. + +/// @assertion Let D be a late and final local variable declaration that +/// declares a variable v. If an object o is assigned to v in a situation where +/// v is unbound then v is bound to o. If an object o is assigned to v in a +/// situation where v is bound to an object o′ then a dynamic error occurs (it +/// does not matter whether o is the same object as o′). +/// +/// @description Checks that it is a dynamic error if an object `o` is assigned +/// to a late final local variable `v` in a situation where `v` is bound to some +/// object +/// @author sgrekhov22@gmail.com + +import '../../../Utils/expect.dart'; + +class C { + int id; + C(this.id); +} + +main() { + C c = C(1); + late final v; + if (2 > 1) { + v = c; + } + Expect.throws(() { + v = C(42); + }); + Expect.throws(() { + v = c; + }); +} diff --git a/Language/Statements/Local_Variable_Declaration/reference_error_A01_t02.dart b/Language/Statements/Local_Variable_Declaration/reference_error_A01_t02.dart new file mode 100644 index 0000000000..f34e5309bc --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/reference_error_A01_t02.dart @@ -0,0 +1,40 @@ +// Copyright (c) 2023 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. + +/// @assertion It is a compile-time error if a local variable is referenced at a +/// source code location that is before the end of its initializing expression, +/// if any, and otherwise before the declaring occurrence of the identifier +/// which names the variable. +/// +/// @description Checks that a variable is introduced into the scope and the +/// name of this variable cannot be used in its initialization. +/// @author sgrekhov22@gmail.com + +var x = 0; + +f(y) { + var z = x; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + if (y) { + x = x + 1; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + print(x); +// ^ +// [analyzer] unspecified +// [cfe] unspecified + } + var x = x++; +// ^ +// [analyzer] unspecified +// [cfe] unspecified + print(x); +} + +main() { + f(true); +} diff --git a/Language/Statements/Local_Variable_Declaration/reference_error_A01_t03.dart b/Language/Statements/Local_Variable_Declaration/reference_error_A01_t03.dart new file mode 100644 index 0000000000..32cd6987de --- /dev/null +++ b/Language/Statements/Local_Variable_Declaration/reference_error_A01_t03.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2023 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. + +/// @assertion It is a compile-time error if a local variable is referenced at a +/// source code location that is before the end of its initializing expression, +/// if any, and otherwise before the declaring occurrence of the identifier +/// which names the variable. +/// +/// @description Checks that it is not an error if a local variable is +/// referenced at a source code location that is after the end of its +/// initializing expression +/// @author sgrekhov22@gmail.com + +import '../../../Utils/expect.dart'; + +main() { + var x1 = 1, y1 = x1; + int x2 = 2, y2 = x2; + final x3 = 3, y3 = x3; + final int x4 = 4, y4 = x4; + late final int x5 = 5, y5 = x5; + late int x6 = 6, y6 = x6; + late final x7 = 7, y7 = x7; + late var x8 = 8, y8 = x8; + + Expect.equals(1, y1); + Expect.equals(2, y2); + Expect.equals(3, y3); + Expect.equals(4, y4); + Expect.equals(5, y5); + Expect.equals(6, y6); + Expect.equals(7, y7); + Expect.equals(8, y8); +}