Skip to content

Commit 76aa5c3

Browse files
committed
Skip lookup on protocols
1 parent 4d5accf commit 76aa5c3

File tree

10 files changed

+41
-12
lines changed

10 files changed

+41
-12
lines changed

crates/red_knot_python_semantic/resources/mdtest/annotations/stdlib_typing_aliases.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ import typing
7171
class ListSubclass(typing.List): ...
7272

7373
# TODO: should have `Generic`, should not have `Unknown`
74-
# revealed: tuple[Literal[ListSubclass], Literal[list], Literal[object]]
74+
# revealed: tuple[Literal[ListSubclass], Literal[list], Literal[MutableSequence], Literal[Sequence], Literal[Reversible], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(protocol), Literal[object]]
7575
reveal_type(ListSubclass.__mro__)
7676

7777
class DictSubclass(typing.Dict): ...

crates/red_knot_python_semantic/resources/mdtest/generics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class MySecureBox[T](MyBox[T]): ...
3939
secure_box: MySecureBox[int] = MySecureBox(5)
4040
reveal_type(secure_box) # revealed: MySecureBox
4141
# TODO reveal int
42-
reveal_type(secure_box.data) # revealed: Unknown
42+
reveal_type(secure_box.data) # revealed: T
4343
```
4444

4545
## Cyclical class definition

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ is unbound.
99
```py
1010
reveal_type(__name__) # revealed: str
1111
reveal_type(__file__) # revealed: str | None
12-
reveal_type(__loader__) # revealed: @Todo(Support for protocols) | None
12+
reveal_type(__loader__) # revealed: LoaderProtocol | None
1313
reveal_type(__package__) # revealed: str | None
1414
reveal_type(__doc__) # revealed: str | None
1515

crates/red_knot_python_semantic/resources/mdtest/stubs/class.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ class Foo[T]: ...
1313
class Bar(Foo[Bar]): ...
1414

1515
reveal_type(Bar) # revealed: Literal[Bar]
16-
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Unknown, Literal[object]]
16+
17+
# TODO: Support for generic `Foo`
18+
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Literal[Foo], Literal[object]]
1719
```
1820

1921
## Access to attributes declarated in stubs

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,7 @@ class C(Tuple): ...
119119

120120
# Runtime value: `(C, tuple, typing.Generic, object)`
121121
# TODO: Add `Generic` to the MRO
122-
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[tuple], Literal[object]]
122+
reveal_type(
123+
C.__mro__
124+
) # revealed: tuple[Literal[C], Literal[tuple], Literal[Sequence], Literal[Reversible], Literal[Collection], Literal[Iterable], Literal[Container], @Todo(protocol), Literal[object]]
123125
```

crates/red_knot_python_semantic/src/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3181,6 +3181,8 @@ pub enum DynamicType {
31813181
///
31823182
/// This variant should be created with the `todo_type!` macro.
31833183
Todo(TodoType),
3184+
/// Temporary type until we support protocols.
3185+
TodoProtocol,
31843186
}
31853187

31863188
impl std::fmt::Display for DynamicType {
@@ -3191,6 +3193,7 @@ impl std::fmt::Display for DynamicType {
31913193
// `DynamicType::Todo`'s display should be explicit that is not a valid display of
31923194
// any other type
31933195
DynamicType::Todo(todo) => write!(f, "@Todo{todo}"),
3196+
DynamicType::TodoProtocol => f.write_str("@Todo(protocol)"),
31943197
}
31953198
}
31963199
}

