[syntax-errors] nonlocal declaration at module level (#17559)

## Summary

Part of #17412

Add a new compile-time syntax error for detecting `nonlocal`
declarations at a module level.

## Test Plan

- Added new inline tests for the syntax error
- Updated existing tests for `nonlocal` statement parsing to be inside a
function scope

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
This commit is contained in:
Abhijeet Prasad Bodas 2025-04-25 01:41:46 +05:30 committed by GitHub
parent 538393d1f3
commit cf59cee928
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 363 additions and 131 deletions

View file

@ -897,12 +897,14 @@ impl<'src> Parser<'src> {
self.bump(TokenKind::Nonlocal);
// test_err nonlocal_stmt_trailing_comma
// nonlocal ,
// nonlocal x,
// nonlocal x, y,
// def _():
// nonlocal ,
// nonlocal x,
// nonlocal x, y,
// test_err nonlocal_stmt_expression
// nonlocal x + 1
// def _():
// nonlocal x + 1
let names = self.parse_comma_separated_list_into_vec(
RecoveryContextKind::Identifiers,
Parser::parse_identifier,
@ -910,7 +912,8 @@ impl<'src> Parser<'src> {
if names.is_empty() {
// test_err nonlocal_stmt_empty
// nonlocal
// def _():
// nonlocal
self.add_error(
ParseErrorType::EmptyNonlocalNames,
self.current_token_range(),
@ -918,8 +921,9 @@ impl<'src> Parser<'src> {
}
// test_ok nonlocal_stmt
// nonlocal x
// nonlocal x, y, z
// def _():
// nonlocal x
// nonlocal x, y, z
ast::StmtNonlocal {
range: self.node_range(start),
names,

View file

@ -142,6 +142,22 @@ impl SemanticSyntaxChecker {
AwaitOutsideAsyncFunctionKind::AsyncWith,
);
}
Stmt::Nonlocal(ast::StmtNonlocal { range, .. }) => {
// test_ok nonlocal_declaration_at_module_level
// def _():
// nonlocal x
// test_err nonlocal_declaration_at_module_level
// nonlocal x
// nonlocal x, y
if ctx.in_module_scope() {
Self::add_error(
ctx,
SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel,
*range,
);
}
}
_ => {}
}
@ -933,6 +949,9 @@ impl Display for SemanticSyntaxError {
SemanticSyntaxErrorKind::DuplicateParameter(name) => {
write!(f, r#"Duplicate parameter "{name}""#)
}
SemanticSyntaxErrorKind::NonlocalDeclarationAtModuleLevel => {
write!(f, "nonlocal declaration not allowed at module level")
}
}
}
}
@ -1254,6 +1273,9 @@ pub enum SemanticSyntaxErrorKind {
/// lambda x, x: ...
/// ```
DuplicateParameter(String),
/// Represents a nonlocal declaration at module level
NonlocalDeclarationAtModuleLevel,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]