From 311a09a24b2b5a7b6d9df6d3428227e9c5747aea Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Wed, 19 Jul 2023 13:12:51 +0300 Subject: [PATCH 1/4] #2139. Add generator functions element type tests --- Language/Functions/element_type_A01_t01.dart | 56 +++++++++++++++++++ Language/Functions/element_type_A02_t01.dart | 57 ++++++++++++++++++++ Language/Functions/element_type_A03_t01.dart | 54 +++++++++++++++++++ Language/Functions/element_type_A03_t02.dart | 54 +++++++++++++++++++ 4 files changed, 221 insertions(+) create mode 100644 Language/Functions/element_type_A01_t01.dart create mode 100644 Language/Functions/element_type_A02_t01.dart create mode 100644 Language/Functions/element_type_A03_t01.dart create mode 100644 Language/Functions/element_type_A03_t02.dart diff --git a/Language/Functions/element_type_A01_t01.dart b/Language/Functions/element_type_A01_t01.dart new file mode 100644 index 0000000000..f453a4f53a --- /dev/null +++ b/Language/Functions/element_type_A01_t01.dart @@ -0,0 +1,56 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. If `f` is +/// a synchronous generator and `S` implements `Iterable` for some `U` then +/// the element type of `f` is `U`. +/// +/// @description Check that element type of a synchronous generator function `f` +/// is `U`, where `S` is a union-free type of the declared return type of `f` +/// and `S` implements `Iterable` +/// @author sgrekhov22@gmail.com + +import "dart:async"; + +Iterable? f1() sync* { + yield 1; + yield 3.14; + yield null; // Ok, element type is `num?` +} + +Iterable? f2() sync* { + yield 1; + yield null; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +FutureOr?> f3() sync* { + yield 1; + yield null; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + yield Future.value(null); +// ^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + yield Future.value(1); +// ^^^^^^^^^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + f1(); + f2(); + f3(); +} diff --git a/Language/Functions/element_type_A02_t01.dart b/Language/Functions/element_type_A02_t01.dart new file mode 100644 index 0000000000..4edbfa35e3 --- /dev/null +++ b/Language/Functions/element_type_A02_t01.dart @@ -0,0 +1,57 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. +/// ... +/// If `f` is an asynchronous generator and `S` implements `Stream` for some +/// `U` then the element type of `f` is `U`. +/// +/// @description Check that element type of an asynchronous generator function +/// `f` is `U`, where `S` is a union-free type of the declared return type of +/// `f` and `S` implements `Stream` +/// @author sgrekhov22@gmail.com + +import "dart:async"; + +Stream? f1() async* { + yield 1; + yield 3.14; + yield null; // Ok, element type is `num?` +} + +Stream? f2() async* { + yield 1; + yield null; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +FutureOr?> f3() async* { + yield 1; + yield null; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + yield Future.value(null); +// ^^^^^^^^^^^^^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified + yield Future.value(1); +// ^^^^^^^^^^^^^^^^^^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + f1(); + f2(); + f3(); +} diff --git a/Language/Functions/element_type_A03_t01.dart b/Language/Functions/element_type_A03_t01.dart new file mode 100644 index 0000000000..49ba5052a3 --- /dev/null +++ b/Language/Functions/element_type_A03_t01.dart @@ -0,0 +1,54 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. +/// ... +/// Otherwise, if `f` is a generator (synchronous or asynchronous) and `S` is a +/// supertype of `Object` then the element type of `f` is dynamic +/// +/// @description Check that element type of a synchronous generator function `f` +/// is `dynamic`, if `S` is a union-free type of the declared return type of `f` +/// and `S` is a supertype of `Object` +/// @author sgrekhov22@gmail.com + +import "dart:async"; + +Object? f1() sync* { + yield 1; + yield 3.14; + yield null; + yield "42"; +} + +Object f2() sync* { + yield 1; + yield null; +} + +FutureOr f3() sync* { + yield 1; + yield null; + yield Future.value(null); + yield Future.value(1); +} + +FutureOr? f4() sync* { + yield 1; + yield null; + yield Future.value(null); + yield Future.value(1); +} + +main() { + f1(); + f2(); + f3(); + f4(); +} diff --git a/Language/Functions/element_type_A03_t02.dart b/Language/Functions/element_type_A03_t02.dart new file mode 100644 index 0000000000..745894a009 --- /dev/null +++ b/Language/Functions/element_type_A03_t02.dart @@ -0,0 +1,54 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. +/// ... +/// Otherwise, if `f` is a generator (synchronous or asynchronous) and `S` is a +/// supertype of Object then the element type of `f` is dynamic +/// +/// @description Check that element type of an asynchronous generator function +/// `f` is `dynamic`, if `S` is a union-free type of the declared return type of +/// `f` and `S` is a supertype of `Object` +/// @author sgrekhov22@gmail.com + +import "dart:async"; + +Object? f1() sync* { + yield 1; + yield 3.14; + yield null; + yield "42"; +} + +Object f2() sync* { + yield 1; + yield null; +} + +FutureOr f3() sync* { + yield 1; + yield null; + yield Future.value(null); + yield Future.value(1); +} + +FutureOr? f4() sync* { + yield 1; + yield null; + yield Future.value(null); + yield Future.value(1); +} + +main() { + f1(); + f2(); + f3(); + f4(); +} From 19ffe8d7277d3b182aa4da91ad73ba25193c7cf3 Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Thu, 27 Jul 2023 14:44:38 +0300 Subject: [PATCH 2/4] Add more generator functions tests --- Language/Functions/element_type_A01_t01.dart | 6 +- Language/Functions/element_type_A01_t02.dart | 49 ++++++++++++++++ Language/Functions/element_type_A01_t03.dart | 30 ++++++++++ Language/Functions/element_type_A01_t04.dart | 41 +++++++++++++ Language/Functions/element_type_A01_t05.dart | 50 ++++++++++++++++ Language/Functions/element_type_A01_t06.dart | 51 ++++++++++++++++ Language/Functions/element_type_A02_t01.dart | 6 +- Language/Functions/element_type_A02_t02.dart | 50 ++++++++++++++++ Language/Functions/element_type_A02_t03.dart | 32 ++++++++++ Language/Functions/element_type_A02_t04.dart | 42 ++++++++++++++ Language/Functions/element_type_A02_t05.dart | 53 +++++++++++++++++ Language/Functions/element_type_A02_t06.dart | 57 ++++++++++++++++++ Language/Functions/element_type_A03_t01.dart | 34 +++++++++-- Language/Functions/element_type_A03_t02.dart | 58 +++++++++++++++---- .../Functions/generator_return_type_t01.dart | 4 +- .../Functions/generator_return_type_t02.dart | 4 +- .../Functions/generator_return_type_t05.dart | 4 +- .../Functions/generator_return_type_t06.dart | 4 +- Utils/expect_common.dart | 38 ++++++++++++ .../iterableElementRuntimeIsNot_A01_t01.dart | 47 +++++++++++++++ .../iterableElementRuntimeIs_A01_t01.dart | 51 ++++++++++++++++ .../iterableElementRuntimeIs_A01_t02.dart | 30 ++++++++++ 22 files changed, 713 insertions(+), 28 deletions(-) create mode 100644 Language/Functions/element_type_A01_t02.dart create mode 100644 Language/Functions/element_type_A01_t03.dart create mode 100644 Language/Functions/element_type_A01_t04.dart create mode 100644 Language/Functions/element_type_A01_t05.dart create mode 100644 Language/Functions/element_type_A01_t06.dart create mode 100644 Language/Functions/element_type_A02_t02.dart create mode 100644 Language/Functions/element_type_A02_t03.dart create mode 100644 Language/Functions/element_type_A02_t04.dart create mode 100644 Language/Functions/element_type_A02_t05.dart create mode 100644 Language/Functions/element_type_A02_t06.dart create mode 100644 Utils/tests/Expect/iterableElementRuntimeIsNot_A01_t01.dart create mode 100644 Utils/tests/Expect/iterableElementRuntimeIs_A01_t01.dart create mode 100644 Utils/tests/Expect/iterableElementRuntimeIs_A01_t02.dart diff --git a/Language/Functions/element_type_A01_t01.dart b/Language/Functions/element_type_A01_t01.dart index f453a4f53a..14f987fb3f 100644 --- a/Language/Functions/element_type_A01_t01.dart +++ b/Language/Functions/element_type_A01_t01.dart @@ -12,9 +12,9 @@ /// a synchronous generator and `S` implements `Iterable` for some `U` then /// the element type of `f` is `U`. /// -/// @description Check that element type of a synchronous generator function `f` -/// is `U`, where `S` is a union-free type of the declared return type of `f` -/// and `S` implements `Iterable` +/// @description Check that it is a compile-time error if an element type of a +/// synchronous generator function `f` is not `U`, where `S` is a union-free +/// type of the declared return type of `f` and `S` implements `Iterable` /// @author sgrekhov22@gmail.com import "dart:async"; diff --git a/Language/Functions/element_type_A01_t02.dart b/Language/Functions/element_type_A01_t02.dart new file mode 100644 index 0000000000..c5c071126e --- /dev/null +++ b/Language/Functions/element_type_A01_t02.dart @@ -0,0 +1,49 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. If `f` is +/// a synchronous generator and `S` implements `Iterable` for some `U` then +/// the element type of `f` is `U`. +/// +/// @description Check that it is a compile-time error if an element type of a +/// synchronous generator function `f` is not `U`, where `S` is a union-free +/// type of the declared return type of `f` and `S` implements `Iterable` +/// @author sgrekhov22@gmail.com + +import "dart:async"; + +Iterable? f1() sync* { + yield 1; + yield 3.14; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + yield "2"; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +FutureOr?> f2() sync* { + yield 1; + yield 3.14; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + yield "2"; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + f1(); + f2(); +} diff --git a/Language/Functions/element_type_A01_t03.dart b/Language/Functions/element_type_A01_t03.dart new file mode 100644 index 0000000000..0963d2033a --- /dev/null +++ b/Language/Functions/element_type_A01_t03.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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. If `f` is +/// a synchronous generator and `S` implements `Iterable` for some `U` then +/// the element type of `f` is `U`. +/// +/// @description Check a run-time type of a return value of a synchronous +/// generator function +/// @author sgrekhov22@gmail.com + +import "dart:async"; + +FutureOr?> foo() sync* { + yield 1; + yield 2; + yield 3; +} + +main() { + FutureOr?> o = foo() as dynamic; + o as FutureOr?>; +} diff --git a/Language/Functions/element_type_A01_t04.dart b/Language/Functions/element_type_A01_t04.dart new file mode 100644 index 0000000000..fd353ac7bd --- /dev/null +++ b/Language/Functions/element_type_A01_t04.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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. If `f` is +/// a synchronous generator and `S` implements `Iterable` for some `U` then +/// the element type of `f` is `U`. +/// +/// @description Check that element type of a synchronous generator function `f` +/// is `U`, where `S` is a union-free type of the declared return type of `f` +/// and `S` implements `Iterable` +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../Utils/expect.dart"; +import "../../Utils/static_type_helper.dart"; + +FutureOr?> foo() sync* { + yield 1; + yield 2; + yield 3; +} + +main() { + var o = foo(); + o.expectStaticType?>>>(); + if (o is Future?>) { + print("No"); + } else if (o == null) { + print("No"); + } else { + o.expectStaticType>>(); + Expect.isTrue(o is Iterable); + } +} diff --git a/Language/Functions/element_type_A01_t05.dart b/Language/Functions/element_type_A01_t05.dart new file mode 100644 index 0000000000..23ca1557d0 --- /dev/null +++ b/Language/Functions/element_type_A01_t05.dart @@ -0,0 +1,50 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. If `f` is +/// a synchronous generator and `S` implements `Iterable` for some `U` then +/// the element type of `f` is `U`. +/// +/// @description Check that runtime type of an element type of a synchronous +/// generator function `f` is `U`, where `S` is a union-free type of the +/// declared return type of `f` and `S` implements `Iterable`. Test the +/// run-time types of objects returned by a synchronous generator function +/// @author sgrekhov22@gmail.com + +import "../../Utils/expect.dart"; + +Iterable? f1() sync* { + yield 1; + yield 2; + yield null; +} + +Iterable? f2() sync* { + yield 1; + yield 2; + yield 3; +} + +main() { + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIs(f1()); + + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIs(f2()); +} diff --git a/Language/Functions/element_type_A01_t06.dart b/Language/Functions/element_type_A01_t06.dart new file mode 100644 index 0000000000..e19dc9f492 --- /dev/null +++ b/Language/Functions/element_type_A01_t06.dart @@ -0,0 +1,51 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. If `f` is +/// a synchronous generator and `S` implements `Iterable` for some `U` then +/// the element type of `f` is `U`. +/// +/// @description Check that runtime type of an element type of a synchronous +/// generator function `f` is `U`, where `S` is a union-free type of the +/// declared return type of `f` and `S` implements `Iterable`. Test the +/// run-time types of objects returned by a synchronous generator function +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../Utils/expect.dart"; + +FutureOr?> f1() sync* { + yield 1; + yield 2; + yield null; +} + +FutureOr?>? f2() sync* { + yield 1; + yield 2; + yield 3; +} + +main() { + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIsNot(f1()); + Expect.iterableElementsRuntimeIs(f1()); + + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIsNot(f2()); + Expect.iterableElementsRuntimeIs(f2()); +} diff --git a/Language/Functions/element_type_A02_t01.dart b/Language/Functions/element_type_A02_t01.dart index 4edbfa35e3..c665aa05bd 100644 --- a/Language/Functions/element_type_A02_t01.dart +++ b/Language/Functions/element_type_A02_t01.dart @@ -13,9 +13,9 @@ /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. /// -/// @description Check that element type of an asynchronous generator function -/// `f` is `U`, where `S` is a union-free type of the declared return type of -/// `f` and `S` implements `Stream` +/// @description Check that it is a compile-time error if an element type of a +/// synchronous generator function `f` is not `U`, where `S` is a union-free +/// type of the declared return type of `f` and `S` implements `Stream` /// @author sgrekhov22@gmail.com import "dart:async"; diff --git a/Language/Functions/element_type_A02_t02.dart b/Language/Functions/element_type_A02_t02.dart new file mode 100644 index 0000000000..8e2b419a3d --- /dev/null +++ b/Language/Functions/element_type_A02_t02.dart @@ -0,0 +1,50 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. +/// ... +/// If `f` is an asynchronous generator and `S` implements `Stream` for some +/// `U` then the element type of `f` is `U`. +/// +/// @description Check that it is a compile-time error if an element type of an +/// asynchronous generator function `f` is not `U`, where `S` is a union-free +/// type of the declared return type of `f` and `S` implements `Stream` +/// @author sgrekhov22@gmail.com + +import "dart:async"; + +Stream? f1() async* { + yield 1; + yield 3.14; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + yield "2"; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +FutureOr?> f2() async* { + yield 1; + yield 3.14; +// ^^^^ +// [analyzer] unspecified +// [cfe] unspecified + yield "2"; +// ^^^ +// [analyzer] unspecified +// [cfe] unspecified +} + +main() { + f1(); + f2(); +} diff --git a/Language/Functions/element_type_A02_t03.dart b/Language/Functions/element_type_A02_t03.dart new file mode 100644 index 0000000000..ed5e9dd4b3 --- /dev/null +++ b/Language/Functions/element_type_A02_t03.dart @@ -0,0 +1,32 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. +/// ... +/// If `f` is an asynchronous generator and `S` implements `Stream` for some +/// `U` then the element type of `f` is `U`. +/// +/// @description Check a run-time type of a returned value of an asynchronous +/// generator function +/// @author sgrekhov22@gmail.com + +import "dart:async"; + +FutureOr?> foo() async* { + yield 1; + yield 2; + yield 3; +} + +main() async { + dynamic d = await foo(); + FutureOr?> o = d; + o as FutureOr?>; +} diff --git a/Language/Functions/element_type_A02_t04.dart b/Language/Functions/element_type_A02_t04.dart new file mode 100644 index 0000000000..9d1aee09a7 --- /dev/null +++ b/Language/Functions/element_type_A02_t04.dart @@ -0,0 +1,42 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. +/// ... +/// If `f` is an asynchronous generator and `S` implements `Stream` for some +/// `U` then the element type of `f` is `U`. +/// +/// @description Check that element type of an asynchronous generator function +/// `f` is `U`, where `S` is a union-free type of the declared return type of +/// `f` and `S` implements `Stream` +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../Utils/expect.dart"; +import "../../Utils/static_type_helper.dart"; + +FutureOr?> foo() async* { + yield 1; + yield 2; + yield 3; +} + +main() async { + var o = await foo(); + o.expectStaticType?>>(); + if (o is Future?>) { + print("No"); + } else if (o == null) { + print("No"); + } else { + o.expectStaticType>>(); + Expect.isTrue(o is Stream); + } +} diff --git a/Language/Functions/element_type_A02_t05.dart b/Language/Functions/element_type_A02_t05.dart new file mode 100644 index 0000000000..2ecc4fba99 --- /dev/null +++ b/Language/Functions/element_type_A02_t05.dart @@ -0,0 +1,53 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. +/// ... +/// If `f` is an asynchronous generator and `S` implements `Stream` for some +/// `U` then the element type of `f` is `U`. +/// +/// @description Check that runtime type of an element type of an asynchronous +/// generator function `f` is `U`, where `S` is a union-free type of the +/// declared return type of `f` and `S` implements `Stream`. Test the +/// run-time types of objects returned by an asynchronous generator function +/// @author sgrekhov22@gmail.com + +import "../../Utils/expect.dart"; + +Stream? f1() async* { + yield 1; + yield 2; + yield null; +} + +Stream? f2() async* { + yield 1; + yield 2; + yield 3; +} + +main() async { + var it1 = await f1()?.toList(); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIs(it1); + + var it2 = await f2()?.toList(); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIs(it2); +} diff --git a/Language/Functions/element_type_A02_t06.dart b/Language/Functions/element_type_A02_t06.dart new file mode 100644 index 0000000000..57512a2b09 --- /dev/null +++ b/Language/Functions/element_type_A02_t06.dart @@ -0,0 +1,57 @@ +// 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 We define the union-free type of a type `T` as follows: +/// If `T` is of the form `S?` or the form `FutureOr` then the union-free +/// type of `T` is the union-free type of `S`. Otherwise, the union-free type +/// of `T` is T. +/// +/// We define the element type of a generator function `f` as follows: +/// Let `S` be the union-free type of the declared return type of `f`. +/// ... +/// If `f` is an asynchronous generator and `S` implements `Stream` for some +/// `U` then the element type of `f` is `U`. +/// +/// @description Check that runtime type of an element type of an asynchronous +/// generator function `f` is `U`, where `S` is a union-free type of the +/// declared return type of `f` and `S` implements `Stream`. Test the +/// run-time types of objects returned by an asynchronous generator function +/// @author sgrekhov22@gmail.com +/// @issue 53051 + +import "dart:async"; +import "../../Utils/expect.dart"; + +FutureOr?> f1() async* { + yield 1; + yield 2; + yield null; +} + +FutureOr?>? f2() async* { + yield 1; + yield 2; + yield 3; +} + +main() async { + var res1 = await f1(); + var it1 = await res1?.toList(); + + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIsNot(it1); + Expect.iterableElementsRuntimeIs(it1); + + var it2 = (await f2())?.toList(); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIsNot(it2); + Expect.iterableElementsRuntimeIs(it2); +} diff --git a/Language/Functions/element_type_A03_t01.dart b/Language/Functions/element_type_A03_t01.dart index 49ba5052a3..d77dc2dd18 100644 --- a/Language/Functions/element_type_A03_t01.dart +++ b/Language/Functions/element_type_A03_t01.dart @@ -19,6 +19,7 @@ /// @author sgrekhov22@gmail.com import "dart:async"; +import "../../Utils/expect.dart"; Object? f1() sync* { yield 1; @@ -30,11 +31,13 @@ Object? f1() sync* { Object f2() sync* { yield 1; yield null; + yield "42"; } FutureOr f3() sync* { yield 1; yield null; + yield "42"; yield Future.value(null); yield Future.value(1); } @@ -42,13 +45,36 @@ FutureOr f3() sync* { FutureOr? f4() sync* { yield 1; yield null; + yield "42"; + yield Future.value(null); + yield Future.value(1); +} + +FutureOr f5() sync* { + yield 1; + yield null; + yield "42"; + yield Future.value(null); + yield Future.value(1); + yield Future.value(1); + yield Future.value(null); +} + +FutureOr? f6() sync* { + yield 1; + yield null; + yield "42"; yield Future.value(null); yield Future.value(1); + yield Future.value(1); + yield Future.value(null); } main() { - f1(); - f2(); - f3(); - f4(); + Expect.iterableElementsRuntimeIs(f1()); + Expect.iterableElementsRuntimeIs(f2()); + Expect.iterableElementsRuntimeIs(f3()); + Expect.iterableElementsRuntimeIs(f4()); + Expect.iterableElementsRuntimeIs(f5()); + Expect.iterableElementsRuntimeIs(f6()); } diff --git a/Language/Functions/element_type_A03_t02.dart b/Language/Functions/element_type_A03_t02.dart index 745894a009..7d6a6c662b 100644 --- a/Language/Functions/element_type_A03_t02.dart +++ b/Language/Functions/element_type_A03_t02.dart @@ -11,7 +11,7 @@ /// Let `S` be the union-free type of the declared return type of `f`. /// ... /// Otherwise, if `f` is a generator (synchronous or asynchronous) and `S` is a -/// supertype of Object then the element type of `f` is dynamic +/// supertype of `Object` then the element type of `f` is dynamic /// /// @description Check that element type of an asynchronous generator function /// `f` is `dynamic`, if `S` is a union-free type of the declared return type of @@ -19,36 +19,74 @@ /// @author sgrekhov22@gmail.com import "dart:async"; +import "../../Utils/expect.dart"; -Object? f1() sync* { +Object? f1() async* { yield 1; yield 3.14; yield null; yield "42"; } -Object f2() sync* { +Object f2() async* { yield 1; yield null; + yield "42"; } -FutureOr f3() sync* { +FutureOr f3() async* { yield 1; yield null; + yield "42"; yield Future.value(null); yield Future.value(1); } -FutureOr? f4() sync* { +FutureOr? f4() async* { yield 1; yield null; + yield "42"; yield Future.value(null); yield Future.value(1); } -main() { - f1(); - f2(); - f3(); - f4(); +FutureOr f5() async* { + yield 1; + yield null; + yield "42"; + yield Future.value(null); + yield Future.value(1); + yield Future.value(1); + yield Future.value(null); +} + +FutureOr? f6() async* { + yield 1; + yield null; + yield "42"; + yield Future.value(null); + yield Future.value(1); + yield Future.value(1); + yield Future.value(null); +} + +main() async { + dynamic r1 = await f1(); + var v1 = await r1.toList(); + Expect.iterableElementsRuntimeIs(v1); + + dynamic r2 = await f2(); + var v2 = await r2.toList(); + Expect.iterableElementsRuntimeIs(v2); + + dynamic r3 = await f3(); + var v3 = await r3.toList(); + Expect.iterableElementsRuntimeIs(v3); + + dynamic r4 = await f4(); + var v4 = await r4.toList(); + Expect.iterableElementsRuntimeIs(v4); + + // Can't check runtime types of return values of f5() and f6() because it's + // `void` } diff --git a/Language/Functions/generator_return_type_t01.dart b/Language/Functions/generator_return_type_t01.dart index baf71407c3..908ec08d12 100644 --- a/Language/Functions/generator_return_type_t01.dart +++ b/Language/Functions/generator_return_type_t01.dart @@ -9,8 +9,8 @@ /// of synchronous generator function is not a supertype of `Iterable` /// @author a.semenov@unipro.ru -int f() sync* { } -//^ +/**/int f() sync* { } +// ^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/Language/Functions/generator_return_type_t02.dart b/Language/Functions/generator_return_type_t02.dart index 55c3457fa1..a01c5bbd2c 100644 --- a/Language/Functions/generator_return_type_t02.dart +++ b/Language/Functions/generator_return_type_t02.dart @@ -10,8 +10,8 @@ /// @issue 32192 /// @author a.semenov@unipro.ru -void h() sync* { } -//^ +/**/void h() sync* { } +// ^^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/Language/Functions/generator_return_type_t05.dart b/Language/Functions/generator_return_type_t05.dart index 79b6f623e1..7fcf6f59bf 100644 --- a/Language/Functions/generator_return_type_t05.dart +++ b/Language/Functions/generator_return_type_t05.dart @@ -9,8 +9,8 @@ /// of a function marked `async*` is not a supertype of Stream /// @author a.semenov@unipro.ru -int f() async* { } -//^ +/**/int f() async* { } +// ^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/Language/Functions/generator_return_type_t06.dart b/Language/Functions/generator_return_type_t06.dart index 2df4888430..04c893a148 100644 --- a/Language/Functions/generator_return_type_t06.dart +++ b/Language/Functions/generator_return_type_t06.dart @@ -10,8 +10,8 @@ /// @issue 32192 /// @author a.semenov@unipro.ru -void h() async* { } -//^ +/**/void h() async* { } +// ^^^^ // [analyzer] unspecified // [cfe] unspecified diff --git a/Utils/expect_common.dart b/Utils/expect_common.dart index 6d0a275490..4bc7704368 100644 --- a/Utils/expect_common.dart +++ b/Utils/expect_common.dart @@ -355,6 +355,44 @@ class Expect { static void runtimeIsNotType(Object? o) { _checkType(_checkIs, false, o); } + + /// Checks that all elements of this `Iterable` have type `T`, not a subtype + /// of `T`. For example `[1, 2, 3] is Iterable` returns `true`, but + /// `iterableElementsRuntimeIs([1, 2, 3])` will throw + /// `ExpectException`. Fails if `it` is not instance of `Iterable` + static void iterableElementsRuntimeIs(dynamic it) { + if (it is! Iterable) { + throw ExpectException("Expected Iterable<$T> but got ${it.runtimeType}"); + } + if (it.isNotEmpty) { + X combine(X x, X _) => x; + try { + (it.reduce)(combine); + } catch (e) { + throw ExpectException("Not $T in collection $it."); + } + } + } + + /// Checks that all elements of this `Iterable` don't have type `T`, but may + /// be a subtype of `T`. For example + /// `iterableElementsRuntimeIsNot([1, 2, 3])` is Ok, but + /// iterableElementsRuntimeIsNot([1, 2, 3 as num]) throws an + /// `ExpectException` + static void iterableElementsRuntimeIsNot(dynamic it) { + if (it is! Iterable) { + return; // Ok + } + X combine(X x, X _) => x; + try { + (it.reduce)(combine); + throw ExpectException("All elements in Iterable are $T."); + } catch (e) { + if (e is ExpectException) { + rethrow; + } + } + } } bool _identical(a, b) => identical(a, b); diff --git a/Utils/tests/Expect/iterableElementRuntimeIsNot_A01_t01.dart b/Utils/tests/Expect/iterableElementRuntimeIsNot_A01_t01.dart new file mode 100644 index 0000000000..be5c73f67d --- /dev/null +++ b/Utils/tests/Expect/iterableElementRuntimeIsNot_A01_t01.dart @@ -0,0 +1,47 @@ +// 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 static void iterableElementsRuntimeIsNot(dynamic it) +/// Failure if `it` is an instance of `Iterable` and has an element type of +/// which is not exactly the `T` +/// +/// @description Checks no exception is thrown when `it` is an `Iterable` and +/// all elements of it have a type `T` (not a subtype) +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + Expect.iterableElementsRuntimeIsNot([1, 2, 3]); + Expect.iterableElementsRuntimeIsNot([]); + Expect.iterableElementsRuntimeIsNot([]); + Expect.iterableElementsRuntimeIsNot(Object()); + Expect.iterableElementsRuntimeIsNot(Object()); + Expect.iterableElementsRuntimeIsNot([1, 2, 3]); + Expect.iterableElementsRuntimeIsNot([1, 2, 3]); + Expect.iterableElementsRuntimeIsNot([1, 2, 3]); + Expect.iterableElementsRuntimeIsNot([1, 2, 3]); + Expect.iterableElementsRuntimeIsNot([1, 2, 3]); + + Future> f = Future>.value([1, 2, 3]); + Expect.iterableElementsRuntimeIsNot(f); + + FutureOr> o1 = [1, 2, 3]; + Expect.iterableElementsRuntimeIsNot(o1); + + FutureOr> o2 = Future>.value([1, 2, 3]); + Expect.iterableElementsRuntimeIsNot(o2); + + Expect.throws(() { + Expect.iterableElementsRuntimeIsNot([1, 2, 3]); + }, (e) => e is ExpectException); + Expect.throws(() { + FutureOr> o = [1, 2, 3]; + Expect.iterableElementsRuntimeIsNot(o); + }, (e) => e is ExpectException); + Expect.throws(() { + Expect.iterableElementsRuntimeIsNot([1, 2, 3 as num]); + }); +} diff --git a/Utils/tests/Expect/iterableElementRuntimeIs_A01_t01.dart b/Utils/tests/Expect/iterableElementRuntimeIs_A01_t01.dart new file mode 100644 index 0000000000..fef0db43a1 --- /dev/null +++ b/Utils/tests/Expect/iterableElementRuntimeIs_A01_t01.dart @@ -0,0 +1,51 @@ +// 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 static void iterableElementsRuntimeIs(dynamic it) +/// Failure if `it` is not instance of `Iterable` or has an element type of +/// which is not exactly the `T` +/// +/// @description Checks no exception is thrown when `it` is an `Iterable` and +/// all elements of it have a type `T` (not a subtype) +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + Expect.iterableElementsRuntimeIs([1, 2, 3]); + Expect.iterableElementsRuntimeIs([]); + Expect.iterableElementsRuntimeIs([1, 2, 3]); + Expect.iterableElementsRuntimeIs([]); + FutureOr> o = [1, 2, 3]; + Expect.iterableElementsRuntimeIs(o); + + Expect.throws(() { + Expect.iterableElementsRuntimeIs([]); + }, (e) => e is ExpectException); + Expect.throws(() { + Expect.iterableElementsRuntimeIs([1, 2, 3]); + }, (e) => e is ExpectException); + Expect.throws(() { + Expect.iterableElementsRuntimeIs([1, 2, 3 as num]); + }, (e) => e is ExpectException); + Expect.throws(() { + Expect.iterableElementsRuntimeIs([]); + }, (e) => e is ExpectException); + Expect.throws(() { + Expect.iterableElementsRuntimeIs([1, 2, 3]); + }); + Expect.throws(() { + Expect.iterableElementsRuntimeIs([1, 2, 3]); + }); + Expect.throws(() { + Expect.iterableElementsRuntimeIs([1, 2, 3]); + }); + Expect.throws(() { + Expect.iterableElementsRuntimeIs([1, 2, 3]); + }); + Expect.throws(() { + Expect.iterableElementsRuntimeIs([1, 2, 3]); + }); +} diff --git a/Utils/tests/Expect/iterableElementRuntimeIs_A01_t02.dart b/Utils/tests/Expect/iterableElementRuntimeIs_A01_t02.dart new file mode 100644 index 0000000000..4103c06467 --- /dev/null +++ b/Utils/tests/Expect/iterableElementRuntimeIs_A01_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 static void iterableElementsRuntimeIs(dynamic it) +/// Failure if `it` is not instance of `Iterable` or has an element type of +/// which is not exactly the `T` +/// +/// @description Checks no exception is thrown when `it` is an `Iterable` and +/// all elements of it have a type `T` (not a subtype) +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + Expect.throws(() { + Expect.iterableElementsRuntimeIs(Object()); + }, (e) => e is ExpectException); + + Expect.throws(() { + Future> o = Future.value([1, 2, 3]); + Expect.iterableElementsRuntimeIs(o); + }, (e) => e is ExpectException); + + Expect.throws(() { + FutureOr> o = Future.value([1, 2, 3]); + Expect.iterableElementsRuntimeIs(o); + }, (e) => e is ExpectException); +} From 0e23d148b12258fa459e910bcceb356225ab520c Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Wed, 9 Aug 2023 10:39:54 +0200 Subject: [PATCH 3/4] Implement review recommendations --- Language/Functions/element_type_A01_t01.dart | 21 +++++---- Language/Functions/element_type_A01_t02.dart | 21 +++++---- Language/Functions/element_type_A01_t03.dart | 18 +++---- Language/Functions/element_type_A01_t04.dart | 19 ++++---- Language/Functions/element_type_A01_t05.dart | 40 ++++++++-------- Language/Functions/element_type_A01_t06.dart | 40 ++++++++-------- Language/Functions/element_type_A02_t01.dart | 17 +++---- Language/Functions/element_type_A02_t02.dart | 17 +++---- Language/Functions/element_type_A02_t03.dart | 27 ++++++++--- Language/Functions/element_type_A02_t04.dart | 29 ++++++++---- Language/Functions/element_type_A02_t05.dart | 36 +++++++------- Language/Functions/element_type_A02_t06.dart | 36 +++++++------- Language/Functions/element_type_A03_t01.dart | 22 ++++----- Language/Functions/element_type_A03_t02.dart | 18 +++---- Utils/expect_common.dart | 40 +++++++--------- .../isNotRuntimeTypeIterable_A01_t01.dart | 47 +++++++++++++++++++ ...art => isRuntimeTypeIterable_A01_t01.dart} | 34 +++++++------- ...art => isRuntimeTypeIterable_A01_t02.dart} | 10 ++-- .../iterableElementRuntimeIsNot_A01_t01.dart | 47 ------------------- 19 files changed, 283 insertions(+), 256 deletions(-) create mode 100644 Utils/tests/Expect/isNotRuntimeTypeIterable_A01_t01.dart rename Utils/tests/Expect/{iterableElementRuntimeIs_A01_t01.dart => isRuntimeTypeIterable_A01_t01.dart} (50%) rename Utils/tests/Expect/{iterableElementRuntimeIs_A01_t02.dart => isRuntimeTypeIterable_A01_t02.dart} (73%) delete mode 100644 Utils/tests/Expect/iterableElementRuntimeIsNot_A01_t01.dart diff --git a/Language/Functions/element_type_A01_t01.dart b/Language/Functions/element_type_A01_t01.dart index 14f987fb3f..eac1944583 100644 --- a/Language/Functions/element_type_A01_t01.dart +++ b/Language/Functions/element_type_A01_t01.dart @@ -2,19 +2,20 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. If `f` is -/// a synchronous generator and `S` implements `Iterable` for some `U` then -/// the element type of `f` is `U`. +/// Let S be the union-free type derived from the declared return type of f. If +/// f is a synchronous generator and S implements Iterable for some U then +/// the element type of f is U. /// -/// @description Check that it is a compile-time error if an element type of a -/// synchronous generator function `f` is not `U`, where `S` is a union-free -/// type of the declared return type of `f` and `S` implements `Iterable` +/// @description Check that if the declared return type of a synchronous +/// generator function `f` is `T`, and `S` is the union-free type derived from +/// `T`, and `S` is of the form `Iterable`, it is a compile-time error to +/// yield an expression whose static type isn't assignable to `U`. /// @author sgrekhov22@gmail.com import "dart:async"; diff --git a/Language/Functions/element_type_A01_t02.dart b/Language/Functions/element_type_A01_t02.dart index c5c071126e..17b39cc4e5 100644 --- a/Language/Functions/element_type_A01_t02.dart +++ b/Language/Functions/element_type_A01_t02.dart @@ -2,19 +2,20 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. If `f` is -/// a synchronous generator and `S` implements `Iterable` for some `U` then -/// the element type of `f` is `U`. +/// Let S be the union-free type derived from the declared return type of f. If +/// f is a synchronous generator and S implements Iterable for some U then +/// the element type of f is U. /// -/// @description Check that it is a compile-time error if an element type of a -/// synchronous generator function `f` is not `U`, where `S` is a union-free -/// type of the declared return type of `f` and `S` implements `Iterable` +/// @description Check that if the declared return type of a synchronous +/// generator function `f` is `T`, and `S` is the union-free type derived from +/// `T`, and `S` is of the form `Iterable`, it is a compile-time error to +/// yield an expression whose static type isn't assignable to `U`. /// @author sgrekhov22@gmail.com import "dart:async"; diff --git a/Language/Functions/element_type_A01_t03.dart b/Language/Functions/element_type_A01_t03.dart index 0963d2033a..7075ab8627 100644 --- a/Language/Functions/element_type_A01_t03.dart +++ b/Language/Functions/element_type_A01_t03.dart @@ -2,21 +2,22 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. If `f` is -/// a synchronous generator and `S` implements `Iterable` for some `U` then -/// the element type of `f` is `U`. +/// Let S be the union-free type derived from the declared return type of f. If +/// f is a synchronous generator and S implements Iterable for some U then +/// the element type of f is U. /// /// @description Check a run-time type of a return value of a synchronous /// generator function /// @author sgrekhov22@gmail.com import "dart:async"; +import "../../Utils/expect.dart"; FutureOr?> foo() sync* { yield 1; @@ -26,5 +27,6 @@ FutureOr?> foo() sync* { main() { FutureOr?> o = foo() as dynamic; - o as FutureOr?>; + o as FutureOr>; + Expect.isRuntimeTypeIterable(o); } diff --git a/Language/Functions/element_type_A01_t04.dart b/Language/Functions/element_type_A01_t04.dart index fd353ac7bd..5e39a0b1b7 100644 --- a/Language/Functions/element_type_A01_t04.dart +++ b/Language/Functions/element_type_A01_t04.dart @@ -2,15 +2,15 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. If `f` is -/// a synchronous generator and `S` implements `Iterable` for some `U` then -/// the element type of `f` is `U`. +/// Let S be the union-free type derived from the declared return type of f. If +/// f is a synchronous generator and S implements Iterable for some U then +/// the element type of f is U. /// /// @description Check that element type of a synchronous generator function `f` /// is `U`, where `S` is a union-free type of the declared return type of `f` @@ -35,7 +35,10 @@ main() { } else if (o == null) { print("No"); } else { + // Now static type must be `Iterable o.expectStaticType>>(); - Expect.isTrue(o is Iterable); + Expect.isTrue(o is Iterable, ": o is ${o.runtimeType}"); + Expect.isRuntimeTypeIterable(o); + Expect.isNotRuntimeTypeIterable(o); } } diff --git a/Language/Functions/element_type_A01_t05.dart b/Language/Functions/element_type_A01_t05.dart index 23ca1557d0..8e7308bcd0 100644 --- a/Language/Functions/element_type_A01_t05.dart +++ b/Language/Functions/element_type_A01_t05.dart @@ -2,15 +2,15 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. If `f` is -/// a synchronous generator and `S` implements `Iterable` for some `U` then -/// the element type of `f` is `U`. +/// Let S be the union-free type derived from the declared return type of f. If +/// f is a synchronous generator and S implements Iterable for some U then +/// the element type of f is U. /// /// @description Check that runtime type of an element type of a synchronous /// generator function `f` is `U`, where `S` is a union-free type of the @@ -33,18 +33,18 @@ Iterable? f2() sync* { } main() { - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIs(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isRuntimeTypeIterable(f1()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIs(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isRuntimeTypeIterable(f2()); } diff --git a/Language/Functions/element_type_A01_t06.dart b/Language/Functions/element_type_A01_t06.dart index e19dc9f492..b83eae0f2f 100644 --- a/Language/Functions/element_type_A01_t06.dart +++ b/Language/Functions/element_type_A01_t06.dart @@ -2,15 +2,15 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. If `f` is -/// a synchronous generator and `S` implements `Iterable` for some `U` then -/// the element type of `f` is `U`. +/// Let S be the union-free type derived from the declared return type of f. If +/// f is a synchronous generator and S implements Iterable for some U then +/// the element type of f is U. /// /// @description Check that runtime type of an element type of a synchronous /// generator function `f` is `U`, where `S` is a union-free type of the @@ -34,18 +34,18 @@ FutureOr?>? f2() sync* { } main() { - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIsNot(f1()); - Expect.iterableElementsRuntimeIs(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isNotRuntimeTypeIterable(f1()); + Expect.isRuntimeTypeIterable(f1()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIsNot(f2()); - Expect.iterableElementsRuntimeIs(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isNotRuntimeTypeIterable(f2()); + Expect.isRuntimeTypeIterable(f2()); } diff --git a/Language/Functions/element_type_A02_t01.dart b/Language/Functions/element_type_A02_t01.dart index c665aa05bd..26f89b6126 100644 --- a/Language/Functions/element_type_A02_t01.dart +++ b/Language/Functions/element_type_A02_t01.dart @@ -2,20 +2,21 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. +/// Let S be the union-free type derived from the declared return type of f. /// ... /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. /// -/// @description Check that it is a compile-time error if an element type of a -/// synchronous generator function `f` is not `U`, where `S` is a union-free -/// type of the declared return type of `f` and `S` implements `Stream` +/// @description Check that if the declared return type of an asynchronous +/// generator function `f` is `T`, and `S` is the union-free type derived from +/// `T`, and `S` is of the form `Stream`, it is a compile-time error to +/// yield an expression whose static type isn't assignable to `U`. /// @author sgrekhov22@gmail.com import "dart:async"; diff --git a/Language/Functions/element_type_A02_t02.dart b/Language/Functions/element_type_A02_t02.dart index 8e2b419a3d..c1074ddc82 100644 --- a/Language/Functions/element_type_A02_t02.dart +++ b/Language/Functions/element_type_A02_t02.dart @@ -2,20 +2,21 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. +/// Let S be the union-free type derived from the declared return type of f. /// ... /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. /// -/// @description Check that it is a compile-time error if an element type of an -/// asynchronous generator function `f` is not `U`, where `S` is a union-free -/// type of the declared return type of `f` and `S` implements `Stream` +/// @description Check that if the declared return type of an asynchronous +/// generator function `f` is `T`, and `S` is the union-free type derived from +/// `T`, and `S` is of the form `Stream`, it is a compile-time error to +/// yield an expression whose static type isn't assignable to `U`. /// @author sgrekhov22@gmail.com import "dart:async"; diff --git a/Language/Functions/element_type_A02_t03.dart b/Language/Functions/element_type_A02_t03.dart index ed5e9dd4b3..e08702a60b 100644 --- a/Language/Functions/element_type_A02_t03.dart +++ b/Language/Functions/element_type_A02_t03.dart @@ -2,13 +2,13 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. +/// Let S be the union-free type derived from the declared return type of f. /// ... /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. @@ -18,6 +18,19 @@ /// @author sgrekhov22@gmail.com import "dart:async"; +import "../../Utils/expect.dart"; + +void isRuntimeTypeStream(Object? o) async { + if (o is! Stream) { + throw ExpectException("Not a Stream<$T>: ${o.runtimeType}"); + } + List list = await o.toList(); + try { + list.addAll([]); + } on TypeError catch (_) { + throw ExpectException("Expected Stream<$T> but found $o"); + } +} FutureOr?> foo() async* { yield 1; @@ -27,6 +40,6 @@ FutureOr?> foo() async* { main() async { dynamic d = await foo(); - FutureOr?> o = d; - o as FutureOr?>; + FutureOr> o = d; + isRuntimeTypeStream(d); } diff --git a/Language/Functions/element_type_A02_t04.dart b/Language/Functions/element_type_A02_t04.dart index 9d1aee09a7..aa2f969dfd 100644 --- a/Language/Functions/element_type_A02_t04.dart +++ b/Language/Functions/element_type_A02_t04.dart @@ -2,13 +2,13 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. +/// Let S be the union-free type derived from the declared return type of f. /// ... /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. @@ -22,6 +22,18 @@ import "dart:async"; import "../../Utils/expect.dart"; import "../../Utils/static_type_helper.dart"; +void isRuntimeTypeStream(Object? o) async { + if (o is! Stream) { + throw ExpectException("Not a Stream<$T>: ${o.runtimeType}"); + } + List list = await o.toList(); + try { + list.addAll([]); + } on TypeError catch (_) { + throw ExpectException("Expected Stream<$T> but found $o"); + } +} + FutureOr?> foo() async* { yield 1; yield 2; @@ -31,12 +43,11 @@ FutureOr?> foo() async* { main() async { var o = await foo(); o.expectStaticType?>>(); - if (o is Future?>) { - print("No"); - } else if (o == null) { + if (o == null) { print("No"); } else { + // Now static type must be `Stream o.expectStaticType>>(); - Expect.isTrue(o is Stream); + isRuntimeTypeStream(o); } } diff --git a/Language/Functions/element_type_A02_t05.dart b/Language/Functions/element_type_A02_t05.dart index 2ecc4fba99..627bb442f4 100644 --- a/Language/Functions/element_type_A02_t05.dart +++ b/Language/Functions/element_type_A02_t05.dart @@ -2,13 +2,13 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. +/// Let S be the union-free type derived from the declared return type of f. /// ... /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. @@ -35,19 +35,19 @@ Stream? f2() async* { main() async { var it1 = await f1()?.toList(); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIs(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isRuntimeTypeIterable(it1); var it2 = await f2()?.toList(); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIs(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isRuntimeTypeIterable(it2); } diff --git a/Language/Functions/element_type_A02_t06.dart b/Language/Functions/element_type_A02_t06.dart index 57512a2b09..6930d71c3f 100644 --- a/Language/Functions/element_type_A02_t06.dart +++ b/Language/Functions/element_type_A02_t06.dart @@ -2,13 +2,13 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. +/// Let S be the union-free type derived from the declared return type of f. /// ... /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. @@ -39,19 +39,19 @@ main() async { var res1 = await f1(); var it1 = await res1?.toList(); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIsNot(it1); - Expect.iterableElementsRuntimeIs(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isNotRuntimeTypeIterable(it1); + Expect.isRuntimeTypeIterable(it1); var it2 = (await f2())?.toList(); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIsNot(it2); - Expect.iterableElementsRuntimeIs(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isNotRuntimeTypeIterable(it2); + Expect.isRuntimeTypeIterable(it2); } diff --git a/Language/Functions/element_type_A03_t01.dart b/Language/Functions/element_type_A03_t01.dart index d77dc2dd18..a392b9d1f6 100644 --- a/Language/Functions/element_type_A03_t01.dart +++ b/Language/Functions/element_type_A03_t01.dart @@ -2,13 +2,13 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. +/// Let S be the union-free type derived from the declared return type of f. /// ... /// Otherwise, if `f` is a generator (synchronous or asynchronous) and `S` is a /// supertype of `Object` then the element type of `f` is dynamic @@ -71,10 +71,10 @@ FutureOr? f6() sync* { } main() { - Expect.iterableElementsRuntimeIs(f1()); - Expect.iterableElementsRuntimeIs(f2()); - Expect.iterableElementsRuntimeIs(f3()); - Expect.iterableElementsRuntimeIs(f4()); - Expect.iterableElementsRuntimeIs(f5()); - Expect.iterableElementsRuntimeIs(f6()); + Expect.isRuntimeTypeIterable(f1()); + Expect.isRuntimeTypeIterable(f2()); + Expect.isRuntimeTypeIterable(f3()); + Expect.isRuntimeTypeIterable(f4()); + Expect.isRuntimeTypeIterable(f5()); + Expect.isRuntimeTypeIterable(f6()); } diff --git a/Language/Functions/element_type_A03_t02.dart b/Language/Functions/element_type_A03_t02.dart index 7d6a6c662b..52f4c3e918 100644 --- a/Language/Functions/element_type_A03_t02.dart +++ b/Language/Functions/element_type_A03_t02.dart @@ -2,13 +2,13 @@ // 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 We define the union-free type of a type `T` as follows: -/// If `T` is of the form `S?` or the form `FutureOr` then the union-free -/// type of `T` is the union-free type of `S`. Otherwise, the union-free type -/// of `T` is T. +/// @assertion We define the union-free type derived from a type T as follows: +/// If T is of the form S? or the form FutureOr then the union-free type +/// derived from T is the union-free type derived from S. Otherwise, the +/// union-free type derived from T is T /// /// We define the element type of a generator function `f` as follows: -/// Let `S` be the union-free type of the declared return type of `f`. +/// Let S be the union-free type derived from the declared return type of f. /// ... /// Otherwise, if `f` is a generator (synchronous or asynchronous) and `S` is a /// supertype of `Object` then the element type of `f` is dynamic @@ -73,19 +73,19 @@ FutureOr? f6() async* { main() async { dynamic r1 = await f1(); var v1 = await r1.toList(); - Expect.iterableElementsRuntimeIs(v1); + Expect.isRuntimeTypeIterable(v1); dynamic r2 = await f2(); var v2 = await r2.toList(); - Expect.iterableElementsRuntimeIs(v2); + Expect.isRuntimeTypeIterable(v2); dynamic r3 = await f3(); var v3 = await r3.toList(); - Expect.iterableElementsRuntimeIs(v3); + Expect.isRuntimeTypeIterable(v3); dynamic r4 = await f4(); var v4 = await r4.toList(); - Expect.iterableElementsRuntimeIs(v4); + Expect.isRuntimeTypeIterable(v4); // Can't check runtime types of return values of f5() and f6() because it's // `void` diff --git a/Utils/expect_common.dart b/Utils/expect_common.dart index 4bc7704368..3e651c2659 100644 --- a/Utils/expect_common.dart +++ b/Utils/expect_common.dart @@ -358,40 +358,32 @@ class Expect { /// Checks that all elements of this `Iterable` have type `T`, not a subtype /// of `T`. For example `[1, 2, 3] is Iterable` returns `true`, but - /// `iterableElementsRuntimeIs([1, 2, 3])` will throw + /// `isRuntimeTypeIterable([1, 2, 3])` will throw /// `ExpectException`. Fails if `it` is not instance of `Iterable` - static void iterableElementsRuntimeIs(dynamic it) { - if (it is! Iterable) { - throw ExpectException("Expected Iterable<$T> but got ${it.runtimeType}"); + static void isRuntimeTypeIterable(Object? o) { + if (o is! Iterable) { + throw ExpectException("Not Iterable<$T>: ${o.runtimeType}"); } - if (it.isNotEmpty) { - X combine(X x, X _) => x; - try { - (it.reduce)(combine); - } catch (e) { - throw ExpectException("Not $T in collection $it."); - } + List list = o.toList(growable: true); + try { + list.addAll([]); + } on TypeError catch (_) { + throw ExpectException("Expected Iterable<$T> but found $o"); } } /// Checks that all elements of this `Iterable` don't have type `T`, but may /// be a subtype of `T`. For example - /// `iterableElementsRuntimeIsNot([1, 2, 3])` is Ok, but - /// iterableElementsRuntimeIsNot([1, 2, 3 as num]) throws an + /// `isNotRuntimeTypeIterable([1, 2, 3])` is Ok, but + /// isNotRuntimeTypeIterable([1, 2, 3 as num]) throws an /// `ExpectException` - static void iterableElementsRuntimeIsNot(dynamic it) { - if (it is! Iterable) { - return; // Ok - } - X combine(X x, X _) => x; + static void isNotRuntimeTypeIterable(Object? o) { try { - (it.reduce)(combine); - throw ExpectException("All elements in Iterable are $T."); - } catch (e) { - if (e is ExpectException) { - rethrow; - } + Expect.isRuntimeTypeIterable(o); + } on ExpectException catch (_) { + return; } + throw ExpectException("All elements in Iterable are $T"); } } diff --git a/Utils/tests/Expect/isNotRuntimeTypeIterable_A01_t01.dart b/Utils/tests/Expect/isNotRuntimeTypeIterable_A01_t01.dart new file mode 100644 index 0000000000..35f382816b --- /dev/null +++ b/Utils/tests/Expect/isNotRuntimeTypeIterable_A01_t01.dart @@ -0,0 +1,47 @@ +// 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 static void isNotRuntimeTypeIterable(Object? it) +/// Failure if `it` is an instance of `Iterable` and all elements have type +/// which is exactly the `T` +/// +/// @description Checks no exception is thrown when `it` is not an `Iterable` +/// or not all elements of it have a type `T` (not a subtype). Throws otherwise +/// @author sgrekhov22@gmail.com + +import "dart:async"; +import "../../../Utils/expect.dart"; + +main() { + Expect.isNotRuntimeTypeIterable([1, 2, 3]); + Expect.isNotRuntimeTypeIterable([]); + Expect.isNotRuntimeTypeIterable([]); + Expect.isNotRuntimeTypeIterable(Object()); + Expect.isNotRuntimeTypeIterable(Object()); + Expect.isNotRuntimeTypeIterable([1, 2, 3]); + Expect.isNotRuntimeTypeIterable([1, 2, 3]); + Expect.isNotRuntimeTypeIterable([1, 2, 3]); + Expect.isNotRuntimeTypeIterable([1, 2, 3]); + Expect.isNotRuntimeTypeIterable([1, 2, 3]); + + Future> f = Future>.value([1, 2, 3]); + Expect.isNotRuntimeTypeIterable(f); + + FutureOr> o1 = [1, 2, 3]; + Expect.isNotRuntimeTypeIterable(o1); + + FutureOr> o2 = Future>.value([1, 2, 3]); + Expect.isNotRuntimeTypeIterable(o2); + + Expect.throws(() { + Expect.isNotRuntimeTypeIterable([1, 2, 3]); + }, (e) => e is ExpectException); + Expect.throws(() { + FutureOr> o = [1, 2, 3]; + Expect.isNotRuntimeTypeIterable(o); + }, (e) => e is ExpectException); + Expect.throws(() { + Expect.isNotRuntimeTypeIterable([1, 2, 3 as num]); + }); +} diff --git a/Utils/tests/Expect/iterableElementRuntimeIs_A01_t01.dart b/Utils/tests/Expect/isRuntimeTypeIterable_A01_t01.dart similarity index 50% rename from Utils/tests/Expect/iterableElementRuntimeIs_A01_t01.dart rename to Utils/tests/Expect/isRuntimeTypeIterable_A01_t01.dart index fef0db43a1..d6c13bd211 100644 --- a/Utils/tests/Expect/iterableElementRuntimeIs_A01_t01.dart +++ b/Utils/tests/Expect/isRuntimeTypeIterable_A01_t01.dart @@ -2,50 +2,52 @@ // 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 static void iterableElementsRuntimeIs(dynamic it) +/// @assertion static void isRuntimeTypeIterable(Object? it) /// Failure if `it` is not instance of `Iterable` or has an element type of /// which is not exactly the `T` /// /// @description Checks no exception is thrown when `it` is an `Iterable` and -/// all elements of it have a type `T` (not a subtype) +/// all elements of it have a type `T` (not a subtype). Throws otherwise. /// @author sgrekhov22@gmail.com import "dart:async"; import "../../../Utils/expect.dart"; main() { - Expect.iterableElementsRuntimeIs([1, 2, 3]); - Expect.iterableElementsRuntimeIs([]); - Expect.iterableElementsRuntimeIs([1, 2, 3]); - Expect.iterableElementsRuntimeIs([]); + Expect.isRuntimeTypeIterable([1, 2, 3]); + Expect.isRuntimeTypeIterable([]); + Expect.isRuntimeTypeIterable([]); FutureOr> o = [1, 2, 3]; - Expect.iterableElementsRuntimeIs(o); + Expect.isRuntimeTypeIterable(o); Expect.throws(() { - Expect.iterableElementsRuntimeIs([]); + Expect.isRuntimeTypeIterable([1, 2, 3]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.iterableElementsRuntimeIs([1, 2, 3]); + Expect.isRuntimeTypeIterable([]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.iterableElementsRuntimeIs([1, 2, 3 as num]); + Expect.isRuntimeTypeIterable([]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.iterableElementsRuntimeIs([]); + Expect.isRuntimeTypeIterable([1, 2, 3 as num]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.iterableElementsRuntimeIs([1, 2, 3]); + Expect.isRuntimeTypeIterable([]); + }, (e) => e is ExpectException); + Expect.throws(() { + Expect.isRuntimeTypeIterable([1, 2, 3]); }); Expect.throws(() { - Expect.iterableElementsRuntimeIs([1, 2, 3]); + Expect.isRuntimeTypeIterable([1, 2, 3]); }); Expect.throws(() { - Expect.iterableElementsRuntimeIs([1, 2, 3]); + Expect.isRuntimeTypeIterable([1, 2, 3]); }); Expect.throws(() { - Expect.iterableElementsRuntimeIs([1, 2, 3]); + Expect.isRuntimeTypeIterable([1, 2, 3]); }); Expect.throws(() { - Expect.iterableElementsRuntimeIs([1, 2, 3]); + Expect.isRuntimeTypeIterable([1, 2, 3]); }); } diff --git a/Utils/tests/Expect/iterableElementRuntimeIs_A01_t02.dart b/Utils/tests/Expect/isRuntimeTypeIterable_A01_t02.dart similarity index 73% rename from Utils/tests/Expect/iterableElementRuntimeIs_A01_t02.dart rename to Utils/tests/Expect/isRuntimeTypeIterable_A01_t02.dart index 4103c06467..656efbc2cc 100644 --- a/Utils/tests/Expect/iterableElementRuntimeIs_A01_t02.dart +++ b/Utils/tests/Expect/isRuntimeTypeIterable_A01_t02.dart @@ -6,8 +6,8 @@ /// Failure if `it` is not instance of `Iterable` or has an element type of /// which is not exactly the `T` /// -/// @description Checks no exception is thrown when `it` is an `Iterable` and -/// all elements of it have a type `T` (not a subtype) +/// @description Checks that an exception is thrown when `it` is not +/// `Iterable` /// @author sgrekhov22@gmail.com import "dart:async"; @@ -15,16 +15,16 @@ import "../../../Utils/expect.dart"; main() { Expect.throws(() { - Expect.iterableElementsRuntimeIs(Object()); + Expect.isRuntimeTypeIterable(Object()); }, (e) => e is ExpectException); Expect.throws(() { Future> o = Future.value([1, 2, 3]); - Expect.iterableElementsRuntimeIs(o); + Expect.isRuntimeTypeIterable(o); }, (e) => e is ExpectException); Expect.throws(() { FutureOr> o = Future.value([1, 2, 3]); - Expect.iterableElementsRuntimeIs(o); + Expect.isRuntimeTypeIterable(o); }, (e) => e is ExpectException); } diff --git a/Utils/tests/Expect/iterableElementRuntimeIsNot_A01_t01.dart b/Utils/tests/Expect/iterableElementRuntimeIsNot_A01_t01.dart deleted file mode 100644 index be5c73f67d..0000000000 --- a/Utils/tests/Expect/iterableElementRuntimeIsNot_A01_t01.dart +++ /dev/null @@ -1,47 +0,0 @@ -// 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 static void iterableElementsRuntimeIsNot(dynamic it) -/// Failure if `it` is an instance of `Iterable` and has an element type of -/// which is not exactly the `T` -/// -/// @description Checks no exception is thrown when `it` is an `Iterable` and -/// all elements of it have a type `T` (not a subtype) -/// @author sgrekhov22@gmail.com - -import "dart:async"; -import "../../../Utils/expect.dart"; - -main() { - Expect.iterableElementsRuntimeIsNot([1, 2, 3]); - Expect.iterableElementsRuntimeIsNot([]); - Expect.iterableElementsRuntimeIsNot([]); - Expect.iterableElementsRuntimeIsNot(Object()); - Expect.iterableElementsRuntimeIsNot(Object()); - Expect.iterableElementsRuntimeIsNot([1, 2, 3]); - Expect.iterableElementsRuntimeIsNot([1, 2, 3]); - Expect.iterableElementsRuntimeIsNot([1, 2, 3]); - Expect.iterableElementsRuntimeIsNot([1, 2, 3]); - Expect.iterableElementsRuntimeIsNot([1, 2, 3]); - - Future> f = Future>.value([1, 2, 3]); - Expect.iterableElementsRuntimeIsNot(f); - - FutureOr> o1 = [1, 2, 3]; - Expect.iterableElementsRuntimeIsNot(o1); - - FutureOr> o2 = Future>.value([1, 2, 3]); - Expect.iterableElementsRuntimeIsNot(o2); - - Expect.throws(() { - Expect.iterableElementsRuntimeIsNot([1, 2, 3]); - }, (e) => e is ExpectException); - Expect.throws(() { - FutureOr> o = [1, 2, 3]; - Expect.iterableElementsRuntimeIsNot(o); - }, (e) => e is ExpectException); - Expect.throws(() { - Expect.iterableElementsRuntimeIsNot([1, 2, 3 as num]); - }); -} From 42b0377efefbc12b6873cc73ebadab2822e08f4b Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Wed, 9 Aug 2023 15:38:44 +0200 Subject: [PATCH 4/4] Implement review recommendations. Iteration 2 --- Language/Functions/element_type_A01_t03.dart | 2 +- Language/Functions/element_type_A01_t04.dart | 18 ++----- Language/Functions/element_type_A01_t05.dart | 23 ++------- Language/Functions/element_type_A01_t06.dart | 23 ++------- Language/Functions/element_type_A02_t03.dart | 4 +- Language/Functions/element_type_A02_t04.dart | 16 ++----- Language/Functions/element_type_A02_t05.dart | 22 ++------- Language/Functions/element_type_A02_t06.dart | 23 ++------- Language/Functions/element_type_A03_t01.dart | 18 +++---- Language/Functions/element_type_A03_t02.dart | 31 +++++++----- Utils/expect_common.dart | 25 +++------- .../isNotRuntimeTypeIterable_A01_t01.dart | 47 ------------------- .../Expect/isRuntimeTypeIterable_A01_t01.dart | 28 +++++------ .../Expect/isRuntimeTypeIterable_A01_t02.dart | 6 +-- 14 files changed, 82 insertions(+), 204 deletions(-) delete mode 100644 Utils/tests/Expect/isNotRuntimeTypeIterable_A01_t01.dart diff --git a/Language/Functions/element_type_A01_t03.dart b/Language/Functions/element_type_A01_t03.dart index 7075ab8627..b0276ff83a 100644 --- a/Language/Functions/element_type_A01_t03.dart +++ b/Language/Functions/element_type_A01_t03.dart @@ -28,5 +28,5 @@ FutureOr?> foo() sync* { main() { FutureOr?> o = foo() as dynamic; o as FutureOr>; - Expect.isRuntimeTypeIterable(o); + Expect.isRuntimeTypeImplementsIterable(o); } diff --git a/Language/Functions/element_type_A01_t04.dart b/Language/Functions/element_type_A01_t04.dart index 5e39a0b1b7..28b19d9d01 100644 --- a/Language/Functions/element_type_A01_t04.dart +++ b/Language/Functions/element_type_A01_t04.dart @@ -12,9 +12,9 @@ /// f is a synchronous generator and S implements Iterable for some U then /// the element type of f is U. /// -/// @description Check that element type of a synchronous generator function `f` -/// is `U`, where `S` is a union-free type of the declared return type of `f` -/// and `S` implements `Iterable` +/// @description Let `f` be a synchronous generator function whose declared +/// return type derives the union-free type `S`, and assume that `S` implements +/// `Iterable`. Then check that the element type of `f` is `U`. /// @author sgrekhov22@gmail.com import "dart:async"; @@ -30,15 +30,5 @@ FutureOr?> foo() sync* { main() { var o = foo(); o.expectStaticType?>>>(); - if (o is Future?>) { - print("No"); - } else if (o == null) { - print("No"); - } else { - // Now static type must be `Iterable - o.expectStaticType>>(); - Expect.isTrue(o is Iterable, ": o is ${o.runtimeType}"); - Expect.isRuntimeTypeIterable(o); - Expect.isNotRuntimeTypeIterable(o); - } + Expect.isRuntimeTypeImplementsIterable(o); } diff --git a/Language/Functions/element_type_A01_t05.dart b/Language/Functions/element_type_A01_t05.dart index 8e7308bcd0..af13803086 100644 --- a/Language/Functions/element_type_A01_t05.dart +++ b/Language/Functions/element_type_A01_t05.dart @@ -12,10 +12,9 @@ /// f is a synchronous generator and S implements Iterable for some U then /// the element type of f is U. /// -/// @description Check that runtime type of an element type of a synchronous -/// generator function `f` is `U`, where `S` is a union-free type of the -/// declared return type of `f` and `S` implements `Iterable`. Test the -/// run-time types of objects returned by a synchronous generator function +/// @description Let `f` be a synchronous generator function whose declared +/// return type derives the union-free type `S`, and assume that `S` implements +/// `Iterable`. Then check that the element type of `f` is `U`. /// @author sgrekhov22@gmail.com import "../../Utils/expect.dart"; @@ -33,18 +32,6 @@ Iterable? f2() sync* { } main() { - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isRuntimeTypeIterable(f1()); - - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isRuntimeTypeIterable(f2()); + Expect.isRuntimeTypeImplementsIterable(f1()); + Expect.isRuntimeTypeImplementsIterable(f2()); } diff --git a/Language/Functions/element_type_A01_t06.dart b/Language/Functions/element_type_A01_t06.dart index b83eae0f2f..5423ca5645 100644 --- a/Language/Functions/element_type_A01_t06.dart +++ b/Language/Functions/element_type_A01_t06.dart @@ -12,10 +12,9 @@ /// f is a synchronous generator and S implements Iterable for some U then /// the element type of f is U. /// -/// @description Check that runtime type of an element type of a synchronous -/// generator function `f` is `U`, where `S` is a union-free type of the -/// declared return type of `f` and `S` implements `Iterable`. Test the -/// run-time types of objects returned by a synchronous generator function +/// @description Let `f` be a synchronous generator function whose declared +/// return type derives the union-free type `S`, and assume that `S` implements +/// `Iterable`. Then check that the element type of `f` is `U`. /// @author sgrekhov22@gmail.com import "dart:async"; @@ -34,18 +33,6 @@ FutureOr?>? f2() sync* { } main() { - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isNotRuntimeTypeIterable(f1()); - Expect.isRuntimeTypeIterable(f1()); - - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isNotRuntimeTypeIterable(f2()); - Expect.isRuntimeTypeIterable(f2()); + Expect.isRuntimeTypeImplementsIterable(f1()); + Expect.isRuntimeTypeImplementsIterable(f2()); } diff --git a/Language/Functions/element_type_A02_t03.dart b/Language/Functions/element_type_A02_t03.dart index e08702a60b..4dbfe1aae3 100644 --- a/Language/Functions/element_type_A02_t03.dart +++ b/Language/Functions/element_type_A02_t03.dart @@ -20,7 +20,7 @@ import "dart:async"; import "../../Utils/expect.dart"; -void isRuntimeTypeStream(Object? o) async { +void isRuntimeTypeImplementsStream(Object? o) async { if (o is! Stream) { throw ExpectException("Not a Stream<$T>: ${o.runtimeType}"); } @@ -41,5 +41,5 @@ FutureOr?> foo() async* { main() async { dynamic d = await foo(); FutureOr> o = d; - isRuntimeTypeStream(d); + isRuntimeTypeImplementsStream(d); } diff --git a/Language/Functions/element_type_A02_t04.dart b/Language/Functions/element_type_A02_t04.dart index aa2f969dfd..d3c548588f 100644 --- a/Language/Functions/element_type_A02_t04.dart +++ b/Language/Functions/element_type_A02_t04.dart @@ -13,16 +13,16 @@ /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. /// -/// @description Check that element type of an asynchronous generator function -/// `f` is `U`, where `S` is a union-free type of the declared return type of -/// `f` and `S` implements `Stream` +/// @description Let `f` be an asynchronous generator function whose declared +/// return type derives the union-free type `S`, and assume that `S` implements +/// `Stream`. Then check that the element type of `f` is `U`. /// @author sgrekhov22@gmail.com import "dart:async"; import "../../Utils/expect.dart"; import "../../Utils/static_type_helper.dart"; -void isRuntimeTypeStream(Object? o) async { +void isRuntimeTypeImplementsStream(Object? o) async { if (o is! Stream) { throw ExpectException("Not a Stream<$T>: ${o.runtimeType}"); } @@ -43,11 +43,5 @@ FutureOr?> foo() async* { main() async { var o = await foo(); o.expectStaticType?>>(); - if (o == null) { - print("No"); - } else { - // Now static type must be `Stream - o.expectStaticType>>(); - isRuntimeTypeStream(o); - } + isRuntimeTypeImplementsStream(o); } diff --git a/Language/Functions/element_type_A02_t05.dart b/Language/Functions/element_type_A02_t05.dart index 627bb442f4..52aa383414 100644 --- a/Language/Functions/element_type_A02_t05.dart +++ b/Language/Functions/element_type_A02_t05.dart @@ -13,10 +13,9 @@ /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. /// -/// @description Check that runtime type of an element type of an asynchronous -/// generator function `f` is `U`, where `S` is a union-free type of the -/// declared return type of `f` and `S` implements `Stream`. Test the -/// run-time types of objects returned by an asynchronous generator function +/// @description Let `f` be an asynchronous generator function whose declared +/// return type derives the union-free type `S`, and assume that `S` implements +/// `Stream`. Then check that the element type of `f` is `U`. /// @author sgrekhov22@gmail.com import "../../Utils/expect.dart"; @@ -35,19 +34,8 @@ Stream? f2() async* { main() async { var it1 = await f1()?.toList(); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isRuntimeTypeIterable(it1); + Expect.isRuntimeTypeImplementsIterable(it1); var it2 = await f2()?.toList(); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isRuntimeTypeIterable(it2); + Expect.isRuntimeTypeImplementsIterable(it2); } diff --git a/Language/Functions/element_type_A02_t06.dart b/Language/Functions/element_type_A02_t06.dart index 6930d71c3f..df4187ba65 100644 --- a/Language/Functions/element_type_A02_t06.dart +++ b/Language/Functions/element_type_A02_t06.dart @@ -13,10 +13,9 @@ /// If `f` is an asynchronous generator and `S` implements `Stream` for some /// `U` then the element type of `f` is `U`. /// -/// @description Check that runtime type of an element type of an asynchronous -/// generator function `f` is `U`, where `S` is a union-free type of the -/// declared return type of `f` and `S` implements `Stream`. Test the -/// run-time types of objects returned by an asynchronous generator function +/// @description Let `f` be an asynchronous generator function whose declared +/// return type derives the union-free type `S`, and assume that `S` implements +/// `Stream`. Then check that the element type of `f` is `U`. /// @author sgrekhov22@gmail.com /// @issue 53051 @@ -38,20 +37,8 @@ FutureOr?>? f2() async* { main() async { var res1 = await f1(); var it1 = await res1?.toList(); - - Expect.isNotRuntimeTypeIterable(it1); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isNotRuntimeTypeIterable(it1); - Expect.isRuntimeTypeIterable(it1); + Expect.isRuntimeTypeImplementsIterable(it1); var it2 = (await f2())?.toList(); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isNotRuntimeTypeIterable(it2); - Expect.isRuntimeTypeIterable(it2); + Expect.isRuntimeTypeImplementsIterable(it2); } diff --git a/Language/Functions/element_type_A03_t01.dart b/Language/Functions/element_type_A03_t01.dart index a392b9d1f6..3af6390546 100644 --- a/Language/Functions/element_type_A03_t01.dart +++ b/Language/Functions/element_type_A03_t01.dart @@ -13,9 +13,9 @@ /// Otherwise, if `f` is a generator (synchronous or asynchronous) and `S` is a /// supertype of `Object` then the element type of `f` is dynamic /// -/// @description Check that element type of a synchronous generator function `f` -/// is `dynamic`, if `S` is a union-free type of the declared return type of `f` -/// and `S` is a supertype of `Object` +/// @description Let `f` be a synchronous generator function whose declared +/// return type derives a union-free type which is a supertype of `Object` +/// (including `Object` itself). Then check that its element type is `dynamic`. /// @author sgrekhov22@gmail.com import "dart:async"; @@ -71,10 +71,10 @@ FutureOr? f6() sync* { } main() { - Expect.isRuntimeTypeIterable(f1()); - Expect.isRuntimeTypeIterable(f2()); - Expect.isRuntimeTypeIterable(f3()); - Expect.isRuntimeTypeIterable(f4()); - Expect.isRuntimeTypeIterable(f5()); - Expect.isRuntimeTypeIterable(f6()); + Expect.isRuntimeTypeImplementsIterable(f1()); + Expect.isRuntimeTypeImplementsIterable(f2()); + Expect.isRuntimeTypeImplementsIterable(f3()); + Expect.isRuntimeTypeImplementsIterable(f4()); + Expect.isRuntimeTypeImplementsIterable(f5()); + Expect.isRuntimeTypeImplementsIterable(f6()); } diff --git a/Language/Functions/element_type_A03_t02.dart b/Language/Functions/element_type_A03_t02.dart index 52f4c3e918..d28b08f523 100644 --- a/Language/Functions/element_type_A03_t02.dart +++ b/Language/Functions/element_type_A03_t02.dart @@ -13,9 +13,9 @@ /// Otherwise, if `f` is a generator (synchronous or asynchronous) and `S` is a /// supertype of `Object` then the element type of `f` is dynamic /// -/// @description Check that element type of an asynchronous generator function -/// `f` is `dynamic`, if `S` is a union-free type of the declared return type of -/// `f` and `S` is a supertype of `Object` +/// @description Let `f` be an asynchronous generator function whose declared +/// return type derives a union-free type which is a supertype of `Object` +/// (including `Object` itself). Then check that its element type is `dynamic`. /// @author sgrekhov22@gmail.com import "dart:async"; @@ -71,22 +71,27 @@ FutureOr? f6() async* { } main() async { - dynamic r1 = await f1(); + dynamic r1 = f1(); var v1 = await r1.toList(); - Expect.isRuntimeTypeIterable(v1); + Expect.isRuntimeTypeImplementsIterable(v1); - dynamic r2 = await f2(); + dynamic r2 = f2(); var v2 = await r2.toList(); - Expect.isRuntimeTypeIterable(v2); + Expect.isRuntimeTypeImplementsIterable(v2); - dynamic r3 = await f3(); + dynamic r3 = f3(); var v3 = await r3.toList(); - Expect.isRuntimeTypeIterable(v3); + Expect.isRuntimeTypeImplementsIterable(v3); - dynamic r4 = await f4(); + dynamic r4 = f4(); var v4 = await r4.toList(); - Expect.isRuntimeTypeIterable(v4); + Expect.isRuntimeTypeImplementsIterable(v4); - // Can't check runtime types of return values of f5() and f6() because it's - // `void` + dynamic r5 = f5(); + var v5 = await r5.toList(); + Expect.isRuntimeTypeImplementsIterable(v5); + + dynamic r6 = f6(); + var v6 = await r6.toList(); + Expect.isRuntimeTypeImplementsIterable(v6); } diff --git a/Utils/expect_common.dart b/Utils/expect_common.dart index 3e651c2659..c7ce53dfc1 100644 --- a/Utils/expect_common.dart +++ b/Utils/expect_common.dart @@ -356,11 +356,12 @@ class Expect { _checkType(_checkIs, false, o); } - /// Checks that all elements of this `Iterable` have type `T`, not a subtype - /// of `T`. For example `[1, 2, 3] is Iterable` returns `true`, but - /// `isRuntimeTypeIterable([1, 2, 3])` will throw - /// `ExpectException`. Fails if `it` is not instance of `Iterable` - static void isRuntimeTypeIterable(Object? o) { + /// Checks that the run-time type of [o] implements `Iterable`, otherwise + /// throws. For example, + /// `isRuntimeTypeImplementsIterable([1, 2, 3])` will throw + /// `ExpectException`, but + /// `isRuntimeTypeImplementsIterable([1, 2, 3])` succeeds. + static void isRuntimeTypeImplementsIterable(Object? o) { if (o is! Iterable) { throw ExpectException("Not Iterable<$T>: ${o.runtimeType}"); } @@ -371,20 +372,6 @@ class Expect { throw ExpectException("Expected Iterable<$T> but found $o"); } } - - /// Checks that all elements of this `Iterable` don't have type `T`, but may - /// be a subtype of `T`. For example - /// `isNotRuntimeTypeIterable([1, 2, 3])` is Ok, but - /// isNotRuntimeTypeIterable([1, 2, 3 as num]) throws an - /// `ExpectException` - static void isNotRuntimeTypeIterable(Object? o) { - try { - Expect.isRuntimeTypeIterable(o); - } on ExpectException catch (_) { - return; - } - throw ExpectException("All elements in Iterable are $T"); - } } bool _identical(a, b) => identical(a, b); diff --git a/Utils/tests/Expect/isNotRuntimeTypeIterable_A01_t01.dart b/Utils/tests/Expect/isNotRuntimeTypeIterable_A01_t01.dart deleted file mode 100644 index 35f382816b..0000000000 --- a/Utils/tests/Expect/isNotRuntimeTypeIterable_A01_t01.dart +++ /dev/null @@ -1,47 +0,0 @@ -// 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 static void isNotRuntimeTypeIterable(Object? it) -/// Failure if `it` is an instance of `Iterable` and all elements have type -/// which is exactly the `T` -/// -/// @description Checks no exception is thrown when `it` is not an `Iterable` -/// or not all elements of it have a type `T` (not a subtype). Throws otherwise -/// @author sgrekhov22@gmail.com - -import "dart:async"; -import "../../../Utils/expect.dart"; - -main() { - Expect.isNotRuntimeTypeIterable([1, 2, 3]); - Expect.isNotRuntimeTypeIterable([]); - Expect.isNotRuntimeTypeIterable([]); - Expect.isNotRuntimeTypeIterable(Object()); - Expect.isNotRuntimeTypeIterable(Object()); - Expect.isNotRuntimeTypeIterable([1, 2, 3]); - Expect.isNotRuntimeTypeIterable([1, 2, 3]); - Expect.isNotRuntimeTypeIterable([1, 2, 3]); - Expect.isNotRuntimeTypeIterable([1, 2, 3]); - Expect.isNotRuntimeTypeIterable([1, 2, 3]); - - Future> f = Future>.value([1, 2, 3]); - Expect.isNotRuntimeTypeIterable(f); - - FutureOr> o1 = [1, 2, 3]; - Expect.isNotRuntimeTypeIterable(o1); - - FutureOr> o2 = Future>.value([1, 2, 3]); - Expect.isNotRuntimeTypeIterable(o2); - - Expect.throws(() { - Expect.isNotRuntimeTypeIterable([1, 2, 3]); - }, (e) => e is ExpectException); - Expect.throws(() { - FutureOr> o = [1, 2, 3]; - Expect.isNotRuntimeTypeIterable(o); - }, (e) => e is ExpectException); - Expect.throws(() { - Expect.isNotRuntimeTypeIterable([1, 2, 3 as num]); - }); -} diff --git a/Utils/tests/Expect/isRuntimeTypeIterable_A01_t01.dart b/Utils/tests/Expect/isRuntimeTypeIterable_A01_t01.dart index d6c13bd211..31409e2661 100644 --- a/Utils/tests/Expect/isRuntimeTypeIterable_A01_t01.dart +++ b/Utils/tests/Expect/isRuntimeTypeIterable_A01_t01.dart @@ -14,40 +14,40 @@ import "dart:async"; import "../../../Utils/expect.dart"; main() { - Expect.isRuntimeTypeIterable([1, 2, 3]); - Expect.isRuntimeTypeIterable([]); - Expect.isRuntimeTypeIterable([]); + Expect.isRuntimeTypeImplementsIterable([1, 2, 3]); + Expect.isRuntimeTypeImplementsIterable([]); + Expect.isRuntimeTypeImplementsIterable([]); FutureOr> o = [1, 2, 3]; - Expect.isRuntimeTypeIterable(o); + Expect.isRuntimeTypeImplementsIterable(o); Expect.throws(() { - Expect.isRuntimeTypeIterable([1, 2, 3]); + Expect.isRuntimeTypeImplementsIterable([1, 2, 3]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.isRuntimeTypeIterable([]); + Expect.isRuntimeTypeImplementsIterable([]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.isRuntimeTypeIterable([]); + Expect.isRuntimeTypeImplementsIterable([]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.isRuntimeTypeIterable([1, 2, 3 as num]); + Expect.isRuntimeTypeImplementsIterable([1, 2, 3 as num]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.isRuntimeTypeIterable([]); + Expect.isRuntimeTypeImplementsIterable([]); }, (e) => e is ExpectException); Expect.throws(() { - Expect.isRuntimeTypeIterable([1, 2, 3]); + Expect.isRuntimeTypeImplementsIterable([1, 2, 3]); }); Expect.throws(() { - Expect.isRuntimeTypeIterable([1, 2, 3]); + Expect.isRuntimeTypeImplementsIterable([1, 2, 3]); }); Expect.throws(() { - Expect.isRuntimeTypeIterable([1, 2, 3]); + Expect.isRuntimeTypeImplementsIterable([1, 2, 3]); }); Expect.throws(() { - Expect.isRuntimeTypeIterable([1, 2, 3]); + Expect.isRuntimeTypeImplementsIterable([1, 2, 3]); }); Expect.throws(() { - Expect.isRuntimeTypeIterable([1, 2, 3]); + Expect.isRuntimeTypeImplementsIterable([1, 2, 3]); }); } diff --git a/Utils/tests/Expect/isRuntimeTypeIterable_A01_t02.dart b/Utils/tests/Expect/isRuntimeTypeIterable_A01_t02.dart index 656efbc2cc..f99c78cb60 100644 --- a/Utils/tests/Expect/isRuntimeTypeIterable_A01_t02.dart +++ b/Utils/tests/Expect/isRuntimeTypeIterable_A01_t02.dart @@ -15,16 +15,16 @@ import "../../../Utils/expect.dart"; main() { Expect.throws(() { - Expect.isRuntimeTypeIterable(Object()); + Expect.isRuntimeTypeImplementsIterable(Object()); }, (e) => e is ExpectException); Expect.throws(() { Future> o = Future.value([1, 2, 3]); - Expect.isRuntimeTypeIterable(o); + Expect.isRuntimeTypeImplementsIterable(o); }, (e) => e is ExpectException); Expect.throws(() { FutureOr> o = Future.value([1, 2, 3]); - Expect.isRuntimeTypeIterable(o); + Expect.isRuntimeTypeImplementsIterable(o); }, (e) => e is ExpectException); }