Skip to content

Commit 212c0d0

Browse files
authored
Fix future annotation block alignment (#8506)
1 parent 6701520 commit 212c0d0

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

crates/codegen/src/compile.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5083,6 +5083,14 @@ impl<'warnings> Compiler<'warnings> {
50835083
func_range: TextRange,
50845084
) -> CompileResult<bool> {
50855085
if !self.next_function_annotation_symbol_table_uses_annotations() {
5086+
// CPython creates a hidden AnnotationBlock for every function
5087+
// signature under `from __future__ import annotations`, including
5088+
// an unannotated one. It still belongs to this function: consume
5089+
// it so the next function sees its own block rather than remaining
5090+
// pinned to this unused entry.
5091+
if self.push_annotation_symbol_table() {
5092+
self.pop_annotation_symbol_table();
5093+
}
50865094
return Ok(false);
50875095
}
50885096

@@ -31247,6 +31255,25 @@ def f(x: T): pass
3124731255
);
3124831256
}
3124931257

31258+
#[test]
31259+
fn future_unannotated_function_does_not_hide_next_annotation_block() {
31260+
let code = compile_exec(
31261+
"\
31262+
from __future__ import annotations
31263+
def plain(x): pass
31264+
def annotated(x: int): pass
31265+
",
31266+
);
31267+
let annotate = find_direct_child_code(&code, "__annotate__")
31268+
.expect("second function must retain its annotation closure");
31269+
assert!(
31270+
annotate.constants.iter().any(
31271+
|constant| matches!(constant, ConstantData::Str { value } if value.as_str() == Ok("int"))
31272+
),
31273+
"annotation closure must belong to the annotated function"
31274+
);
31275+
}
31276+
3125031277
#[test]
3125131278
fn deferred_annotation_format_name_does_not_capture_helper_parameter() {
3125231279
let code = compile_exec(

0 commit comments

Comments
 (0)