mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +00:00
[ty] Remove use of ClassBase::try_from_type
from super()
machinery (#19902)
This commit is contained in:
parent
ce938fe205
commit
82350a398e
2 changed files with 41 additions and 16 deletions
|
@ -331,6 +331,9 @@ instance or a subclass of the first. If either condition is violated, a `TypeErr
|
|||
runtime.
|
||||
|
||||
```py
|
||||
import typing
|
||||
import collections
|
||||
|
||||
def f(x: int):
|
||||
# error: [invalid-super-argument] "`int` is not a valid class"
|
||||
super(x, x)
|
||||
|
@ -367,6 +370,19 @@ reveal_type(super(B, A))
|
|||
reveal_type(super(B, object))
|
||||
|
||||
super(object, object()).__class__
|
||||
|
||||
# Not all objects valid in a class's bases list are valid as the first argument to `super()`.
|
||||
# For example, it's valid to inherit from `typing.ChainMap`, but it's not valid as the first argument to `super()`.
|
||||
#
|
||||
# error: [invalid-super-argument] "`typing.ChainMap` is not a valid class"
|
||||
reveal_type(super(typing.ChainMap, collections.ChainMap())) # revealed: Unknown
|
||||
|
||||
# Meanwhile, it's not valid to inherit from unsubscripted `typing.Generic`,
|
||||
# but it *is* valid as the first argument to `super()`.
|
||||
reveal_type(super(typing.Generic, typing.SupportsInt)) # revealed: <super: typing.Generic, <class 'SupportsInt'>>
|
||||
|
||||
def _(x: type[typing.Any], y: typing.Any):
|
||||
reveal_type(super(x, y)) # revealed: <super: Any, Any>
|
||||
```
|
||||
|
||||
### Instance Member Access via `super`
|
||||
|
|
|
@ -9526,23 +9526,32 @@ impl<'db> BoundSuperType<'db> {
|
|||
));
|
||||
}
|
||||
|
||||
// TODO: having to get a class-literal just to pass it in here is silly.
|
||||
// `BoundSuperType` should probably not be using `ClassBase::try_from_type` here;
|
||||
// this also leads to false negatives in some cases. See discussion in
|
||||
// <https://github.com/astral-sh/ruff/pull/19560#discussion_r2271570071>.
|
||||
let pivot_class = ClassBase::try_from_type(
|
||||
db,
|
||||
pivot_class_type,
|
||||
KnownClass::Object
|
||||
.to_class_literal(db)
|
||||
.into_class_literal()
|
||||
.expect("`object` should always exist in typeshed"),
|
||||
// We don't use `Classbase::try_from_type` here because:
|
||||
// - There are objects that may validly be present in a class's bases list
|
||||
// but are not valid as pivot classes, e.g. `typing.ChainMap`
|
||||
// - There are objects that are not valid in a class's bases list
|
||||
// but are valid as pivot classes, e.g. unsubscripted `typing.Generic`
|
||||
let pivot_class = match pivot_class_type {
|
||||
Type::ClassLiteral(class) => ClassBase::Class(ClassType::NonGeneric(class)),
|
||||
Type::GenericAlias(class) => ClassBase::Class(ClassType::Generic(class)),
|
||||
Type::SubclassOf(subclass_of) if subclass_of.subclass_of().is_dynamic() => {
|
||||
ClassBase::Dynamic(
|
||||
subclass_of
|
||||
.subclass_of()
|
||||
.into_dynamic()
|
||||
.expect("Checked in branch arm"),
|
||||
)
|
||||
.ok_or({
|
||||
BoundSuperError::InvalidPivotClassType {
|
||||
pivot_class: pivot_class_type,
|
||||
}
|
||||
})?;
|
||||
Type::SpecialForm(SpecialFormType::Protocol) => ClassBase::Protocol,
|
||||
Type::SpecialForm(SpecialFormType::Generic) => ClassBase::Generic,
|
||||
Type::SpecialForm(SpecialFormType::TypedDict) => ClassBase::TypedDict,
|
||||
Type::Dynamic(dynamic) => ClassBase::Dynamic(dynamic),
|
||||
_ => {
|
||||
return Err(BoundSuperError::InvalidPivotClassType {
|
||||
pivot_class: pivot_class_type,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let owner = SuperOwnerKind::try_from_type(db, owner_type)
|
||||
.and_then(|owner| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue