mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-23 11:54:39 +00:00
[ty] Fallback to Unknown if no type is stored for an expression (#19517)
## Summary See discussion at https://github.com/astral-sh/ruff/pull/19478/files#r2223870292 Fixes https://github.com/astral-sh/ty/issues/865 ## Test Plan Added one mdtest for invalid Callable annotation; removed `pull-types: skip` from that test file. Co-authored-by: lipefree <willy.ngo.2000@gmail.com>
This commit is contained in:
parent
c8c80e054e
commit
ae9d450b5f
3 changed files with 28 additions and 35 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
def a(x: Callable[.., None]): ...
|
||||||
|
|
||||||
|
def b(x: Callable[..
|
|
@ -58,8 +58,6 @@ def _(c: Callable[[int, 42, str, False], None]):
|
||||||
|
|
||||||
### Missing return type
|
### Missing return type
|
||||||
|
|
||||||
<!-- pull-types:skip -->
|
|
||||||
|
|
||||||
Using a parameter list:
|
Using a parameter list:
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
@ -90,6 +88,21 @@ def _(c: Callable[ # error: [invalid-type-form] "Special form `typing.Callable`
|
||||||
reveal_type(c) # revealed: (...) -> Unknown
|
reveal_type(c) # revealed: (...) -> Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Invalid parameters and return type
|
||||||
|
|
||||||
|
```py
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
# fmt: off
|
||||||
|
|
||||||
|
def _(c: Callable[
|
||||||
|
# error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
|
||||||
|
{1, 2}, 2 # error: [invalid-type-form] "The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`"
|
||||||
|
]
|
||||||
|
):
|
||||||
|
reveal_type(c) # revealed: (...) -> Unknown
|
||||||
|
```
|
||||||
|
|
||||||
### More than two arguments
|
### More than two arguments
|
||||||
|
|
||||||
We can't reliably infer the callable type if there are more then 2 arguments because we don't know
|
We can't reliably infer the callable type if there are more then 2 arguments because we don't know
|
||||||
|
|
|
@ -452,14 +452,9 @@ impl<'db> ScopeInference<'db> {
|
||||||
self.extra.as_deref().map(|extra| &extra.diagnostics)
|
self.extra.as_deref().map(|extra| &extra.diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub(crate) fn expression_type(&self, expression: impl Into<ExpressionNodeKey>) -> Type<'db> {
|
pub(crate) fn expression_type(&self, expression: impl Into<ExpressionNodeKey>) -> Type<'db> {
|
||||||
self.try_expression_type(expression).expect(
|
self.try_expression_type(expression)
|
||||||
"Failed to retrieve the inferred type for an `ast::Expr` node \
|
.unwrap_or_else(Type::unknown)
|
||||||
passed to `TypeInference::expression_type()`. The `TypeInferenceBuilder` \
|
|
||||||
should infer and store types for all `ast::Expr` nodes in any `TypeInference` \
|
|
||||||
region it analyzes.",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn try_expression_type(
|
pub(crate) fn try_expression_type(
|
||||||
|
@ -541,14 +536,9 @@ impl<'db> DefinitionInference<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub(crate) fn expression_type(&self, expression: impl Into<ExpressionNodeKey>) -> Type<'db> {
|
pub(crate) fn expression_type(&self, expression: impl Into<ExpressionNodeKey>) -> Type<'db> {
|
||||||
self.try_expression_type(expression).expect(
|
self.try_expression_type(expression)
|
||||||
"Failed to retrieve the inferred type for an `ast::Expr` node \
|
.unwrap_or_else(Type::unknown)
|
||||||
passed to `TypeInference::expression_type()`. The `TypeInferenceBuilder` \
|
|
||||||
should infer and store types for all `ast::Expr` nodes in any `TypeInference` \
|
|
||||||
region it analyzes.",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn try_expression_type(
|
pub(crate) fn try_expression_type(
|
||||||
|
@ -675,14 +665,9 @@ impl<'db> ExpressionInference<'db> {
|
||||||
.or_else(|| self.fallback_type())
|
.or_else(|| self.fallback_type())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub(crate) fn expression_type(&self, expression: impl Into<ExpressionNodeKey>) -> Type<'db> {
|
pub(crate) fn expression_type(&self, expression: impl Into<ExpressionNodeKey>) -> Type<'db> {
|
||||||
self.try_expression_type(expression).expect(
|
self.try_expression_type(expression)
|
||||||
"Failed to retrieve the inferred type for an `ast::Expr` node \
|
.unwrap_or_else(Type::unknown)
|
||||||
passed to `TypeInference::expression_type()`. The `TypeInferenceBuilder` \
|
|
||||||
should infer and store types for all `ast::Expr` nodes in any `TypeInference` \
|
|
||||||
region it analyzes.",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_cycle_callback(&self) -> bool {
|
fn is_cycle_callback(&self) -> bool {
|
||||||
|
@ -959,19 +944,9 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
self.context.in_stub()
|
self.context.in_stub()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the already-inferred type of an expression node.
|
/// Get the already-inferred type of an expression node, or Unknown.
|
||||||
///
|
|
||||||
/// ## Panics
|
|
||||||
/// If the expression is not within this region, or if no type has yet been inferred for
|
|
||||||
/// this node.
|
|
||||||
#[track_caller]
|
|
||||||
fn expression_type(&self, expr: &ast::Expr) -> Type<'db> {
|
fn expression_type(&self, expr: &ast::Expr) -> Type<'db> {
|
||||||
self.try_expression_type(expr).expect(
|
self.try_expression_type(expr).unwrap_or_else(Type::unknown)
|
||||||
"Failed to retrieve the inferred type for an `ast::Expr` node \
|
|
||||||
passed to `TypeInference::expression_type()`. The `TypeInferenceBuilder` \
|
|
||||||
should infer and store types for all `ast::Expr` nodes in any `TypeInference` \
|
|
||||||
region it analyzes.",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_expression_type(&self, expr: &ast::Expr) -> Option<Type<'db>> {
|
fn try_expression_type(&self, expr: &ast::Expr) -> Option<Type<'db>> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue