Skip to content

#1401. Async for-in tests for patterns #2032

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// @assertion It is a compile-time error if an asynchronous for-in statement
/// appears inside a synchronous function
///
/// @description Checks that it is a compile-time error if an asynchronous
/// for-in statement appears inside a synchronous function
/// @author [email protected]
/// @issue 52228

// SharedOptions=--enable-experiment=patterns,records

import "patterns_lib.dart";

test1() {
await for (var (v1 && v2) in Stream.fromIterable([1, 2, 3])) {
// ^^
// [analyzer] unspecified
// [cfe] unspecified
print(v1);
print(v2);
}
}

test2() {
await for (final (num v) in Stream.fromIterable([1, 2, 3])) {
// ^^
// [analyzer] unspecified
// [cfe] unspecified
print(v);
}
}

test3() {
await for (var (v) in Stream.fromIterable([1, 2, 3])) {
// ^^
// [analyzer] unspecified
// [cfe] unspecified
print(v);
}
}

test4() {
await for (final [v] in Stream.fromIterable([[1], [2], [3]])) {
// ^^
// [analyzer] unspecified
// [cfe] unspecified
print(v);
}
}

test5() {
await for (var {"k": v} in Stream.fromIterable([{"k": 1}])) {
// ^^
// [analyzer] unspecified
// [cfe] unspecified
print(v);
}
}

test6() {
await for (final (v1, n: v2) in Stream.fromIterable([(1, n: 2)])) {
// ^^
// [analyzer] unspecified
// [cfe] unspecified
print(v1);
print(v2);
}
}

test7() {
await for (var Square(area: v) in Stream.fromIterable([Square(1)])) {
// ^^
// [analyzer] unspecified
// [cfe] unspecified
print(v);
}
}

