Skip to content

Commit 7c58f4a

Browse files
committed
Fast locals part 3
1 parent 92b8e59 commit 7c58f4a

File tree

18 files changed

+244
-151
lines changed

18 files changed

+244
-151
lines changed

Lib/test/test_builtin.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,6 @@ def keys(self):
562562
return 1 # used to be 'a' but that's no longer an error
563563
self.assertRaises(TypeError, eval, 'dir()', globals(), C())
564564

565-
# TODO: RUSTPYTHON
566-
@unittest.expectedFailure
567565
def test_exec(self):
568566
g = {}
569567
exec('z = 1', g)

Lib/test/test_grammar.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,8 +1067,6 @@ def g2(x):
10671067
self.assertEqual(g2(False), 0)
10681068
self.assertEqual(g2(True), ('end', 1))
10691069

1070-
# TODO: RUSTPYTHON
1071-
@unittest.expectedFailure
10721070
def test_yield(self):
10731071
# Allowed as standalone statement
10741072
def g(): yield 1

Lib/test/test_importlib/test_api.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,6 @@ def test_reload_loader_replaced(self):
242242
self.assertIs(reloaded, types)
243243
self.assertIs(sys.modules['types'], types)
244244

245-
# TODO: RUSTPYTHON
246-
@unittest.expectedFailure
247245
def test_reload_location_changed(self):
248246
name = 'spam'
249247
with support.temp_cwd(None) as cwd:
@@ -295,8 +293,6 @@ def test_reload_location_changed(self):
295293
self.maxDiff = None
296294
self.assertEqual(ns, expected)
297295

298-
# TODO: RUSTPYTHON
299-
@unittest.expectedFailure
300296
def test_reload_namespace_changed(self):
301297
name = 'spam'
302298
with support.temp_cwd(None) as cwd:

Lib/test/test_named_expression.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,6 @@ def spam(a):
336336
self.assertEqual(res, [(1, 1, 1.0), (2, 2, 1.0), (3, 3, 1.0)])
337337
self.assertEqual(y, 3)
338338

339-
# TODO RustPython, added test_named_expression_scope_06_rp_modified as
340-
# minimaly modified variant of this test.
341-
@unittest.expectedFailure
342339
def test_named_expression_scope_06(self):
343340
res = [[spam := i for i in range(3)] for j in range(2)]
344341

@@ -385,8 +382,6 @@ def eggs(b):
385382
self.assertEqual(res, [0, 2])
386383
self.assertEqual(a, 2)
387384

388-
# TODO RustPython, added test_named_expression_scope_10_rp_modified
389-
@unittest.expectedFailure
390385
def test_named_expression_scope_10(self):
391386
res = [b := [a := 1 for i in range(2)] for j in range(2)]
392387

@@ -522,7 +517,6 @@ def test_named_expression_variable_reuse_in_comprehensions(self):
522517
self.assertEqual(ns["x"], 2)
523518
self.assertEqual(ns["result"], [0, 1, 2])
524519

525-
@unittest.expectedFailure # TODO: RUSTPYTHON
526520
def test_named_expression_global_scope(self):
527521
sentinel = object()
528522
global GLOBAL_VAR

Lib/test/test_opcodes.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ class C: pass
3838
with self.assertRaises(AttributeError):
3939
C.__annotations__
4040

41-
# TODO: RUSTPYTHON
42-
@unittest.expectedFailure
4341
def test_use_existing_annotations(self):
4442
ns = {'__annotations__': {1: 2}}
4543
exec('x: int', ns)

Lib/test/test_os.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,12 @@ def get_single(f):
18881888
def helper(self):
18891889
if hasattr(os, f):
18901890
self.check(getattr(os, f))
1891+
1892+
# TODO: RUSTPYTHON; io.FileIO(fd) should check if the fd passed is valid
1893+
if f == "fdopen":
1894+
# this is test_fdopen
1895+
helper = unittest.expectedFailure(helper)
1896+
18911897
return helper
18921898
for f in singles:
18931899
locals()["test_"+f] = get_single(f)

Lib/test/test_scope.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ def h():
136136
h = g(2, 4, 6)
137137
self.assertEqual(h(), 39)
138138

