Skip to content

Commit 863a04a

Browse files
committed
[red-knot] Trust module-level undeclared symbols in stubs
1 parent 99fa850 commit 863a04a

File tree

6 files changed

+24
-12
lines changed

6 files changed

+24
-12
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ x = int
404404
class C:
405405
var: ClassVar[x]
406406

407-
reveal_type(C.var) # revealed: Unknown | str
407+
reveal_type(C.var) # revealed: str
408408

409409
x = str
410410
```

crates/red_knot_python_semantic/resources/mdtest/subscript/lists.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ x = [1, 2, 3]
1212
reveal_type(x) # revealed: list
1313

1414
# TODO reveal int
15-
reveal_type(x[0]) # revealed: Unknown
15+
reveal_type(x[0]) # revealed: @Todo(Support for `typing.TypeVar` instances in type expressions)
1616

1717
# TODO reveal list
1818
reveal_type(x[0:1]) # revealed: @Todo(specialized non-generic class)

crates/red_knot_python_semantic/resources/mdtest/type_properties/is_singleton.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,7 @@ python-version = "3.10"
128128
import types
129129
from knot_extensions import static_assert, is_singleton
130130

131-
# TODO: types.NotImplementedType is a TypeAlias of builtins._NotImplementedType
132-
# Once TypeAlias support is added, it should satisfy `is_singleton`
133-
reveal_type(types.NotImplementedType) # revealed: Unknown | Literal[_NotImplementedType]
134-
static_assert(not is_singleton(types.NotImplementedType))
131+
static_assert(is_singleton(types.NotImplementedType))
135132
```
136133

137134
### Callables

crates/red_knot_python_semantic/src/semantic_index/symbol.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ impl<'db> ScopeId<'db> {
115115
self.node(db).scope_kind().is_function_like()
116116
}
117117

118+
pub(crate) fn is_module_scope(self, db: &'db dyn Db) -> bool {
119+
self.node(db).scope_kind().is_module()
120+
}
121+
118122
pub(crate) fn is_type_parameter(self, db: &'db dyn Db) -> bool {
119123
self.node(db).scope_kind().is_type_parameter()
120124
}
@@ -263,6 +267,10 @@ impl ScopeKind {
263267
matches!(self, ScopeKind::Class)
264268
}
265269

270+
pub(crate) fn is_module(self) -> bool {
271+
matches!(self, ScopeKind::Module)
272+
}
273+
266274
pub(crate) fn is_type_parameter(self) -> bool {
267275
matches!(self, ScopeKind::Annotation | ScopeKind::TypeAlias)
268276
}

crates/red_knot_python_semantic/src/symbol.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,18 @@ fn symbol_by_id<'db>(
593593
"__slots__" | "TYPE_CHECKING"
594594
);
595595

596-
widen_type_for_undeclared_public_symbol(db, inferred, is_considered_non_modifiable)
597-
.into()
596+
if scope.is_module_scope(db) && scope.file(db).is_stub(db.upcast()) {
597+
// We generally trust module-level undeclared symbols in stubs and do not union
598+
// with `Unknown`. If we don't do this, simple aliases like `IOError = OSError` in
599+
// stubs would result in `IOError` being a union of `OSError` and `Unknown`, which
600+
// leads to all sorts of downstream problems. Similarly, type variables are often
601+
// defined as `_T = TypeVar("_T")`, without being declared.
602+
603+
inferred.into()
604+
} else {
605+
widen_type_for_undeclared_public_symbol(db, inferred, is_considered_non_modifiable)
606+
.into()
607+
}
598608
}
599609
// Symbol has conflicting declared types
600610
Err((declared, _)) => {

crates/red_knot_python_semantic/src/types/signatures.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,10 +1631,7 @@ mod tests {
16311631
assert_eq!(a_name, "a");
16321632
assert_eq!(b_name, "b");
16331633
// Parameter resolution deferred; we should see B
1634-
assert_eq!(
1635-
a_annotated_ty.unwrap().display(&db).to_string(),
1636-
"Unknown | B"
1637-
);
1634+
assert_eq!(a_annotated_ty.unwrap().display(&db).to_string(), "B");
16381635
assert_eq!(b_annotated_ty.unwrap().display(&db).to_string(), "T");
16391636
}
16401637

0 commit comments

Comments
 (0)