Skip to content
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
Expand Up @@ -3,3 +3,5 @@ class I[T]((yield 1)): ...
class J[T]((yield from 1)): ...
class K[T: (yield 1)]: ... # yield in TypeVar
class L[T: (x := 1)]: ... # named expr in TypeVar
class M[T]((await 1)): ...
class N[T: (await 1)]: ...
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
def d[T]() -> (await 1): ...
def e[T](arg: (await 1)): ...
def f[T]() -> (y := 3): ...
def g[T](arg: (x := 1)): ...
def h[T](x: (yield 1)): ...
Expand All @@ -12,3 +14,7 @@ def t[T: (x := 1)](): ... # named expr in TypeVar bound
def u[T = (x := 1)](): ... # named expr in TypeVar default
def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default
def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default
def t[T: (await 1)](): ... # await in TypeVar bound
def u[T = (await 1)](): ... # await in TypeVar default
def v[*Ts = (await 1)](): ... # await in TypeVarTuple default
def w[**Ts = (await 1)](): ... # await in ParamSpec default
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ def i(x: (yield 1)): ...
def k() -> (yield 1): ...
def m(x: (yield from 1)): ...
def o() -> (yield from 1): ...
async def outer():
def f() -> (await 1): ...
def g(arg: (await 1)): ...
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# parse_options: {"target-version": "3.14"}
a: (x := 1)
def outer():
b: (yield 1)
c: (yield from 1)
async def outer():
d: (await 1)
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
type X[**Ts = (yield 1)] = int # ParamSpec default
type Y = (yield 1) # yield in value
type Y = (x := 1) # named expr in value
type Y[T: (await 1)] = int # await in bound
type Y = (await 1) # await in value
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ class F(y := list): ...
def f():
class G((yield 1)): ...
class H((yield from 1)): ...
async def f():
class G((await 1)): ...
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# parse_options: {"target-version": "3.13"}
def f() -> (y := 3): ...
def g(arg: (x := 1)): ...
def outer():
def i(x: (yield 1)): ...
def k() -> (yield 1): ...
def m(x: (yield from 1)): ...
def o() -> (yield from 1): ...
async def outer():
def f() -> (await 1): ...
def g(arg: (await 1)): ...
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# parse_options: {"target-version": "3.13"}
a: (x := 1)
def outer():
b: (yield 1)
c: (yield from 1)
async def outer():
d: (await 1)
59 changes: 58 additions & 1 deletion crates/ruff_python_parser/src/semantic_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,50 @@ impl SemanticSyntaxChecker {

fn check_annotation<Ctx: SemanticSyntaxContext>(stmt: &ast::Stmt, ctx: &Ctx) {
match stmt {
Stmt::AnnAssign(ast::StmtAnnAssign { annotation, .. }) => {
if ctx.python_version() > PythonVersion::PY313 {
// test_ok valid_annotation_py313
// # parse_options: {"target-version": "3.13"}
// a: (x := 1)
// def outer():
// b: (yield 1)
// c: (yield from 1)
// async def outer():
// d: (await 1)

// test_err invalid_annotation_py314
// # parse_options: {"target-version": "3.14"}
// a: (x := 1)
// def outer():
// b: (yield 1)
// c: (yield from 1)
// async def outer():
// d: (await 1)
let mut visitor = InvalidExpressionVisitor {
position: InvalidExpressionPosition::TypeAnnotation,
ctx,
};
visitor.visit_expr(annotation);
}
}
Stmt::FunctionDef(ast::StmtFunctionDef {
type_params,
parameters,
returns,
..
}) => {
// test_ok valid_annotation_function
// test_ok valid_annotation_function_py313
// # parse_options: {"target-version": "3.13"}
// def f() -> (y := 3): ...
// def g(arg: (x := 1)): ...
// def outer():
// def i(x: (yield 1)): ...
// def k() -> (yield 1): ...
// def m(x: (yield from 1)): ...
// def o() -> (yield from 1): ...
// async def outer():
// def f() -> (await 1): ...
// def g(arg: (await 1)): ...

// test_err invalid_annotation_function_py314
// # parse_options: {"target-version": "3.14"}
Expand All @@ -143,8 +173,13 @@ impl SemanticSyntaxChecker {
// def k() -> (yield 1): ...
// def m(x: (yield from 1)): ...
// def o() -> (yield from 1): ...
// async def outer():
// def f() -> (await 1): ...
// def g(arg: (await 1)): ...

// test_err invalid_annotation_function
// def d[T]() -> (await 1): ...
// def e[T](arg: (await 1)): ...
// def f[T]() -> (y := 3): ...
// def g[T](arg: (x := 1)): ...
// def h[T](x: (yield 1)): ...
Expand All @@ -159,6 +194,10 @@ impl SemanticSyntaxChecker {
// def u[T = (x := 1)](): ... # named expr in TypeVar default
// def v[*Ts = (x := 1)](): ... # named expr in TypeVarTuple default
// def w[**Ts = (x := 1)](): ... # named expr in ParamSpec default
// def t[T: (await 1)](): ... # await in TypeVar bound
// def u[T = (await 1)](): ... # await in TypeVar default
// def v[*Ts = (await 1)](): ... # await in TypeVarTuple default
// def w[**Ts = (await 1)](): ... # await in ParamSpec default
let mut visitor = InvalidExpressionVisitor {
position: InvalidExpressionPosition::TypeAnnotation,
ctx,
Expand Down Expand Up @@ -194,13 +233,17 @@ impl SemanticSyntaxChecker {
// def f():
// class G((yield 1)): ...
// class H((yield from 1)): ...
// async def f():
// class G((await 1)): ...

// test_err invalid_annotation_class
// class F[T](y := list): ...
// class I[T]((yield 1)): ...
// class J[T]((yield from 1)): ...
// class K[T: (yield 1)]: ... # yield in TypeVar
// class L[T: (x := 1)]: ... # named expr in TypeVar
// class M[T]((await 1)): ...
// class N[T: (await 1)]: ...
let mut visitor = InvalidExpressionVisitor {
position: InvalidExpressionPosition::TypeAnnotation,
ctx,
Expand All @@ -221,6 +264,8 @@ impl SemanticSyntaxChecker {
// type X[**Ts = (yield 1)] = int # ParamSpec default
// type Y = (yield 1) # yield in value
// type Y = (x := 1) # named expr in value
// type Y[T: (await 1)] = int # await in bound
// type Y = (await 1) # await in value
let mut visitor = InvalidExpressionVisitor {
position: InvalidExpressionPosition::TypeAlias,
ctx,
Expand Down Expand Up @@ -878,13 +923,15 @@ impl Display for InvalidExpressionPosition {
pub enum InvalidExpressionKind {
Yield,
NamedExpr,
Await,
}

impl Display for InvalidExpressionKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
InvalidExpressionKind::Yield => "yield expression",
InvalidExpressionKind::NamedExpr => "named expression",
InvalidExpressionKind::Await => "await expression",
})
}
}
Expand Down Expand Up @@ -1115,6 +1162,16 @@ where
*range,
);
}
Expr::Await(ast::ExprAwait { range, .. }) => {
SemanticSyntaxChecker::add_error(
self.ctx,
SemanticSyntaxErrorKind::InvalidExpression(
InvalidExpressionKind::Await,
self.position,
),
*range,
);
}
_ => {}
}
ast::visitor::walk_expr(self, expr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ input_file: crates/ruff_python_parser/resources/inline/err/invalid_annotation_cl
```
Module(
ModModule {
range: 0..193,
range: 0..247,
body: [
ClassDef(
StmtClassDef {
Expand Down Expand Up @@ -319,6 +319,122 @@ Module(
],
},
),
ClassDef(
StmtClassDef {
range: 193..219,
decorator_list: [],
name: Identifier {
id: Name("M"),
range: 199..200,
},
type_params: Some(
TypeParams {
range: 200..203,
type_params: [
TypeVar(
TypeParamTypeVar {
range: 201..202,
name: Identifier {
id: Name("T"),
range: 201..202,
},
bound: None,
default: None,
},
),
],
},
),
arguments: Some(
Arguments {
range: 203..214,
args: [
Await(
ExprAwait {
range: 205..212,
value: NumberLiteral(
ExprNumberLiteral {
range: 211..212,
value: Int(
1,
),
},
),
},
),
],
keywords: [],
},
),
body: [
Expr(
StmtExpr {
range: 216..219,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 216..219,
},
),
},
),
],
},
),
ClassDef(
StmtClassDef {
range: 220..246,
decorator_list: [],
name: Identifier {
id: Name("N"),
range: 226..227,
},
type_params: Some(
TypeParams {
range: 227..241,
type_params: [
TypeVar(
TypeParamTypeVar {
range: 228..240,
name: Identifier {
id: Name("T"),
range: 228..229,
},
bound: Some(
Await(
ExprAwait {
range: 232..239,
value: NumberLiteral(
ExprNumberLiteral {
range: 238..239,
value: Int(
1,
),
},
),
},
),
),
default: None,
},
),
],
},
),
arguments: None,
body: [
Expr(
StmtExpr {
range: 243..246,
value: EllipsisLiteral(
ExprEllipsisLiteral {
range: 243..246,
},
),
},
),
],
},
),
],
},
)
Expand Down Expand Up @@ -358,6 +474,7 @@ Module(
4 | class K[T: (yield 1)]: ... # yield in TypeVar
| ^^^^^^^ Syntax Error: yield expression cannot be used within a TypeVar bound
5 | class L[T: (x := 1)]: ... # named expr in TypeVar
6 | class M[T]((await 1)): ...
|


Expand All @@ -366,4 +483,23 @@ Module(
4 | class K[T: (yield 1)]: ... # yield in TypeVar
5 | class L[T: (x := 1)]: ... # named expr in TypeVar
| ^^^^^^ Syntax Error: named expression cannot be used within a TypeVar bound
6 | class M[T]((await 1)): ...
7 | class N[T: (await 1)]: ...
|


|
4 | class K[T: (yield 1)]: ... # yield in TypeVar
5 | class L[T: (x := 1)]: ... # named expr in TypeVar
6 | class M[T]((await 1)): ...
| ^^^^^^^ Syntax Error: await expression cannot be used within a generic definition
7 | class N[T: (await 1)]: ...
|


|
5 | class L[T: (x := 1)]: ... # named expr in TypeVar
6 | class M[T]((await 1)): ...
7 | class N[T: (await 1)]: ...
| ^^^^^^^ Syntax Error: await expression cannot be used within a TypeVar bound
|
Loading
Loading