Skip to content

Commit d778452

Browse files
authored
Fix #2485. Updateas and is expressions tests with a function type (#2538)
Update`as` and `is` expressions tests with a function type
1 parent ef86d60 commit d778452

File tree

4 files changed

+87
-3
lines changed

4 files changed

+87
-3
lines changed

Language/Expressions/Constants/as_type_A01_t02.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ main() {
7474

7575
const f1 = foo as void Function();
7676
const f2 = as as void Function();
77-
const f3 = bar<int> as int Function(int);
77+
const f3 = (bar<int>) as int Function(int);
7878

7979
const d = 2 as dynamic;
8080

Language/Expressions/Constants/is_not_type_A01_t02.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ main() {
7272
const fo7 = IntET2(1) is! FutureOr<IntET1Alias>;
7373

7474
const f1 = foo is! void Function();
75-
const f2 = bar<int> is! int Function(int);
75+
const f2 = (bar<int>) is! int Function(int);
7676

7777
const d = 2 is! dynamic;
7878

Language/Expressions/Constants/is_type_A01_t02.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ main() {
7373
const fo7 = IntET2(1) is FutureOr<IntET1Alias>;
7474

7575
const f1 = foo is void Function();
76-
const f2 = bar<int> is int Function<int>(int);
76+
const f2 = (bar<int>) is int Function(int);
7777

7878
const d = 2 is dynamic;
7979

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion This new syntax also introduces new ambiguities in the grammar,
6+
/// similar to the one we introduced with generic functions. Examples include:
7+
///
8+
/// f(a<b,c>(d)); // Existing ambiguity, resolved to a generic method call.
9+
/// f(x.a<b,c>[d]); // f((x.a<b, c>)[d]) or f((x.a < b), (c > [d]))
10+
/// f(x.a<b,c>-d); // f((x.a<b, c>)-d) or f((x.a < b), (c > -d]))
11+
/// The x.a<b,c> can be an explicitly instantiated generic function tear-off or
12+
/// an explicitly instantiated type literal named using a prefix, which is new.
13+
/// While neither type objects nor functions declare operator- or operator[],
14+
/// such could be added using extension methods.
15+
///
16+
/// We will disambiguate such situations heuristically based on the token
17+
/// following the > that matches the < we are ambiguous about. In the existing
18+
/// ambiguity we treat ( as a sign that the < starts a generic invocation. We
19+
/// extend the number of tokens which, when following a potential type argument
20+
/// list, makes us choose to parse the previous tokens as that type argument
21+
/// list.
22+
///
23+
/// There is a number of tokens which very consistently end an expression, and
24+
/// we include all those:
25+
///
26+
/// ), }, ], ;, :, ,
27+
///
28+
/// Then we include tokens which we predict will continue a generic instantiation:
29+
///
30+
/// ( . == !=
31+
///
32+
/// The first six are tokens which cannot possibly start an expression, and
33+
/// therefore cannot occur after a greater-than infix operator. The last four
34+
/// tokens can continue an expression, and of those only ( can also start an
35+
/// expression, and we already decided how to disambiguate that).
36+
///
37+
/// There are many other tokens which currently cannot continue an expression
38+
/// (and therefore cannot validly follow a type argument list) or which cannot
39+
/// start an expression (and therefore cannot validly follow a greater-than
40+
/// operator), but in the service of keeping our future options open, we choose
41+
/// a design that does not rely on those restrictions. For example we omit most
42+
/// infix operators from being "continuation tokens", even though they currently
43+
/// cannot start a new expression, and therefore cannot follow a > infix
44+
/// operator. This leaves us open to allowing some of those operators as prefix
45+
/// operators in the future, like we currently allow the - operator.
46+
///
47+
/// @description Checks that it is a syntax error if function with type argument
48+
/// specified is part of `as`, `as!` or `is` expressions
49+
/// @author [email protected]
50+
51+
int bar<T>(T t) => 42;
52+
void foo<T1, T2, T3>() {}
53+
54+
main() {
55+
const c1 = bar<int> as int Function(int);
56+
// ^^^
57+
// [analyzer] unspecified
58+
// [cfe] unspecified
59+
60+
const c2 = bar<int> is! int Function(int);
61+
// ^^^
62+
// [analyzer] unspecified
63+
// [cfe] unspecified
64+
65+
const c3 = bar<int> is int Function(int);
66+
// ^^^
67+
// [analyzer] unspecified
68+
// [cfe] unspecified
69+
70+
const c4 = foo<int, String, bool> as void Function();
71+
// ^
72+
// [analyzer] unspecified
73+
// [cfe] unspecified
74+
75+
const c5 = foo<int, String, bool> is! void Function();
76+
// ^
77+
// [analyzer] unspecified
78+
// [cfe] unspecified
79+
80+
const c6 = foo<int, String, bool> is void Function();
81+
// ^
82+
// [analyzer] unspecified
83+
// [cfe] unspecified
84+
}

0 commit comments

Comments
 (0)