139-
@unittest.expectedFailure # TODO: RUSTPYTHON
140139
def testFreeVarInMethod(self):
141140

142141
def test():
@@ -202,7 +201,6 @@ def fact(n):
202201

203202
self.assertEqual(f(6), 720)
204203

205-
@unittest.expectedFailure # TODO: RUSTPYTHON
206204
def testUnoptimizedNamespaces(self):
207205

208206
check_syntax_error(self, """if 1:
@@ -262,7 +260,6 @@ def testLambdas(self):
262260
h = g(2, 4, 6)
263261
self.assertEqual(h(), 18)
264262

265-
@unittest.expectedFailure # TODO: RUSTPYTHON
266263
def testUnboundLocal(self):
267264

268265
def errorInOuter():
@@ -280,7 +277,6 @@ def inner():
280277
self.assertRaises(UnboundLocalError, errorInOuter)
281278
self.assertRaises(NameError, errorInInner)
282279

283-
@unittest.expectedFailure # TODO: RUSTPYTHON
284280
def testUnboundLocal_AfterDel(self):
285281
# #4617: It is now legal to delete a cell variable.
286282
# The following functions must obviously compile,
@@ -302,7 +298,6 @@ def inner():
302298
self.assertRaises(UnboundLocalError, errorInOuter)
303299
self.assertRaises(NameError, errorInInner)
304300

305-
@unittest.expectedFailure # TODO: RUSTPYTHON
306301
def testUnboundLocal_AugAssign(self):
307302
# test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation
308303
exec("""if 1:
@@ -335,7 +330,6 @@ def returner():
335330

336331
self.assertEqual(makeReturner2(a=11)()['a'], 11)
337332

338-
@unittest.expectedFailure # TODO: RUSTPYTHON
339333
def testScopeOfGlobalStmt(self):
340334
# Examples posted by Samuele Pedroni to python-dev on 3/1/2001
341335

@@ -414,7 +408,6 @@ def get(self):
414408
self.assertEqual(g.get(), 13)
415409
""")
416410

417-
@unittest.expectedFailure # TODO: RUSTPYTHON
418411
def testLeaks(self):
419412

420413
class Foo:
@@ -437,7 +430,6 @@ def f2():
437430

438431
self.assertEqual(Foo.count, 0)
439432

440-
@unittest.expectedFailure # TODO: RUSTPYTHON
441433
def testClassAndGlobal(self):
442434

443435
exec("""if 1:
@@ -460,7 +452,6 @@ class X:
460452
self.assertTrue(X.passed)
461453
""")
462454

463-
@unittest.expectedFailure # TODO: RUSTPYTHON
464455
def testLocalsFunction(self):
465456

466457
def f(x):
@@ -568,7 +559,6 @@ class TestClass:
568559

569560
self.assertRaises(TypeError, sys.settrace)
570561

571-
@unittest.expectedFailure # TODO: RUSTPYTHON
572562
def testEvalExecFreeVars(self):
573563

574564
def f(x):
@@ -603,7 +593,6 @@ def x():
603593
except NameError:
604594
pass
605595

606-
@unittest.expectedFailure # TODO: RUSTPYTHON
607596
def testEvalFreeVars(self):
608597

609598
def f(x):
@@ -661,7 +650,10 @@ def dec(self):
661650
self.assertEqual(c.dec(), 1)
662651
self.assertEqual(c.dec(), 0)
663652

664-
@unittest.expectedFailure # TODO: RUSTPYTHON
653+
# TODO: RUSTPYTHON, figure out how to communicate that `y = 9` should be
654+
# stored as a global rather than a STORE_NAME, even when
655+
# the `global y` is in a nested subscope
656+
@unittest.expectedFailure
665657
def testGlobalInParallelNestedFunctions(self):
666658
# A symbol table bug leaked the global statement from one
667659
# function to other nested functions in the same block.
@@ -741,7 +733,6 @@ def top(a):
741733
def b():
742734
global a
743735

744-
@unittest.expectedFailure # TODO: RUSTPYTHON
745736
def testClassNamespaceOverridesClosure(self):
746737
# See #17853.
747738
x = 42

Lib/test/test_symtable.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ def test_nonlocal(self):
121121
expected = ("some_var",)
122122
self.assertEqual(self.other_internal.get_nonlocals(), expected)
123123

124+
# TODO: RUSTPYTHON
125+
@unittest.expectedFailure
124126
def test_local(self):
125127
self.assertTrue(self.spam.lookup("x").is_local())
126128
self.assertFalse(self.spam.lookup("bar").is_local())

Lib/unittest/test/test_runner.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,6 @@ def MockResultClass(*args):
277277
self.assertEqual(runner._makeResult(), expectedresult)
278278

279279

280-
# TODO: RUSTPYTHON; -W arg for warning control
281-
@unittest.expectedFailure
282280
def test_warnings(self):
283281
"""
284282
Check that warnings argument of TextTestRunner correctly affects the

compiler/src/compile.rs

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -273,14 +273,13 @@ impl Compiler {
273273
let cellvar_cache = table
274274
.symbols
275275
.iter()
276-
.filter(|(_, s)| matches!(s.scope, SymbolScope::Cell))
276+
.filter(|(_, s)| s.scope == SymbolScope::Cell)
277277
.map(|(var, _)| var.clone())
278278
.collect();
279279
let freevar_cache = table
280280
.symbols
281281
.iter()
282-
// TODO: check if Free or FREE_CLASS symbol
283-
.filter(|(_, s)| matches!(s.scope, SymbolScope::Free))
282+
.filter(|(_, s)| s.scope == SymbolScope::Free || s.is_free_class)
284283
.map(|(var, _)| var.clone())
285284
.collect();
286285

@@ -336,6 +335,11 @@ impl Compiler {
336335
let doc = self.name("__doc__");
337336
self.emit(Instruction::StoreGlobal(doc))
338337
}
338+
339+
if self.find_ann(statements) {
340+
self.emit(Instruction::SetupAnnotation);
341+
}
342+
339343
self.compile_statements(statements)?;
340344

341345
assert_eq!(self.code_stack.len(), size_before);
@@ -433,9 +437,12 @@ impl Compiler {
433437
cache = &mut info.varname_cache;
434438
NameOpType::Fast
435439
}
436-
SymbolScope::GlobalImplicit if self.ctx.in_func() => NameOpType::Global,
437-
SymbolScope::Local | SymbolScope::GlobalImplicit => NameOpType::Local,
438440
SymbolScope::GlobalExplicit => NameOpType::Global,
441+
SymbolScope::GlobalImplicit | SymbolScope::Unknown if self.ctx.in_func() => {
442+
NameOpType::Global
443+
}
444+
SymbolScope::GlobalImplicit | SymbolScope::Unknown => NameOpType::Local,
445+
SymbolScope::Local => NameOpType::Local,
439446
SymbolScope::Free => {
440447
cache = &mut info.freevar_cache;
441448
NameOpType::Deref
@@ -444,8 +451,8 @@ impl Compiler {
444451
cache = &mut info.cellvar_cache;
445452
NameOpType::Deref
446453
}
447-
// TODO: is this right?
448-
SymbolScope::Unknown => NameOpType::Global,
454+
// // TODO: is this right?
455+
// SymbolScope::Unknown => NameOpType::Global,
449456
};
450457
let mut idx = cache
451458
.get_index_of(name)
@@ -527,6 +534,10 @@ impl Compiler {
527534
let module_idx = module.as_ref().map(|s| self.name(s));
528535

529536
if import_star {
537+
if self.ctx.in_func() {
538+
return Err(self
539+
.error_loc(CompileErrorType::FunctionImportStar, statement.location));
540+
}
530541
let star = self.name("*");
531542
// from .... import *
532543
self.emit(Instruction::Import {
@@ -1069,6 +1080,8 @@ impl Compiler {
10691080
}
10701081

10711082
let mut code = self.pop_code_object();
1083+
self.current_qualified_path = old_qualified_path;
1084+
self.ctx = prev_ctx;
10721085

10731086
// Prepare type annotations:
10741087
let mut num_annotations = 0;
@@ -1138,9 +1151,6 @@ impl Compiler {
11381151
let doc = self.name("__doc__");
11391152
self.emit(Instruction::StoreAttr { idx: doc });
11401153

1141-
self.current_qualified_path = old_qualified_path;
1142-
self.ctx = prev_ctx;
1143-
11441154
self.apply_decorators(decorator_list);
11451155

11461156
self.store_name(name);
@@ -1151,12 +1161,17 @@ impl Compiler {
11511161
fn build_closure(&mut self, code: &CodeObject) {
11521162
if !code.freevars.is_empty() {
11531163
for var in &code.freevars {
1154-
let symbol = self.symbol_table_stack.last().unwrap().lookup(var).unwrap();
1164+
let table = self.symbol_table_stack.last().unwrap();
1165+
let symbol = table.lookup(var).unwrap();
11551166
let parent_code = self.code_stack.last().unwrap();
11561167
let vars = match symbol.scope {
11571168
SymbolScope::Free => &parent_code.freevar_cache,
11581169
SymbolScope::Cell => &parent_code.cellvar_cache,
1159-
_ => unreachable!(),
1170+
_ if symbol.is_free_class => &parent_code.freevar_cache,
1171+
x => unreachable!(
1172+
"var {} in a {:?} should be free or cell but it's {:?}",
1173+
var, table.typ, x
1174+
),
11601175
};
11611176
let mut idx = vars.get_index_of(var).unwrap();
11621177
if let SymbolScope::Free = symbol.scope {
@@ -1236,6 +1251,8 @@ impl Compiler {
12361251
keywords: &[ast::Keyword],
12371252
decorator_list: &[ast::Expression],
12381253
) -> CompileResult<()> {
1254+
self.prepare_decorators(decorator_list)?;
1255+
12391256
let prev_ctx = self.ctx;
12401257
self.ctx = CompileContext {
12411258
func: FunctionContext::NoFunction,
@@ -1247,7 +1264,6 @@ impl Compiler {
12471264
let old_qualified_path = self.current_qualified_path.take();
12481265
self.current_qualified_path = Some(qualified_name.clone());
12491266

1250-
self.prepare_decorators(decorator_list)?;
12511267
self.emit(Instruction::LoadBuildClass);
12521268
let line_number = self.get_source_line_number();
12531269
self.push_output(CodeObject::new(
@@ -1301,6 +1317,9 @@ impl Compiler {
13011317

13021318
let code = self.pop_code_object();
13031319

1320+
self.current_qualified_path = old_qualified_path;
1321+
self.ctx = prev_ctx;
1322+
13041323
self.build_closure(&code);
13051324

13061325
self.emit_constant(bytecode::ConstantData::Code {
@@ -1350,8 +1369,6 @@ impl Compiler {
13501369
self.apply_decorators(decorator_list);
13511370

13521371
self.store_name(name);
1353-
self.current_qualified_path = old_qualified_path;
1354-
self.ctx = prev_ctx;
13551372
Ok(())
13561373
}
13571374

@@ -1579,18 +1596,17 @@ impl Compiler {
15791596

15801597
if let ast::ExpressionType::Identifier { name } = &target.node {
15811598
// Store as dict entry in __annotations__ dict:
1582-
if !self.ctx.in_func() {
1583-
let annotations = self.name("__annotations__");
1584-
self.emit(Instruction::LoadNameAny(annotations));
1585-
self.emit_constant(bytecode::ConstantData::Str {
1586-
value: name.to_owned(),
1587-
});
1588-
self.emit(Instruction::StoreSubscript);
1589-
}
1599+
let annotations = self.name("__annotations__");
1600+
self.emit(Instruction::LoadNameAny(annotations));
1601+
self.emit_constant(bytecode::ConstantData::Str {
1602+
value: name.to_owned(),
1603+
});
1604+
self.emit(Instruction::StoreSubscript);
15901605
} else {
15911606
// Drop annotation if not assigned to simple identifier.
15921607
self.emit(Instruction::Pop);
15931608
}
1609+
15941610
Ok(())
15951611
}
15961612

@@ -2187,7 +2203,7 @@ impl Compiler {
21872203
let line_number = self.get_source_line_number();
21882204
// Create magnificent function <listcomp>:
21892205
self.push_output(CodeObject::new(
2190-
Default::default(),
2206+
bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED,
21912207
1,
21922208
1,
21932209
0,

0 commit comments

Comments
 (0)