Skip to content

Commit 9123932

Browse files
committed
[syntax-errors] Extend annotation checks to await
Summary -- This PR extends the changes in #17101 to include `await` in the same positions. I also renamed the `valid_annotation_function` test to include `_py313` and explicitly passed a Python version to contrast it with the `_py314` version. Test Plan -- New test cases added to existing files.
1 parent 5e0f563 commit 9123932

13 files changed

+1695
-233
lines changed

crates/ruff_python_parser/resources/inline/err/invalid_annotation_class.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ class I[T]((yield 1)): ...
33
class J[T]((yield from 1)): ...
44
class K[T: (yield 1)]: ... # yield in TypeVar
55
class L[T: (x := 1)]: ... # named expr in TypeVar
6+
class M[T]((await 1)): ...
7+
class N[T: (await 1)]: ...

crates/ruff_python_parser/resources/inline/err/invalid_annotation_function.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
def d[T]() -> (await 1): ...
2+
def e[T](arg: (await 1)): ...
13
def f[T]() -> (y := 3): ...
24
def g[T](arg: (x := 1)): ...
35
def h[T](x: (yield 1)): ...
@@ -12,3 +14,7 @@ def t[T: (x := 1)](): ... # named expr in TypeVar bound
1214
def u[T = (x := 1)](): ... # named expr in TypeVar default
1315
def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default
1416
def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default
17+
def t[T: (await 1)](): ... # await in TypeVar bound
18+
def u[T = (await 1)](): ... # await in TypeVar default
19+
def v[*Ts = (await 1)](): ... # await in TypeVarTuple default
20+
def w[**Ts = (await 1)](): ... # await in ParamSpec default

crates/ruff_python_parser/resources/inline/err/invalid_annotation_function_py314.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ def i(x: (yield 1)): ...
66
def k() -> (yield 1): ...
77
def m(x: (yield from 1)): ...
88
def o() -> (yield from 1): ...
9+
async def outer():
10+
def f() -> (await 1): ...
11+
def g(arg: (await 1)): ...

crates/ruff_python_parser/resources/inline/err/invalid_annotation_type_alias.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@
44
type X[**Ts = (yield 1)] = int # ParamSpec default
55
type Y = (yield 1) # yield in value
66
type Y = (x := 1) # named expr in value
7+
type Y[T: (await 1)] = int # await in bound
8+
type Y = (await 1) # await in value

crates/ruff_python_parser/resources/inline/ok/valid_annotation_class.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ class F(y := list): ...
22
def f():
33
class G((yield 1)): ...
44
class H((yield from 1)): ...
5+
async def f():
6+
class G((await 1)): ...
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
# parse_options: {"target-version": "3.13"}
12
def f() -> (y := 3): ...
23
def g(arg: (x := 1)): ...
34
def outer():
45
def i(x: (yield 1)): ...
56
def k() -> (yield 1): ...
67
def m(x: (yield from 1)): ...
78
def o() -> (yield from 1): ...
9+
async def outer():
10+
def f() -> (await 1): ...
11+
def g(arg: (await 1)): ...

