Skip to content

Commit 54ba45f

Browse files
committed
symboltable takes responsibility of __debug__
1 parent edd19b4 commit 54ba45f

File tree

3 files changed

+54
-53
lines changed

3 files changed

+54
-53
lines changed

crates/codegen/src/compile.rs

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,6 @@ enum NameUsage {
110110
Store,
111111
Delete,
112112
}
113-
114-
fn is_forbidden_name(name: &str) -> bool {
115-
// See https://docs.python.org/3/library/constants.html#built-in-constants
116-
const BUILTIN_CONSTANTS: &[&str] = &["__debug__"];
117-
118-
BUILTIN_CONSTANTS.contains(&name)
119-
}
120-
121113
/// Main structure holding the state of compilation.
122114
struct Compiler {
123115
code_stack: Vec<ir::CodeInfo>,
@@ -1523,11 +1515,7 @@ impl Compiler {
15231515
self._name_inner(name, |i| &mut i.metadata.names)
15241516
}
15251517
fn varname(&mut self, name: &str) -> CompileResult<bytecode::NameIdx> {
1526-
if Self::is_forbidden_arg_name(name) {
1527-
return Err(self.error(CodegenErrorType::SyntaxError(format!(
1528-
"cannot assign to {name}",
1529-
))));
1530-
}
1518+
// Note: __debug__ checks are now handled in symboltable phase
15311519
Ok(self._name_inner(name, |i| &mut i.metadata.varnames))
15321520
}
15331521
fn _name_inner(
@@ -1812,15 +1800,6 @@ impl Compiler {
18121800
symboltable::mangle_name(private, name)
18131801
}
18141802

1815-
fn check_forbidden_name(&mut self, name: &str, usage: NameUsage) -> CompileResult<()> {
1816-
let msg = match usage {
1817-
NameUsage::Store if is_forbidden_name(name) => "cannot assign to",
1818-
NameUsage::Delete if is_forbidden_name(name) => "cannot delete",
1819-
_ => return Ok(()),
1820-
};
1821-
Err(self.error(CodegenErrorType::SyntaxError(format!("{msg} {name}"))))
1822-
}
1823-
18241803
// = compiler_nameop
18251804
fn compile_name(&mut self, name: &str, usage: NameUsage) -> CompileResult<()> {
18261805
enum NameOp {
@@ -1832,7 +1811,6 @@ impl Compiler {
18321811
}
18331812

18341813
let name = self.mangle(name);
1835-
self.check_forbidden_name(&name, usage)?;
18361814

18371815
// Special handling for __debug__
18381816
if NameUsage::Load == usage && name == "__debug__" {
@@ -2434,7 +2412,6 @@ impl Compiler {
24342412
match &expression {
24352413
Expr::Name(ExprName { id, .. }) => self.compile_name(id.as_str(), NameUsage::Delete)?,
24362414
Expr::Attribute(ExprAttribute { value, attr, .. }) => {
2437-
self.check_forbidden_name(attr.as_str(), NameUsage::Delete)?;
24382415
self.compile_expression(value)?;
24392416
let idx = self.name(attr.as_str());
24402417
emit!(self, Instruction::DeleteAttr { idx });
@@ -3453,10 +3430,6 @@ impl Compiler {
34533430
Ok(())
34543431
}
34553432

3456-
fn is_forbidden_arg_name(name: &str) -> bool {
3457-
is_forbidden_name(name)
3458-
}
3459-
34603433
/// Compile default arguments
34613434
// = compiler_default_arguments
34623435
fn compile_default_arguments(
@@ -5996,7 +5969,6 @@ impl Compiler {
59965969
self.compile_subscript(value, slice, *ctx)?;
59975970
}
59985971
Expr::Attribute(ExprAttribute { value, attr, .. }) => {
5999-
self.check_forbidden_name(attr.as_str(), NameUsage::Store)?;
60005972
self.compile_expression(value)?;
60015973
let idx = self.name(attr.as_str());
60025974
emit!(self, Instruction::StoreAttr { idx });
@@ -6091,7 +6063,6 @@ impl Compiler {
60916063
}
60926064
Expr::Attribute(ExprAttribute { value, attr, .. }) => {
60936065
let attr = attr.as_str();
6094-
self.check_forbidden_name(attr, NameUsage::Store)?;
60956066
self.compile_expression(value)?;
60966067
emit!(self, Instruction::Copy { index: 1_u32 });
60976068
let idx = self.name(attr);
@@ -6919,12 +6890,6 @@ impl Compiler {
69196890
let (size, unpack) = self.gather_elements(additional_positional, &arguments.args)?;
69206891
let has_double_star = arguments.keywords.iter().any(|k| k.arg.is_none());
69216892

6922-
for keyword in &arguments.keywords {
6923-
if let Some(name) = &keyword.arg {
6924-
self.check_forbidden_name(name.as_str(), NameUsage::Store)?;
6925-
}
6926-
}
6927-
69286893
if unpack || has_double_star {
69296894
// Create a tuple with positional args:
69306895
if unpack {

crates/codegen/src/symboltable.rs

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,12 @@ impl SymbolTableBuilder {
988988
}
989989

990990
fn scan_parameter(&mut self, parameter: &Parameter) -> SymbolTableResult {
991+
self.check_name(
992+
parameter.name.as_str(),
993+
ExpressionContext::Store,
994+
parameter.name.range,
995+
)?;
996+
991997
let usage = if parameter.annotation.is_some() {
992998
SymbolUsage::AnnotationParameter
993999
} else {
@@ -1306,7 +1312,11 @@ impl SymbolTableBuilder {
13061312
// https://github.com/python/cpython/blob/main/Python/symtable.c#L1233
13071313
match &**target {
13081314
Expr::Name(ast::ExprName { id, .. }) if *simple => {
1309-
self.register_name(id.as_str(), SymbolUsage::AnnotationAssigned, *range)?;
1315+
let id_str = id.as_str();
1316+
1317+
self.check_name(id_str, ExpressionContext::Store, *range)?;
1318+
1319+
self.register_name(id_str, SymbolUsage::AnnotationAssigned, *range)?;
13101320
// PEP 649: Register annotate function in module/class scope
13111321
let current_scope = self.tables.last().map(|t| t.typ);
13121322
match current_scope {
@@ -1523,8 +1533,9 @@ impl SymbolTableBuilder {
15231533
self.scan_expression(slice, ExpressionContext::Load)?;
15241534
}
15251535
Expr::Attribute(ExprAttribute {
1526-
value, range: _, ..
1536+
value, attr, range, ..
15271537
}) => {
1538+
self.check_name(attr.as_str(), context, *range)?;
15281539
self.scan_expression(value, ExpressionContext::Load)?;
15291540
}
15301541
Expr::Dict(ExprDict {
@@ -1668,11 +1679,17 @@ impl SymbolTableBuilder {
16681679

16691680
self.scan_expressions(&arguments.args, ExpressionContext::Load)?;
16701681
for keyword in &arguments.keywords {
1682+
if let Some(arg) = &keyword.arg {
1683+
self.check_name(arg.as_str(), ExpressionContext::Store, keyword.range)?;
1684+
}
16711685
self.scan_expression(&keyword.value, ExpressionContext::Load)?;
16721686
}
16731687
}
16741688
Expr::Name(ExprName { id, range, .. }) => {
16751689
let id = id.as_str();
1690+
1691+
self.check_name(id, context, *range)?;
1692+
16761693
// Determine the contextual usage of this symbol:
16771694
match context {
16781695
ExpressionContext::Delete => {
@@ -2161,6 +2178,37 @@ impl SymbolTableBuilder {
21612178
self.register_name(ident.as_str(), role, ident.range)
21622179
}
21632180

2181+
fn check_name(
2182+
&self,
2183+
name: &str,
2184+
context: ExpressionContext,
2185+
range: TextRange,
2186+
) -> SymbolTableResult {
2187+
if name == "__debug__" {
2188+
let location = Some(
2189+
self.source_file
2190+
.to_source_code()
2191+
.source_location(range.start(), PositionEncoding::Utf8),
2192+
);
2193+
match context {
2194+
ExpressionContext::Store => {
2195+
return Err(SymbolTableError {
2196+
error: "cannot assign to __debug__".to_owned(),
2197+
location,
2198+
});
2199+
}
2200+
ExpressionContext::Delete => {
2201+
return Err(SymbolTableError {
2202+
error: "cannot delete __debug__".to_owned(),
2203+
location,
2204+
});
2205+
}
2206+
_ => {}
2207+
}
2208+
}
2209+
Ok(())
2210+
}
2211+
21642212
fn register_name(
21652213
&mut self,
21662214
name: &str,
@@ -2173,18 +2221,7 @@ impl SymbolTableBuilder {
21732221
.source_location(range.start(), PositionEncoding::Utf8);
21742222
let location = Some(location);
21752223

2176-
// Check for forbidden names like __debug__
2177-
if name == "__debug__"
2178-
&& matches!(
2179-
role,
2180-
SymbolUsage::Parameter | SymbolUsage::AnnotationParameter | SymbolUsage::Assigned
2181-
)
2182-
{
2183-
return Err(SymbolTableError {
2184-
error: "cannot assign to __debug__".to_owned(),
2185-
location,
2186-
});
2187-
}
2224+
// Note: __debug__ checks are handled by check_name function, so no check needed here.
21882225

21892226
let scope_depth = self.tables.len();
21902227
let table = self.tables.last_mut().unwrap();

extra_tests/snippets/syntax_forbidden_name.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,5 @@ def raisesSyntaxError(parse_stmt, exec_stmt=None):
2121
raisesSyntaxError("", "del __debug__")
2222
raisesSyntaxError("", "(a, __debug__, c) = (1, 2, 3)")
2323
raisesSyntaxError("", "(a, *__debug__, c) = (1, 2, 3)")
24-
25-
# TODO:
26-
# raisesSyntaxError("", "__debug__ : int")
24+
raisesSyntaxError("", "__debug__ : int")
25+
raisesSyntaxError("", "__debug__ : int = 1")

0 commit comments

Comments
 (0)