@@ -24,12 +24,13 @@ use ruff_python_ast::{
2424 Alias , Arguments , BoolOp , CmpOp , Comprehension , ConversionFlag , DebugText , Decorator , DictItem ,
2525 ExceptHandler , ExceptHandlerExceptHandler , Expr , ExprAttribute , ExprBoolOp , ExprContext ,
2626 ExprFString , ExprList , ExprName , ExprSlice , ExprStarred , ExprSubscript , ExprTuple , ExprUnaryOp ,
27- FString , FStringFlags , FStringPart , Identifier , Int , InterpolatedElement ,
28- InterpolatedStringElement , InterpolatedStringElements , Keyword , MatchCase , ModExpression ,
29- ModModule , Operator , Parameters , Pattern , PatternMatchAs , PatternMatchClass ,
30- PatternMatchMapping , PatternMatchOr , PatternMatchSequence , PatternMatchSingleton ,
31- PatternMatchStar , PatternMatchValue , Singleton , Stmt , StmtExpr , TypeParam , TypeParamParamSpec ,
32- TypeParamTypeVar , TypeParamTypeVarTuple , TypeParams , UnaryOp , WithItem ,
27+ FString , FStringFlags , FStringPart , Identifier , Int , InterpolatedStringElement ,
28+ InterpolatedStringElements , Keyword , MatchCase , ModExpression , ModModule , Operator , Parameters ,
29+ Pattern , PatternMatchAs , PatternMatchClass , PatternMatchMapping , PatternMatchOr ,
30+ PatternMatchSequence , PatternMatchSingleton , PatternMatchStar , PatternMatchValue , Singleton ,
31+ Stmt , StmtExpr , TypeParam , TypeParamParamSpec , TypeParamTypeVar , TypeParamTypeVarTuple ,
32+ TypeParams , UnaryOp , WithItem ,
33+ visitor:: { Visitor , walk_expr} ,
3334} ;
3435use ruff_text_size:: { Ranged , TextRange } ;
3536use rustpython_compiler_core:: {
@@ -5435,134 +5436,35 @@ impl Compiler {
54355436
54365437 /// Whether the expression contains an await expression and
54375438 /// thus requires the function to be async.
5438- /// Async with and async for are statements, so I won't check for them here
5439+ ///
5440+ /// Both:
5441+ /// ```py
5442+ /// async with: ...
5443+ /// async for: ...
5444+ /// ```
5445+ /// are statements, so we won't check for them here
54395446 fn contains_await ( expression : & Expr ) -> bool {
5440- use ruff_python_ast:: * ;
5447+ #[ derive( Default ) ]
5448+ struct AwaitVisitor {
5449+ found : bool ,
5450+ }
54415451
5442- match & expression {
5443- Expr :: Call ( ExprCall {
5444- func, arguments, ..
5445- } ) => {
5446- Self :: contains_await ( func)
5447- || arguments. args . iter ( ) . any ( Self :: contains_await)
5448- || arguments
5449- . keywords
5450- . iter ( )
5451- . any ( |kw| Self :: contains_await ( & kw. value ) )
5452- }
5453- Expr :: BoolOp ( ExprBoolOp { values, .. } ) => values. iter ( ) . any ( Self :: contains_await) ,
5454- Expr :: BinOp ( ExprBinOp { left, right, .. } ) => {
5455- Self :: contains_await ( left) || Self :: contains_await ( right)
5456- }
5457- Expr :: Subscript ( ExprSubscript { value, slice, .. } ) => {
5458- Self :: contains_await ( value) || Self :: contains_await ( slice)
5459- }
5460- Expr :: UnaryOp ( ExprUnaryOp { operand, .. } ) => Self :: contains_await ( operand) ,
5461- Expr :: Attribute ( ExprAttribute { value, .. } ) => Self :: contains_await ( value) ,
5462- Expr :: Compare ( ExprCompare {
5463- left, comparators, ..
5464- } ) => Self :: contains_await ( left) || comparators. iter ( ) . any ( Self :: contains_await) ,
5465- Expr :: List ( ExprList { elts, .. } ) => elts. iter ( ) . any ( Self :: contains_await) ,
5466- Expr :: Tuple ( ExprTuple { elts, .. } ) => elts. iter ( ) . any ( Self :: contains_await) ,
5467- Expr :: Set ( ExprSet { elts, .. } ) => elts. iter ( ) . any ( Self :: contains_await) ,
5468- Expr :: Dict ( ExprDict { items, .. } ) => items
5469- . iter ( )
5470- . flat_map ( |item| & item. key )
5471- . any ( Self :: contains_await) ,
5472- Expr :: Slice ( ExprSlice {
5473- lower, upper, step, ..
5474- } ) => {
5475- lower. as_deref ( ) . is_some_and ( Self :: contains_await)
5476- || upper. as_deref ( ) . is_some_and ( Self :: contains_await)
5477- || step. as_deref ( ) . is_some_and ( Self :: contains_await)
5478- }
5479- Expr :: Yield ( ExprYield { value, .. } ) => {
5480- value. as_deref ( ) . is_some_and ( Self :: contains_await)
5481- }
5482- Expr :: Await ( ExprAwait { .. } ) => true ,
5483- Expr :: YieldFrom ( ExprYieldFrom { value, .. } ) => Self :: contains_await ( value) ,
5484- Expr :: Name ( ExprName { .. } ) => false ,
5485- Expr :: Lambda ( ExprLambda { body, .. } ) => Self :: contains_await ( body) ,
5486- Expr :: ListComp ( ExprListComp {
5487- elt, generators, ..
5488- } ) => {
5489- Self :: contains_await ( elt)
5490- || generators. iter ( ) . any ( |jen| Self :: contains_await ( & jen. iter ) )
5491- }
5492- Expr :: SetComp ( ExprSetComp {
5493- elt, generators, ..
5494- } ) => {
5495- Self :: contains_await ( elt)
5496- || generators. iter ( ) . any ( |jen| Self :: contains_await ( & jen. iter ) )
5497- }
5498- Expr :: DictComp ( ExprDictComp {
5499- key,
5500- value,
5501- generators,
5502- ..
5503- } ) => {
5504- Self :: contains_await ( key)
5505- || Self :: contains_await ( value)
5506- || generators. iter ( ) . any ( |jen| Self :: contains_await ( & jen. iter ) )
5507- }
5508- Expr :: Generator ( ExprGenerator {
5509- elt, generators, ..
5510- } ) => {
5511- Self :: contains_await ( elt)
5512- || generators. iter ( ) . any ( |jen| Self :: contains_await ( & jen. iter ) )
5513- }
5514- Expr :: Starred ( expr) => Self :: contains_await ( & expr. value ) ,
5515- Expr :: If ( ExprIf {
5516- test, body, orelse, ..
5517- } ) => {
5518- Self :: contains_await ( test)
5519- || Self :: contains_await ( body)
5520- || Self :: contains_await ( orelse)
5521- }
5452+ impl Visitor < ' _ > for AwaitVisitor {
5453+ fn visit_expr ( & mut self , expr : & Expr ) {
5454+ if self . found {
5455+ return ;
5456+ }
55225457
5523- Expr :: Named ( ExprNamed {
5524- target,
5525- value,
5526- node_index : _,
5527- range : _,
5528- } ) => Self :: contains_await ( target) || Self :: contains_await ( value) ,
5529- Expr :: FString ( fstring) => {
5530- Self :: interpolated_string_contains_await ( fstring. value . elements ( ) )
5531- }
5532- Expr :: TString ( tstring) => {
5533- Self :: interpolated_string_contains_await ( tstring. value . elements ( ) )
5458+ match expr {
5459+ Expr :: Await ( _) => self . found = true ,
5460+ _ => walk_expr ( self , expr) ,
5461+ }
55345462 }
5535- Expr :: StringLiteral ( _)
5536- | Expr :: BytesLiteral ( _)
5537- | Expr :: NumberLiteral ( _)
5538- | Expr :: BooleanLiteral ( _)
5539- | Expr :: NoneLiteral ( _)
5540- | Expr :: EllipsisLiteral ( _)
5541- | Expr :: IpyEscapeCommand ( _) => false ,
5542- }
5543- }
5544-
5545- fn interpolated_string_contains_await < ' a > (
5546- mut elements : impl Iterator < Item = & ' a InterpolatedStringElement > ,
5547- ) -> bool {
5548- fn interpolated_element_contains_await < F : Copy + Fn ( & Expr ) -> bool > (
5549- expr_element : & InterpolatedElement ,
5550- contains_await : F ,
5551- ) -> bool {
5552- contains_await ( & expr_element. expression )
5553- || expr_element
5554- . format_spec
5555- . iter ( )
5556- . flat_map ( |spec| spec. elements . interpolations ( ) )
5557- . any ( |element| interpolated_element_contains_await ( element, contains_await) )
55585463 }
55595464
5560- elements. any ( |element| match element {
5561- InterpolatedStringElement :: Interpolation ( expr_element) => {
5562- interpolated_element_contains_await ( expr_element, Self :: contains_await)
5563- }
5564- InterpolatedStringElement :: Literal ( _) => false ,
5565- } )
5465+ let mut visitor = AwaitVisitor :: default ( ) ;
5466+ visitor. visit_expr ( expression) ;
5467+ visitor. found
55665468 }
55675469
55685470 fn compile_expr_fstring ( & mut self , fstring : & ExprFString ) -> CompileResult < ( ) > {
0 commit comments