Skip to content

Commit 1e790d3

Browse files
authored
[red-knot] Port 'deferred annotations' unit tests to Markdown (#15686)
## Summary - Port "deferred annotations" unit tests to Markdown - Port `implicit_global_in_function` unit test to Markdown - Removed `resolve_method` and `local_inference` unit tests. These seem like relics from a time where type inference was in it's early stages. There is no way that these tests would fail today without lots of other things going wrong as well. part of #13696 based on #15683 ## Test Plan New MD tests for existing Rust unit tests.
1 parent 7855f03 commit 1e790d3

File tree

3 files changed

+55
-148
lines changed

3 files changed

+55
-148
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Deferred annotations
2+
3+
## Deferred annotations in stubs always resolve
4+
5+
```pyi path=mod.pyi
6+
def get_foo() -> Foo: ...
7+
class Foo: ...
8+
```
9+
10+
```py
11+
from mod import get_foo
12+
13+
reveal_type(get_foo()) # revealed: Foo
14+
```
15+
16+
## Deferred annotations in regular code fail
17+
18+
In (regular) source files, annotations are *not* deferred. This also tests that imports from
19+
`__future__` that are not `annotations` are ignored.
20+
21+
```py
22+
from __future__ import with_statement as annotations
23+
24+
# error: [unresolved-reference]
25+
def get_foo() -> Foo: ...
26+
27+
class Foo: ...
28+
29+
reveal_type(get_foo()) # revealed: Unknown
30+
```
31+
32+
## Deferred annotations in regular code with `__future__.annotations`
33+
34+
If `__future__.annotations` is imported, annotations *are* deferred.
35+
36+
```py
37+
from __future__ import annotations
38+
39+
def get_foo() -> Foo: ...
40+
41+
class Foo: ...
42+
43+
reveal_type(get_foo()) # revealed: Foo
44+
```

crates/red_knot_python_semantic/resources/mdtest/scopes/nonlocal.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,14 @@ def f():
4343
def h():
4444
reveal_type(x) # revealed: Literal[1]
4545
```
46+
47+
## Implicit global in function
48+
49+
A name reference to a never-defined symbol in a function is implicitly a global lookup.
50+
51+
```py
52+
x = 1
53+
54+
def f():
55+
reveal_type(x) # revealed: Literal[1]
56+
```

crates/red_knot_python_semantic/src/types/infer.rs

Lines changed: 0 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -6008,7 +6008,6 @@ mod tests {
60086008
use crate::semantic_index::symbol::FileScopeId;
60096009
use crate::semantic_index::{global_scope, semantic_index, symbol_table, use_def_map};
60106010
use crate::types::check_types;
6011-
use crate::{HasType, SemanticModel};
60126011
use ruff_db::files::{system_path_to_file, File};
60136012
use ruff_db::system::DbWithTestSystem;
60146013
use ruff_db::testing::assert_function_query_was_not_run;
@@ -6080,29 +6079,6 @@ mod tests {
60806079
assert_diagnostic_messages(diagnostics, expected);
60816080
}
60826081

6083-
#[test]
6084-
fn resolve_method() -> anyhow::Result<()> {
6085-
let mut db = setup_db();
6086-
6087-
db.write_dedented(
6088-
"src/mod.py",
6089-
"
6090-
class C:
6091-
def f(self): pass
6092-
",
6093-
)?;
6094-
6095-
let mod_file = system_path_to_file(&db, "src/mod.py").unwrap();
6096-
let class_ty = global_symbol(&db, mod_file, "C")
6097-
.expect_type()
6098-
.expect_class_literal();
6099-
let member_ty = class_ty.member(&db, "f").expect_type();
6100-
let func = member_ty.expect_function_literal();
6101-
6102-
assert_eq!(func.name(&db), "f");
6103-
Ok(())
6104-
}
6105-
61066082
#[test]
61076083
fn not_literal_string() -> anyhow::Result<()> {
61086084
let mut db = setup_db();
@@ -6229,130 +6205,6 @@ mod tests {
62296205
Ok(())
62306206
}
62316207

6232-
/// A name reference to a never-defined symbol in a function is implicitly a global lookup.
6233-
#[test]
6234-
fn implicit_global_in_function() -> anyhow::Result<()> {
6235-
let mut db = setup_db();
6236-
6237-
db.write_dedented(
6238-
"src/a.py",
6239-
"
6240-
x = 1
6241-
def f():
6242-
y = x
6243-
",
6244-
)?;
6245-
6246-
let file = system_path_to_file(&db, "src/a.py").expect("file to exist");
6247-
let index = semantic_index(&db, file);
6248-
let function_scope = index
6249-
.child_scopes(FileScopeId::global())
6250-
.next()
6251-
.unwrap()
6252-
.0
6253-
.to_scope_id(&db, file);
6254-
6255-
let x_ty = symbol(&db, function_scope, "x");
6256-
assert!(x_ty.is_unbound());
6257-
6258-
let y_ty = symbol(&db, function_scope, "y").expect_type();
6259-
assert_eq!(y_ty.display(&db).to_string(), "Literal[1]");
6260-
6261-
Ok(())
6262-
}
6263-
6264-
#[test]
6265-
fn local_inference() -> anyhow::Result<()> {
6266-
let mut db = setup_db();
6267-
6268-
db.write_file("/src/a.py", "x = 10")?;
6269-
let a = system_path_to_file(&db, "/src/a.py").unwrap();
6270-
6271-
let parsed = parsed_module(&db, a);
6272-
6273-
let statement = parsed.suite().first().unwrap().as_assign_stmt().unwrap();
6274-
let model = SemanticModel::new(&db, a);
6275-
6276-
let literal_ty = statement.value.inferred_type(&model);
6277-
6278-
assert_eq!(format!("{}", literal_ty.display(&db)), "Literal[10]");
6279-
6280-
Ok(())
6281-
}
6282-
6283-
#[test]
6284-
fn deferred_annotation_builtin() -> anyhow::Result<()> {
6285-
let mut db = setup_db();
6286-
db.write_file("/src/a.pyi", "class C(object): pass")?;
6287-
let file = system_path_to_file(&db, "/src/a.pyi").unwrap();
6288-
let ty = global_symbol(&db, file, "C").expect_type();
6289-
let base = ty
6290-
.expect_class_literal()
6291-
.class
6292-
.iter_mro(&db)
6293-
.nth(1)
6294-
.unwrap();
6295-
assert_eq!(base.display(&db).to_string(), "<class 'object'>");
6296-
Ok(())
6297-
}
6298-
6299-
#[test]
6300-
fn deferred_annotation_in_stubs_always_resolve() -> anyhow::Result<()> {
6301-
let mut db = setup_db();
6302-
6303-
// Stub files should always resolve deferred annotations
6304-
db.write_dedented(
6305-
"/src/stub.pyi",
6306-
"
6307-
def get_foo() -> Foo: ...
6308-
class Foo: ...
6309-
foo = get_foo()
6310-
",
6311-
)?;
6312-
assert_public_type(&db, "/src/stub.pyi", "foo", "Foo");
6313-
6314-
Ok(())
6315-
}
6316-
6317-
#[test]
6318-
fn deferred_annotations_regular_source_fails() -> anyhow::Result<()> {
6319-
let mut db = setup_db();
6320-
6321-
// In (regular) source files, annotations are *not* deferred
6322-
// Also tests imports from `__future__` that are not annotations
6323-
db.write_dedented(
6324-
"/src/source.py",
6325-
"
6326-
from __future__ import with_statement as annotations
6327-
def get_foo() -> Foo: ...
6328-
class Foo: ...
6329-
foo = get_foo()
6330-
",
6331-
)?;
6332-
assert_public_type(&db, "/src/source.py", "foo", "Unknown");
6333-
6334-
Ok(())
6335-
}
6336-
6337-
#[test]
6338-
fn deferred_annotation_in_sources_with_future_resolves() -> anyhow::Result<()> {
6339-
let mut db = setup_db();
6340-
6341-
// In source files with `__future__.annotations`, deferred annotations are resolved
6342-
db.write_dedented(
6343-
"/src/source_with_future.py",
6344-
"
6345-
from __future__ import annotations
6346-
def get_foo() -> Foo: ...
6347-
class Foo: ...
6348-
foo = get_foo()
6349-
",
6350-
)?;
6351-
assert_public_type(&db, "/src/source_with_future.py", "foo", "Foo");
6352-
6353-
Ok(())
6354-
}
6355-
63566208
#[test]
63576209
fn basic_comprehension() -> anyhow::Result<()> {
63586210
let mut db = setup_db();

0 commit comments

Comments
 (0)