crates/red_knot_python_semantic/src/types/class.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use crate::{
99
Boundness, LookupError, LookupResult, Symbol, SymbolAndQualifiers,
1010
},
1111
types::{
12-
definition_expression_type, CallArguments, CallError, MetaclassCandidate, TupleType,
13-
UnionBuilder, UnionCallError,
12+
definition_expression_type, CallArguments, CallError, DynamicType, MetaclassCandidate,
13+
TupleType, UnionBuilder, UnionCallError,
1414
},
1515
Db, KnownModule, Program,
1616
};
@@ -339,6 +339,11 @@ impl<'db> Class<'db> {
339339

340340
for superclass in self.iter_mro(db) {
341341
match superclass {
342+
ClassBase::Dynamic(DynamicType::TodoProtocol) => {
343+
// TODO: We currently skip protocols when looking up class members, in order to
344+
// avoid creating many dynamic types in our test suite that would otherwise
345+
// result from looking up attributes on builtin types like `str`, `list`, `tuple`
346+
}
342347
ClassBase::Dynamic(_) => {
343348
// Note: calling `Type::from(superclass).member()` would be incorrect here.
344349
// What we'd really want is a `Type::Any.own_class_member()` method,
@@ -407,6 +412,11 @@ impl<'db> Class<'db> {
407412

408413
for superclass in self.iter_mro(db) {
409414
match superclass {
415+
ClassBase::Dynamic(DynamicType::TodoProtocol) => {
416+
// TODO: We currently skip protocols when looking up instance members, in order to
417+
// avoid creating many dynamic types in our test suite that would otherwise
418+
// result from looking up attributes on builtin types like `str`, `list`, `tuple`
419+
}
410420
ClassBase::Dynamic(_) => {
411421
return SymbolAndQualifiers::todo(
412422
"instance attribute on class with dynamic base",

crates/red_knot_python_semantic/src/types/class_base.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,7 @@ impl<'db> ClassBase<'db> {
144144
KnownInstanceType::Callable => {
145145
Self::try_from_type(db, todo_type!("Support for Callable as a base class"))
146146
}
147-
KnownInstanceType::Protocol => {
148-
Self::try_from_type(db, todo_type!("Support for protocols"))
149-
}
147+
KnownInstanceType::Protocol => Some(ClassBase::Dynamic(DynamicType::TodoProtocol)),
150148
},
151149
}
152150
}

crates/red_knot_python_semantic/src/types/infer.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4005,6 +4005,8 @@ impl<'db> TypeInferenceBuilder<'db> {
40054005
| (_, unknown @ Type::Dynamic(DynamicType::Unknown), _) => Some(unknown),
40064006
(todo @ Type::Dynamic(DynamicType::Todo(_)), _, _)
40074007
| (_, todo @ Type::Dynamic(DynamicType::Todo(_)), _) => Some(todo),
4008+
(todo @ Type::Dynamic(DynamicType::TodoProtocol), _, _)
4009+
| (_, todo @ Type::Dynamic(DynamicType::TodoProtocol), _) => Some(todo),
40084010
(Type::Never, _, _) | (_, Type::Never, _) => Some(Type::Never),
40094011

40104012
(Type::IntLiteral(n), Type::IntLiteral(m), ast::Operator::Add) => Some(
@@ -5178,6 +5180,9 @@ impl<'db> TypeInferenceBuilder<'db> {
51785180
value_ty,
51795181
Type::IntLiteral(i64::from(bool)),
51805182
),
5183+
(Type::KnownInstance(KnownInstanceType::Protocol), _) => {
5184+
Type::Dynamic(DynamicType::TodoProtocol)
5185+
}
51815186
(value_ty, slice_ty) => {
51825187
// If the class defines `__getitem__`, return its return type.
51835188
//
@@ -5283,7 +5288,13 @@ impl<'db> TypeInferenceBuilder<'db> {
52835288
);
52845289
}
52855290

5286-
Type::unknown()
5291+
match value_ty {
5292+
Type::ClassLiteral(_) => {
5293+
// TODO: proper support for generic classes
5294+
value_ty
5295+
}
5296+
_ => Type::unknown(),
5297+
}
52875298
}
52885299
}
52895300
}
@@ -6146,7 +6157,7 @@ impl<'db> TypeInferenceBuilder<'db> {
61466157
}
61476158
KnownInstanceType::Protocol => {
61486159
self.infer_type_expression(arguments_slice);
6149-
todo_type!("Generic protocol")
6160+
Type::Dynamic(DynamicType::TodoProtocol)
61506161
}
61516162
KnownInstanceType::NoReturn
61526163
| KnownInstanceType::Never

crates/red_knot_python_semantic/src/types/type_ordering.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,5 +288,8 @@ fn dynamic_elements_ordering(left: DynamicType, right: DynamicType) -> Ordering
288288

289289
#[cfg(not(debug_assertions))]
290290
(DynamicType::Todo(TodoType), DynamicType::Todo(TodoType)) => Ordering::Equal,
291+
292+
(DynamicType::TodoProtocol, _) => Ordering::Less,
293+
(_, DynamicType::TodoProtocol) => Ordering::Greater,
291294
}
292295
}

0 commit comments

Comments
 (0)