Skip to main content

ruff_python_parser/
semantic_errors.rs

1//! [`SemanticSyntaxChecker`] for AST-based syntax errors.
2//!
3//! This checker is not responsible for traversing the AST itself. Instead, its
4//! [`SemanticSyntaxChecker::visit_stmt`] and [`SemanticSyntaxChecker::visit_expr`] methods should
5//! be called in a parent `Visitor`'s `visit_stmt` and `visit_expr` methods, respectively.
6
7use ruff_python_ast::{
8    self as ast, Expr, ExprContext, IrrefutablePatternKind, Pattern, PythonVersion, Stmt, StmtExpr,
9    StmtFunctionDef, StmtImportFrom,
10    comparable::ComparableExpr,
11    helpers,
12    visitor::{Visitor, walk_expr, walk_stmt},
13};
14use ruff_text_size::{Ranged, TextRange, TextSize};
15use rustc_hash::{FxBuildHasher, FxHashSet};
16use std::fmt::Display;
17
18#[derive(Debug, Default)]
19pub struct SemanticSyntaxChecker {
20    /// The checker has traversed past the `__future__` import boundary.
21    ///
22    /// For example, the checker could be visiting `x` in:
23    ///
24    /// ```python
25    /// from __future__ import annotations
26    ///
27    /// import os
28    ///
29    /// x: int = 1
30    /// ```
31    ///
32    /// Python considers it a syntax error to import from `__future__` after any other
33    /// non-`__future__`-importing statements.
34    seen_futures_boundary: bool,
35
36    /// The checker has traversed past the module docstring boundary (i.e. seen any statement in the
37    /// module).
38    seen_module_docstring_boundary: bool,
39}
40
41impl SemanticSyntaxChecker {
42    pub fn new() -> Self {
43        Self::default()
44    }
45}
46
47impl SemanticSyntaxChecker {
48    fn add_error<Ctx: SemanticSyntaxContext>(
49        context: &Ctx,
50        kind: SemanticSyntaxErrorKind,
51        range: TextRange,
52    ) {
53        context.report_semantic_error(SemanticSyntaxError {
54            kind,
55            range,
56            python_version: context.python_version(),
57        });
58    }
59
60    fn check_stmt<Ctx: SemanticSyntaxContext>(&mut self, stmt: &ast::Stmt, ctx: &Ctx) {
61        match stmt {
62            Stmt::ImportFrom(StmtImportFrom {
63                range,
64                module,
65                level,
66                names,
67                ..
68            }) => {
69                if matches!(module.as_deref(), Some("__future__")) {
70                    for name in names {
71                        if !is_known_future_feature(&name.name) {
72                            // test_ok valid_future_feature
73                            // from __future__ import annotations
74
75                            // test_err invalid_future_feature
76                            // from __future__ import invalid_feature
77                            // from __future__ import annotations, invalid_feature
78                            // from __future__ import invalid_feature_1, invalid_feature_2
79                            Self::add_error(
80                                ctx,
81                                SemanticSyntaxErrorKind::FutureFeatureNotDefined(
82                                    name.name.to_string(),
83                                ),
84                                name.range,
85                            );
86                        }
87                    }
88                    if self.seen_futures_boundary {
89                        Self::add_error(ctx, SemanticSyntaxErrorKind::LateFutureImport, *range);
90                    }
91                }
92                for alias in names {
93                    if alias.name.as_str() == "*" && !ctx.in_module_scope() {
94                        // test_err import_from_star
95                        // def f1():
96                        //     from module import *
97                        // class C:
98                        //     from module import *
99                        // def f2():
100                        //     from ..module import *
101                        // def f3():
102                        //     from module import *, *
103
104                        // test_ok import_from_star
105                        // from module import *
106                        Self::add_error(
107                            ctx,
108                            SemanticSyntaxErrorKind::NonModuleImportStar(
109                                helpers::format_import_from(*level, module.as_deref()).to_string(),
110                            ),
111                            *range,
112                        );
113                        break;
114                    }
115                }
116            }
117            Stmt::Match(match_stmt) => {
118                Self::irrefutable_match_case(match_stmt, ctx);
119                for case in &match_stmt.cases {
120                    let mut visitor = MatchPatternVisitor {
121                        names: FxHashSet::default(),
122                        ctx,
123                    };
124                    visitor.visit_pattern(&case.pattern);
125                }
126            }
127            Stmt::FunctionDef(ast::StmtFunctionDef {
128                type_params,
129                parameters,
130                ..
131            }) => {
132                if let Some(type_params) = type_params {
133                    Self::duplicate_type_parameter_name(type_params, ctx);
134                }
135                Self::duplicate_parameter_name(parameters, ctx);
136            }
137            Stmt::Global(ast::StmtGlobal { names, .. }) => {
138                for name in names {
139                    if ctx.is_bound_parameter(name) {
140                        Self::add_error(
141                            ctx,
142                            SemanticSyntaxErrorKind::GlobalParameter(name.to_string()),
143                            name.range,
144                        );
145                    }
146                }
147            }
148            Stmt::ClassDef(ast::StmtClassDef {
149                type_params: Some(type_params),
150                ..
151            })
152            | Stmt::TypeAlias(ast::StmtTypeAlias {
153                type_params: Some(type_params),
154                ..
155            }) => {
156                Self::duplicate_type_parameter_name(type_params, ctx);
157                Self::type_parameter_default_order(type_params, ctx);
158            }
159            Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
160                if let [Expr::Starred(ast::ExprStarred { range, .. })] = targets.as_slice() {
161                    // test_ok single_starred_assignment_target
162                    // (*a,) = (1,)
163                    // *a, = (1,)
164                    // [*a] = (1,)
165
166                    // test_err single_starred_assignment_target
167                    // *a = (1,)
168                    Self::add_error(
169                        ctx,
170                        SemanticSyntaxErrorKind::SingleStarredAssignment,
171                        *range,
172                    );
173                }
174
175                // test_ok assign_stmt_starred_expr_value
176                // _ = 4
177                // _ = [4]
178                // _ = (*[1],)
179                // _ = *[1],
180
181                // test_err assign_stmt_starred_expr_value
182                // _ = *[42]
183                // _ = *{42}
184                // _ = *list()
185                // _ = *(p + q)
186                Self::invalid_star_expression(value, ctx);
187            }
188            Stmt::Return(ast::StmtReturn {
189                value,
190                range,
191                node_index: _,
192            }) => {
193                if let Some(value) = value {
194                    // test_err single_star_return
195                    // def f(): return *x
196                    Self::invalid_star_expression(value, ctx);
197                }
198                if !ctx.in_function_scope() {
199                    Self::add_error(ctx, SemanticSyntaxErrorKind::ReturnOutsideFunction, *range);
200                }
201            }
202            Stmt::For(ast::StmtFor {
203                target,
204                iter,
205                is_async,
206                ..
207            }) => {
208                // test_err single_star_for
209                // for _ in *x: ...
210                // for *x in xs: ...
211                Self::invalid_star_expression(target, ctx);
212                Self::invalid_star_expression(iter, ctx);
213                if *is_async {
214                    Self::await_outside_async_function(
215                        ctx,
216                        stmt,
217                        AwaitOutsideAsyncFunctionKind::AsyncFor,
218                    );
219                }
220            }
221            Stmt::With(ast::StmtWith { is_async: true, .. }) => {
222                Self::await_outside_async_function(
223                    ctx,
224                    stmt,
225                    AwaitOutsideAsyncFunctionKind::AsyncWith,
226                );
227            }
228            Stmt::Nonlocal(ast::StmtNonlocal { names, range, .. }) => {
229                // test_ok nonlocal_declaration_at_module_level
230                // def _():
231                //     nonlocal x
232
233                // test_err nonlocal_declaration_at_module_level
234                // nonlocal x
235                // nonlocal x, y
236                if ctx.in_module_scope() {
237                    Self::add_error(
238                        ctx,
239                        SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel,
240                        *range,
241                    );
242                }
243
244                if !ctx.in_module_scope() {
245                    for name in names {
246                        if !ctx.has_nonlocal_binding(name) {
247                            Self::add_error(
248                                ctx,
249                                SemanticSyntaxErrorKind::NonlocalWithoutBinding(name.to_string()),
250                                name.range,
251                            );
252                        }
253                    }
254                }
255            }
256            Stmt::Break(ast::StmtBreak { range, .. }) => {
257                if !ctx.in_loop_context() {
258                    Self::add_error(ctx, SemanticSyntaxErrorKind::BreakOutsideLoop, *range);
259                }
260            }
261            Stmt::Continue(ast::StmtContinue { range, .. }) => {
262                if !ctx.in_loop_context() {
263                    Self::add_error(ctx, SemanticSyntaxErrorKind::ContinueOutsideLoop, *range);
264                }
265            }
266            _ => {}
267        }
268
269        Self::debug_shadowing(stmt, ctx);
270        Self::check_annotation(stmt, ctx);
271    }
272
273    fn check_annotation<Ctx: SemanticSyntaxContext>(stmt: &ast::Stmt, ctx: &Ctx) {
274        match stmt {
275            Stmt::AnnAssign(ast::StmtAnnAssign {
276                target, annotation, ..
277            }) => {
278                if ctx.python_version() > PythonVersion::PY313 {
279                    // test_ok valid_annotation_py313
280                    // # parse_options: {"target-version": "3.13"}
281                    // a: (x := 1)
282                    // def outer():
283                    //     b: (yield 1)
284                    //     c: (yield from 1)
285                    // async def outer():
286                    //     d: (await 1)
287
288                    // test_err invalid_annotation_py314
289                    // # parse_options: {"target-version": "3.14"}
290                    // a: (x := 1)
291                    // def outer():
292                    //     b: (yield 1)
293                    //     c: (yield from 1)
294                    // async def outer():
295                    //     d: (await 1)
296                    let mut visitor = InvalidExpressionVisitor {
297                        position: InvalidExpressionPosition::TypeAnnotation,
298                        ctx,
299                    };
300                    visitor.visit_expr(annotation);
301                }
302                if let Expr::Name(ast::ExprName { id, .. }) = target.as_ref() {
303                    if let Some(global_stmt) = ctx.global(id.as_str()) {
304                        let global_start = global_stmt.start();
305                        if !ctx.in_module_scope() || target.start() < global_start {
306                            Self::add_error(
307                                ctx,
308                                SemanticSyntaxErrorKind::AnnotatedGlobal(id.to_string()),
309                                target.range(),
310                            );
311                        }
312                    }
313                }
314            }
315            Stmt::FunctionDef(ast::StmtFunctionDef {
316                type_params,
317                parameters,
318                returns,
319                ..
320            }) => {
321                // test_ok valid_annotation_function_py313
322                // # parse_options: {"target-version": "3.13"}
323                // def f() -> (y := 3): ...
324                // def g(arg: (x := 1)): ...
325                // def outer():
326                //     def i(x: (yield 1)): ...
327                //     def k() -> (yield 1): ...
328                //     def m(x: (yield from 1)): ...
329                //     def o() -> (yield from 1): ...
330                // async def outer():
331                //     def f() -> (await 1): ...
332                //     def g(arg: (await 1)): ...
333
334                // test_err invalid_annotation_function_py314
335                // # parse_options: {"target-version": "3.14"}
336                // def f() -> (y := 3): ...
337                // def g(arg: (x := 1)): ...
338                // def outer():
339                //     def i(x: (yield 1)): ...
340                //     def k() -> (yield 1): ...
341                //     def m(x: (yield from 1)): ...
342                //     def o() -> (yield from 1): ...
343                // async def outer():
344                //     def f() -> (await 1): ...
345                //     def g(arg: (await 1)): ...
346
347                // test_err invalid_annotation_function
348                // def d[T]() -> (await 1): ...
349                // def e[T](arg: (await 1)): ...
350                // def f[T]() -> (y := 3): ...
351                // def g[T](arg: (x := 1)): ...
352                // def h[T](x: (yield 1)): ...
353                // def j[T]() -> (yield 1): ...
354                // def l[T](x: (yield from 1)): ...
355                // def n[T]() -> (yield from 1): ...
356                // def p[T: (yield 1)](): ...      # yield in TypeVar bound
357                // def q[T = (yield 1)](): ...     # yield in TypeVar default
358                // def r[*Ts = (yield 1)](): ...   # yield in TypeVarTuple default
359                // def s[**Ts = (yield 1)](): ...  # yield in ParamSpec default
360                // def t[T: (x := 1)](): ...       # named expr in TypeVar bound
361                // def u[T = (x := 1)](): ...      # named expr in TypeVar default
362                // def v[*Ts = (x := 1)](): ...    # named expr in TypeVarTuple default
363                // def w[**Ts = (x := 1)](): ...   # named expr in ParamSpec default
364                // def t[T: (await 1)](): ...       # await in TypeVar bound
365                // def u[T = (await 1)](): ...      # await in TypeVar default
366                // def v[*Ts = (await 1)](): ...    # await in TypeVarTuple default
367                // def w[**Ts = (await 1)](): ...   # await in ParamSpec default
368                let mut visitor = InvalidExpressionVisitor {
369                    position: InvalidExpressionPosition::TypeAnnotation,
370                    ctx,
371                };
372                if let Some(type_params) = type_params {
373                    visitor.visit_type_params(type_params);
374                }
375                // the __future__ annotation error takes precedence over the generic error
376                if ctx.future_annotations_or_stub() || ctx.python_version() > PythonVersion::PY313 {
377                    visitor.position = InvalidExpressionPosition::TypeAnnotation;
378                } else if type_params.is_some() {
379                    visitor.position = InvalidExpressionPosition::GenericDefinition;
380                } else {
381                    return;
382                }
383                for param in parameters
384                    .iter()
385                    .filter_map(ast::AnyParameterRef::annotation)
386                {
387                    visitor.visit_expr(param);
388                }
389                if let Some(returns) = returns {
390                    visitor.visit_expr(returns);
391                }
392            }
393            Stmt::ClassDef(ast::StmtClassDef {
394                type_params: Some(type_params),
395                arguments,
396                ..
397            }) => {
398                // test_ok valid_annotation_class
399                // class F(y := list): ...
400                // def f():
401                //     class G((yield 1)): ...
402                //     class H((yield from 1)): ...
403                // async def f():
404                //     class G((await 1)): ...
405
406                // test_err invalid_annotation_class
407                // class F[T](y := list): ...
408                // class I[T]((yield 1)): ...
409                // class J[T]((yield from 1)): ...
410                // class K[T: (yield 1)]: ...      # yield in TypeVar
411                // class L[T: (x := 1)]: ...       # named expr in TypeVar
412                // class M[T]((await 1)): ...
413                // class N[T: (await 1)]: ...
414                let mut visitor = InvalidExpressionVisitor {
415                    position: InvalidExpressionPosition::TypeAnnotation,
416                    ctx,
417                };
418                visitor.visit_type_params(type_params);
419                if let Some(arguments) = arguments {
420                    visitor.position = InvalidExpressionPosition::GenericDefinition;
421                    visitor.visit_arguments(arguments);
422                }
423            }
424            Stmt::TypeAlias(ast::StmtTypeAlias {
425                type_params, value, ..
426            }) => {
427                // test_err invalid_annotation_type_alias
428                // type X[T: (yield 1)] = int      # TypeVar bound
429                // type X[T = (yield 1)] = int     # TypeVar default
430                // type X[*Ts = (yield 1)] = int   # TypeVarTuple default
431                // type X[**Ts = (yield 1)] = int  # ParamSpec default
432                // type Y = (yield 1)              # yield in value
433                // type Y = (x := 1)               # named expr in value
434                // type Y[T: (await 1)] = int      # await in bound
435                // type Y = (await 1)              # await in value
436                let mut visitor = InvalidExpressionVisitor {
437                    position: InvalidExpressionPosition::TypeAlias,
438                    ctx,
439                };
440                visitor.visit_expr(value);
441                if let Some(type_params) = type_params {
442                    visitor.visit_type_params(type_params);
443                }
444            }
445            _ => {}
446        }
447    }
448
449    /// Emit a [`SemanticSyntaxErrorKind::InvalidStarExpression`] if `expr` is starred.
450    fn invalid_star_expression<Ctx: SemanticSyntaxContext>(expr: &Expr, ctx: &Ctx) {
451        // test_ok single_star_in_tuple
452        // def f(): yield (*x,)
453        // def f(): return (*x,)
454        // for _ in (*x,): ...
455        // for (*x,) in xs: ...
456        if expr.is_starred_expr() {
457            Self::add_error(
458                ctx,
459                SemanticSyntaxErrorKind::InvalidStarExpression,
460                expr.range(),
461            );
462        }
463    }
464
465    fn multiple_star_expression<Ctx: SemanticSyntaxContext>(
466        ctx: &Ctx,
467        expr_ctx: ExprContext,
468        elts: &[Expr],
469        range: TextRange,
470    ) {
471        if expr_ctx.is_store() {
472            let mut has_starred = false;
473            for elt in elts {
474                if elt.is_starred_expr() {
475                    if has_starred {
476                        // test_err multiple_starred_assignment_target
477                        // (*a, *b) = (1, 2)
478                        // [*a, *b] = (1, 2)
479                        // (*a, *b, c) = (1, 2, 3)
480                        // [*a, *b, c] = (1, 2, 3)
481                        // (*a, *b, (*c, *d)) = (1, 2)
482
483                        // test_ok multiple_starred_assignment_target
484                        // (*a, b) = (1, 2)
485                        // (*_, normed), *_ = [(1,), 2]
486                        Self::add_error(
487                            ctx,
488                            SemanticSyntaxErrorKind::MultipleStarredExpressions,
489                            range,
490                        );
491                        return;
492                    }
493                    has_starred = true;
494                }
495            }
496        }
497    }
498
499    /// Check for [`SemanticSyntaxErrorKind::WriteToDebug`] in `stmt`.
500    fn debug_shadowing<Ctx: SemanticSyntaxContext>(stmt: &ast::Stmt, ctx: &Ctx) {
501        match stmt {
502            Stmt::FunctionDef(ast::StmtFunctionDef {
503                name,
504                type_params,
505                parameters,
506                ..
507            }) => {
508                // test_err debug_shadow_function
509                // def __debug__(): ...  # function name
510                // def f[__debug__](): ...  # type parameter name
511                // def f(__debug__): ...  # parameter name
512                Self::check_identifier(name, ctx);
513                if let Some(type_params) = type_params {
514                    for type_param in type_params.iter() {
515                        Self::check_identifier(type_param.name(), ctx);
516                    }
517                }
518                for parameter in parameters {
519                    Self::check_identifier(parameter.name(), ctx);
520                }
521            }
522            Stmt::ClassDef(ast::StmtClassDef {
523                name, type_params, ..
524            }) => {
525                // test_err debug_shadow_class
526                // class __debug__: ...  # class name
527                // class C[__debug__]: ...  # type parameter name
528                Self::check_identifier(name, ctx);
529                if let Some(type_params) = type_params {
530                    for type_param in type_params.iter() {
531                        Self::check_identifier(type_param.name(), ctx);
532                    }
533                }
534            }
535            Stmt::TypeAlias(ast::StmtTypeAlias {
536                type_params: Some(type_params),
537                ..
538            }) => {
539                // test_err debug_shadow_type_alias
540                // type __debug__ = list[int]  # visited as an Expr but still flagged
541                // type Debug[__debug__] = str
542                for type_param in type_params.iter() {
543                    Self::check_identifier(type_param.name(), ctx);
544                }
545            }
546            Stmt::Import(ast::StmtImport { names, .. })
547            | Stmt::ImportFrom(ast::StmtImportFrom { names, .. }) => {
548                // test_err debug_shadow_import
549                // import __debug__
550                // import debug as __debug__
551                // from x import __debug__
552                // from x import debug as __debug__
553
554                // test_ok debug_rename_import
555                // import __debug__ as debug
556                // from __debug__ import Some
557                // from x import __debug__ as debug
558                for name in names {
559                    match &name.asname {
560                        Some(asname) => Self::check_identifier(asname, ctx),
561                        None => Self::check_identifier(&name.name, ctx),
562                    }
563                }
564            }
565            Stmt::Try(ast::StmtTry { handlers, .. }) => {
566                // test_err debug_shadow_try
567                // try: ...
568                // except Exception as __debug__: ...
569                for handler in handlers
570                    .iter()
571                    .filter_map(ast::ExceptHandler::as_except_handler)
572                {
573                    if let Some(name) = &handler.name {
574                        Self::check_identifier(name, ctx);
575                    }
576                }
577            }
578            // test_err debug_shadow_with
579            // with open("foo.txt") as __debug__: ...
580            _ => {}
581        }
582    }
583
584    /// Check if `ident` is equal to `__debug__` and emit a
585    /// [`SemanticSyntaxErrorKind::WriteToDebug`] if so.
586    fn check_identifier<Ctx: SemanticSyntaxContext>(ident: &ast::Identifier, ctx: &Ctx) {
587        if ident.id == "__debug__" {
588            Self::add_error(
589                ctx,
590                SemanticSyntaxErrorKind::WriteToDebug(WriteToDebugKind::Store),
591                ident.range,
592            );
593        }
594    }
595
596    fn duplicate_type_parameter_name<Ctx: SemanticSyntaxContext>(
597        type_params: &ast::TypeParams,
598        ctx: &Ctx,
599    ) {
600        if type_params.len() < 2 {
601            return;
602        }
603
604        for (i, type_param) in type_params.iter().enumerate() {
605            if type_params
606                .iter()
607                .take(i)
608                .any(|t| t.name().id == type_param.name().id)
609            {
610                // test_ok non_duplicate_type_parameter_names
611                // type Alias[T] = list[T]
612                // def f[T](t: T): ...
613                // class C[T]: ...
614                // class C[T, U, V]: ...
615                // type Alias[T, U: str, V: (str, bytes), *Ts, **P, D = default] = ...
616
617                // test_err duplicate_type_parameter_names
618                // type Alias[T, T] = ...
619                // def f[T, T](t: T): ...
620                // class C[T, T]: ...
621                // type Alias[T, U: str, V: (str, bytes), *Ts, **P, T = default] = ...
622                // def f[T, T, T](): ...  # two errors
623                // def f[T, *T](): ...    # star is still duplicate
624                // def f[T, **T](): ...   # as is double star
625                Self::add_error(
626                    ctx,
627                    SemanticSyntaxErrorKind::DuplicateTypeParameter,
628                    type_param.range(),
629                );
630            }
631        }
632    }
633
634    fn type_parameter_default_order<Ctx: SemanticSyntaxContext>(
635        type_params: &ast::TypeParams,
636        ctx: &Ctx,
637    ) {
638        let mut seen_default = false;
639        for type_param in type_params.iter() {
640            let has_default = match type_param {
641                ast::TypeParam::TypeVar(ast::TypeParamTypeVar { default, .. })
642                | ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { default, .. })
643                | ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { default, .. }) => {
644                    default.is_some()
645                }
646            };
647
648            if seen_default && !has_default {
649                // test_err type_parameter_default_order
650                // class C[T = int, U]: ...
651                // class C[T1, T2 = int, T3, T4]: ...
652                // type Alias[T = int, U] = ...
653                Self::add_error(
654                    ctx,
655                    SemanticSyntaxErrorKind::TypeParameterDefaultOrder(
656                        type_param.name().id.to_string(),
657                    ),
658                    type_param.range(),
659                );
660            }
661            if has_default {
662                seen_default = true;
663            }
664        }
665    }
666
667    fn duplicate_parameter_name<Ctx: SemanticSyntaxContext>(
668        parameters: &ast::Parameters,
669        ctx: &Ctx,
670    ) {
671        if parameters.len() < 2 {
672            return;
673        }
674
675        let mut all_arg_names =
676            FxHashSet::with_capacity_and_hasher(parameters.len(), FxBuildHasher);
677
678        for parameter in parameters {
679            let range = parameter.name().range();
680            let param_name = parameter.name().as_str();
681            if !all_arg_names.insert(param_name) {
682                // test_err params_duplicate_names
683                // def foo(a, a=10, *a, a, a: str, **a): ...
684                Self::add_error(
685                    ctx,
686                    SemanticSyntaxErrorKind::DuplicateParameter(param_name.to_string()),
687                    range,
688                );
689            }
690        }
691    }
692
693    fn irrefutable_match_case<Ctx: SemanticSyntaxContext>(stmt: &ast::StmtMatch, ctx: &Ctx) {
694        // test_ok irrefutable_case_pattern_at_end
695        // match x:
696        //     case 2: ...
697        //     case var: ...
698        // match x:
699        //     case 2: ...
700        //     case _: ...
701        // match x:
702        //     case var if True: ...  # don't try to refute a guarded pattern
703        //     case 2: ...
704
705        // test_err irrefutable_case_pattern
706        // match x:
707        //     case var: ...  # capture pattern
708        //     case 2: ...
709        // match x:
710        //     case _: ...
711        //     case 2: ...    # wildcard pattern
712        // match x:
713        //     case var1 as var2: ...  # as pattern with irrefutable left-hand side
714        //     case 2: ...
715        // match x:
716        //     case enum.variant | var: ...  # or pattern with irrefutable part
717        //     case 2: ...
718        for case in stmt
719            .cases
720            .iter()
721            .rev()
722            .skip(1)
723            .filter_map(|case| match case.guard {
724                Some(_) => None,
725                None => case.pattern.irrefutable_pattern(),
726            })
727        {
728            Self::add_error(
729                ctx,
730                SemanticSyntaxErrorKind::IrrefutableCasePattern(case.kind),
731                case.range,
732            );
733        }
734    }
735
736    /// Check `stmt` for semantic syntax errors and update the checker's internal state.
737    ///
738    /// Note that this method should only be called when traversing `stmt` *and* its children. For
739    /// example, if traversal of function bodies needs to be deferred, avoid calling `visit_stmt` on
740    /// the function itself until the deferred body is visited too. Failing to defer `visit_stmt` in
741    /// this case will break any internal state that depends on function scopes, such as `async`
742    /// context detection.
743    pub fn visit_stmt<Ctx: SemanticSyntaxContext>(&mut self, stmt: &ast::Stmt, ctx: &Ctx) {
744        // check for errors
745        self.check_stmt(stmt, ctx);
746
747        // update internal state
748        match stmt {
749            Stmt::Expr(StmtExpr { value, .. })
750                if !self.seen_module_docstring_boundary && value.is_string_literal_expr() => {}
751            Stmt::ImportFrom(StmtImportFrom { module, .. }) => {
752                // Allow __future__ imports until we see a non-__future__ import.
753                if !matches!(module.as_deref(), Some("__future__")) {
754                    self.seen_futures_boundary = true;
755                }
756            }
757            Stmt::FunctionDef(StmtFunctionDef { is_async, body, .. }) => {
758                if *is_async {
759                    let mut visitor = ReturnVisitor::default();
760                    visitor.visit_body(body);
761
762                    if visitor.has_yield {
763                        if let Some(return_range) = visitor.return_range {
764                            Self::add_error(
765                                ctx,
766                                SemanticSyntaxErrorKind::ReturnInGenerator,
767                                return_range,
768                            );
769                        }
770                    }
771                }
772                self.seen_futures_boundary = true;
773            }
774            _ => {
775                self.seen_futures_boundary = true;
776            }
777        }
778
779        self.seen_module_docstring_boundary = true;
780    }
781
782    /// Check `expr` for semantic syntax errors and update the checker's internal state.
783    pub fn visit_expr<Ctx: SemanticSyntaxContext>(&mut self, expr: &Expr, ctx: &Ctx) {
784        match expr {
785            Expr::ListComp(ast::ExprListComp {
786                elt, generators, ..
787            })
788            | Expr::SetComp(ast::ExprSetComp {
789                elt, generators, ..
790            }) => {
791                Self::check_generator_expr(elt, generators, ctx);
792                Self::async_comprehension_in_sync_comprehension(ctx, generators);
793                for generator in generators.iter().filter(|g| g.is_async) {
794                    Self::await_outside_async_function(
795                        ctx,
796                        generator,
797                        AwaitOutsideAsyncFunctionKind::AsyncComprehension,
798                    );
799                }
800            }
801            Expr::DictComp(ast::ExprDictComp {
802                key,
803                value,
804                generators,
805                ..
806            }) => {
807                Self::check_generator_expr(key, generators, ctx);
808                Self::check_generator_expr(value, generators, ctx);
809                Self::async_comprehension_in_sync_comprehension(ctx, generators);
810                for generator in generators.iter().filter(|g| g.is_async) {
811                    Self::await_outside_async_function(
812                        ctx,
813                        generator,
814                        AwaitOutsideAsyncFunctionKind::AsyncComprehension,
815                    );
816                }
817            }
818            Expr::Generator(ast::ExprGenerator {
819                elt, generators, ..
820            }) => {
821                Self::check_generator_expr(elt, generators, ctx);
822                // Note that `await_outside_async_function` is not called here because generators
823                // are evaluated lazily. See the note in the function for more details.
824            }
825            Expr::Name(ast::ExprName {
826                range,
827                id,
828                ctx: expr_ctx,
829                node_index: _,
830            }) => {
831                // test_err write_to_debug_expr
832                // del __debug__
833                // del x, y, __debug__, z
834                // __debug__ = 1
835                // x, y, __debug__, z = 1, 2, 3, 4
836
837                // test_err del_debug_py39
838                // # parse_options: {"target-version": "3.9"}
839                // del __debug__
840
841                // test_ok del_debug_py38
842                // # parse_options: {"target-version": "3.8"}
843                // del __debug__
844
845                // test_ok read_from_debug
846                // if __debug__: ...
847                // x = __debug__
848                if id == "__debug__" {
849                    match expr_ctx {
850                        ExprContext::Store => Self::add_error(
851                            ctx,
852                            SemanticSyntaxErrorKind::WriteToDebug(WriteToDebugKind::Store),
853                            *range,
854                        ),
855                        ExprContext::Del => {
856                            let version = ctx.python_version();
857                            if version >= PythonVersion::PY39 {
858                                Self::add_error(
859                                    ctx,
860                                    SemanticSyntaxErrorKind::WriteToDebug(
861                                        WriteToDebugKind::Delete(version),
862                                    ),
863                                    *range,
864                                );
865                            }
866                        }
867                        _ => {}
868                    }
869                }
870
871                // PLE0118
872                if let Some(stmt) = ctx.global(id) {
873                    let start = stmt.start();
874                    if expr.start() < start {
875                        Self::add_error(
876                            ctx,
877                            SemanticSyntaxErrorKind::LoadBeforeGlobalDeclaration {
878                                name: id.to_string(),
879                                start,
880                            },
881                            expr.range(),
882                        );
883                    }
884                }
885            }
886            Expr::Yield(ast::ExprYield { value, .. }) => {
887                if let Some(value) = value {
888                    // test_err single_star_yield
889                    // def f(): yield *x
890                    Self::invalid_star_expression(value, ctx);
891                }
892                Self::yield_outside_function(ctx, expr, YieldOutsideFunctionKind::Yield);
893            }
894            Expr::YieldFrom(_) => {
895                Self::yield_outside_function(ctx, expr, YieldOutsideFunctionKind::YieldFrom);
896                if ctx.in_function_scope() && ctx.in_async_context() {
897                    // test_err yield_from_in_async_function
898                    // async def f(): yield from x
899
900                    Self::add_error(
901                        ctx,
902                        SemanticSyntaxErrorKind::YieldFromInAsyncFunction,
903                        expr.range(),
904                    );
905                }
906            }
907            Expr::Await(_) => {
908                Self::yield_outside_function(ctx, expr, YieldOutsideFunctionKind::Await);
909                Self::await_outside_async_function(ctx, expr, AwaitOutsideAsyncFunctionKind::Await);
910            }
911            Expr::Tuple(ast::ExprTuple {
912                elts,
913                ctx: expr_ctx,
914                range,
915                ..
916            })
917            | Expr::List(ast::ExprList {
918                elts,
919                ctx: expr_ctx,
920                range,
921                ..
922            }) => {
923                Self::multiple_star_expression(ctx, *expr_ctx, elts, *range);
924            }
925            Expr::Lambda(ast::ExprLambda {
926                parameters: Some(parameters),
927                ..
928            }) => {
929                Self::duplicate_parameter_name(parameters, ctx);
930            }
931            _ => {}
932        }
933    }
934
935    /// PLE1142
936    fn await_outside_async_function<Ctx: SemanticSyntaxContext, Node: Ranged>(
937        ctx: &Ctx,
938        node: Node,
939        kind: AwaitOutsideAsyncFunctionKind,
940    ) {
941        if ctx.in_async_context() {
942            return;
943        }
944        // `await` is allowed at the top level of a Jupyter notebook.
945        // See: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html.
946        if ctx.in_module_scope() && ctx.in_notebook() {
947            return;
948        }
949        // Generators are evaluated lazily, so you can use `await` in them. For example:
950        //
951        // ```python
952        // # This is valid
953        // def f():
954        //     (await x for x in y)
955        //     (x async for x in y)
956        //
957        // # This is invalid
958        // def f():
959        //     (x for x in await y)
960        //     [await x for x in y]
961        // ```
962        //
963        // This check is required in addition to avoiding calling this function in `visit_expr`
964        // because the generator scope applies to nested parts of the `Expr::Generator` that are
965        // visited separately.
966        if ctx.in_generator_context() {
967            return;
968        }
969        Self::add_error(
970            ctx,
971            SemanticSyntaxErrorKind::AwaitOutsideAsyncFunction(kind),
972            node.range(),
973        );
974    }
975
976    /// F704
977    fn yield_outside_function<Ctx: SemanticSyntaxContext>(
978        ctx: &Ctx,
979        expr: &Expr,
980        kind: YieldOutsideFunctionKind,
981    ) {
982        // We are intentionally not inspecting the async status of the scope for now to mimic F704.
983        // await-outside-async is PLE1142 instead, so we'll end up emitting both syntax errors for
984        // cases that trigger F704
985
986        if ctx.in_function_scope() {
987            return;
988        }
989
990        if kind.is_await() {
991            // `await` is allowed at the top level of a Jupyter notebook.
992            // See: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html.
993            if ctx.in_module_scope() && ctx.in_notebook() {
994                return;
995            }
996            if ctx.in_await_allowed_context() {
997                return;
998            }
999        } else if ctx.in_yield_allowed_context() {
1000            return;
1001        }
1002
1003        Self::add_error(
1004            ctx,
1005            SemanticSyntaxErrorKind::YieldOutsideFunction(kind),
1006            expr.range(),
1007        );
1008    }
1009
1010    /// Add a [`SyntaxErrorKind::ReboundComprehensionVariable`] if `expr` rebinds an iteration
1011    /// variable in `generators`.
1012    fn check_generator_expr<Ctx: SemanticSyntaxContext>(
1013        expr: &Expr,
1014        comprehensions: &[ast::Comprehension],
1015        ctx: &Ctx,
1016    ) {
1017        let rebound_variables = {
1018            let mut visitor = ReboundComprehensionVisitor {
1019                comprehensions,
1020                rebound_variables: Vec::new(),
1021            };
1022            visitor.visit_expr(expr);
1023            visitor.rebound_variables
1024        };
1025
1026        // TODO(brent) with multiple diagnostic ranges, we could mark both the named expr (current)
1027        // and the name expr being rebound
1028        for range in rebound_variables {
1029            // test_err rebound_comprehension_variable
1030            // [(a := 0) for a in range(0)]
1031            // {(a := 0) for a in range(0)}
1032            // {(a := 0): val for a in range(0)}
1033            // {key: (a := 0) for a in range(0)}
1034            // ((a := 0) for a in range(0))
1035            // [[(a := 0)] for a in range(0)]
1036            // [(a := 0) for b in range (0) for a in range(0)]
1037            // [(a := 0) for a in range (0) for b in range(0)]
1038            // [((a := 0), (b := 1)) for a in range (0) for b in range(0)]
1039
1040            // test_ok non_rebound_comprehension_variable
1041            // [a := 0 for x in range(0)]
1042            Self::add_error(
1043                ctx,
1044                SemanticSyntaxErrorKind::ReboundComprehensionVariable,
1045                range,
1046            );
1047        }
1048    }
1049
1050    fn async_comprehension_in_sync_comprehension<Ctx: SemanticSyntaxContext>(
1051        ctx: &Ctx,
1052        generators: &[ast::Comprehension],
1053    ) {
1054        let python_version = ctx.python_version();
1055        if python_version >= PythonVersion::PY311 {
1056            return;
1057        }
1058        // async allowed at notebook top-level
1059        if ctx.in_notebook() && ctx.in_module_scope() {
1060            return;
1061        }
1062        if !ctx.in_sync_comprehension() {
1063            return;
1064        }
1065        for generator in generators.iter().filter(|generator| generator.is_async) {
1066            // test_ok nested_async_comprehension_py311
1067            // # parse_options: {"target-version": "3.11"}
1068            // async def f(): return [[x async for x in foo(n)] for n in range(3)]    # list
1069            // async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict
1070            // async def h(): return [{x async for x in foo(n)} for n in range(3)]    # set
1071
1072            // test_ok nested_async_comprehension_py310
1073            // # parse_options: {"target-version": "3.10"}
1074            // async def f():
1075            //     [_ for n in range(3)]
1076            //     [_ async for n in range(3)]
1077            // async def f():
1078            //     def g(): ...
1079            //     [_ async for n in range(3)]
1080
1081            // test_ok all_async_comprehension_py310
1082            // # parse_options: {"target-version": "3.10"}
1083            // async def test(): return [[x async for x in elements(n)] async for n in range(3)]
1084
1085            // test_err nested_async_comprehension_py310
1086            // # parse_options: {"target-version": "3.10"}
1087            // async def f(): return [[x async for x in foo(n)] for n in range(3)]    # list
1088            // async def g(): return [{x: 1 async for x in foo(n)} for n in range(3)] # dict
1089            // async def h(): return [{x async for x in foo(n)} for n in range(3)]    # set
1090            // async def i(): return [([y async for y in range(1)], [z for z in range(2)]) for x in range(5)]
1091            // async def j(): return [([y for y in range(1)], [z async for z in range(2)]) for x in range(5)]
1092            Self::add_error(
1093                ctx,
1094                SemanticSyntaxErrorKind::AsyncComprehensionInSyncComprehension(python_version),
1095                generator.range,
1096            );
1097        }
1098    }
1099}
1100
1101fn is_known_future_feature(name: &str) -> bool {
1102    matches!(
1103        name,
1104        "nested_scopes"
1105            | "generators"
1106            | "division"
1107            | "absolute_import"
1108            | "with_statement"
1109            | "print_function"
1110            | "unicode_literals"
1111            | "barry_as_FLUFL"
1112            | "generator_stop"
1113            | "annotations"
1114    )
1115}
1116
1117#[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)]
1118pub struct SemanticSyntaxError {
1119    pub kind: SemanticSyntaxErrorKind,
1120    pub range: TextRange,
1121    pub python_version: PythonVersion,
1122}
1123
1124impl Display for SemanticSyntaxError {
1125    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1126        match &self.kind {
1127            SemanticSyntaxErrorKind::LateFutureImport => {
1128                f.write_str("__future__ imports must be at the top of the file")
1129            }
1130            SemanticSyntaxErrorKind::ReboundComprehensionVariable => {
1131                f.write_str("assignment expression cannot rebind comprehension variable")
1132            }
1133            SemanticSyntaxErrorKind::DuplicateTypeParameter => {
1134                f.write_str("duplicate type parameter")
1135            }
1136            SemanticSyntaxErrorKind::TypeParameterDefaultOrder(name) => {
1137                write!(
1138                    f,
1139                    "non default type parameter `{name}` follows default type parameter"
1140                )
1141            }
1142            SemanticSyntaxErrorKind::MultipleCaseAssignment(name) => {
1143                write!(f, "multiple assignments to name `{name}` in pattern")
1144            }
1145            SemanticSyntaxErrorKind::IrrefutableCasePattern(kind) => match kind {
1146                // These error messages are taken from CPython's syntax errors
1147                IrrefutablePatternKind::Name(name) => {
1148                    write!(
1149                        f,
1150                        "name capture `{name}` makes remaining patterns unreachable"
1151                    )
1152                }
1153                IrrefutablePatternKind::Wildcard => {
1154                    f.write_str("wildcard makes remaining patterns unreachable")
1155                }
1156            },
1157            SemanticSyntaxErrorKind::SingleStarredAssignment => {
1158                f.write_str("starred assignment target must be in a list or tuple")
1159            }
1160            SemanticSyntaxErrorKind::WriteToDebug(kind) => match kind {
1161                WriteToDebugKind::Store => f.write_str("cannot assign to `__debug__`"),
1162                WriteToDebugKind::Delete(python_version) => {
1163                    write!(
1164                        f,
1165                        "cannot delete `__debug__` on Python {python_version} (syntax was removed in 3.9)"
1166                    )
1167                }
1168            },
1169            SemanticSyntaxErrorKind::InvalidExpression(kind, position) => {
1170                write!(f, "{kind} cannot be used within a {position}")
1171            }
1172            SemanticSyntaxErrorKind::DuplicateMatchKey(key) => {
1173                write!(
1174                    f,
1175                    "mapping pattern checks duplicate key `{}`",
1176                    EscapeDefault(key)
1177                )
1178            }
1179            SemanticSyntaxErrorKind::DuplicateMatchClassAttribute(name) => {
1180                write!(f, "attribute name `{name}` repeated in class pattern",)
1181            }
1182            SemanticSyntaxErrorKind::LoadBeforeGlobalDeclaration { name, start: _ } => {
1183                write!(f, "name `{name}` is used prior to global declaration")
1184            }
1185            SemanticSyntaxErrorKind::LoadBeforeNonlocalDeclaration { name, start: _ } => {
1186                write!(f, "name `{name}` is used prior to nonlocal declaration")
1187            }
1188            SemanticSyntaxErrorKind::InvalidStarExpression => {
1189                f.write_str("Starred expression cannot be used here")
1190            }
1191            SemanticSyntaxErrorKind::AsyncComprehensionInSyncComprehension(python_version) => {
1192                write!(
1193                    f,
1194                    "cannot use an asynchronous comprehension inside of a synchronous comprehension \
1195                        on Python {python_version} (syntax was added in 3.11)",
1196                )
1197            }
1198            SemanticSyntaxErrorKind::YieldOutsideFunction(kind) => {
1199                write!(f, "`{kind}` statement outside of a function")
1200            }
1201            SemanticSyntaxErrorKind::ReturnOutsideFunction => {
1202                f.write_str("`return` statement outside of a function")
1203            }
1204            SemanticSyntaxErrorKind::AwaitOutsideAsyncFunction(kind) => {
1205                write!(f, "{kind} outside of an asynchronous function")
1206            }
1207            SemanticSyntaxErrorKind::DuplicateParameter(name) => {
1208                write!(f, r#"Duplicate parameter "{name}""#)
1209            }
1210            SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel => {
1211                write!(f, "nonlocal declaration not allowed at module level")
1212            }
1213            SemanticSyntaxErrorKind::NonlocalAndGlobal(name) => {
1214                write!(f, "name `{name}` is nonlocal and global")
1215            }
1216            SemanticSyntaxErrorKind::AnnotatedGlobal(name) => {
1217                write!(f, "annotated name `{name}` can't be global")
1218            }
1219            SemanticSyntaxErrorKind::AnnotatedNonlocal(name) => {
1220                write!(f, "annotated name `{name}` can't be nonlocal")
1221            }
1222            SemanticSyntaxErrorKind::YieldFromInAsyncFunction => {
1223                f.write_str("`yield from` statement in async function; use `async for` instead")
1224            }
1225            SemanticSyntaxErrorKind::NonModuleImportStar(name) => {
1226                write!(f, "`from {name} import *` only allowed at module level")
1227            }
1228            SemanticSyntaxErrorKind::MultipleStarredExpressions => {
1229                write!(f, "Two starred expressions in assignment")
1230            }
1231            SemanticSyntaxErrorKind::FutureFeatureNotDefined(name) => {
1232                write!(f, "Future feature `{name}` is not defined")
1233            }
1234            SemanticSyntaxErrorKind::BreakOutsideLoop => f.write_str("`break` outside loop"),
1235            SemanticSyntaxErrorKind::ContinueOutsideLoop => f.write_str("`continue` outside loop"),
1236            SemanticSyntaxErrorKind::GlobalParameter(name) => {
1237                write!(f, "name `{name}` is parameter and global")
1238            }
1239            SemanticSyntaxErrorKind::DifferentMatchPatternBindings => {
1240                write!(f, "alternative patterns bind different names")
1241            }
1242            SemanticSyntaxErrorKind::NonlocalWithoutBinding(name) => {
1243                write!(f, "no binding for nonlocal `{name}` found")
1244            }
1245            SemanticSyntaxErrorKind::ReturnInGenerator => {
1246                write!(f, "`return` with value in async generator")
1247            }
1248        }
1249    }
1250}
1251
1252impl Ranged for SemanticSyntaxError {
1253    fn range(&self) -> TextRange {
1254        self.range
1255    }
1256}
1257
1258#[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)]
1259pub enum SemanticSyntaxErrorKind {
1260    /// Represents the use of a `__future__` import after the beginning of a file.
1261    ///
1262    /// ## Examples
1263    ///
1264    /// ```python
1265    /// from pathlib import Path
1266    ///
1267    /// from __future__ import annotations
1268    /// ```
1269    ///
1270    /// This corresponds to the [`late-future-import`] (`F404`) rule in ruff.
1271    ///
1272    /// [`late-future-import`]: https://docs.astral.sh/ruff/rules/late-future-import/
1273    LateFutureImport,
1274
1275    /// Represents the rebinding of the iteration variable of a list, set, or dict comprehension or
1276    /// a generator expression.
1277    ///
1278    /// ## Examples
1279    ///
1280    /// ```python
1281    /// [(a := 0) for a in range(0)]
1282    /// {(a := 0) for a in range(0)}
1283    /// {(a := 0): val for a in range(0)}
1284    /// {key: (a := 0) for a in range(0)}
1285    /// ((a := 0) for a in range(0))
1286    /// ```
1287    ReboundComprehensionVariable,
1288
1289    /// Represents a duplicate type parameter name in a function definition, class definition, or
1290    /// type alias statement.
1291    ///
1292    /// ## Examples
1293    ///
1294    /// ```python
1295    /// type Alias[T, T] = ...
1296    /// def f[T, T](t: T): ...
1297    /// class C[T, T]: ...
1298    /// ```
1299    DuplicateTypeParameter,
1300
1301    /// Represents a duplicate binding in a `case` pattern of a `match` statement.
1302    ///
1303    /// ## Examples
1304    ///
1305    /// ```python
1306    /// match x:
1307    ///     case [x, y, x]: ...
1308    ///     case x as x: ...
1309    ///     case Class(x=1, x=2): ...
1310    /// ```
1311    MultipleCaseAssignment(ast::name::Name),
1312
1313    /// Represents an irrefutable `case` pattern before the last `case` in a `match` statement.
1314    ///
1315    /// According to the [Python reference], "a match statement may have at most one irrefutable
1316    /// case block, and it must be last."
1317    ///
1318    /// ## Examples
1319    ///
1320    /// ```python
1321    /// match x:
1322    ///     case value: ...  # irrefutable capture pattern
1323    ///     case other: ...
1324    ///
1325    /// match x:
1326    ///     case _: ...      # irrefutable wildcard pattern
1327    ///     case other: ...
1328    /// ```
1329    ///
1330    /// [Python reference]: https://docs.python.org/3/reference/compound_stmts.html#irrefutable-case-blocks
1331    IrrefutableCasePattern(IrrefutablePatternKind),
1332
1333    /// Represents a single starred assignment target outside of a tuple or list.
1334    ///
1335    /// ## Examples
1336    ///
1337    /// ```python
1338    /// *a = (1,)  # SyntaxError
1339    /// ```
1340    ///
1341    /// A starred assignment target can only occur within a tuple or list:
1342    ///
1343    /// ```python
1344    /// b, *a = 1, 2, 3
1345    /// (*a,) = 1, 2, 3
1346    /// [*a] = 1, 2, 3
1347    /// ```
1348    SingleStarredAssignment,
1349
1350    /// Represents a write to `__debug__`. This includes simple assignments and deletions as well
1351    /// other kinds of statements that can introduce bindings, such as type parameters in functions,
1352    /// classes, and aliases, `match` arms, and imports, among others.
1353    ///
1354    /// ## Examples
1355    ///
1356    /// ```python
1357    /// del __debug__
1358    /// __debug__ = False
1359    /// def f(__debug__): ...
1360    /// class C[__debug__]: ...
1361    /// ```
1362    ///
1363    /// See [BPO 45000] for more information.
1364    ///
1365    /// [BPO 45000]: https://github.com/python/cpython/issues/89163
1366    WriteToDebug(WriteToDebugKind),
1367
1368    /// Represents the use of an invalid expression kind in one of several locations.
1369    ///
1370    /// The kinds include `yield` and `yield from` expressions and named expressions, and locations
1371    /// include type parameter bounds and defaults, type annotations, type aliases, and base class
1372    /// lists.
1373    ///
1374    /// ## Examples
1375    ///
1376    /// ```python
1377    /// type X[T: (yield 1)] = int
1378    /// type Y = (yield 1)
1379    /// def f[T](x: int) -> (y := 3): return x
1380    /// ```
1381    InvalidExpression(InvalidExpressionKind, InvalidExpressionPosition),
1382
1383    /// Represents a duplicate key in a `match` mapping pattern.
1384    ///
1385    /// The [CPython grammar] allows keys in mapping patterns to be literals or attribute accesses:
1386    ///
1387    /// ```text
1388    /// key_value_pattern:
1389    ///     | (literal_expr | attr) ':' pattern
1390    /// ```
1391    ///
1392    /// But only literals are checked for duplicates:
1393    ///
1394    /// ```pycon
1395    /// >>> match x:
1396    /// ...     case {"x": 1, "x": 2}: ...
1397    /// ...
1398    ///   File "<python-input-160>", line 2
1399    ///     case {"x": 1, "x": 2}: ...
1400    ///          ^^^^^^^^^^^^^^^^
1401    /// SyntaxError: mapping pattern checks duplicate key ('x')
1402    /// >>> match x:
1403    /// ...     case {x.a: 1, x.a: 2}: ...
1404    /// ...
1405    /// >>>
1406    /// ```
1407    ///
1408    /// ## Examples
1409    ///
1410    /// ```python
1411    /// match x:
1412    ///     case {"x": 1, "x": 2}: ...
1413    /// ```
1414    ///
1415    /// [CPython grammar]: https://docs.python.org/3/reference/grammar.html
1416    DuplicateMatchKey(String),
1417
1418    /// Represents a duplicate attribute name in a `match` class pattern.
1419    ///
1420    /// ## Examples
1421    ///
1422    /// ```python
1423    /// match x:
1424    ///     case Class(x=1, x=2): ...
1425    /// ```
1426    DuplicateMatchClassAttribute(ast::name::Name),
1427
1428    /// Represents the use of a `global` variable before its `global` declaration.
1429    ///
1430    /// ## Examples
1431    ///
1432    /// ```python
1433    /// counter = 1
1434    /// def increment():
1435    ///     print(f"Adding 1 to {counter}")
1436    ///     global counter
1437    ///     counter += 1
1438    /// ```
1439    ///
1440    /// ## Known Issues
1441    ///
1442    /// Note that the order in which the parts of a `try` statement are visited was changed in 3.13,
1443    /// as tracked in Python issue [#111123]. For example, this code was valid on Python 3.12:
1444    ///
1445    /// ```python
1446    /// a = 10
1447    /// def g():
1448    ///     try:
1449    ///         1 / 0
1450    ///     except:
1451    ///         a = 1
1452    ///     else:
1453    ///         global a
1454    /// ```
1455    ///
1456    /// While this more intuitive behavior aligned with the textual order was a syntax error:
1457    ///
1458    /// ```python
1459    /// a = 10
1460    /// def f():
1461    ///     try:
1462    ///         pass
1463    ///     except:
1464    ///         global a
1465    ///     else:
1466    ///         a = 1  # SyntaxError: name 'a' is assigned to before global declaration
1467    /// ```
1468    ///
1469    /// This was reversed in version 3.13 to make the second case valid and the first case a syntax
1470    /// error. We intentionally enforce the 3.13 ordering, regardless of the Python version, which
1471    /// will lead to both false positives and false negatives on 3.12 code that takes advantage of
1472    /// the old behavior. However, as mentioned in the Python issue, we expect code relying on this
1473    /// to be very rare and not worth the additional complexity to detect.
1474    ///
1475    /// [#111123]: https://github.com/python/cpython/issues/111123
1476    LoadBeforeGlobalDeclaration { name: String, start: TextSize },
1477
1478    /// Represents the use of a `nonlocal` variable before its `nonlocal` declaration.
1479    ///
1480    /// ## Examples
1481    ///
1482    /// ```python
1483    /// def f():
1484    ///     counter = 0
1485    ///     def increment():
1486    ///         print(f"Adding 1 to {counter}")
1487    ///         nonlocal counter  # SyntaxError: name 'counter' is used prior to nonlocal declaration
1488    ///         counter += 1
1489    /// ```
1490    ///
1491    /// ## Known Issues
1492    ///
1493    /// See [`LoadBeforeGlobalDeclaration`][Self::LoadBeforeGlobalDeclaration].
1494    LoadBeforeNonlocalDeclaration { name: String, start: TextSize },
1495
1496    /// Represents the use of a starred expression in an invalid location, such as a `return` or
1497    /// `yield` statement.
1498    ///
1499    /// ## Examples
1500    ///
1501    /// ```python
1502    /// def f(): return *x
1503    /// def f(): yield *x
1504    /// for _ in *x: ...
1505    /// for *x in xs: ...
1506    /// ```
1507    InvalidStarExpression,
1508
1509    /// Represents the use of an asynchronous comprehension inside of a synchronous comprehension
1510    /// before Python 3.11.
1511    ///
1512    /// ## Examples
1513    ///
1514    /// Before Python 3.11, code like this produces a syntax error because of the implicit function
1515    /// scope introduced by the outer comprehension:
1516    ///
1517    /// ```python
1518    /// async def elements(n): yield n
1519    ///
1520    /// async def test(): return { n: [x async for x in elements(n)] for n in range(3)}
1521    /// ```
1522    ///
1523    /// This was discussed in [BPO 33346] and fixed in Python 3.11.
1524    ///
1525    /// [BPO 33346]: https://github.com/python/cpython/issues/77527
1526    AsyncComprehensionInSyncComprehension(PythonVersion),
1527
1528    /// Represents the use of `yield`, `yield from`, or `await` outside of a function scope.
1529    ///
1530    ///
1531    /// ## Examples
1532    ///
1533    /// `yield` and `yield from` are only allowed if the immediately-enclosing scope is a function
1534    /// or lambda and not allowed otherwise:
1535    ///
1536    /// ```python
1537    /// yield 1  # error
1538    ///
1539    /// def f():
1540    ///     [(yield 1) for x in y]  # error
1541    /// ```
1542    ///
1543    /// `await` is additionally allowed in comprehensions, if the comprehension itself is in a
1544    /// function scope:
1545    ///
1546    /// ```python
1547    /// await 1  # error
1548    ///
1549    /// async def f():
1550    ///     await 1  # okay
1551    ///     [await 1 for x in y]  # also okay
1552    /// ```
1553    ///
1554    /// This last case _is_ an error, but it has to do with the lambda not being an async function.
1555    /// For the sake of this error kind, this is okay.
1556    ///
1557    /// ## References
1558    ///
1559    /// See [PEP 255] for details on `yield`, [PEP 380] for the extension to `yield from`, [PEP 492]
1560    /// for async-await syntax, and [PEP 530] for async comprehensions.
1561    ///
1562    /// [PEP 255]: https://peps.python.org/pep-0255/
1563    /// [PEP 380]: https://peps.python.org/pep-0380/
1564    /// [PEP 492]: https://peps.python.org/pep-0492/
1565    /// [PEP 530]: https://peps.python.org/pep-0530/
1566    YieldOutsideFunction(YieldOutsideFunctionKind),
1567
1568    /// Represents the use of `return` outside of a function scope.
1569    ReturnOutsideFunction,
1570
1571    /// Represents the use of `await`, `async for`, or `async with` outside of an asynchronous
1572    /// function.
1573    ///
1574    /// ## Examples
1575    ///
1576    /// ```python
1577    /// def f():
1578    ///     await 1                # error
1579    ///     async for x in y: ...  # error
1580    ///     async with x: ...      # error
1581    /// ```
1582    AwaitOutsideAsyncFunction(AwaitOutsideAsyncFunctionKind),
1583
1584    /// Represents a duplicate parameter name in a function or lambda expression.
1585    ///
1586    /// ## Examples
1587    ///
1588    /// ```python
1589    /// def f(x, x): ...
1590    /// lambda x, x: ...
1591    /// ```
1592    DuplicateParameter(String),
1593
1594    /// Represents a nonlocal declaration at module level
1595    NonlocalDeclarationAtModuleLevel,
1596
1597    /// Represents the same variable declared as both nonlocal and global
1598    NonlocalAndGlobal(String),
1599
1600    /// Represents a type annotation on a variable that's been declared global
1601    AnnotatedGlobal(String),
1602
1603    /// Represents a type annotation on a variable that's been declared nonlocal
1604    AnnotatedNonlocal(String),
1605
1606    /// Represents the use of `yield from` inside an asynchronous function.
1607    YieldFromInAsyncFunction,
1608
1609    /// Represents the use of `from <module> import *` outside module scope.
1610    NonModuleImportStar(String),
1611
1612    /// Represents the use of more than one starred expression in an assignment.
1613    ///
1614    /// Python only allows a single starred target when unpacking values on the
1615    /// left-hand side of an assignment. Using multiple starred expressions makes
1616    /// the statement invalid and results in a `SyntaxError`.
1617    MultipleStarredExpressions,
1618
1619    /// Represents the use of a `__future__` feature that is not defined.
1620    FutureFeatureNotDefined(String),
1621
1622    /// Represents the use of a `break` statement outside of a loop.
1623    BreakOutsideLoop,
1624
1625    /// Represents the use of a `continue` statement outside of a loop.
1626    ContinueOutsideLoop,
1627
1628    /// Represents a function parameter that is also declared as `global`.
1629    ///
1630    /// Declaring a parameter as `global` is invalid, since parameters are already
1631    /// bound in the local scope of the function. Using `global` on them introduces
1632    /// ambiguity and will result in a `SyntaxError`.
1633    GlobalParameter(String),
1634
1635    /// Represents the use of alternative patterns in a `match` statement that bind different names.
1636    ///
1637    /// Python requires all alternatives in an OR pattern (`|`) to bind the same set of names.
1638    /// Using different names results in a `SyntaxError`.
1639    ///
1640    /// ## Example:
1641    ///
1642    /// ```python
1643    /// match 5:
1644    ///     case [x] | [y]:  # error
1645    ///         ...
1646    /// ```
1647    DifferentMatchPatternBindings,
1648
1649    /// Represents a nonlocal statement for a name that has no binding in an enclosing scope.
1650    NonlocalWithoutBinding(String),
1651
1652    /// Represents a default type parameter followed by a non-default type parameter.
1653    TypeParameterDefaultOrder(String),
1654
1655    /// Represents a `return` statement with a value in an asynchronous generator.
1656    ReturnInGenerator,
1657}
1658
1659#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)]
1660pub enum AwaitOutsideAsyncFunctionKind {
1661    Await,
1662    AsyncFor,
1663    AsyncWith,
1664    AsyncComprehension,
1665}
1666
1667impl Display for AwaitOutsideAsyncFunctionKind {
1668    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1669        f.write_str(match self {
1670            AwaitOutsideAsyncFunctionKind::Await => "`await`",
1671            AwaitOutsideAsyncFunctionKind::AsyncFor => "`async for`",
1672            AwaitOutsideAsyncFunctionKind::AsyncWith => "`async with`",
1673            AwaitOutsideAsyncFunctionKind::AsyncComprehension => "asynchronous comprehension",
1674        })
1675    }
1676}
1677
1678#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)]
1679pub enum YieldOutsideFunctionKind {
1680    Yield,
1681    YieldFrom,
1682    Await,
1683}
1684
1685impl YieldOutsideFunctionKind {
1686    pub fn is_await(&self) -> bool {
1687        matches!(self, Self::Await)
1688    }
1689}
1690
1691impl Display for YieldOutsideFunctionKind {
1692    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1693        f.write_str(match self {
1694            YieldOutsideFunctionKind::Yield => "yield",
1695            YieldOutsideFunctionKind::YieldFrom => "yield from",
1696            YieldOutsideFunctionKind::Await => "await",
1697        })
1698    }
1699}
1700
1701#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)]
1702pub enum InvalidExpressionPosition {
1703    TypeVarBound,
1704    TypeVarDefault,
1705    TypeVarTupleDefault,
1706    ParamSpecDefault,
1707    TypeAnnotation,
1708    GenericDefinition,
1709    TypeAlias,
1710}
1711
1712impl Display for InvalidExpressionPosition {
1713    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1714        f.write_str(match self {
1715            InvalidExpressionPosition::TypeVarBound => "TypeVar bound",
1716            InvalidExpressionPosition::TypeVarDefault => "TypeVar default",
1717            InvalidExpressionPosition::TypeVarTupleDefault => "TypeVarTuple default",
1718            InvalidExpressionPosition::ParamSpecDefault => "ParamSpec default",
1719            InvalidExpressionPosition::TypeAnnotation => "type annotation",
1720            InvalidExpressionPosition::GenericDefinition => "generic definition",
1721            InvalidExpressionPosition::TypeAlias => "type alias",
1722        })
1723    }
1724}
1725
1726#[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)]
1727pub enum InvalidExpressionKind {
1728    Yield,
1729    NamedExpr,
1730    Await,
1731}
1732
1733impl Display for InvalidExpressionKind {
1734    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1735        f.write_str(match self {
1736            InvalidExpressionKind::Yield => "yield expression",
1737            InvalidExpressionKind::NamedExpr => "named expression",
1738            InvalidExpressionKind::Await => "await expression",
1739        })
1740    }
1741}
1742
1743#[derive(Debug, Clone, PartialEq, Eq, Hash, get_size2::GetSize)]
1744pub enum WriteToDebugKind {
1745    Store,
1746    Delete(PythonVersion),
1747}
1748
1749/// Searches for the first named expression (`x := y`) rebinding one of the `iteration_variables` in
1750/// a comprehension or generator expression.
1751struct ReboundComprehensionVisitor<'a> {
1752    comprehensions: &'a [ast::Comprehension],
1753    rebound_variables: Vec<TextRange>,
1754}
1755
1756impl Visitor<'_> for ReboundComprehensionVisitor<'_> {
1757    fn visit_expr(&mut self, expr: &Expr) {
1758        if let Expr::Named(ast::ExprNamed { target, .. }) = expr {
1759            if let Expr::Name(ast::ExprName { id, range, .. }) = &**target {
1760                if self.comprehensions.iter().any(|comp| {
1761                    comp.target
1762                        .as_name_expr()
1763                        .is_some_and(|name| name.id == *id)
1764                }) {
1765                    self.rebound_variables.push(*range);
1766                }
1767            }
1768        }
1769        walk_expr(self, expr);
1770    }
1771}
1772
1773#[derive(Default)]
1774struct ReturnVisitor {
1775    return_range: Option<TextRange>,
1776    has_yield: bool,
1777}
1778
1779impl Visitor<'_> for ReturnVisitor {
1780    fn visit_stmt(&mut self, stmt: &Stmt) {
1781        match stmt {
1782            // Do not recurse into nested functions; they're evaluated separately.
1783            Stmt::FunctionDef(_) | Stmt::ClassDef(_) => {}
1784            Stmt::Return(ast::StmtReturn {
1785                value: Some(_),
1786                range,
1787                ..
1788            }) => {
1789                self.return_range = Some(*range);
1790                walk_stmt(self, stmt);
1791            }
1792            _ => walk_stmt(self, stmt),
1793        }
1794    }
1795
1796    fn visit_expr(&mut self, expr: &Expr) {
1797        match expr {
1798            Expr::Lambda(_) => {}
1799            Expr::Yield(_) | Expr::YieldFrom(_) => {
1800                self.has_yield = true;
1801            }
1802            _ => walk_expr(self, expr),
1803        }
1804    }
1805}
1806
1807struct MatchPatternVisitor<'a, Ctx> {
1808    names: FxHashSet<&'a ast::name::Name>,
1809    ctx: &'a Ctx,
1810}
1811
1812impl<'a, Ctx: SemanticSyntaxContext> MatchPatternVisitor<'a, Ctx> {
1813    fn visit_pattern(&mut self, pattern: &'a Pattern) {
1814        // test_ok class_keyword_in_case_pattern
1815        // match 2:
1816        //     case Class(x=x): ...
1817
1818        // test_err multiple_assignment_in_case_pattern
1819        // match 2:
1820        //     case [y, z, y]: ...  # MatchSequence
1821        //     case [y, z, *y]: ...  # MatchSequence
1822        //     case [y, y, y]: ...  # MatchSequence multiple
1823        //     case {1: x, 2: x}: ...  # MatchMapping duplicate pattern
1824        //     case {1: x, **x}: ...  # MatchMapping duplicate in **rest
1825        //     case Class(x, x): ...  # MatchClass positional
1826        //     case Class(y=x, z=x): ...  # MatchClass keyword
1827        //     case [x] | {1: x} | Class(y=x, z=x): ...  # MatchOr
1828        //     case x as x: ...  # MatchAs
1829        match pattern {
1830            Pattern::MatchValue(_) | Pattern::MatchSingleton(_) => {}
1831            Pattern::MatchStar(ast::PatternMatchStar { name, .. }) => {
1832                if let Some(name) = name {
1833                    self.insert(name);
1834                }
1835            }
1836            Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => {
1837                for pattern in patterns {
1838                    self.visit_pattern(pattern);
1839                }
1840            }
1841            Pattern::MatchMapping(ast::PatternMatchMapping {
1842                keys,
1843                patterns,
1844                rest,
1845                ..
1846            }) => {
1847                for pattern in patterns {
1848                    self.visit_pattern(pattern);
1849                }
1850                if let Some(rest) = rest {
1851                    self.insert(rest);
1852                }
1853
1854                let mut seen = FxHashSet::default();
1855                for key in keys
1856                    .iter()
1857                    // complex numbers (`1 + 2j`) are allowed as keys but are not literals
1858                    // because they are represented as a `BinOp::Add` between a real number and
1859                    // an imaginary number
1860                    .filter(|key| key.is_literal_expr() || key.is_bin_op_expr())
1861                {
1862                    if !seen.insert(ComparableExpr::from(key)) {
1863                        let key_range = key.range();
1864                        let duplicate_key = self.ctx.source()[key_range].to_string();
1865                        // test_ok duplicate_match_key_attr
1866                        // match x:
1867                        //     case {x.a: 1, x.a: 2}: ...
1868
1869                        // test_err duplicate_match_key
1870                        // match x:
1871                        //     case {"x": 1, "x": 2}: ...
1872                        //     case {b"x": 1, b"x": 2}: ...
1873                        //     case {0: 1, 0: 2}: ...
1874                        //     case {1.0: 1, 1.0: 2}: ...
1875                        //     case {1.0 + 2j: 1, 1.0 + 2j: 2}: ...
1876                        //     case {True: 1, True: 2}: ...
1877                        //     case {None: 1, None: 2}: ...
1878                        //     case {
1879                        //     """x
1880                        //     y
1881                        //     z
1882                        //     """: 1,
1883                        //     """x
1884                        //     y
1885                        //     z
1886                        //     """: 2}: ...
1887                        //     case {"x": 1, "x": 2, "x": 3}: ...
1888                        //     case {0: 1, "x": 1, 0: 2, "x": 2}: ...
1889                        //     case [{"x": 1, "x": 2}]: ...
1890                        //     case Foo(x=1, y={"x": 1, "x": 2}): ...
1891                        //     case [Foo(x=1), Foo(x=1, y={"x": 1, "x": 2})]: ...
1892                        SemanticSyntaxChecker::add_error(
1893                            self.ctx,
1894                            SemanticSyntaxErrorKind::DuplicateMatchKey(duplicate_key),
1895                            key_range,
1896                        );
1897                    }
1898                }
1899            }
1900            Pattern::MatchClass(ast::PatternMatchClass { arguments, .. }) => {
1901                for pattern in &arguments.patterns {
1902                    self.visit_pattern(pattern);
1903                }
1904                let mut seen = FxHashSet::default();
1905                for keyword in &arguments.keywords {
1906                    if !seen.insert(&keyword.attr.id) {
1907                        // test_err duplicate_match_class_attr
1908                        // match x:
1909                        //     case Class(x=1, x=2): ...
1910                        //     case [Class(x=1, x=2)]: ...
1911                        //     case {"x": x, "y": Foo(x=1, x=2)}: ...
1912                        //     case [{}, {"x": x, "y": Foo(x=1, x=2)}]: ...
1913                        //     case Class(x=1, d={"x": 1, "x": 2}, other=Class(x=1, x=2)): ...
1914                        SemanticSyntaxChecker::add_error(
1915                            self.ctx,
1916                            SemanticSyntaxErrorKind::DuplicateMatchClassAttribute(
1917                                keyword.attr.id.clone(),
1918                            ),
1919                            keyword.attr.range,
1920                        );
1921                    }
1922                    self.visit_pattern(&keyword.pattern);
1923                }
1924            }
1925            Pattern::MatchAs(ast::PatternMatchAs { pattern, name, .. }) => {
1926                if let Some(pattern) = pattern {
1927                    self.visit_pattern(pattern);
1928                }
1929                if let Some(name) = name {
1930                    self.insert(name);
1931                }
1932            }
1933            Pattern::MatchOr(ast::PatternMatchOr {
1934                patterns, range, ..
1935            }) => {
1936                // each of these patterns should be visited separately because patterns can only be
1937                // duplicated within a single arm of the or pattern. For example, the case below is
1938                // a valid pattern.
1939
1940                // test_ok multiple_assignment_in_case_pattern
1941                // match 2:
1942                //     case Class(x) | [x] | x: ...
1943
1944                let mut previous_names: Option<FxHashSet<&ast::name::Name>> = None;
1945                for pattern in patterns {
1946                    let mut visitor = Self {
1947                        names: FxHashSet::default(),
1948                        ctx: self.ctx,
1949                    };
1950                    visitor.visit_pattern(pattern);
1951                    let Some(prev) = &previous_names else {
1952                        previous_names = Some(visitor.names);
1953                        continue;
1954                    };
1955                    if prev.symmetric_difference(&visitor.names).next().is_some() {
1956                        // test_err different_match_pattern_bindings
1957                        // match x:
1958                        //     case [a] | [b]: ...
1959                        //     case [a] | []: ...
1960                        //     case (x, y) | (x,): ...
1961                        //     case [a, _] | [a, b]: ...
1962                        //     case (x, (y | z)): ...
1963                        //     case [a] | [b] | [c]: ...
1964                        //     case [] | [a]: ...
1965                        //     case [a] | [C(x)]: ...
1966                        //     case [[a] | [b]]: ...
1967                        //     case [C(a)] | [C(b)]: ...
1968                        //     case [C(D(a))] | [C(D(b))]: ...
1969                        //     case [(a, b)] | [(c, d)]: ...
1970
1971                        // test_ok different_match_pattern_bindings
1972                        // match x:
1973                        //     case [a] | [a]: ...
1974                        //     case (x, y) | (x, y): ...
1975                        //     case (x, (y | y)): ...
1976                        //     case [a, _] | [a, _]: ...
1977                        //     case [a] | [C(a)]: ...
1978
1979                        // test_ok nested_alternative_patterns
1980                        // match ruff:
1981                        //     case {"lint": {"select": x} | {"extend-select": x}} | {"select": x}:
1982                        //         ...
1983                        // match 42:
1984                        //     case [[x] | [x]] | x: ...
1985                        // match 42:
1986                        //     case [[x | x] | [x]] | x: ...
1987                        // match 42:
1988                        //     case ast.Subscript(n, ast.Constant() | ast.Slice()) | ast.Attribute(n): ...
1989                        SemanticSyntaxChecker::add_error(
1990                            self.ctx,
1991                            SemanticSyntaxErrorKind::DifferentMatchPatternBindings,
1992                            *range,
1993                        );
1994                        break;
1995                    }
1996                    self.names.extend(visitor.names);
1997                }
1998            }
1999        }
2000    }
2001
2002    /// Add an identifier to the set of visited names in `self` and emit a [`SemanticSyntaxError`]
2003    /// if `ident` has already been seen.
2004    fn insert(&mut self, ident: &'a ast::Identifier) {
2005        if !self.names.insert(&ident.id) {
2006            SemanticSyntaxChecker::add_error(
2007                self.ctx,
2008                SemanticSyntaxErrorKind::MultipleCaseAssignment(ident.id.clone()),
2009                ident.range(),
2010            );
2011        }
2012        // test_err debug_shadow_match
2013        // match x:
2014        //     case __debug__: ...
2015        SemanticSyntaxChecker::check_identifier(ident, self.ctx);
2016    }
2017}
2018
2019struct InvalidExpressionVisitor<'a, Ctx> {
2020    /// Context used for emitting errors.
2021    ctx: &'a Ctx,
2022
2023    position: InvalidExpressionPosition,
2024}
2025
2026impl<Ctx> Visitor<'_> for InvalidExpressionVisitor<'_, Ctx>
2027where
2028    Ctx: SemanticSyntaxContext,
2029{
2030    fn visit_expr(&mut self, expr: &Expr) {
2031        match expr {
2032            Expr::Named(ast::ExprNamed { range, .. }) => {
2033                SemanticSyntaxChecker::add_error(
2034                    self.ctx,
2035                    SemanticSyntaxErrorKind::InvalidExpression(
2036                        InvalidExpressionKind::NamedExpr,
2037                        self.position,
2038                    ),
2039                    *range,
2040                );
2041            }
2042            Expr::Yield(ast::ExprYield { range, .. })
2043            | Expr::YieldFrom(ast::ExprYieldFrom { range, .. }) => {
2044                SemanticSyntaxChecker::add_error(
2045                    self.ctx,
2046                    SemanticSyntaxErrorKind::InvalidExpression(
2047                        InvalidExpressionKind::Yield,
2048                        self.position,
2049                    ),
2050                    *range,
2051                );
2052            }
2053            Expr::Await(ast::ExprAwait { range, .. }) => {
2054                SemanticSyntaxChecker::add_error(
2055                    self.ctx,
2056                    SemanticSyntaxErrorKind::InvalidExpression(
2057                        InvalidExpressionKind::Await,
2058                        self.position,
2059                    ),
2060                    *range,
2061                );
2062            }
2063            _ => {}
2064        }
2065        ast::visitor::walk_expr(self, expr);
2066    }
2067
2068    fn visit_type_param(&mut self, type_param: &ast::TypeParam) {
2069        match type_param {
2070            ast::TypeParam::TypeVar(ast::TypeParamTypeVar { bound, default, .. }) => {
2071                if let Some(expr) = bound {
2072                    self.position = InvalidExpressionPosition::TypeVarBound;
2073                    self.visit_expr(expr);
2074                }
2075                if let Some(expr) = default {
2076                    self.position = InvalidExpressionPosition::TypeVarDefault;
2077                    self.visit_expr(expr);
2078                }
2079            }
2080            ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { default, .. }) => {
2081                if let Some(expr) = default {
2082                    self.position = InvalidExpressionPosition::TypeVarTupleDefault;
2083                    self.visit_expr(expr);
2084                }
2085            }
2086            ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { default, .. }) => {
2087                if let Some(expr) = default {
2088                    self.position = InvalidExpressionPosition::ParamSpecDefault;
2089                    self.visit_expr(expr);
2090                }
2091            }
2092        }
2093    }
2094}
2095
2096/// Information needed from a parent visitor to emit semantic syntax errors.
2097///
2098/// Note that the `in_*_scope` methods should refer to the immediately-enclosing scope. For example,
2099/// `in_function_scope` should return true for this case:
2100///
2101/// ```python
2102/// def f():
2103///     x  # here
2104/// ```
2105///
2106/// but not for this case:
2107///
2108/// ```python
2109/// def f():
2110///     class C:
2111///         x  # here
2112/// ```
2113///
2114/// In contrast, the `in_*_context` methods should traverse parent scopes. For example,
2115/// `in_function_context` should return true for this case:
2116///
2117/// ```python
2118/// def f():
2119///     [x  # here
2120///         for x in range(3)]
2121/// ```
2122///
2123/// but not here:
2124///
2125/// ```python
2126/// def f():
2127///     class C:
2128///         x  # here, classes break function scopes
2129/// ```
2130pub trait SemanticSyntaxContext {
2131    /// Returns `true` if `__future__`-style type annotations are enabled.
2132    fn future_annotations_or_stub(&self) -> bool;
2133
2134    /// The target Python version for detecting backwards-incompatible syntax changes.
2135    fn python_version(&self) -> PythonVersion;
2136
2137    /// Returns the source text under analysis.
2138    fn source(&self) -> &str;
2139
2140    /// Return the [`TextRange`] at which a name is declared as `global` in the current scope.
2141    fn global(&self, name: &str) -> Option<TextRange>;
2142
2143    /// Returns `true` if `name` has a binding in an enclosing scope.
2144    fn has_nonlocal_binding(&self, name: &str) -> bool;
2145
2146    /// Returns `true` if the visitor is currently in an async context, i.e. an async function.
2147    fn in_async_context(&self) -> bool;
2148
2149    /// Returns `true` if the visitor is currently in a context where the `await` keyword is
2150    /// allowed.
2151    ///
2152    /// Note that this is method is primarily used to report `YieldOutsideFunction` errors for
2153    /// `await` outside function scopes, irrespective of their async status. As such, this differs
2154    /// from `in_async_context` in two ways:
2155    ///
2156    /// 1. `await` is allowed in a lambda, despite it not being async
2157    /// 2. `await` is allowed in any function, regardless of its async status
2158    ///
2159    /// In short, only nested class definitions should cause this method to return `false`, for
2160    /// example:
2161    ///
2162    /// ```python
2163    /// def f():
2164    ///     await 1  # okay, in a function
2165    ///     class C:
2166    ///         await 1  # error
2167    /// ```
2168    ///
2169    /// See the trait-level documentation for more details.
2170    fn in_await_allowed_context(&self) -> bool;
2171
2172    /// Returns `true` if the visitor is currently in a context where `yield` and `yield from`
2173    /// expressions are allowed.
2174    ///
2175    /// Yield expressions are allowed only in:
2176    /// 1. Function definitions
2177    /// 2. Lambda expressions
2178    ///
2179    /// Unlike `await`, yield is not allowed in:
2180    /// - Comprehensions (list, set, dict)
2181    /// - Generator expressions
2182    /// - Class definitions
2183    ///
2184    /// This method should traverse parent scopes to check if the closest relevant scope
2185    /// is a function or lambda, and that no disallowed context (class, comprehension, generator)
2186    /// intervenes. For example:
2187    ///
2188    /// ```python
2189    /// def f():
2190    ///     yield 1  # okay, in a function
2191    ///     lambda: (yield 1)  # okay, in a lambda
2192    ///
2193    ///     [(yield 1) for x in range(3)]  # error, in a comprehension
2194    ///     ((yield 1) for x in range(3))  # error, in a generator expression
2195    ///     class C:
2196    ///         yield 1  # error, in a class within a function
2197    /// ```
2198    ///
2199    fn in_yield_allowed_context(&self) -> bool;
2200
2201    /// Returns `true` if the visitor is currently inside of a synchronous comprehension.
2202    ///
2203    /// This method is necessary because `in_async_context` only checks for the nearest, enclosing
2204    /// function to determine the (a)sync context. Instead, this method will search all enclosing
2205    /// scopes until it finds a sync comprehension. As a result, the two methods will typically be
2206    /// used together.
2207    fn in_sync_comprehension(&self) -> bool;
2208
2209    /// Returns `true` if the visitor is at the top-level module scope.
2210    fn in_module_scope(&self) -> bool;
2211
2212    /// Returns `true` if the visitor is in a function scope.
2213    fn in_function_scope(&self) -> bool;
2214
2215    /// Returns `true` if the visitor is within a generator scope.
2216    ///
2217    /// Note that this refers to an `Expr::Generator` precisely, not to comprehensions more
2218    /// generally.
2219    fn in_generator_context(&self) -> bool;
2220
2221    /// Returns `true` if the source file is a Jupyter notebook.
2222    fn in_notebook(&self) -> bool;
2223
2224    fn report_semantic_error(&self, error: SemanticSyntaxError);
2225
2226    /// Returns `true` if the visitor is inside a `for` or `while` loop.
2227    fn in_loop_context(&self) -> bool;
2228
2229    /// Returns `true` if `name` is a bound parameter in the current function or lambda scope.
2230    fn is_bound_parameter(&self, name: &str) -> bool;
2231}
2232
2233/// Modified version of [`std::str::EscapeDefault`] that does not escape single or double quotes.
2234struct EscapeDefault<'a>(&'a str);
2235
2236impl Display for EscapeDefault<'_> {
2237    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2238        use std::fmt::Write;
2239
2240        for c in self.0.chars() {
2241            match c {
2242                '\'' | '\"' => f.write_char(c)?,
2243                _ => write!(f, "{}", c.escape_default())?,
2244            }
2245        }
2246        Ok(())
2247    }
2248}