main() async {
test1();
test2();
test3();
test4();
test5();
test6();
test7();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// 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.

/// TODO (sgrekhov) Update assertion part when appropriate spec will be ready
/// @assertion
/// A statement of the form:
///
/// for (<keyword> <pattern> in <expression>) <statement>
///
/// Where <keyword> is var or final is treated like so:
/// 1. Let I be the static type of <expression>, inferred using context type
/// schema Iterable<P> where P is the context type schema of <pattern>.
/// 2. Calculate the element type of I:
/// i. If I implements Iterable<T> for some T then E is T.
/// ii. Else if I is dynamic then E is dynamic.
/// iii. Else it is a compile-time error.
/// 3. Type check <pattern> with matched value type E.
/// 4. If there are no compile-time errors, then execution proceeds as the
/// following code, where id1 and id2 are fresh identifiers:
/// ```dart
/// var id1 = <expression>;
/// var id2 = id1.iterator;
/// while (id2.moveNext()) {
/// <keyword> <pattern> = id2.current;
/// { <statement> }
/// }
/// ```
/// @description Checks that in an async for-in loop if `I` implements
/// `Stream<T>` for some `T` then `E` is `T`. Test `T` inferred from `<pattern>`
/// to `<expression>` and from `<expression>` to `<pattern>`
/// @author [email protected]

// SharedOptions=--enable-experiment=patterns,records

import "../../Utils/expect.dart";
import "../../Utils/static_type_helper.dart";
import "patterns_lib.dart";

extension Storing on Object? {
static dynamic stored;
void get store => stored = this;
}

main() async {
String log = "";
await for (var (num v1) in Stream.fromIterable([1, 2, 3])..store) {
v1.expectStaticType<Exactly<num>>();
log += "$v1;";
}
Expect.equals("1;2;3;", log);
Expect.isTrue(Storing.stored is Stream<num>);

log = "";
await for (final (v2) in Stream<num>.fromIterable([1, 2, 3])) {
v2.expectStaticType<Exactly<num>>();
log += "$v2;";
}
Expect.equals("1;2;3;", log);
log = "";

log = "";
await for (var <num>[v3] in Stream.fromIterable([
[1],
[2],
[3]
])..store) {
v3.expectStaticType<Exactly<num>>();
log += "$v3;";
}
Expect.equals("1;2;3;", log);
Expect.isTrue(Storing.stored is Stream<List<num>>);

log = "";
await for (final [v4] in Stream<List<num>>.fromIterable([
[1],
[2],
[3]
])) {
v4.expectStaticType<Exactly<num>>();
log += "$v4;";
}
Expect.equals("1;2;3;", log);

log = "";
await for (var <String, num>{"k1": v5} in Stream.fromIterable([
{"k1": 1}
])..store) {
v5.expectStaticType<Exactly<num>>();
log += "$v5;";
}
Expect.equals("1;", log);
Expect.isTrue(Storing.stored is Stream<Map<String, num>>);

log = "";
await for (final {"k1": v6} in Stream<Map<String, num>>.fromIterable([
{"k1": 1}
])) {
v6.expectStaticType<Exactly<num>>();
log += "$v6;";
}
Expect.equals("1;", log);

log = "";
await for (var (num v7, n: num v8) in Stream.fromIterable([(1, n: 2)])
..store) {
v7.expectStaticType<Exactly<num>>();
v8.expectStaticType<Exactly<num>>();
log += "$v7;$v8;";
}
Expect.equals("1;2;", log);
Expect.isTrue(Storing.stored is Stream<(num, {num n})>);

log = "";
await for (final (v9, n: v10)
in Stream<(num, {num n})>.fromIterable([(1, n: 2)])) {
v9.expectStaticType<Exactly<num>>();
v10.expectStaticType<Exactly<num>>();
log += "$v9;$v10;";
}
Expect.equals("1;2;", log);

log = "";
await for (var Square<Centimeter>(area: v11)
in Stream.fromIterable([Square(1)])..store) {
v11.expectStaticType<Exactly<Unit<Centimeter>>>();
log += "$v11;";
}
Expect.equals("1;", log);
Expect.isTrue(Storing.stored is Stream<Square<Centimeter>>);

log = "";
await for (final Square(area: v12)
in Stream<Square<Centimeter>>.fromIterable([Square<Centimeter>(1)])) {
v12.expectStaticType<Exactly<Unit<Centimeter>>>();
log += "$v12;";
}
Expect.equals("1;", log);

log = "";
await for (var (num v1 && v2) in Stream.fromIterable([1, 2, 3])..store) {
v1.expectStaticType<Exactly<num>>();
v2.expectStaticType<Exactly<num>>();
log += "$v1&&$v2;";
}
Expect.equals("1&&1;2&&2;3&&3;", log);
Expect.isTrue(Storing.stored is Stream<num>);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// 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.

/// TODO (sgrekhov) Update assertion part when appropriate spec will be ready
/// @assertion
/// A statement of the form:
///
/// for (<keyword> <pattern> in <expression>) <statement>
///
/// Where <keyword> is var or final is treated like so:
/// 1. Let I be the static type of <expression>, inferred using context type
/// schema Iterable<P> where P is the context type schema of <pattern>.
/// 2. Calculate the element type of I:
/// i. If I implements Iterable<T> for some T then E is T.
/// ii. Else if I is dynamic then E is dynamic.
/// iii. Else it is a compile-time error.
/// 3. Type check <pattern> with matched value type E.
/// 4. If there are no compile-time errors, then execution proceeds as the
/// following code, where id1 and id2 are fresh identifiers:
/// ```dart
/// var id1 = <expression>;
/// var id2 = id1.iterator;
/// while (id2.moveNext()) {
/// <keyword> <pattern> = id2.current;
/// { <statement> }
/// }
/// ```
/// @description Checks that in an async for-in loop if `I` is `dynamic` and
/// runtime type of `I` is `Stream<T>` where `T` is assignable to `<pattern>`
/// required type then for-in statement works as expected. In particular, if `I`
/// is `dynamic` then element type is `dynamic` and execution of the body does
/// take place
/// @author [email protected]

// SharedOptions=--enable-experiment=patterns,records

import "../../Utils/expect.dart";
import "../../Utils/static_type_helper.dart";
import "patterns_lib.dart";

main() async {
String log = "";
await for (var (num v1) in Stream.fromIterable([1, 2, 3]) as dynamic) {
v1.expectStaticType<Exactly<num>>();
log += "$v1;";
}
Expect.equals("1;2;3;", log);

log = "";
await for (final (v2) in Stream<num>.fromIterable([1, 2, 3]) as dynamic) {
Expect.throws(() {
v2.whatever;
}); // v2 is dynamic
log += "$v2;";
}
Expect.equals("1;2;3;", log);
log = "";

log = "";
await for (var <num>[v3] in Stream.fromIterable([
[1],
[2],
[3]
]) as dynamic) {
v3.expectStaticType<Exactly<num>>();
log += "$v3;";
}
Expect.equals("1;2;3;", log);

log = "";
await for (final [v4] in Stream<List<num>>.fromIterable([
[1],
[2],
[3]
]) as dynamic) {
Expect.throws(() {
v4.whatever;
});
log += "$v4;";
}
Expect.equals("1;2;3;", log);

log = "";
await for (var <String, num>{"k1": v5} in Stream.fromIterable([
{"k1": 1}
]) as dynamic) {
v5.expectStaticType<Exactly<num>>();
log += "$v5;";
}
Expect.equals("1;", log);

log = "";
await for (final {"k1": v6} in Stream<Map<String, num>>.fromIterable([
{"k1": 1}
]) as dynamic) {
Expect.throws(() {
v6.whatever;
});
log += "$v6;";
}
Expect.equals("1;", log);

log = "";
await for (var (num v7, n: num v8)
in Stream.fromIterable([(1, n: 2)]) as dynamic) {
v7.expectStaticType<Exactly<num>>();
v8.expectStaticType<Exactly<num>>();
log += "$v7;$v8;";
}
Expect.equals("1;2;", log);

log = "";
await for (final (v9, n: v10)
in Stream<(num, {num n})>.fromIterable([(1, n: 2)]) as dynamic) {
Expect.throws(() {
v9.whatever;
});
Expect.throws(() {
v10.whatever;
});
log += "$v9;$v10;";
}
Expect.equals("1;2;", log);

log = "";
await for (var Square<Centimeter>(area: v11)
in Stream.fromIterable([Square<Centimeter>(1)]) as dynamic) {
v11.expectStaticType<Exactly<Unit<Centimeter>>>();
log += "$v11;";
}
Expect.equals("1;", log);

log = "";
await for (final Square(area: v12)
in Stream<Square<Centimeter>>.fromIterable([Square<Centimeter>(1)])
as dynamic) {
v12.expectStaticType<Exactly<Unit<MetricUnits>>>();
log += "$v12;";
}
Expect.equals("1;", log);
}
Loading