crates/ruff_python_parser/src/semantic_errors.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,18 @@ impl SemanticSyntaxChecker {
125125
returns,
126126
..
127127
}) => {
128-
// test_ok valid_annotation_function
128+
// test_ok valid_annotation_function_py313
129+
// # parse_options: {"target-version": "3.13"}
129130
// def f() -> (y := 3): ...
130131
// def g(arg: (x := 1)): ...
131132
// def outer():
132133
// def i(x: (yield 1)): ...
133134
// def k() -> (yield 1): ...
134135
// def m(x: (yield from 1)): ...
135136
// def o() -> (yield from 1): ...
137+
// async def outer():
138+
// def f() -> (await 1): ...
139+
// def g(arg: (await 1)): ...
136140

137141
// test_err invalid_annotation_function_py314
138142
// # parse_options: {"target-version": "3.14"}
@@ -143,8 +147,13 @@ impl SemanticSyntaxChecker {
143147
// def k() -> (yield 1): ...
144148
// def m(x: (yield from 1)): ...
145149
// def o() -> (yield from 1): ...
150+
// async def outer():
151+
// def f() -> (await 1): ...
152+
// def g(arg: (await 1)): ...
146153

147154
// test_err invalid_annotation_function
155+
// def d[T]() -> (await 1): ...
156+
// def e[T](arg: (await 1)): ...
148157
// def f[T]() -> (y := 3): ...
149158
// def g[T](arg: (x := 1)): ...
150159
// def h[T](x: (yield 1)): ...
@@ -159,6 +168,10 @@ impl SemanticSyntaxChecker {
159168
// def u[T = (x := 1)](): ... # named expr in TypeVar default
160169
// def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default
161170
// def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default
171+
// def t[T: (await 1)](): ... # await in TypeVar bound
172+
// def u[T = (await 1)](): ... # await in TypeVar default
173+
// def v[*Ts = (await 1)](): ... # await in TypeVarTuple default
174+
// def w[**Ts = (await 1)](): ... # await in ParamSpec default
162175
let mut visitor = InvalidExpressionVisitor {
163176
position: InvalidExpressionPosition::TypeAnnotation,
164177
ctx,
@@ -194,13 +207,17 @@ impl SemanticSyntaxChecker {
194207
// def f():
195208
// class G((yield 1)): ...
196209
// class H((yield from 1)): ...
210+
// async def f():
211+
// class G((await 1)): ...
197212

198213
// test_err invalid_annotation_class
199214
// class F[T](y := list): ...
200215
// class I[T]((yield 1)): ...
201216
// class J[T]((yield from 1)): ...
202217
// class K[T: (yield 1)]: ... # yield in TypeVar
203218
// class L[T: (x := 1)]: ... # named expr in TypeVar
219+
// class M[T]((await 1)): ...
220+
// class N[T: (await 1)]: ...
204221
let mut visitor = InvalidExpressionVisitor {
205222
position: InvalidExpressionPosition::TypeAnnotation,
206223
ctx,
@@ -221,6 +238,8 @@ impl SemanticSyntaxChecker {
221238
// type X[**Ts = (yield 1)] = int # ParamSpec default
222239
// type Y = (yield 1) # yield in value
223240
// type Y = (x := 1) # named expr in value
241+
// type Y[T: (await 1)] = int # await in bound
242+
// type Y = (await 1) # await in value
224243
let mut visitor = InvalidExpressionVisitor {
225244
position: InvalidExpressionPosition::TypeAlias,
226245
ctx,
@@ -878,13 +897,15 @@ impl Display for InvalidExpressionPosition {
878897
pub enum InvalidExpressionKind {
879898
Yield,
880899
NamedExpr,
900+
Await,
881901
}
882902

883903
impl Display for InvalidExpressionKind {
884904
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
885905
f.write_str(match self {
886906
InvalidExpressionKind::Yield => "yield expression",
887907
InvalidExpressionKind::NamedExpr => "named expression",
908+
InvalidExpressionKind::Await => "await expression",
888909
})
889910
}
890911
}
@@ -1115,6 +1136,16 @@ where
11151136
*range,
11161137
);
11171138
}
1139+
Expr::Await(ast::ExprAwait { range, .. }) => {
1140+
SemanticSyntaxChecker::add_error(
1141+
self.ctx,
1142+
SemanticSyntaxErrorKind::InvalidExpression(
1143+
InvalidExpressionKind::Await,
1144+
self.position,
1145+
),
1146+
*range,
1147+
);
1148+
}
11181149
_ => {}
11191150
}
11201151
ast::visitor::walk_expr(self, expr);

crates/ruff_python_parser/tests/snapshots/invalid_syntax@invalid_annotation_class.py.snap

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_cl
77
```
88
Module(
99
ModModule {
10-
range: 0..193,
10+
range: 0..247,
1111
body: [
1212
ClassDef(
1313
StmtClassDef {
@@ -319,6 +319,122 @@ Module(
319319
],
320320
},
321321
),
322+
ClassDef(
323+
StmtClassDef {
324+
range: 193..219,
325+
decorator_list: [],
326+
name: Identifier {
327+
id: Name("M"),
328+
range: 199..200,
329+
},
330+
type_params: Some(
331+
TypeParams {
332+
range: 200..203,
333+
type_params: [
334+
TypeVar(
335+
TypeParamTypeVar {
336+
range: 201..202,
337+
name: Identifier {
338+
id: Name("T"),
339+
range: 201..202,
340+
},
341+
bound: None,
342+
default: None,
343+
},
344+
),
345+
],
346+
},
347+
),
348+
arguments: Some(
349+
Arguments {
350+
range: 203..214,
351+
args: [
352+
Await(
353+
ExprAwait {
354+
range: 205..212,
355+
value: NumberLiteral(
356+
ExprNumberLiteral {
357+
range: 211..212,
358+
value: Int(
359+
1,
360+
),
361+
},
362+
),
363+
},
364+
),
365+
],
366+
keywords: [],
367+
},
368+
),
369+
body: [
370+
Expr(
371+
StmtExpr {
372+
range: 216..219,
373+
value: EllipsisLiteral(
374+
ExprEllipsisLiteral {
375+
range: 216..219,
376+
},
377+
),
378+
},
379+
),
380+
],
381+
},
382+
),
383+
ClassDef(
384+
StmtClassDef {
385+
range: 220..246,
386+
decorator_list: [],
387+
name: Identifier {
388+
id: Name("N"),
389+
range: 226..227,
390+
},
391+
type_params: Some(
392+
TypeParams {
393+
range: 227..241,
394+
type_params: [
395+
TypeVar(
396+
TypeParamTypeVar {
397+
range: 228..240,
398+
name: Identifier {
399+
id: Name("T"),
400+
range: 228..229,
401+
},
402+
bound: Some(
403+
Await(
404+
ExprAwait {
405+
range: 232..239,
406+
value: NumberLiteral(
407+
ExprNumberLiteral {
408+
range: 238..239,
409+
value: Int(
410+
1,
411+
),
412+
},
413+
),
414+
},
415+
),
416+
),
417+
default: None,
418+
},
419+
),
420+
],
421+
},
422+
),
423+
arguments: None,
424+
body: [
425+
Expr(
426+
StmtExpr {
427+
range: 243..246,
428+
value: EllipsisLiteral(
429+
ExprEllipsisLiteral {
430+
range: 243..246,
431+
},
432+
),
433+
},
434+
),
435+
],
436+
},
437+
),
322438
],
323439
},
324440
)
@@ -358,6 +474,7 @@ Module(
358474
4 | class K[T: (yield 1)]: ... # yield in TypeVar
359475
| ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound
360476
5 | class L[T: (x := 1)]: ... # named expr in TypeVar
477+
6 | class M[T]((await 1)): ...
361478
|
362479

363480

@@ -366,4 +483,23 @@ Module(
366483
4 | class K[T: (yield 1)]: ... # yield in TypeVar
367484
5 | class L[T: (x := 1)]: ... # named expr in TypeVar
368485
| ^^^^^^ Syntax Error: named expression cannot be used within a TypeVar bound
486+
6 | class M[T]((await 1)): ...
487+
7 | class N[T: (await 1)]: ...
488+
|
489+
490+
491+
|
492+
4 | class K[T: (yield 1)]: ... # yield in TypeVar
493+
5 | class L[T: (x := 1)]: ... # named expr in TypeVar
494+
6 | class M[T]((await 1)): ...
495+
| ^^^^^^^ Syntax Error: await expression cannot be used within a generic definition
496+
7 | class N[T: (await 1)]: ...
497+
|
498+
499+
500+
|
501+
5 | class L[T: (x := 1)]: ... # named expr in TypeVar
502+
6 | class M[T]((await 1)): ...
503+
7 | class N[T: (await 1)]: ...
504+
| ^^^^^^^ Syntax Error: await expression cannot be used within a TypeVar bound
369505
|

0 commit comments

Comments
 (0)