mirror of https://github.com/astral-sh/ruff
even more hack
This commit is contained in:
parent
beb2956a14
commit
a0f64bd0ae
|
|
@ -15,9 +15,9 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/deprecated.md
|
||||||
1 | from typing_extensions import deprecated
|
1 | from typing_extensions import deprecated
|
||||||
2 |
|
2 |
|
||||||
3 | @deprecated("use OtherClass")
|
3 | @deprecated("use OtherClass")
|
||||||
4 | def myfunc(): ...
|
4 | def myfunc(x: int): ...
|
||||||
5 |
|
5 |
|
||||||
6 | myfunc() # error: [deprecated] "use OtherClass"
|
6 | myfunc(1) # error: [deprecated] "use OtherClass"
|
||||||
7 | from typing_extensions import deprecated
|
7 | from typing_extensions import deprecated
|
||||||
8 |
|
8 |
|
||||||
9 | @deprecated("use BetterClass")
|
9 | @deprecated("use BetterClass")
|
||||||
|
|
@ -42,9 +42,9 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/deprecated.md
|
||||||
warning[deprecated]: The function `myfunc` is deprecated
|
warning[deprecated]: The function `myfunc` is deprecated
|
||||||
--> src/mdtest_snippet.py:6:1
|
--> src/mdtest_snippet.py:6:1
|
||||||
|
|
|
|
||||||
4 | def myfunc(): ...
|
4 | def myfunc(x: int): ...
|
||||||
5 |
|
5 |
|
||||||
6 | myfunc() # error: [deprecated] "use OtherClass"
|
6 | myfunc(1) # error: [deprecated] "use OtherClass"
|
||||||
| ^^^^^^ use OtherClass
|
| ^^^^^^ use OtherClass
|
||||||
7 | from typing_extensions import deprecated
|
7 | from typing_extensions import deprecated
|
||||||
|
|
|
|
||||||
|
|
|
||||||
|
|
@ -907,8 +907,22 @@ impl<'db> Type<'db> {
|
||||||
previous: Self,
|
previous: Self,
|
||||||
cycle: &salsa::Cycle,
|
cycle: &salsa::Cycle,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Note: other parts of this crate assume that this union will be ordered with the types
|
// When we encounter a salsa cycle, we want to avoid oscillating between two or more types
|
||||||
// from later cycle iterations appearing first.
|
// without converging on a fixed-point result. Most of the time, we union together the
|
||||||
|
// types from each cycle iteration to ensure that our result is monotonic, even if we
|
||||||
|
// encounter oscillation.
|
||||||
|
//
|
||||||
|
// However, there are several parts of our type inference machinery that assume that we
|
||||||
|
// infer a single Type::FunctionLiteral type for each overload of each function definition.
|
||||||
|
// So we avoid the union behavior for those cases, and instead return the inferred type of
|
||||||
|
// the last cycle iteration.
|
||||||
|
//
|
||||||
|
// TODO: If this reintroduces "too many cycle iterations" panics, then we will need to
|
||||||
|
// consider a different union-like behavior for combining function signatures to ensure
|
||||||
|
// monotonicity.
|
||||||
|
if self.is_function_literal() && previous.is_function_literal() {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
UnionType::from_elements_cycle_recovery(db, [self, previous])
|
UnionType::from_elements_cycle_recovery(db, [self, previous])
|
||||||
.recursive_type_normalized(db, cycle)
|
.recursive_type_normalized(db, cycle)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -372,35 +372,12 @@ impl<'db> OverloadLiteral<'db> {
|
||||||
.name
|
.name
|
||||||
.scoped_use_id(db, scope);
|
.scoped_use_id(db, scope);
|
||||||
|
|
||||||
let Place::Defined(previous_type, _, Definedness::AlwaysDefined) =
|
let Place::Defined(Type::FunctionLiteral(previous_type), _, Definedness::AlwaysDefined) =
|
||||||
place_from_bindings(db, use_def.bindings_at_use(use_id))
|
place_from_bindings(db, use_def.bindings_at_use(use_id))
|
||||||
else {
|
else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: When we encounter a salsa cycle during type inference, we currently union together
|
|
||||||
// the inferred types from each cycle iteration. That means that in certain cases
|
|
||||||
// (especially involving decorators), we can end up with a union of FunctionLiterals for
|
|
||||||
// each overload, instead of a single bare FunctionLiteral. If we do see a union
|
|
||||||
// (containing _only_ function literals), pull out the first function literal and use it as
|
|
||||||
// the type of the overload. Note that this depends on how Type::cycle_normalized orders
|
|
||||||
// things so that later cycle iterations appear first in the union.
|
|
||||||
let previous_type = match previous_type {
|
|
||||||
Type::FunctionLiteral(function) => function,
|
|
||||||
Type::Union(union_type)
|
|
||||||
if union_type
|
|
||||||
.elements(db)
|
|
||||||
.iter()
|
|
||||||
.all(Type::is_function_literal) =>
|
|
||||||
{
|
|
||||||
// SAFETY: We just checked this
|
|
||||||
union_type.elements(db)[0]
|
|
||||||
.as_function_literal()
|
|
||||||
.expect("type should be a function literal")
|
|
||||||
}
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let previous_literal = previous_type.literal(db);
|
let previous_literal = previous_type.literal(db);
|
||||||
let previous_overload = previous_literal.last_definition(db);
|
let previous_overload = previous_literal.last_definition(db);
|
||||||
if !previous_overload.is_overload(db) {
|
if !previous_overload.is_overload(db) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue