Repository: astral-sh/ruff
File: crates/ruff_python_parser/src/semantic_errors.rs (Rust)

Code before:
            }) => {
                if let Some(type_params) = type_params {
                    Self::duplicate_type_parameter_name(type_params, ctx);
                }
                Self::duplicate_parameter_name(parameters, ctx);
            }
            Stmt::Global(ast::StmtGlobal { names, .. }) => {
                for name in names {
                    if ctx.is_bound_parameter(name) {
                        Self::add_error(
                            ctx,
                            SemanticSyntaxErrorKind::GlobalParameter(name.to_string()),
                            name.range,
                        );
                    }
                }
            }
            Stmt::ClassDef(ast::StmtClassDef {
                type_params: Some(type_params),
                ..
            }) => {
                Self::duplicate_type_parameter_name(type_params, ctx);
                Self::type_parameter_default_order(type_params, ctx);
            }
            Stmt::TypeAlias(ast::StmtTypeAlias {
                type_params: Some(type_params),
                ..
            }) => {
                Self::duplicate_type_parameter_name(type_params, ctx);
            }
            Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
                if let [Expr::Starred(ast::ExprStarred { range, .. })] = targets.as_slice() {
                    // test_ok single_starred_assignment_target
                    // (*a,) = (1,)
                    // *a, = (1,)
                    // [*a] = (1,)

                    // test_err single_starred_assignment_target
                    // *a = (1,)
                    Self::add_error(
                        ctx,
                        SemanticSyntaxErrorKind::SingleStarredAssignment,
                        *range,
                    );
                }

                // test_ok assign_stmt_starred_expr_value
                // _ = 4
                // _ = [4]
                // _ = (*[1],)
                // _ = *[1],

Review comment (suggestion):
This check needs to be applied to type aliases as well:

```python
In [1]: type Int[T = int, U] = int
  Cell In[1], line 1
    type Int[T = int, U] = int
                      ^
SyntaxError: non-default type parameter 'U' follows default type parameter
```

Code after:
            }) => {
                if let Some(type_params) = type_params {
                    Self::duplicate_type_parameter_name(type_params, ctx);
                }
                Self::duplicate_parameter_name(parameters, ctx);
            }
            Stmt::Global(ast::StmtGlobal { names, .. }) => {
                for name in names {
                    if ctx.is_bound_parameter(name) {
                        Self::add_error(
                            ctx,
                            SemanticSyntaxErrorKind::GlobalParameter(name.to_string()),
                            name.range,
                        );
                    }
                }
            }
            Stmt::ClassDef(ast::StmtClassDef {
                type_params: Some(type_params),
                ..
            })
            | Stmt::TypeAlias(ast::StmtTypeAlias {
                type_params: Some(type_params),
                ..
            }) => {
                Self::duplicate_type_parameter_name(type_params, ctx);
                Self::type_parameter_default_order(type_params, ctx);
            }
            Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
                if let [Expr::Starred(ast::ExprStarred { range, .. })] = targets.as_slice() {
                    // test_ok single_starred_assignment_target
                    // (*a,) = (1,)
                    // *a, = (1,)
                    // [*a] = (1,)

                    // test_err single_starred_assignment_target
                    // *a = (1,)
                    Self::add_error(
                        ctx,
                        SemanticSyntaxErrorKind::SingleStarredAssignment,
                        *range,
                    );
                }

                // test_ok assign_stmt_starred_expr_value
                // _ = 4
                // _ = [4]
                // _ = (*[1],)
                // _ = *[1],

                // test_err assign_stmt_starred_expr_value