mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-30 15:17:59 +00:00
[red-knot] Rename *_ty functions (#15617)
## Summary General rules: * Change the `_ty` suffix of all functions to `_type`. * `_type_and_qualifiers` suffixes seem too long, so we ignore the existence of qualifiers and still speak of "types" * Functions only have a `_type` suffix if they return either `Type`, `Option<Type>`, or `TypeAndQualifiers` Free functions: * `binding_ty` => `binding_type` * `declaration_ty` => `declaration_type` * `definition_expression_ty` => `definition_expression_type` Methods: * `CallDunderResult::return_ty` => `return_type` * `NotCallableError::return_ty` => `return_type` * `NotCallableError::called_ty` => `called_type` * `TypeAndQualifiers::inner_ty` => `inner_type` * `TypeAliasType::value_ty` => `value_type` * `TypeInference::expression_ty` => `expression_type` * `TypeInference::try_expression_ty` => `try_expression_type` * `TypeInference::binding_ty` => `binding_type` * `TypeInference::declaration_ty` => `declaration_type` * `TypeInferenceBuilder::expression_ty` => `expression_type` * `TypeInferenceBuilder::file_expression_ty` => `file_expression_type` * `TypeInferenceBuilder::module_ty_from_name` => `module_type_from_name` * `ClassBase::try_from_ty` => `try_from_type` * `Parameter::annotated_ty` => `annotated_type` * `Parameter::default_ty` => `default_type` * `CallOutcome::return_ty` => `return_type` * `CallOutcome::return_ty_result` => `return_type_result` * `CallBinding::from_return_ty` => `from_return_type` * `CallBinding::set_return_ty` => `set_return_type` * `CallBinding::return_ty` => `return_type` * `CallBinding::parameter_tys` => `parameter_types` * `CallBinding::one_parameter_ty` => `one_parameter_type` * `CallBinding::two_parameter_tys` => `two_parameter_types` * `Unpacker::tuple_ty_elements` => `tuple_type_elements` * `StringPartsCollector::ty` => `string_type` Traits * `HasTy` => `HasType` * `HasTy::ty` => `inferred_type` Test functions: * `assert_public_ty` => `assert_public_type` * `assert_scope_ty` => `assert_scope_type` closes #15569 ## Test Plan —
This commit is contained in:
parent
6fe404a40f
commit
792f9e357e
15 changed files with 334 additions and 328 deletions
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use red_knot_project::{ProjectDatabase, ProjectMetadata};
|
use red_knot_project::{ProjectDatabase, ProjectMetadata};
|
||||||
use red_knot_python_semantic::{HasTy, SemanticModel};
|
use red_knot_python_semantic::{HasType, SemanticModel};
|
||||||
use ruff_db::files::{system_path_to_file, File};
|
use ruff_db::files::{system_path_to_file, File};
|
||||||
use ruff_db::parsed::parsed_module;
|
use ruff_db::parsed::parsed_module;
|
||||||
use ruff_db::system::{SystemPath, SystemPathBuf, TestSystem};
|
use ruff_db::system::{SystemPath, SystemPathBuf, TestSystem};
|
||||||
|
@ -197,10 +197,10 @@ impl SourceOrderVisitor<'_> for PullTypesVisitor<'_> {
|
||||||
fn visit_stmt(&mut self, stmt: &Stmt) {
|
fn visit_stmt(&mut self, stmt: &Stmt) {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::FunctionDef(function) => {
|
Stmt::FunctionDef(function) => {
|
||||||
let _ty = function.ty(&self.model);
|
let _ty = function.inferred_type(&self.model);
|
||||||
}
|
}
|
||||||
Stmt::ClassDef(class) => {
|
Stmt::ClassDef(class) => {
|
||||||
let _ty = class.ty(&self.model);
|
let _ty = class.inferred_type(&self.model);
|
||||||
}
|
}
|
||||||
Stmt::Assign(assign) => {
|
Stmt::Assign(assign) => {
|
||||||
for target in &assign.targets {
|
for target in &assign.targets {
|
||||||
|
@ -243,25 +243,25 @@ impl SourceOrderVisitor<'_> for PullTypesVisitor<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &Expr) {
|
fn visit_expr(&mut self, expr: &Expr) {
|
||||||
let _ty = expr.ty(&self.model);
|
let _ty = expr.inferred_type(&self.model);
|
||||||
|
|
||||||
source_order::walk_expr(self, expr);
|
source_order::walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_parameter(&mut self, parameter: &Parameter) {
|
fn visit_parameter(&mut self, parameter: &Parameter) {
|
||||||
let _ty = parameter.ty(&self.model);
|
let _ty = parameter.inferred_type(&self.model);
|
||||||
|
|
||||||
source_order::walk_parameter(self, parameter);
|
source_order::walk_parameter(self, parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_parameter_with_default(&mut self, parameter_with_default: &ParameterWithDefault) {
|
fn visit_parameter_with_default(&mut self, parameter_with_default: &ParameterWithDefault) {
|
||||||
let _ty = parameter_with_default.ty(&self.model);
|
let _ty = parameter_with_default.inferred_type(&self.model);
|
||||||
|
|
||||||
source_order::walk_parameter_with_default(self, parameter_with_default);
|
source_order::walk_parameter_with_default(self, parameter_with_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_alias(&mut self, alias: &Alias) {
|
fn visit_alias(&mut self, alias: &Alias) {
|
||||||
let _ty = alias.ty(&self.model);
|
let _ty = alias.inferred_type(&self.model);
|
||||||
|
|
||||||
source_order::walk_alias(self, alias);
|
source_order::walk_alias(self, alias);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub use module_resolver::{resolve_module, system_module_search_paths, KnownModul
|
||||||
pub use program::{Program, ProgramSettings, SearchPathSettings, SitePackages};
|
pub use program::{Program, ProgramSettings, SearchPathSettings, SitePackages};
|
||||||
pub use python_platform::PythonPlatform;
|
pub use python_platform::PythonPlatform;
|
||||||
pub use python_version::PythonVersion;
|
pub use python_version::PythonVersion;
|
||||||
pub use semantic_model::{HasTy, SemanticModel};
|
pub use semantic_model::{HasType, SemanticModel};
|
||||||
|
|
||||||
pub mod ast_node_ref;
|
pub mod ast_node_ref;
|
||||||
mod db;
|
mod db;
|
||||||
|
|
|
@ -603,8 +603,8 @@ impl<'db> SemanticIndexBuilder<'db> {
|
||||||
|
|
||||||
let definition = self.add_definition(symbol, parameter);
|
let definition = self.add_definition(symbol, parameter);
|
||||||
|
|
||||||
// Insert a mapping from the inner Parameter node to the same definition.
|
// Insert a mapping from the inner Parameter node to the same definition. This
|
||||||
// This ensures that calling `HasTy::ty` on the inner parameter returns
|
// ensures that calling `HasType::inferred_type` on the inner parameter returns
|
||||||
// a valid type (and doesn't panic)
|
// a valid type (and doesn't panic)
|
||||||
let existing_definition = self
|
let existing_definition = self
|
||||||
.definitions_by_node
|
.definitions_by_node
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::module_name::ModuleName;
|
||||||
use crate::module_resolver::{resolve_module, Module};
|
use crate::module_resolver::{resolve_module, Module};
|
||||||
use crate::semantic_index::ast_ids::HasScopedExpressionId;
|
use crate::semantic_index::ast_ids::HasScopedExpressionId;
|
||||||
use crate::semantic_index::semantic_index;
|
use crate::semantic_index::semantic_index;
|
||||||
use crate::types::{binding_ty, infer_scope_types, Type};
|
use crate::types::{binding_type, infer_scope_types, Type};
|
||||||
use crate::Db;
|
use crate::Db;
|
||||||
|
|
||||||
pub struct SemanticModel<'db> {
|
pub struct SemanticModel<'db> {
|
||||||
|
@ -40,117 +40,117 @@ impl<'db> SemanticModel<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HasTy {
|
pub trait HasType {
|
||||||
/// Returns the inferred type of `self`.
|
/// Returns the inferred type of `self`.
|
||||||
///
|
///
|
||||||
/// ## Panics
|
/// ## Panics
|
||||||
/// May panic if `self` is from another file than `model`.
|
/// May panic if `self` is from another file than `model`.
|
||||||
fn ty<'db>(&self, model: &SemanticModel<'db>) -> Type<'db>;
|
fn inferred_type<'db>(&self, model: &SemanticModel<'db>) -> Type<'db>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasTy for ast::ExprRef<'_> {
|
impl HasType for ast::ExprRef<'_> {
|
||||||
fn ty<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
fn inferred_type<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
||||||
let index = semantic_index(model.db, model.file);
|
let index = semantic_index(model.db, model.file);
|
||||||
let file_scope = index.expression_scope_id(*self);
|
let file_scope = index.expression_scope_id(*self);
|
||||||
let scope = file_scope.to_scope_id(model.db, model.file);
|
let scope = file_scope.to_scope_id(model.db, model.file);
|
||||||
|
|
||||||
let expression_id = self.scoped_expression_id(model.db, scope);
|
let expression_id = self.scoped_expression_id(model.db, scope);
|
||||||
infer_scope_types(model.db, scope).expression_ty(expression_id)
|
infer_scope_types(model.db, scope).expression_type(expression_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_expression_has_ty {
|
macro_rules! impl_expression_has_type {
|
||||||
($ty: ty) => {
|
($ty: ty) => {
|
||||||
impl HasTy for $ty {
|
impl HasType for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ty<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
fn inferred_type<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
||||||
let expression_ref = ExprRef::from(self);
|
let expression_ref = ExprRef::from(self);
|
||||||
expression_ref.ty(model)
|
expression_ref.inferred_type(model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_expression_has_ty!(ast::ExprBoolOp);
|
impl_expression_has_type!(ast::ExprBoolOp);
|
||||||
impl_expression_has_ty!(ast::ExprNamed);
|
impl_expression_has_type!(ast::ExprNamed);
|
||||||
impl_expression_has_ty!(ast::ExprBinOp);
|
impl_expression_has_type!(ast::ExprBinOp);
|
||||||
impl_expression_has_ty!(ast::ExprUnaryOp);
|
impl_expression_has_type!(ast::ExprUnaryOp);
|
||||||
impl_expression_has_ty!(ast::ExprLambda);
|
impl_expression_has_type!(ast::ExprLambda);
|
||||||
impl_expression_has_ty!(ast::ExprIf);
|
impl_expression_has_type!(ast::ExprIf);
|
||||||
impl_expression_has_ty!(ast::ExprDict);
|
impl_expression_has_type!(ast::ExprDict);
|
||||||
impl_expression_has_ty!(ast::ExprSet);
|
impl_expression_has_type!(ast::ExprSet);
|
||||||
impl_expression_has_ty!(ast::ExprListComp);
|
impl_expression_has_type!(ast::ExprListComp);
|
||||||
impl_expression_has_ty!(ast::ExprSetComp);
|
impl_expression_has_type!(ast::ExprSetComp);
|
||||||
impl_expression_has_ty!(ast::ExprDictComp);
|
impl_expression_has_type!(ast::ExprDictComp);
|
||||||
impl_expression_has_ty!(ast::ExprGenerator);
|
impl_expression_has_type!(ast::ExprGenerator);
|
||||||
impl_expression_has_ty!(ast::ExprAwait);
|
impl_expression_has_type!(ast::ExprAwait);
|
||||||
impl_expression_has_ty!(ast::ExprYield);
|
impl_expression_has_type!(ast::ExprYield);
|
||||||
impl_expression_has_ty!(ast::ExprYieldFrom);
|
impl_expression_has_type!(ast::ExprYieldFrom);
|
||||||
impl_expression_has_ty!(ast::ExprCompare);
|
impl_expression_has_type!(ast::ExprCompare);
|
||||||
impl_expression_has_ty!(ast::ExprCall);
|
impl_expression_has_type!(ast::ExprCall);
|
||||||
impl_expression_has_ty!(ast::ExprFString);
|
impl_expression_has_type!(ast::ExprFString);
|
||||||
impl_expression_has_ty!(ast::ExprStringLiteral);
|
impl_expression_has_type!(ast::ExprStringLiteral);
|
||||||
impl_expression_has_ty!(ast::ExprBytesLiteral);
|
impl_expression_has_type!(ast::ExprBytesLiteral);
|
||||||
impl_expression_has_ty!(ast::ExprNumberLiteral);
|
impl_expression_has_type!(ast::ExprNumberLiteral);
|
||||||
impl_expression_has_ty!(ast::ExprBooleanLiteral);
|
impl_expression_has_type!(ast::ExprBooleanLiteral);
|
||||||
impl_expression_has_ty!(ast::ExprNoneLiteral);
|
impl_expression_has_type!(ast::ExprNoneLiteral);
|
||||||
impl_expression_has_ty!(ast::ExprEllipsisLiteral);
|
impl_expression_has_type!(ast::ExprEllipsisLiteral);
|
||||||
impl_expression_has_ty!(ast::ExprAttribute);
|
impl_expression_has_type!(ast::ExprAttribute);
|
||||||
impl_expression_has_ty!(ast::ExprSubscript);
|
impl_expression_has_type!(ast::ExprSubscript);
|
||||||
impl_expression_has_ty!(ast::ExprStarred);
|
impl_expression_has_type!(ast::ExprStarred);
|
||||||
impl_expression_has_ty!(ast::ExprName);
|
impl_expression_has_type!(ast::ExprName);
|
||||||
impl_expression_has_ty!(ast::ExprList);
|
impl_expression_has_type!(ast::ExprList);
|
||||||
impl_expression_has_ty!(ast::ExprTuple);
|
impl_expression_has_type!(ast::ExprTuple);
|
||||||
impl_expression_has_ty!(ast::ExprSlice);
|
impl_expression_has_type!(ast::ExprSlice);
|
||||||
impl_expression_has_ty!(ast::ExprIpyEscapeCommand);
|
impl_expression_has_type!(ast::ExprIpyEscapeCommand);
|
||||||
|
|
||||||
impl HasTy for ast::Expr {
|
impl HasType for ast::Expr {
|
||||||
fn ty<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
fn inferred_type<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
||||||
match self {
|
match self {
|
||||||
Expr::BoolOp(inner) => inner.ty(model),
|
Expr::BoolOp(inner) => inner.inferred_type(model),
|
||||||
Expr::Named(inner) => inner.ty(model),
|
Expr::Named(inner) => inner.inferred_type(model),
|
||||||
Expr::BinOp(inner) => inner.ty(model),
|
Expr::BinOp(inner) => inner.inferred_type(model),
|
||||||
Expr::UnaryOp(inner) => inner.ty(model),
|
Expr::UnaryOp(inner) => inner.inferred_type(model),
|
||||||
Expr::Lambda(inner) => inner.ty(model),
|
Expr::Lambda(inner) => inner.inferred_type(model),
|
||||||
Expr::If(inner) => inner.ty(model),
|
Expr::If(inner) => inner.inferred_type(model),
|
||||||
Expr::Dict(inner) => inner.ty(model),
|
Expr::Dict(inner) => inner.inferred_type(model),
|
||||||
Expr::Set(inner) => inner.ty(model),
|
Expr::Set(inner) => inner.inferred_type(model),
|
||||||
Expr::ListComp(inner) => inner.ty(model),
|
Expr::ListComp(inner) => inner.inferred_type(model),
|
||||||
Expr::SetComp(inner) => inner.ty(model),
|
Expr::SetComp(inner) => inner.inferred_type(model),
|
||||||
Expr::DictComp(inner) => inner.ty(model),
|
Expr::DictComp(inner) => inner.inferred_type(model),
|
||||||
Expr::Generator(inner) => inner.ty(model),
|
Expr::Generator(inner) => inner.inferred_type(model),
|
||||||
Expr::Await(inner) => inner.ty(model),
|
Expr::Await(inner) => inner.inferred_type(model),
|
||||||
Expr::Yield(inner) => inner.ty(model),
|
Expr::Yield(inner) => inner.inferred_type(model),
|
||||||
Expr::YieldFrom(inner) => inner.ty(model),
|
Expr::YieldFrom(inner) => inner.inferred_type(model),
|
||||||
Expr::Compare(inner) => inner.ty(model),
|
Expr::Compare(inner) => inner.inferred_type(model),
|
||||||
Expr::Call(inner) => inner.ty(model),
|
Expr::Call(inner) => inner.inferred_type(model),
|
||||||
Expr::FString(inner) => inner.ty(model),
|
Expr::FString(inner) => inner.inferred_type(model),
|
||||||
Expr::StringLiteral(inner) => inner.ty(model),
|
Expr::StringLiteral(inner) => inner.inferred_type(model),
|
||||||
Expr::BytesLiteral(inner) => inner.ty(model),
|
Expr::BytesLiteral(inner) => inner.inferred_type(model),
|
||||||
Expr::NumberLiteral(inner) => inner.ty(model),
|
Expr::NumberLiteral(inner) => inner.inferred_type(model),
|
||||||
Expr::BooleanLiteral(inner) => inner.ty(model),
|
Expr::BooleanLiteral(inner) => inner.inferred_type(model),
|
||||||
Expr::NoneLiteral(inner) => inner.ty(model),
|
Expr::NoneLiteral(inner) => inner.inferred_type(model),
|
||||||
Expr::EllipsisLiteral(inner) => inner.ty(model),
|
Expr::EllipsisLiteral(inner) => inner.inferred_type(model),
|
||||||
Expr::Attribute(inner) => inner.ty(model),
|
Expr::Attribute(inner) => inner.inferred_type(model),
|
||||||
Expr::Subscript(inner) => inner.ty(model),
|
Expr::Subscript(inner) => inner.inferred_type(model),
|
||||||
Expr::Starred(inner) => inner.ty(model),
|
Expr::Starred(inner) => inner.inferred_type(model),
|
||||||
Expr::Name(inner) => inner.ty(model),
|
Expr::Name(inner) => inner.inferred_type(model),
|
||||||
Expr::List(inner) => inner.ty(model),
|
Expr::List(inner) => inner.inferred_type(model),
|
||||||
Expr::Tuple(inner) => inner.ty(model),
|
Expr::Tuple(inner) => inner.inferred_type(model),
|
||||||
Expr::Slice(inner) => inner.ty(model),
|
Expr::Slice(inner) => inner.inferred_type(model),
|
||||||
Expr::IpyEscapeCommand(inner) => inner.ty(model),
|
Expr::IpyEscapeCommand(inner) => inner.inferred_type(model),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_binding_has_ty {
|
macro_rules! impl_binding_has_ty {
|
||||||
($ty: ty) => {
|
($ty: ty) => {
|
||||||
impl HasTy for $ty {
|
impl HasType for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ty<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
fn inferred_type<'db>(&self, model: &SemanticModel<'db>) -> Type<'db> {
|
||||||
let index = semantic_index(model.db, model.file);
|
let index = semantic_index(model.db, model.file);
|
||||||
let binding = index.definition(self);
|
let binding = index.definition(self);
|
||||||
binding_ty(model.db, binding)
|
binding_type(model.db, binding)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -168,10 +168,10 @@ mod tests {
|
||||||
use ruff_db::parsed::parsed_module;
|
use ruff_db::parsed::parsed_module;
|
||||||
|
|
||||||
use crate::db::tests::TestDbBuilder;
|
use crate::db::tests::TestDbBuilder;
|
||||||
use crate::{HasTy, SemanticModel};
|
use crate::{HasType, SemanticModel};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_ty() -> anyhow::Result<()> {
|
fn function_type() -> anyhow::Result<()> {
|
||||||
let db = TestDbBuilder::new()
|
let db = TestDbBuilder::new()
|
||||||
.with_file("/src/foo.py", "def test(): pass")
|
.with_file("/src/foo.py", "def test(): pass")
|
||||||
.build()?;
|
.build()?;
|
||||||
|
@ -182,7 +182,7 @@ mod tests {
|
||||||
|
|
||||||
let function = ast.suite()[0].as_function_def_stmt().unwrap();
|
let function = ast.suite()[0].as_function_def_stmt().unwrap();
|
||||||
let model = SemanticModel::new(&db, foo);
|
let model = SemanticModel::new(&db, foo);
|
||||||
let ty = function.ty(&model);
|
let ty = function.inferred_type(&model);
|
||||||
|
|
||||||
assert!(ty.is_function_literal());
|
assert!(ty.is_function_literal());
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn class_ty() -> anyhow::Result<()> {
|
fn class_type() -> anyhow::Result<()> {
|
||||||
let db = TestDbBuilder::new()
|
let db = TestDbBuilder::new()
|
||||||
.with_file("/src/foo.py", "class Test: pass")
|
.with_file("/src/foo.py", "class Test: pass")
|
||||||
.build()?;
|
.build()?;
|
||||||
|
@ -201,7 +201,7 @@ mod tests {
|
||||||
|
|
||||||
let class = ast.suite()[0].as_class_def_stmt().unwrap();
|
let class = ast.suite()[0].as_class_def_stmt().unwrap();
|
||||||
let model = SemanticModel::new(&db, foo);
|
let model = SemanticModel::new(&db, foo);
|
||||||
let ty = class.ty(&model);
|
let ty = class.inferred_type(&model);
|
||||||
|
|
||||||
assert!(ty.is_class_literal());
|
assert!(ty.is_class_literal());
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn alias_ty() -> anyhow::Result<()> {
|
fn alias_type() -> anyhow::Result<()> {
|
||||||
let db = TestDbBuilder::new()
|
let db = TestDbBuilder::new()
|
||||||
.with_file("/src/foo.py", "class Test: pass")
|
.with_file("/src/foo.py", "class Test: pass")
|
||||||
.with_file("/src/bar.py", "from foo import Test")
|
.with_file("/src/bar.py", "from foo import Test")
|
||||||
|
@ -222,7 +222,7 @@ mod tests {
|
||||||
let import = ast.suite()[0].as_import_from_stmt().unwrap();
|
let import = ast.suite()[0].as_import_from_stmt().unwrap();
|
||||||
let alias = &import.names[0];
|
let alias = &import.names[0];
|
||||||
let model = SemanticModel::new(&db, bar);
|
let model = SemanticModel::new(&db, bar);
|
||||||
let ty = alias.ty(&model);
|
let ty = alias.inferred_type(&model);
|
||||||
|
|
||||||
assert!(ty.is_class_literal());
|
assert!(ty.is_class_literal());
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ fn symbol<'db>(db: &'db dyn Db, scope: ScopeId<'db>, name: &str) -> Symbol<'db>
|
||||||
Err((declared_ty, _)) => {
|
Err((declared_ty, _)) => {
|
||||||
// Intentionally ignore conflicting declared types; that's not our problem,
|
// Intentionally ignore conflicting declared types; that's not our problem,
|
||||||
// it's the problem of the module we are importing from.
|
// it's the problem of the module we are importing from.
|
||||||
declared_ty.inner_ty().into()
|
declared_ty.inner_type().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,15 +243,15 @@ pub(crate) fn global_symbol<'db>(db: &'db dyn Db, file: File, name: &str) -> Sym
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Infer the type of a binding.
|
/// Infer the type of a binding.
|
||||||
pub(crate) fn binding_ty<'db>(db: &'db dyn Db, definition: Definition<'db>) -> Type<'db> {
|
pub(crate) fn binding_type<'db>(db: &'db dyn Db, definition: Definition<'db>) -> Type<'db> {
|
||||||
let inference = infer_definition_types(db, definition);
|
let inference = infer_definition_types(db, definition);
|
||||||
inference.binding_ty(definition)
|
inference.binding_type(definition)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Infer the type of a declaration.
|
/// Infer the type of a declaration.
|
||||||
fn declaration_ty<'db>(db: &'db dyn Db, definition: Definition<'db>) -> TypeAndQualifiers<'db> {
|
fn declaration_type<'db>(db: &'db dyn Db, definition: Definition<'db>) -> TypeAndQualifiers<'db> {
|
||||||
let inference = infer_definition_types(db, definition);
|
let inference = infer_definition_types(db, definition);
|
||||||
inference.declaration_ty(definition)
|
inference.declaration_type(definition)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Infer the type of a (possibly deferred) sub-expression of a [`Definition`].
|
/// Infer the type of a (possibly deferred) sub-expression of a [`Definition`].
|
||||||
|
@ -260,7 +260,7 @@ fn declaration_ty<'db>(db: &'db dyn Db, definition: Definition<'db>) -> TypeAndQ
|
||||||
///
|
///
|
||||||
/// ## Panics
|
/// ## Panics
|
||||||
/// If the given expression is not a sub-expression of the given [`Definition`].
|
/// If the given expression is not a sub-expression of the given [`Definition`].
|
||||||
fn definition_expression_ty<'db>(
|
fn definition_expression_type<'db>(
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
definition: Definition<'db>,
|
definition: Definition<'db>,
|
||||||
expression: &ast::Expr,
|
expression: &ast::Expr,
|
||||||
|
@ -273,14 +273,14 @@ fn definition_expression_ty<'db>(
|
||||||
if scope == definition.scope(db) {
|
if scope == definition.scope(db) {
|
||||||
// expression is in the definition scope
|
// expression is in the definition scope
|
||||||
let inference = infer_definition_types(db, definition);
|
let inference = infer_definition_types(db, definition);
|
||||||
if let Some(ty) = inference.try_expression_ty(expr_id) {
|
if let Some(ty) = inference.try_expression_type(expr_id) {
|
||||||
ty
|
ty
|
||||||
} else {
|
} else {
|
||||||
infer_deferred_types(db, definition).expression_ty(expr_id)
|
infer_deferred_types(db, definition).expression_type(expr_id)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// expression is in a type-params sub-scope
|
// expression is in a type-params sub-scope
|
||||||
infer_scope_types(db, scope).expression_ty(expr_id)
|
infer_scope_types(db, scope).expression_type(expr_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ fn symbol_from_bindings<'db>(
|
||||||
.filter_map(|constraint| narrowing_constraint(db, constraint, binding))
|
.filter_map(|constraint| narrowing_constraint(db, constraint, binding))
|
||||||
.peekable();
|
.peekable();
|
||||||
|
|
||||||
let binding_ty = binding_ty(db, binding);
|
let binding_ty = binding_type(db, binding);
|
||||||
if constraint_tys.peek().is_some() {
|
if constraint_tys.peek().is_some() {
|
||||||
let intersection_ty = constraint_tys
|
let intersection_ty = constraint_tys
|
||||||
.fold(
|
.fold(
|
||||||
|
@ -432,7 +432,7 @@ fn symbol_from_declarations<'db>(
|
||||||
if static_visibility.is_always_false() {
|
if static_visibility.is_always_false() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(declaration_ty(db, declaration))
|
Some(declaration_type(db, declaration))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -440,12 +440,12 @@ fn symbol_from_declarations<'db>(
|
||||||
if let Some(first) = types.next() {
|
if let Some(first) = types.next() {
|
||||||
let mut conflicting: Vec<Type<'db>> = vec![];
|
let mut conflicting: Vec<Type<'db>> = vec![];
|
||||||
let declared_ty = if let Some(second) = types.next() {
|
let declared_ty = if let Some(second) = types.next() {
|
||||||
let ty_first = first.inner_ty();
|
let ty_first = first.inner_type();
|
||||||
let mut qualifiers = first.qualifiers();
|
let mut qualifiers = first.qualifiers();
|
||||||
|
|
||||||
let mut builder = UnionBuilder::new(db).add(ty_first);
|
let mut builder = UnionBuilder::new(db).add(ty_first);
|
||||||
for other in std::iter::once(second).chain(types) {
|
for other in std::iter::once(second).chain(types) {
|
||||||
let other_ty = other.inner_ty();
|
let other_ty = other.inner_type();
|
||||||
if !ty_first.is_equivalent_to(db, other_ty) {
|
if !ty_first.is_equivalent_to(db, other_ty) {
|
||||||
conflicting.push(other_ty);
|
conflicting.push(other_ty);
|
||||||
}
|
}
|
||||||
|
@ -466,13 +466,13 @@ fn symbol_from_declarations<'db>(
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(SymbolAndQualifiers(
|
Ok(SymbolAndQualifiers(
|
||||||
Symbol::Type(declared_ty.inner_ty(), boundness),
|
Symbol::Type(declared_ty.inner_type(), boundness),
|
||||||
declared_ty.qualifiers(),
|
declared_ty.qualifiers(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Err((
|
Err((
|
||||||
declared_ty,
|
declared_ty,
|
||||||
std::iter::once(first.inner_ty())
|
std::iter::once(first.inner_type())
|
||||||
.chain(conflicting)
|
.chain(conflicting)
|
||||||
.collect(),
|
.collect(),
|
||||||
))
|
))
|
||||||
|
@ -1787,7 +1787,7 @@ impl<'db> Type<'db> {
|
||||||
|
|
||||||
if let Some(Type::BooleanLiteral(bool_val)) = bool_method
|
if let Some(Type::BooleanLiteral(bool_val)) = bool_method
|
||||||
.call(db, &CallArguments::positional([*instance_ty]))
|
.call(db, &CallArguments::positional([*instance_ty]))
|
||||||
.return_ty(db)
|
.return_type(db)
|
||||||
{
|
{
|
||||||
bool_val.into()
|
bool_val.into()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1864,7 +1864,7 @@ impl<'db> Type<'db> {
|
||||||
CallDunderResult::MethodNotAvailable => return None,
|
CallDunderResult::MethodNotAvailable => return None,
|
||||||
|
|
||||||
CallDunderResult::CallOutcome(outcome) | CallDunderResult::PossiblyUnbound(outcome) => {
|
CallDunderResult::CallOutcome(outcome) | CallDunderResult::PossiblyUnbound(outcome) => {
|
||||||
outcome.return_ty(db)?
|
outcome.return_type(db)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1879,11 +1879,11 @@ impl<'db> Type<'db> {
|
||||||
let mut binding = bind_call(db, arguments, function_type.signature(db), Some(self));
|
let mut binding = bind_call(db, arguments, function_type.signature(db), Some(self));
|
||||||
match function_type.known(db) {
|
match function_type.known(db) {
|
||||||
Some(KnownFunction::RevealType) => {
|
Some(KnownFunction::RevealType) => {
|
||||||
let revealed_ty = binding.one_parameter_ty().unwrap_or(Type::unknown());
|
let revealed_ty = binding.one_parameter_type().unwrap_or(Type::unknown());
|
||||||
CallOutcome::revealed(binding, revealed_ty)
|
CallOutcome::revealed(binding, revealed_ty)
|
||||||
}
|
}
|
||||||
Some(KnownFunction::StaticAssert) => {
|
Some(KnownFunction::StaticAssert) => {
|
||||||
if let Some((parameter_ty, message)) = binding.two_parameter_tys() {
|
if let Some((parameter_ty, message)) = binding.two_parameter_types() {
|
||||||
let truthiness = parameter_ty.bool(db);
|
let truthiness = parameter_ty.bool(db);
|
||||||
|
|
||||||
if truthiness.is_always_true() {
|
if truthiness.is_always_true() {
|
||||||
|
@ -1914,64 +1914,64 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
Some(KnownFunction::IsEquivalentTo) => {
|
Some(KnownFunction::IsEquivalentTo) => {
|
||||||
let (ty_a, ty_b) = binding
|
let (ty_a, ty_b) = binding
|
||||||
.two_parameter_tys()
|
.two_parameter_types()
|
||||||
.unwrap_or((Type::unknown(), Type::unknown()));
|
.unwrap_or((Type::unknown(), Type::unknown()));
|
||||||
binding
|
binding
|
||||||
.set_return_ty(Type::BooleanLiteral(ty_a.is_equivalent_to(db, ty_b)));
|
.set_return_type(Type::BooleanLiteral(ty_a.is_equivalent_to(db, ty_b)));
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
Some(KnownFunction::IsSubtypeOf) => {
|
Some(KnownFunction::IsSubtypeOf) => {
|
||||||
let (ty_a, ty_b) = binding
|
let (ty_a, ty_b) = binding
|
||||||
.two_parameter_tys()
|
.two_parameter_types()
|
||||||
.unwrap_or((Type::unknown(), Type::unknown()));
|
.unwrap_or((Type::unknown(), Type::unknown()));
|
||||||
binding.set_return_ty(Type::BooleanLiteral(ty_a.is_subtype_of(db, ty_b)));
|
binding.set_return_type(Type::BooleanLiteral(ty_a.is_subtype_of(db, ty_b)));
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
Some(KnownFunction::IsAssignableTo) => {
|
Some(KnownFunction::IsAssignableTo) => {
|
||||||
let (ty_a, ty_b) = binding
|
let (ty_a, ty_b) = binding
|
||||||
.two_parameter_tys()
|
.two_parameter_types()
|
||||||
.unwrap_or((Type::unknown(), Type::unknown()));
|
.unwrap_or((Type::unknown(), Type::unknown()));
|
||||||
binding
|
binding
|
||||||
.set_return_ty(Type::BooleanLiteral(ty_a.is_assignable_to(db, ty_b)));
|
.set_return_type(Type::BooleanLiteral(ty_a.is_assignable_to(db, ty_b)));
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
Some(KnownFunction::IsDisjointFrom) => {
|
Some(KnownFunction::IsDisjointFrom) => {
|
||||||
let (ty_a, ty_b) = binding
|
let (ty_a, ty_b) = binding
|
||||||
.two_parameter_tys()
|
.two_parameter_types()
|
||||||
.unwrap_or((Type::unknown(), Type::unknown()));
|
.unwrap_or((Type::unknown(), Type::unknown()));
|
||||||
binding
|
binding
|
||||||
.set_return_ty(Type::BooleanLiteral(ty_a.is_disjoint_from(db, ty_b)));
|
.set_return_type(Type::BooleanLiteral(ty_a.is_disjoint_from(db, ty_b)));
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
Some(KnownFunction::IsGradualEquivalentTo) => {
|
Some(KnownFunction::IsGradualEquivalentTo) => {
|
||||||
let (ty_a, ty_b) = binding
|
let (ty_a, ty_b) = binding
|
||||||
.two_parameter_tys()
|
.two_parameter_types()
|
||||||
.unwrap_or((Type::unknown(), Type::unknown()));
|
.unwrap_or((Type::unknown(), Type::unknown()));
|
||||||
binding.set_return_ty(Type::BooleanLiteral(
|
binding.set_return_type(Type::BooleanLiteral(
|
||||||
ty_a.is_gradual_equivalent_to(db, ty_b),
|
ty_a.is_gradual_equivalent_to(db, ty_b),
|
||||||
));
|
));
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
Some(KnownFunction::IsFullyStatic) => {
|
Some(KnownFunction::IsFullyStatic) => {
|
||||||
let ty = binding.one_parameter_ty().unwrap_or(Type::unknown());
|
let ty = binding.one_parameter_type().unwrap_or(Type::unknown());
|
||||||
binding.set_return_ty(Type::BooleanLiteral(ty.is_fully_static(db)));
|
binding.set_return_type(Type::BooleanLiteral(ty.is_fully_static(db)));
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
Some(KnownFunction::IsSingleton) => {
|
Some(KnownFunction::IsSingleton) => {
|
||||||
let ty = binding.one_parameter_ty().unwrap_or(Type::unknown());
|
let ty = binding.one_parameter_type().unwrap_or(Type::unknown());
|
||||||
binding.set_return_ty(Type::BooleanLiteral(ty.is_singleton(db)));
|
binding.set_return_type(Type::BooleanLiteral(ty.is_singleton(db)));
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
Some(KnownFunction::IsSingleValued) => {
|
Some(KnownFunction::IsSingleValued) => {
|
||||||
let ty = binding.one_parameter_ty().unwrap_or(Type::unknown());
|
let ty = binding.one_parameter_type().unwrap_or(Type::unknown());
|
||||||
binding.set_return_ty(Type::BooleanLiteral(ty.is_single_valued(db)));
|
binding.set_return_type(Type::BooleanLiteral(ty.is_single_valued(db)));
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(KnownFunction::Len) => {
|
Some(KnownFunction::Len) => {
|
||||||
if let Some(first_arg) = binding.one_parameter_ty() {
|
if let Some(first_arg) = binding.one_parameter_type() {
|
||||||
if let Some(len_ty) = first_arg.len(db) {
|
if let Some(len_ty) = first_arg.len(db) {
|
||||||
binding.set_return_ty(len_ty);
|
binding.set_return_type(len_ty);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1979,15 +1979,15 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(KnownFunction::Repr) => {
|
Some(KnownFunction::Repr) => {
|
||||||
if let Some(first_arg) = binding.one_parameter_ty() {
|
if let Some(first_arg) = binding.one_parameter_type() {
|
||||||
binding.set_return_ty(first_arg.repr(db));
|
binding.set_return_type(first_arg.repr(db));
|
||||||
};
|
};
|
||||||
|
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(KnownFunction::AssertType) => {
|
Some(KnownFunction::AssertType) => {
|
||||||
let Some((_, asserted_ty)) = binding.two_parameter_tys() else {
|
let Some((_, asserted_ty)) = binding.two_parameter_types() else {
|
||||||
return CallOutcome::callable(binding);
|
return CallOutcome::callable(binding);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1997,12 +1997,12 @@ impl<'db> Type<'db> {
|
||||||
Some(KnownFunction::Cast) => {
|
Some(KnownFunction::Cast) => {
|
||||||
// TODO: Use `.two_parameter_tys()` exclusively
|
// TODO: Use `.two_parameter_tys()` exclusively
|
||||||
// when overloads are supported.
|
// when overloads are supported.
|
||||||
if binding.two_parameter_tys().is_none() {
|
if binding.two_parameter_types().is_none() {
|
||||||
return CallOutcome::callable(binding);
|
return CallOutcome::callable(binding);
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(casted_ty) = arguments.first_argument() {
|
if let Some(casted_ty) = arguments.first_argument() {
|
||||||
binding.set_return_ty(casted_ty);
|
binding.set_return_type(casted_ty);
|
||||||
};
|
};
|
||||||
|
|
||||||
CallOutcome::callable(binding)
|
CallOutcome::callable(binding)
|
||||||
|
@ -2015,7 +2015,7 @@ impl<'db> Type<'db> {
|
||||||
// TODO annotated return type on `__new__` or metaclass `__call__`
|
// TODO annotated return type on `__new__` or metaclass `__call__`
|
||||||
// TODO check call vs signatures of `__new__` and/or `__init__`
|
// TODO check call vs signatures of `__new__` and/or `__init__`
|
||||||
Type::ClassLiteral(ClassLiteralType { class }) => {
|
Type::ClassLiteral(ClassLiteralType { class }) => {
|
||||||
CallOutcome::callable(CallBinding::from_return_ty(match class.known(db) {
|
CallOutcome::callable(CallBinding::from_return_type(match class.known(db) {
|
||||||
// If the class is the builtin-bool class (for example `bool(1)`), we try to
|
// If the class is the builtin-bool class (for example `bool(1)`), we try to
|
||||||
// return the specific truthiness value of the input arg, `Literal[True]` for
|
// return the specific truthiness value of the input arg, `Literal[True]` for
|
||||||
// the example above.
|
// the example above.
|
||||||
|
@ -2061,7 +2061,7 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic types are callable, and the return type is the same dynamic type
|
// Dynamic types are callable, and the return type is the same dynamic type
|
||||||
Type::Dynamic(_) => CallOutcome::callable(CallBinding::from_return_ty(self)),
|
Type::Dynamic(_) => CallOutcome::callable(CallBinding::from_return_type(self)),
|
||||||
|
|
||||||
Type::Union(union) => CallOutcome::union(
|
Type::Union(union) => CallOutcome::union(
|
||||||
self,
|
self,
|
||||||
|
@ -2071,7 +2071,7 @@ impl<'db> Type<'db> {
|
||||||
.map(|elem| elem.call(db, arguments)),
|
.map(|elem| elem.call(db, arguments)),
|
||||||
),
|
),
|
||||||
|
|
||||||
Type::Intersection(_) => CallOutcome::callable(CallBinding::from_return_ty(
|
Type::Intersection(_) => CallOutcome::callable(CallBinding::from_return_type(
|
||||||
todo_type!("Type::Intersection.call()"),
|
todo_type!("Type::Intersection.call()"),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
|
@ -2117,7 +2117,7 @@ impl<'db> Type<'db> {
|
||||||
match dunder_iter_result {
|
match dunder_iter_result {
|
||||||
CallDunderResult::CallOutcome(ref call_outcome)
|
CallDunderResult::CallOutcome(ref call_outcome)
|
||||||
| CallDunderResult::PossiblyUnbound(ref call_outcome) => {
|
| CallDunderResult::PossiblyUnbound(ref call_outcome) => {
|
||||||
let Some(iterator_ty) = call_outcome.return_ty(db) else {
|
let Some(iterator_ty) = call_outcome.return_type(db) else {
|
||||||
return IterationOutcome::NotIterable {
|
return IterationOutcome::NotIterable {
|
||||||
not_iterable_ty: self,
|
not_iterable_ty: self,
|
||||||
};
|
};
|
||||||
|
@ -2125,7 +2125,7 @@ impl<'db> Type<'db> {
|
||||||
|
|
||||||
return if let Some(element_ty) = iterator_ty
|
return if let Some(element_ty) = iterator_ty
|
||||||
.call_dunder(db, "__next__", &CallArguments::positional([iterator_ty]))
|
.call_dunder(db, "__next__", &CallArguments::positional([iterator_ty]))
|
||||||
.return_ty(db)
|
.return_type(db)
|
||||||
{
|
{
|
||||||
if matches!(dunder_iter_result, CallDunderResult::PossiblyUnbound(..)) {
|
if matches!(dunder_iter_result, CallDunderResult::PossiblyUnbound(..)) {
|
||||||
IterationOutcome::PossiblyUnboundDunderIter {
|
IterationOutcome::PossiblyUnboundDunderIter {
|
||||||
|
@ -2156,7 +2156,7 @@ impl<'db> Type<'db> {
|
||||||
"__getitem__",
|
"__getitem__",
|
||||||
&CallArguments::positional([self, KnownClass::Int.to_instance(db)]),
|
&CallArguments::positional([self, KnownClass::Int.to_instance(db)]),
|
||||||
)
|
)
|
||||||
.return_ty(db)
|
.return_type(db)
|
||||||
{
|
{
|
||||||
IterationOutcome::Iterable { element_ty }
|
IterationOutcome::Iterable { element_ty }
|
||||||
} else {
|
} else {
|
||||||
|
@ -2262,7 +2262,9 @@ impl<'db> Type<'db> {
|
||||||
Type::Dynamic(_) => Ok(*self),
|
Type::Dynamic(_) => Ok(*self),
|
||||||
// TODO map this to a new `Type::TypeVar` variant
|
// TODO map this to a new `Type::TypeVar` variant
|
||||||
Type::KnownInstance(KnownInstanceType::TypeVar(_)) => Ok(*self),
|
Type::KnownInstance(KnownInstanceType::TypeVar(_)) => Ok(*self),
|
||||||
Type::KnownInstance(KnownInstanceType::TypeAliasType(alias)) => Ok(alias.value_ty(db)),
|
Type::KnownInstance(KnownInstanceType::TypeAliasType(alias)) => {
|
||||||
|
Ok(alias.value_type(db))
|
||||||
|
}
|
||||||
Type::KnownInstance(KnownInstanceType::Never | KnownInstanceType::NoReturn) => {
|
Type::KnownInstance(KnownInstanceType::Never | KnownInstanceType::NoReturn) => {
|
||||||
Ok(Type::Never)
|
Ok(Type::Never)
|
||||||
}
|
}
|
||||||
|
@ -2358,7 +2360,8 @@ impl<'db> Type<'db> {
|
||||||
ClassBase::Dynamic(_) => *self,
|
ClassBase::Dynamic(_) => *self,
|
||||||
ClassBase::Class(class) => SubclassOfType::from(
|
ClassBase::Class(class) => SubclassOfType::from(
|
||||||
db,
|
db,
|
||||||
ClassBase::try_from_ty(db, class.metaclass(db)).unwrap_or(ClassBase::unknown()),
|
ClassBase::try_from_type(db, class.metaclass(db))
|
||||||
|
.unwrap_or(ClassBase::unknown()),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -2367,7 +2370,7 @@ impl<'db> Type<'db> {
|
||||||
// TODO intersections
|
// TODO intersections
|
||||||
Type::Intersection(_) => SubclassOfType::from(
|
Type::Intersection(_) => SubclassOfType::from(
|
||||||
db,
|
db,
|
||||||
ClassBase::try_from_ty(db, todo_type!("Intersection meta-type"))
|
ClassBase::try_from_type(db, todo_type!("Intersection meta-type"))
|
||||||
.expect("Type::Todo should be a valid ClassBase"),
|
.expect("Type::Todo should be a valid ClassBase"),
|
||||||
),
|
),
|
||||||
Type::AlwaysTruthy | Type::AlwaysFalsy => KnownClass::Type.to_instance(db),
|
Type::AlwaysTruthy | Type::AlwaysFalsy => KnownClass::Type.to_instance(db),
|
||||||
|
@ -2491,7 +2494,7 @@ impl<'db> TypeAndQualifiers<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forget about type qualifiers and only return the inner type.
|
/// Forget about type qualifiers and only return the inner type.
|
||||||
pub(crate) fn inner_ty(&self) -> Type<'db> {
|
pub(crate) fn inner_type(&self) -> Type<'db> {
|
||||||
self.inner
|
self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3778,7 +3781,7 @@ impl<'db> Class<'db> {
|
||||||
class_stmt
|
class_stmt
|
||||||
.bases()
|
.bases()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|base_node| definition_expression_ty(db, class_definition, base_node))
|
.map(|base_node| definition_expression_type(db, class_definition, base_node))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3807,7 +3810,7 @@ impl<'db> Class<'db> {
|
||||||
.decorator_list
|
.decorator_list
|
||||||
.iter()
|
.iter()
|
||||||
.map(|decorator_node| {
|
.map(|decorator_node| {
|
||||||
definition_expression_ty(db, class_definition, &decorator_node.expression)
|
definition_expression_type(db, class_definition, &decorator_node.expression)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -3866,7 +3869,7 @@ impl<'db> Class<'db> {
|
||||||
.find_keyword("metaclass")?
|
.find_keyword("metaclass")?
|
||||||
.value;
|
.value;
|
||||||
let class_definition = semantic_index(db, self.file(db)).definition(class_stmt);
|
let class_definition = semantic_index(db, self.file(db)).definition(class_stmt);
|
||||||
let metaclass_ty = definition_expression_ty(db, class_definition, metaclass_node);
|
let metaclass_ty = definition_expression_type(db, class_definition, metaclass_node);
|
||||||
Some(metaclass_ty)
|
Some(metaclass_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3926,7 +3929,7 @@ impl<'db> Class<'db> {
|
||||||
let return_ty = outcomes
|
let return_ty = outcomes
|
||||||
.iter()
|
.iter()
|
||||||
.fold(None, |acc, outcome| {
|
.fold(None, |acc, outcome| {
|
||||||
let ty = outcome.return_ty(db);
|
let ty = outcome.return_type(db);
|
||||||
|
|
||||||
match (acc, ty) {
|
match (acc, ty) {
|
||||||
(acc, None) => {
|
(acc, None) => {
|
||||||
|
@ -3957,7 +3960,7 @@ impl<'db> Class<'db> {
|
||||||
CallOutcome::Callable { binding }
|
CallOutcome::Callable { binding }
|
||||||
| CallOutcome::RevealType { binding, .. }
|
| CallOutcome::RevealType { binding, .. }
|
||||||
| CallOutcome::StaticAssertionError { binding, .. }
|
| CallOutcome::StaticAssertionError { binding, .. }
|
||||||
| CallOutcome::AssertType { binding, .. } => Ok(binding.return_ty()),
|
| CallOutcome::AssertType { binding, .. } => Ok(binding.return_type()),
|
||||||
};
|
};
|
||||||
|
|
||||||
return return_ty_result.map(|ty| ty.to_meta_type(db));
|
return return_ty_result.map(|ty| ty.to_meta_type(db));
|
||||||
|
@ -4110,7 +4113,7 @@ impl<'db> Class<'db> {
|
||||||
}
|
}
|
||||||
Err((declared_ty, _conflicting_declarations)) => {
|
Err((declared_ty, _conflicting_declarations)) => {
|
||||||
// Ignore conflicting declarations
|
// Ignore conflicting declarations
|
||||||
SymbolAndQualifiers(declared_ty.inner_ty().into(), declared_ty.qualifiers())
|
SymbolAndQualifiers(declared_ty.inner_type().into(), declared_ty.qualifiers())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -4176,13 +4179,13 @@ pub struct TypeAliasType<'db> {
|
||||||
#[salsa::tracked]
|
#[salsa::tracked]
|
||||||
impl<'db> TypeAliasType<'db> {
|
impl<'db> TypeAliasType<'db> {
|
||||||
#[salsa::tracked]
|
#[salsa::tracked]
|
||||||
pub fn value_ty(self, db: &'db dyn Db) -> Type<'db> {
|
pub fn value_type(self, db: &'db dyn Db) -> Type<'db> {
|
||||||
let scope = self.rhs_scope(db);
|
let scope = self.rhs_scope(db);
|
||||||
|
|
||||||
let type_alias_stmt_node = scope.node(db).expect_type_alias();
|
let type_alias_stmt_node = scope.node(db).expect_type_alias();
|
||||||
let definition = semantic_index(db, scope.file(db)).definition(type_alias_stmt_node);
|
let definition = semantic_index(db, scope.file(db)).definition(type_alias_stmt_node);
|
||||||
|
|
||||||
definition_expression_ty(db, definition, &type_alias_stmt_node.value)
|
definition_expression_type(db, definition, &type_alias_stmt_node.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,13 +89,13 @@ impl<'db> CallOutcome<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the return type of the call, or `None` if not callable.
|
/// Get the return type of the call, or `None` if not callable.
|
||||||
pub(super) fn return_ty(&self, db: &'db dyn Db) -> Option<Type<'db>> {
|
pub(super) fn return_type(&self, db: &'db dyn Db) -> Option<Type<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Callable { binding } => Some(binding.return_ty()),
|
Self::Callable { binding } => Some(binding.return_type()),
|
||||||
Self::RevealType {
|
Self::RevealType {
|
||||||
binding,
|
binding,
|
||||||
revealed_ty: _,
|
revealed_ty: _,
|
||||||
} => Some(binding.return_ty()),
|
} => Some(binding.return_type()),
|
||||||
Self::NotCallable { not_callable_ty: _ } => None,
|
Self::NotCallable { not_callable_ty: _ } => None,
|
||||||
Self::Union {
|
Self::Union {
|
||||||
outcomes,
|
outcomes,
|
||||||
|
@ -105,7 +105,7 @@ impl<'db> CallOutcome<'db> {
|
||||||
// If all outcomes are NotCallable, we return None; if some outcomes are callable
|
// If all outcomes are NotCallable, we return None; if some outcomes are callable
|
||||||
// and some are not, we return a union including Unknown.
|
// and some are not, we return a union including Unknown.
|
||||||
.fold(None, |acc, outcome| {
|
.fold(None, |acc, outcome| {
|
||||||
let ty = outcome.return_ty(db);
|
let ty = outcome.return_type(db);
|
||||||
match (acc, ty) {
|
match (acc, ty) {
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
(None, Some(ty)) => Some(UnionBuilder::new(db).add(ty)),
|
(None, Some(ty)) => Some(UnionBuilder::new(db).add(ty)),
|
||||||
|
@ -113,12 +113,12 @@ impl<'db> CallOutcome<'db> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(UnionBuilder::build),
|
.map(UnionBuilder::build),
|
||||||
Self::PossiblyUnboundDunderCall { call_outcome, .. } => call_outcome.return_ty(db),
|
Self::PossiblyUnboundDunderCall { call_outcome, .. } => call_outcome.return_type(db),
|
||||||
Self::StaticAssertionError { .. } => Some(Type::none(db)),
|
Self::StaticAssertionError { .. } => Some(Type::none(db)),
|
||||||
Self::AssertType {
|
Self::AssertType {
|
||||||
binding,
|
binding,
|
||||||
asserted_ty: _,
|
asserted_ty: _,
|
||||||
} => Some(binding.return_ty()),
|
} => Some(binding.return_type()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ impl<'db> CallOutcome<'db> {
|
||||||
context: &InferContext<'db>,
|
context: &InferContext<'db>,
|
||||||
node: ast::AnyNodeRef,
|
node: ast::AnyNodeRef,
|
||||||
) -> Type<'db> {
|
) -> Type<'db> {
|
||||||
match self.return_ty_result(context, node) {
|
match self.return_type_result(context, node) {
|
||||||
Ok(return_ty) => return_ty,
|
Ok(return_ty) => return_ty,
|
||||||
Err(NotCallableError::Type {
|
Err(NotCallableError::Type {
|
||||||
not_callable_ty,
|
not_callable_ty,
|
||||||
|
@ -194,7 +194,7 @@ impl<'db> CallOutcome<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the return type of the call as a result.
|
/// Get the return type of the call as a result.
|
||||||
pub(super) fn return_ty_result(
|
pub(super) fn return_type_result(
|
||||||
&self,
|
&self,
|
||||||
context: &InferContext<'db>,
|
context: &InferContext<'db>,
|
||||||
node: ast::AnyNodeRef,
|
node: ast::AnyNodeRef,
|
||||||
|
@ -205,7 +205,7 @@ impl<'db> CallOutcome<'db> {
|
||||||
match self {
|
match self {
|
||||||
Self::Callable { binding } => {
|
Self::Callable { binding } => {
|
||||||
binding.report_diagnostics(context, node);
|
binding.report_diagnostics(context, node);
|
||||||
Ok(binding.return_ty())
|
Ok(binding.return_type())
|
||||||
}
|
}
|
||||||
Self::RevealType {
|
Self::RevealType {
|
||||||
binding,
|
binding,
|
||||||
|
@ -218,7 +218,7 @@ impl<'db> CallOutcome<'db> {
|
||||||
Severity::Info,
|
Severity::Info,
|
||||||
format_args!("Revealed type is `{}`", revealed_ty.display(context.db())),
|
format_args!("Revealed type is `{}`", revealed_ty.display(context.db())),
|
||||||
);
|
);
|
||||||
Ok(binding.return_ty())
|
Ok(binding.return_type())
|
||||||
}
|
}
|
||||||
Self::NotCallable { not_callable_ty } => Err(NotCallableError::Type {
|
Self::NotCallable { not_callable_ty } => Err(NotCallableError::Type {
|
||||||
not_callable_ty: *not_callable_ty,
|
not_callable_ty: *not_callable_ty,
|
||||||
|
@ -230,7 +230,7 @@ impl<'db> CallOutcome<'db> {
|
||||||
} => Err(NotCallableError::PossiblyUnboundDunderCall {
|
} => Err(NotCallableError::PossiblyUnboundDunderCall {
|
||||||
callable_ty: *called_ty,
|
callable_ty: *called_ty,
|
||||||
return_ty: call_outcome
|
return_ty: call_outcome
|
||||||
.return_ty(context.db())
|
.return_type(context.db())
|
||||||
.unwrap_or(Type::unknown()),
|
.unwrap_or(Type::unknown()),
|
||||||
}),
|
}),
|
||||||
Self::Union {
|
Self::Union {
|
||||||
|
@ -251,7 +251,7 @@ impl<'db> CallOutcome<'db> {
|
||||||
revealed_ty: _,
|
revealed_ty: _,
|
||||||
} => {
|
} => {
|
||||||
if revealed {
|
if revealed {
|
||||||
binding.return_ty()
|
binding.return_type()
|
||||||
} else {
|
} else {
|
||||||
revealed = true;
|
revealed = true;
|
||||||
outcome.unwrap_with_diagnostic(context, node)
|
outcome.unwrap_with_diagnostic(context, node)
|
||||||
|
@ -329,8 +329,8 @@ impl<'db> CallOutcome<'db> {
|
||||||
binding,
|
binding,
|
||||||
asserted_ty,
|
asserted_ty,
|
||||||
} => {
|
} => {
|
||||||
let [actual_ty, _asserted] = binding.parameter_tys() else {
|
let [actual_ty, _asserted] = binding.parameter_types() else {
|
||||||
return Ok(binding.return_ty());
|
return Ok(binding.return_type());
|
||||||
};
|
};
|
||||||
|
|
||||||
if !actual_ty.is_gradual_equivalent_to(context.db(), *asserted_ty) {
|
if !actual_ty.is_gradual_equivalent_to(context.db(), *asserted_ty) {
|
||||||
|
@ -345,7 +345,7 @@ impl<'db> CallOutcome<'db> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(binding.return_ty())
|
Ok(binding.return_type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,9 +358,9 @@ pub(super) enum CallDunderResult<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> CallDunderResult<'db> {
|
impl<'db> CallDunderResult<'db> {
|
||||||
pub(super) fn return_ty(&self, db: &'db dyn Db) -> Option<Type<'db>> {
|
pub(super) fn return_type(&self, db: &'db dyn Db) -> Option<Type<'db>> {
|
||||||
match self {
|
match self {
|
||||||
Self::CallOutcome(outcome) => outcome.return_ty(db),
|
Self::CallOutcome(outcome) => outcome.return_type(db),
|
||||||
Self::PossiblyUnbound { .. } => None,
|
Self::PossiblyUnbound { .. } => None,
|
||||||
Self::MethodNotAvailable => None,
|
Self::MethodNotAvailable => None,
|
||||||
}
|
}
|
||||||
|
@ -394,7 +394,7 @@ pub(super) enum NotCallableError<'db> {
|
||||||
|
|
||||||
impl<'db> NotCallableError<'db> {
|
impl<'db> NotCallableError<'db> {
|
||||||
/// The return type that should be used when a call is not callable.
|
/// The return type that should be used when a call is not callable.
|
||||||
pub(super) fn return_ty(&self) -> Type<'db> {
|
pub(super) fn return_type(&self) -> Type<'db> {
|
||||||
match self {
|
match self {
|
||||||
Self::Type { return_ty, .. } => *return_ty,
|
Self::Type { return_ty, .. } => *return_ty,
|
||||||
Self::UnionElement { return_ty, .. } => *return_ty,
|
Self::UnionElement { return_ty, .. } => *return_ty,
|
||||||
|
@ -407,7 +407,7 @@ impl<'db> NotCallableError<'db> {
|
||||||
///
|
///
|
||||||
/// For unions, returns the union type itself, which may contain a mix of callable and
|
/// For unions, returns the union type itself, which may contain a mix of callable and
|
||||||
/// non-callable types.
|
/// non-callable types.
|
||||||
pub(super) fn called_ty(&self) -> Type<'db> {
|
pub(super) fn called_type(&self) -> Type<'db> {
|
||||||
match self {
|
match self {
|
||||||
Self::Type {
|
Self::Type {
|
||||||
not_callable_ty, ..
|
not_callable_ty, ..
|
||||||
|
|
|
@ -73,7 +73,7 @@ pub(crate) fn bind_call<'db>(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(expected_ty) = parameter.annotated_ty() {
|
if let Some(expected_ty) = parameter.annotated_type() {
|
||||||
if !argument_ty.is_assignable_to(db, expected_ty) {
|
if !argument_ty.is_assignable_to(db, expected_ty) {
|
||||||
errors.push(CallBindingError::InvalidArgumentType {
|
errors.push(CallBindingError::InvalidArgumentType {
|
||||||
parameter: ParameterContext::new(parameter, index, positional),
|
parameter: ParameterContext::new(parameter, index, positional),
|
||||||
|
@ -109,7 +109,8 @@ pub(crate) fn bind_call<'db>(
|
||||||
for (index, bound_ty) in parameter_tys.iter().enumerate() {
|
for (index, bound_ty) in parameter_tys.iter().enumerate() {
|
||||||
if bound_ty.is_none() {
|
if bound_ty.is_none() {
|
||||||
let param = ¶meters[index];
|
let param = ¶meters[index];
|
||||||
if param.is_variadic() || param.is_keyword_variadic() || param.default_ty().is_some() {
|
if param.is_variadic() || param.is_keyword_variadic() || param.default_type().is_some()
|
||||||
|
{
|
||||||
// variadic/keywords and defaulted arguments are not required
|
// variadic/keywords and defaulted arguments are not required
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +152,7 @@ pub(crate) struct CallBinding<'db> {
|
||||||
|
|
||||||
impl<'db> CallBinding<'db> {
|
impl<'db> CallBinding<'db> {
|
||||||
// TODO remove this constructor and construct always from `bind_call`
|
// TODO remove this constructor and construct always from `bind_call`
|
||||||
pub(crate) fn from_return_ty(return_ty: Type<'db>) -> Self {
|
pub(crate) fn from_return_type(return_ty: Type<'db>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
callable_ty: None,
|
callable_ty: None,
|
||||||
return_ty,
|
return_ty,
|
||||||
|
@ -160,27 +161,27 @@ impl<'db> CallBinding<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_return_ty(&mut self, return_ty: Type<'db>) {
|
pub(crate) fn set_return_type(&mut self, return_ty: Type<'db>) {
|
||||||
self.return_ty = return_ty;
|
self.return_ty = return_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn return_ty(&self) -> Type<'db> {
|
pub(crate) fn return_type(&self) -> Type<'db> {
|
||||||
self.return_ty
|
self.return_ty
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parameter_tys(&self) -> &[Type<'db>] {
|
pub(crate) fn parameter_types(&self) -> &[Type<'db>] {
|
||||||
&self.parameter_tys
|
&self.parameter_tys
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn one_parameter_ty(&self) -> Option<Type<'db>> {
|
pub(crate) fn one_parameter_type(&self) -> Option<Type<'db>> {
|
||||||
match self.parameter_tys() {
|
match self.parameter_types() {
|
||||||
[ty] => Some(*ty),
|
[ty] => Some(*ty),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn two_parameter_tys(&self) -> Option<(Type<'db>, Type<'db>)> {
|
pub(crate) fn two_parameter_types(&self) -> Option<(Type<'db>, Type<'db>)> {
|
||||||
match self.parameter_tys() {
|
match self.parameter_types() {
|
||||||
[first, second] => Some((*first, *second)),
|
[first, second] => Some((*first, *second)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ impl<'db> ClassBase<'db> {
|
||||||
/// Attempt to resolve `ty` into a `ClassBase`.
|
/// Attempt to resolve `ty` into a `ClassBase`.
|
||||||
///
|
///
|
||||||
/// Return `None` if `ty` is not an acceptable type for a class base.
|
/// Return `None` if `ty` is not an acceptable type for a class base.
|
||||||
pub(super) fn try_from_ty(db: &'db dyn Db, ty: Type<'db>) -> Option<Self> {
|
pub(super) fn try_from_type(db: &'db dyn Db, ty: Type<'db>) -> Option<Self> {
|
||||||
match ty {
|
match ty {
|
||||||
Type::Dynamic(dynamic) => Some(Self::Dynamic(dynamic)),
|
Type::Dynamic(dynamic) => Some(Self::Dynamic(dynamic)),
|
||||||
Type::ClassLiteral(ClassLiteralType { class }) => Some(Self::Class(class)),
|
Type::ClassLiteral(ClassLiteralType { class }) => Some(Self::Class(class)),
|
||||||
|
@ -112,40 +112,40 @@ impl<'db> ClassBase<'db> {
|
||||||
KnownInstanceType::Any => Some(Self::any()),
|
KnownInstanceType::Any => Some(Self::any()),
|
||||||
// TODO: Classes inheriting from `typing.Type` et al. also have `Generic` in their MRO
|
// TODO: Classes inheriting from `typing.Type` et al. also have `Generic` in their MRO
|
||||||
KnownInstanceType::Dict => {
|
KnownInstanceType::Dict => {
|
||||||
Self::try_from_ty(db, KnownClass::Dict.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Dict.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::List => {
|
KnownInstanceType::List => {
|
||||||
Self::try_from_ty(db, KnownClass::List.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::List.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Type => {
|
KnownInstanceType::Type => {
|
||||||
Self::try_from_ty(db, KnownClass::Type.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Type.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Tuple => {
|
KnownInstanceType::Tuple => {
|
||||||
Self::try_from_ty(db, KnownClass::Tuple.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Tuple.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Set => {
|
KnownInstanceType::Set => {
|
||||||
Self::try_from_ty(db, KnownClass::Set.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Set.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::FrozenSet => {
|
KnownInstanceType::FrozenSet => {
|
||||||
Self::try_from_ty(db, KnownClass::FrozenSet.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::FrozenSet.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::ChainMap => {
|
KnownInstanceType::ChainMap => {
|
||||||
Self::try_from_ty(db, KnownClass::ChainMap.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::ChainMap.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Counter => {
|
KnownInstanceType::Counter => {
|
||||||
Self::try_from_ty(db, KnownClass::Counter.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Counter.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::DefaultDict => {
|
KnownInstanceType::DefaultDict => {
|
||||||
Self::try_from_ty(db, KnownClass::DefaultDict.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::DefaultDict.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Deque => {
|
KnownInstanceType::Deque => {
|
||||||
Self::try_from_ty(db, KnownClass::Deque.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::Deque.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::OrderedDict => {
|
KnownInstanceType::OrderedDict => {
|
||||||
Self::try_from_ty(db, KnownClass::OrderedDict.to_class_literal(db))
|
Self::try_from_type(db, KnownClass::OrderedDict.to_class_literal(db))
|
||||||
}
|
}
|
||||||
KnownInstanceType::Callable => {
|
KnownInstanceType::Callable => {
|
||||||
Self::try_from_ty(db, todo_type!("Support for Callable as a base class"))
|
Self::try_from_type(db, todo_type!("Support for Callable as a base class"))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ruff_db::{
|
||||||
use ruff_python_ast::AnyNodeRef;
|
use ruff_python_ast::AnyNodeRef;
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
use super::{binding_ty, KnownFunction, TypeCheckDiagnostic, TypeCheckDiagnostics};
|
use super::{binding_type, KnownFunction, TypeCheckDiagnostic, TypeCheckDiagnostics};
|
||||||
|
|
||||||
use crate::semantic_index::semantic_index;
|
use crate::semantic_index::semantic_index;
|
||||||
use crate::semantic_index::symbol::ScopeId;
|
use crate::semantic_index::symbol::ScopeId;
|
||||||
|
@ -144,7 +144,7 @@ impl<'db> InferContext<'db> {
|
||||||
.ancestor_scopes(scope_id)
|
.ancestor_scopes(scope_id)
|
||||||
.filter_map(|(_, scope)| scope.node().as_function())
|
.filter_map(|(_, scope)| scope.node().as_function())
|
||||||
.filter_map(|function| {
|
.filter_map(|function| {
|
||||||
binding_ty(self.db, index.definition(function)).into_function_literal()
|
binding_type(self.db, index.definition(function)).into_function_literal()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Iterate over all functions and test if any is decorated with `@no_type_check`.
|
// Iterate over all functions and test if any is decorated with `@no_type_check`.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//!
|
//!
|
||||||
//! Scope-level inference is for when we are actually checking a file, and need to check types for
|
//! Scope-level inference is for when we are actually checking a file, and need to check types for
|
||||||
//! everything in that file's scopes, or give a linter access to types of arbitrary expressions
|
//! everything in that file's scopes, or give a linter access to types of arbitrary expressions
|
||||||
//! (via the [`HasTy`](crate::semantic_model::HasTy) trait).
|
//! (via the [`HasType`](crate::semantic_model::HasType) trait).
|
||||||
//!
|
//!
|
||||||
//! Definition-level inference allows us to look up the types of symbols in other scopes (e.g. for
|
//! Definition-level inference allows us to look up the types of symbols in other scopes (e.g. for
|
||||||
//! imports) with the minimum inference necessary, so that if we're looking up one symbol from a
|
//! imports) with the minimum inference necessary, so that if we're looking up one symbol from a
|
||||||
|
@ -269,21 +269,21 @@ impl<'db> TypeInference<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub(crate) fn expression_ty(&self, expression: ScopedExpressionId) -> Type<'db> {
|
pub(crate) fn expression_type(&self, expression: ScopedExpressionId) -> Type<'db> {
|
||||||
self.expressions[&expression]
|
self.expressions[&expression]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn try_expression_ty(&self, expression: ScopedExpressionId) -> Option<Type<'db>> {
|
pub(crate) fn try_expression_type(&self, expression: ScopedExpressionId) -> Option<Type<'db>> {
|
||||||
self.expressions.get(&expression).copied()
|
self.expressions.get(&expression).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub(crate) fn binding_ty(&self, definition: Definition<'db>) -> Type<'db> {
|
pub(crate) fn binding_type(&self, definition: Definition<'db>) -> Type<'db> {
|
||||||
self.bindings[&definition]
|
self.bindings[&definition]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub(crate) fn declaration_ty(&self, definition: Definition<'db>) -> TypeAndQualifiers<'db> {
|
pub(crate) fn declaration_type(&self, definition: Definition<'db>) -> TypeAndQualifiers<'db> {
|
||||||
self.declarations[&definition]
|
self.declarations[&definition]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,9 +460,9 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
/// If the expression is not within this region, or if no type has yet been inferred for
|
/// If the expression is not within this region, or if no type has yet been inferred for
|
||||||
/// this node.
|
/// this node.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn expression_ty(&self, expr: &ast::Expr) -> Type<'db> {
|
fn expression_type(&self, expr: &ast::Expr) -> Type<'db> {
|
||||||
self.types
|
self.types
|
||||||
.expression_ty(expr.scoped_expression_id(self.db(), self.scope()))
|
.expression_type(expr.scoped_expression_id(self.db(), self.scope()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the type of an expression from any scope in the same file.
|
/// Get the type of an expression from any scope in the same file.
|
||||||
|
@ -477,13 +477,15 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
///
|
///
|
||||||
/// Can cause query cycles if the expression is from a different scope and type inference is
|
/// Can cause query cycles if the expression is from a different scope and type inference is
|
||||||
/// already in progress for that scope (further up the stack).
|
/// already in progress for that scope (further up the stack).
|
||||||
fn file_expression_ty(&self, expression: &ast::Expr) -> Type<'db> {
|
fn file_expression_type(&self, expression: &ast::Expr) -> Type<'db> {
|
||||||
let file_scope = self.index.expression_scope_id(expression);
|
let file_scope = self.index.expression_scope_id(expression);
|
||||||
let expr_scope = file_scope.to_scope_id(self.db(), self.file());
|
let expr_scope = file_scope.to_scope_id(self.db(), self.file());
|
||||||
let expr_id = expression.scoped_expression_id(self.db(), expr_scope);
|
let expr_id = expression.scoped_expression_id(self.db(), expr_scope);
|
||||||
match self.region {
|
match self.region {
|
||||||
InferenceRegion::Scope(scope) if scope == expr_scope => self.expression_ty(expression),
|
InferenceRegion::Scope(scope) if scope == expr_scope => {
|
||||||
_ => infer_scope_types(self.db(), expr_scope).expression_ty(expr_id),
|
self.expression_type(expression)
|
||||||
|
}
|
||||||
|
_ => infer_scope_types(self.db(), expr_scope).expression_type(expr_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +567,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
.filter_map(|(definition, ty)| {
|
.filter_map(|(definition, ty)| {
|
||||||
// Filter out class literals that result from imports
|
// Filter out class literals that result from imports
|
||||||
if let DefinitionKind::Class(class) = definition.kind(self.db()) {
|
if let DefinitionKind::Class(class) = definition.kind(self.db()) {
|
||||||
ty.inner_ty()
|
ty.inner_type()
|
||||||
.into_class_literal()
|
.into_class_literal()
|
||||||
.map(|ty| (ty.class, class.node()))
|
.map(|ty| (ty.class, class.node()))
|
||||||
} else {
|
} else {
|
||||||
|
@ -873,7 +875,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
conflicting.display(self.db())
|
conflicting.display(self.db())
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
ty.inner_ty()
|
ty.inner_type()
|
||||||
});
|
});
|
||||||
if !bound_ty.is_assignable_to(self.db(), declared_ty) {
|
if !bound_ty.is_assignable_to(self.db(), declared_ty) {
|
||||||
report_invalid_assignment(&self.context, node, declared_ty, bound_ty);
|
report_invalid_assignment(&self.context, node, declared_ty, bound_ty);
|
||||||
|
@ -897,7 +899,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
let inferred_ty = symbol_from_bindings(self.db(), prior_bindings)
|
let inferred_ty = symbol_from_bindings(self.db(), prior_bindings)
|
||||||
.ignore_possibly_unbound()
|
.ignore_possibly_unbound()
|
||||||
.unwrap_or(Type::Never);
|
.unwrap_or(Type::Never);
|
||||||
let ty = if inferred_ty.is_assignable_to(self.db(), ty.inner_ty()) {
|
let ty = if inferred_ty.is_assignable_to(self.db(), ty.inner_type()) {
|
||||||
ty
|
ty
|
||||||
} else {
|
} else {
|
||||||
self.context.report_lint(
|
self.context.report_lint(
|
||||||
|
@ -905,7 +907,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
node,
|
node,
|
||||||
format_args!(
|
format_args!(
|
||||||
"Cannot declare type `{}` for inferred type `{}`",
|
"Cannot declare type `{}` for inferred type `{}`",
|
||||||
ty.inner_ty().display(self.db()),
|
ty.inner_type().display(self.db()),
|
||||||
inferred_ty.display(self.db())
|
inferred_ty.display(self.db())
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -929,17 +931,17 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
declared_ty,
|
declared_ty,
|
||||||
inferred_ty,
|
inferred_ty,
|
||||||
} => {
|
} => {
|
||||||
if inferred_ty.is_assignable_to(self.db(), declared_ty.inner_ty()) {
|
if inferred_ty.is_assignable_to(self.db(), declared_ty.inner_type()) {
|
||||||
(declared_ty, inferred_ty)
|
(declared_ty, inferred_ty)
|
||||||
} else {
|
} else {
|
||||||
report_invalid_assignment(
|
report_invalid_assignment(
|
||||||
&self.context,
|
&self.context,
|
||||||
node,
|
node,
|
||||||
declared_ty.inner_ty(),
|
declared_ty.inner_type(),
|
||||||
inferred_ty,
|
inferred_ty,
|
||||||
);
|
);
|
||||||
// if the assignment is invalid, fall back to assuming the annotation is correct
|
// if the assignment is invalid, fall back to assuming the annotation is correct
|
||||||
(declared_ty, declared_ty.inner_ty())
|
(declared_ty, declared_ty.inner_type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1229,9 +1231,9 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
} = parameter_with_default;
|
} = parameter_with_default;
|
||||||
let default_ty = default
|
let default_ty = default
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|default| self.file_expression_ty(default));
|
.map(|default| self.file_expression_type(default));
|
||||||
if let Some(annotation) = parameter.annotation.as_ref() {
|
if let Some(annotation) = parameter.annotation.as_ref() {
|
||||||
let declared_ty = self.file_expression_ty(annotation);
|
let declared_ty = self.file_expression_type(annotation);
|
||||||
let declared_and_inferred_ty = if let Some(default_ty) = default_ty {
|
let declared_and_inferred_ty = if let Some(default_ty) = default_ty {
|
||||||
if default_ty.is_assignable_to(self.db(), declared_ty) {
|
if default_ty.is_assignable_to(self.db(), declared_ty) {
|
||||||
DeclaredAndInferredType::MightBeDifferent {
|
DeclaredAndInferredType::MightBeDifferent {
|
||||||
|
@ -1283,7 +1285,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
definition: Definition<'db>,
|
definition: Definition<'db>,
|
||||||
) {
|
) {
|
||||||
if let Some(annotation) = parameter.annotation.as_ref() {
|
if let Some(annotation) = parameter.annotation.as_ref() {
|
||||||
let _annotated_ty = self.file_expression_ty(annotation);
|
let _annotated_ty = self.file_expression_type(annotation);
|
||||||
// TODO `tuple[annotated_ty, ...]`
|
// TODO `tuple[annotated_ty, ...]`
|
||||||
let ty = KnownClass::Tuple.to_instance(self.db());
|
let ty = KnownClass::Tuple.to_instance(self.db());
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
|
@ -1312,7 +1314,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
definition: Definition<'db>,
|
definition: Definition<'db>,
|
||||||
) {
|
) {
|
||||||
if let Some(annotation) = parameter.annotation.as_ref() {
|
if let Some(annotation) = parameter.annotation.as_ref() {
|
||||||
let _annotated_ty = self.file_expression_ty(annotation);
|
let _annotated_ty = self.file_expression_type(annotation);
|
||||||
// TODO `dict[str, annotated_ty]`
|
// TODO `dict[str, annotated_ty]`
|
||||||
let ty = KnownClass::Dict.to_instance(self.db());
|
let ty = KnownClass::Dict.to_instance(self.db());
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
|
@ -1531,7 +1533,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
|
|
||||||
let target_ty = self.infer_context_expression(
|
let target_ty = self.infer_context_expression(
|
||||||
&with_item.context_expr,
|
&with_item.context_expr,
|
||||||
self.expression_ty(&with_item.context_expr),
|
self.expression_type(&with_item.context_expr),
|
||||||
is_async,
|
is_async,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1602,7 +1604,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
|
|
||||||
let target_ty = enter_ty
|
let target_ty = enter_ty
|
||||||
.call(self.db(), &CallArguments::positional([context_expression_ty]))
|
.call(self.db(), &CallArguments::positional([context_expression_ty]))
|
||||||
.return_ty_result(&self.context, context_expression.into())
|
.return_type_result(&self.context, context_expression.into())
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
self.context.report_lint(
|
self.context.report_lint(
|
||||||
&INVALID_CONTEXT_MANAGER,
|
&INVALID_CONTEXT_MANAGER,
|
||||||
|
@ -1611,7 +1613,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
Object of type `{context_expression}` cannot be used with `with` because the method `__enter__` of type `{enter_ty}` is not callable", context_expression = context_expression_ty.display(self.db()), enter_ty = enter_ty.display(self.db())
|
Object of type `{context_expression}` cannot be used with `with` because the method `__enter__` of type `{enter_ty}` is not callable", context_expression = context_expression_ty.display(self.db()), enter_ty = enter_ty.display(self.db())
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
err.return_ty()
|
err.return_type()
|
||||||
});
|
});
|
||||||
|
|
||||||
match exit {
|
match exit {
|
||||||
|
@ -1649,7 +1651,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
Type::none(self.db()),
|
Type::none(self.db()),
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
.return_ty_result(&self.context, context_expression.into())
|
.return_type_result(&self.context, context_expression.into())
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
self.context.report_lint(
|
self.context.report_lint(
|
||||||
|
@ -2081,7 +2083,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle various singletons.
|
// Handle various singletons.
|
||||||
if let Type::Instance(InstanceType { class }) = declared_ty.inner_ty() {
|
if let Type::Instance(InstanceType { class }) = declared_ty.inner_type() {
|
||||||
if class.is_known(self.db(), KnownClass::SpecialForm) {
|
if class.is_known(self.db(), KnownClass::SpecialForm) {
|
||||||
if let Some(name_expr) = target.as_name_expr() {
|
if let Some(name_expr) = target.as_name_expr() {
|
||||||
if let Some(known_instance) = KnownInstanceType::try_from_file_and_name(
|
if let Some(known_instance) = KnownInstanceType::try_from_file_and_name(
|
||||||
|
@ -2098,7 +2100,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
if let Some(value) = value.as_deref() {
|
if let Some(value) = value.as_deref() {
|
||||||
let inferred_ty = self.infer_expression(value);
|
let inferred_ty = self.infer_expression(value);
|
||||||
let inferred_ty = if self.in_stub() && value.is_ellipsis_literal_expr() {
|
let inferred_ty = if self.in_stub() && value.is_ellipsis_literal_expr() {
|
||||||
declared_ty.inner_ty()
|
declared_ty.inner_type()
|
||||||
} else {
|
} else {
|
||||||
inferred_ty
|
inferred_ty
|
||||||
};
|
};
|
||||||
|
@ -2150,7 +2152,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
&CallArguments::positional([target_type, value_type]),
|
&CallArguments::positional([target_type, value_type]),
|
||||||
);
|
);
|
||||||
let augmented_return_ty = match call
|
let augmented_return_ty = match call
|
||||||
.return_ty_result(&self.context, AnyNodeRef::StmtAugAssign(assignment))
|
.return_type_result(&self.context, AnyNodeRef::StmtAugAssign(assignment))
|
||||||
{
|
{
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -2163,7 +2165,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
value_type.display(self.db())
|
value_type.display(self.db())
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
e.return_ty()
|
e.return_type()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2338,7 +2340,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resolve the module being imported.
|
// Resolve the module being imported.
|
||||||
let Some(full_module_ty) = self.module_ty_from_name(&full_module_name) else {
|
let Some(full_module_ty) = self.module_type_from_name(&full_module_name) else {
|
||||||
report_unresolved_module(&self.context, alias, 0, Some(name));
|
report_unresolved_module(&self.context, alias, 0, Some(name));
|
||||||
self.add_unknown_declaration_with_binding(alias.into(), definition);
|
self.add_unknown_declaration_with_binding(alias.into(), definition);
|
||||||
return;
|
return;
|
||||||
|
@ -2354,7 +2356,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
// parent package of that module.
|
// parent package of that module.
|
||||||
let topmost_parent_name =
|
let topmost_parent_name =
|
||||||
ModuleName::new(full_module_name.components().next().unwrap()).unwrap();
|
ModuleName::new(full_module_name.components().next().unwrap()).unwrap();
|
||||||
let Some(topmost_parent_ty) = self.module_ty_from_name(&topmost_parent_name) else {
|
let Some(topmost_parent_ty) = self.module_type_from_name(&topmost_parent_name) else {
|
||||||
self.add_unknown_declaration_with_binding(alias.into(), definition);
|
self.add_unknown_declaration_with_binding(alias.into(), definition);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -2522,7 +2524,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(module_ty) = self.module_ty_from_name(&module_name) else {
|
let Some(module_ty) = self.module_type_from_name(&module_name) else {
|
||||||
report_unresolved_module(&self.context, import_from, *level, module);
|
report_unresolved_module(&self.context, import_from, *level, module);
|
||||||
self.add_unknown_declaration_with_binding(alias.into(), definition);
|
self.add_unknown_declaration_with_binding(alias.into(), definition);
|
||||||
return;
|
return;
|
||||||
|
@ -2571,7 +2573,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
if let Some(submodule_name) = ModuleName::new(name) {
|
if let Some(submodule_name) = ModuleName::new(name) {
|
||||||
let mut full_submodule_name = module_name.clone();
|
let mut full_submodule_name = module_name.clone();
|
||||||
full_submodule_name.extend(&submodule_name);
|
full_submodule_name.extend(&submodule_name);
|
||||||
if let Some(submodule_ty) = self.module_ty_from_name(&full_submodule_name) {
|
if let Some(submodule_ty) = self.module_type_from_name(&full_submodule_name) {
|
||||||
self.add_declaration_with_binding(
|
self.add_declaration_with_binding(
|
||||||
alias.into(),
|
alias.into(),
|
||||||
definition,
|
definition,
|
||||||
|
@ -2600,7 +2602,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn module_ty_from_name(&self, module_name: &ModuleName) -> Option<Type<'db>> {
|
fn module_type_from_name(&self, module_name: &ModuleName) -> Option<Type<'db>> {
|
||||||
resolve_module(self.db(), module_name)
|
resolve_module(self.db(), module_name)
|
||||||
.map(|module| Type::module_literal(self.db(), self.file(), module))
|
.map(|module| Type::module_literal(self.db(), self.file(), module))
|
||||||
}
|
}
|
||||||
|
@ -2679,7 +2681,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
let standalone_expression = self.index.expression(expression);
|
let standalone_expression = self.index.expression(expression);
|
||||||
let types = infer_expression_types(self.db(), standalone_expression);
|
let types = infer_expression_types(self.db(), standalone_expression);
|
||||||
self.extend(types);
|
self.extend(types);
|
||||||
self.expression_ty(expression)
|
self.expression_type(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_expression_impl(&mut self, expression: &ast::Expr) -> Type<'db> {
|
fn infer_expression_impl(&mut self, expression: &ast::Expr) -> Type<'db> {
|
||||||
|
@ -2828,7 +2830,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
collector.ty(self.db())
|
collector.string_type(self.db())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_ellipsis_literal_expression(
|
fn infer_ellipsis_literal_expression(
|
||||||
|
@ -3061,10 +3063,10 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
.parent_scope_id(self.scope().file_scope_id(self.db()))
|
.parent_scope_id(self.scope().file_scope_id(self.db()))
|
||||||
.expect("A comprehension should never be the top-level scope")
|
.expect("A comprehension should never be the top-level scope")
|
||||||
.to_scope_id(self.db(), self.file());
|
.to_scope_id(self.db(), self.file());
|
||||||
result.expression_ty(iterable.scoped_expression_id(self.db(), lookup_scope))
|
result.expression_type(iterable.scoped_expression_id(self.db(), lookup_scope))
|
||||||
} else {
|
} else {
|
||||||
self.extend(result);
|
self.extend(result);
|
||||||
result.expression_ty(iterable.scoped_expression_id(self.db(), self.scope()))
|
result.expression_type(iterable.scoped_expression_id(self.db(), self.scope()))
|
||||||
};
|
};
|
||||||
|
|
||||||
let target_ty = if is_async {
|
let target_ty = if is_async {
|
||||||
|
@ -3089,7 +3091,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
let definition = self.index.definition(named);
|
let definition = self.index.definition(named);
|
||||||
let result = infer_definition_types(self.db(), definition);
|
let result = infer_definition_types(self.db(), definition);
|
||||||
self.extend(result);
|
self.extend(result);
|
||||||
result.binding_ty(definition)
|
result.binding_type(definition)
|
||||||
} else {
|
} else {
|
||||||
// For syntactically invalid targets, we still need to run type inference:
|
// For syntactically invalid targets, we still need to run type inference:
|
||||||
self.infer_expression(&named.target);
|
self.infer_expression(&named.target);
|
||||||
|
@ -3500,7 +3502,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
unary_dunder_method,
|
unary_dunder_method,
|
||||||
&CallArguments::positional([operand_type]),
|
&CallArguments::positional([operand_type]),
|
||||||
) {
|
) {
|
||||||
match call.return_ty_result(&self.context, AnyNodeRef::ExprUnaryOp(unary)) {
|
match call.return_type_result(&self.context, AnyNodeRef::ExprUnaryOp(unary)) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.context.report_lint(
|
self.context.report_lint(
|
||||||
|
@ -3511,7 +3513,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
operand_type.display(self.db()),
|
operand_type.display(self.db()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
e.return_ty()
|
e.return_type()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3760,7 +3762,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
reflected_dunder,
|
reflected_dunder,
|
||||||
&CallArguments::positional([right_ty, left_ty]),
|
&CallArguments::positional([right_ty, left_ty]),
|
||||||
)
|
)
|
||||||
.return_ty(self.db())
|
.return_type(self.db())
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
left_ty
|
left_ty
|
||||||
.call_dunder(
|
.call_dunder(
|
||||||
|
@ -3768,7 +3770,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
op.dunder(),
|
op.dunder(),
|
||||||
&CallArguments::positional([left_ty, right_ty]),
|
&CallArguments::positional([left_ty, right_ty]),
|
||||||
)
|
)
|
||||||
.return_ty(self.db())
|
.return_type(self.db())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3778,7 +3780,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
{
|
{
|
||||||
class_member
|
class_member
|
||||||
.call(self.db(), &CallArguments::positional([left_ty, right_ty]))
|
.call(self.db(), &CallArguments::positional([left_ty, right_ty]))
|
||||||
.return_ty(self.db())
|
.return_type(self.db())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -3792,7 +3794,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
{
|
{
|
||||||
class_member
|
class_member
|
||||||
.call(self.db(), &CallArguments::positional([right_ty, left_ty]))
|
.call(self.db(), &CallArguments::positional([right_ty, left_ty]))
|
||||||
.return_ty(self.db())
|
.return_type(self.db())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -3893,8 +3895,8 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
.tuple_windows::<(_, _)>()
|
.tuple_windows::<(_, _)>()
|
||||||
.zip(ops)
|
.zip(ops)
|
||||||
.map(|((left, right), op)| {
|
.map(|((left, right), op)| {
|
||||||
let left_ty = self.expression_ty(left);
|
let left_ty = self.expression_type(left);
|
||||||
let right_ty = self.expression_ty(right);
|
let right_ty = self.expression_type(right);
|
||||||
|
|
||||||
self.infer_binary_type_comparison(left_ty, *op, right_ty)
|
self.infer_binary_type_comparison(left_ty, *op, right_ty)
|
||||||
.unwrap_or_else(|error| {
|
.unwrap_or_else(|error| {
|
||||||
|
@ -4573,18 +4575,18 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
|
|
||||||
return dunder_getitem_method
|
return dunder_getitem_method
|
||||||
.call(self.db(), &CallArguments::positional([value_ty, slice_ty]))
|
.call(self.db(), &CallArguments::positional([value_ty, slice_ty]))
|
||||||
.return_ty_result(&self.context, value_node.into())
|
.return_type_result(&self.context, value_node.into())
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
self.context.report_lint(
|
self.context.report_lint(
|
||||||
&CALL_NON_CALLABLE,
|
&CALL_NON_CALLABLE,
|
||||||
value_node.into(),
|
value_node.into(),
|
||||||
format_args!(
|
format_args!(
|
||||||
"Method `__getitem__` of type `{}` is not callable on object of type `{}`",
|
"Method `__getitem__` of type `{}` is not callable on object of type `{}`",
|
||||||
err.called_ty().display(self.db()),
|
err.called_type().display(self.db()),
|
||||||
value_ty.display(self.db()),
|
value_ty.display(self.db()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
err.return_ty()
|
err.return_type()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4618,18 +4620,18 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
|
|
||||||
return ty
|
return ty
|
||||||
.call(self.db(), &CallArguments::positional([value_ty, slice_ty]))
|
.call(self.db(), &CallArguments::positional([value_ty, slice_ty]))
|
||||||
.return_ty_result(&self.context, value_node.into())
|
.return_type_result(&self.context, value_node.into())
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
self.context.report_lint(
|
self.context.report_lint(
|
||||||
&CALL_NON_CALLABLE,
|
&CALL_NON_CALLABLE,
|
||||||
value_node.into(),
|
value_node.into(),
|
||||||
format_args!(
|
format_args!(
|
||||||
"Method `__class_getitem__` of type `{}` is not callable on object of type `{}`",
|
"Method `__class_getitem__` of type `{}` is not callable on object of type `{}`",
|
||||||
err.called_ty().display(self.db()),
|
err.called_type().display(self.db()),
|
||||||
value_ty.display(self.db()),
|
value_ty.display(self.db()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
err.return_ty()
|
err.return_type()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4837,7 +4839,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
let inner_annotation_ty =
|
let inner_annotation_ty =
|
||||||
self.infer_annotation_expression_impl(inner_annotation);
|
self.infer_annotation_expression_impl(inner_annotation);
|
||||||
|
|
||||||
self.store_expression_type(slice, inner_annotation_ty.inner_ty());
|
self.store_expression_type(slice, inner_annotation_ty.inner_type());
|
||||||
inner_annotation_ty
|
inner_annotation_ty
|
||||||
} else {
|
} else {
|
||||||
self.infer_type_expression(slice);
|
self.infer_type_expression(slice);
|
||||||
|
@ -4892,7 +4894,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
type_expr => self.infer_type_expression_no_store(type_expr).into(),
|
type_expr => self.infer_type_expression_no_store(type_expr).into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.store_expression_type(annotation, annotation_ty.inner_ty());
|
self.store_expression_type(annotation, annotation_ty.inner_type());
|
||||||
|
|
||||||
annotation_ty
|
annotation_ty
|
||||||
}
|
}
|
||||||
|
@ -5831,7 +5833,7 @@ impl StringPartsCollector {
|
||||||
self.expression = true;
|
self.expression = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty(self, db: &dyn Db) -> Type {
|
fn string_type(self, db: &dyn Db) -> Type {
|
||||||
if self.expression {
|
if self.expression {
|
||||||
KnownClass::Str.to_instance(db)
|
KnownClass::Str.to_instance(db)
|
||||||
} else if let Some(concatenated) = self.concatenated {
|
} else if let Some(concatenated) = self.concatenated {
|
||||||
|
@ -5867,7 +5869,7 @@ fn perform_rich_comparison<'db>(
|
||||||
db,
|
db,
|
||||||
&CallArguments::positional([Type::Instance(left), Type::Instance(right)]),
|
&CallArguments::positional([Type::Instance(left), Type::Instance(right)]),
|
||||||
)
|
)
|
||||||
.return_ty(db),
|
.return_type(db),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -5914,7 +5916,7 @@ fn perform_membership_test_comparison<'db>(
|
||||||
db,
|
db,
|
||||||
&CallArguments::positional([Type::Instance(right), Type::Instance(left)]),
|
&CallArguments::positional([Type::Instance(right), Type::Instance(left)]),
|
||||||
)
|
)
|
||||||
.return_ty(db)
|
.return_type(db)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// iteration-based membership test
|
// iteration-based membership test
|
||||||
|
@ -5951,7 +5953,7 @@ mod tests {
|
||||||
use crate::semantic_index::symbol::FileScopeId;
|
use crate::semantic_index::symbol::FileScopeId;
|
||||||
use crate::semantic_index::{global_scope, semantic_index, symbol_table, use_def_map};
|
use crate::semantic_index::{global_scope, semantic_index, symbol_table, use_def_map};
|
||||||
use crate::types::check_types;
|
use crate::types::check_types;
|
||||||
use crate::{HasTy, SemanticModel};
|
use crate::{HasType, SemanticModel};
|
||||||
use ruff_db::files::{system_path_to_file, File};
|
use ruff_db::files::{system_path_to_file, File};
|
||||||
use ruff_db::parsed::parsed_module;
|
use ruff_db::parsed::parsed_module;
|
||||||
use ruff_db::system::DbWithTestSystem;
|
use ruff_db::system::DbWithTestSystem;
|
||||||
|
@ -5960,7 +5962,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn assert_public_ty(db: &TestDb, file_name: &str, symbol_name: &str, expected: &str) {
|
fn assert_public_type(db: &TestDb, file_name: &str, symbol_name: &str, expected: &str) {
|
||||||
let file = system_path_to_file(db, file_name).expect("file to exist");
|
let file = system_path_to_file(db, file_name).expect("file to exist");
|
||||||
|
|
||||||
let ty = global_symbol(db, file, symbol_name).expect_type();
|
let ty = global_symbol(db, file, symbol_name).expect_type();
|
||||||
|
@ -5996,7 +5998,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn assert_scope_ty(
|
fn assert_scope_type(
|
||||||
db: &TestDb,
|
db: &TestDb,
|
||||||
file_name: &str,
|
file_name: &str,
|
||||||
scopes: &[&str],
|
scopes: &[&str],
|
||||||
|
@ -6062,11 +6064,11 @@ mod tests {
|
||||||
);
|
);
|
||||||
db.write_dedented("src/a.py", &content)?;
|
db.write_dedented("src/a.py", &content)?;
|
||||||
|
|
||||||
assert_public_ty(&db, "src/a.py", "v", "bool");
|
assert_public_type(&db, "src/a.py", "v", "bool");
|
||||||
assert_public_ty(&db, "src/a.py", "w", "bool");
|
assert_public_type(&db, "src/a.py", "w", "bool");
|
||||||
assert_public_ty(&db, "src/a.py", "x", "bool");
|
assert_public_type(&db, "src/a.py", "x", "bool");
|
||||||
assert_public_ty(&db, "src/a.py", "z", "Literal[True]");
|
assert_public_type(&db, "src/a.py", "z", "Literal[True]");
|
||||||
assert_public_ty(&db, "src/a.py", "u", "Literal[True]");
|
assert_public_type(&db, "src/a.py", "u", "Literal[True]");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6091,9 +6093,9 @@ mod tests {
|
||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
assert_public_ty(&db, "src/a.py", "w", r#"Literal["hellohello"]"#);
|
assert_public_type(&db, "src/a.py", "w", r#"Literal["hellohello"]"#);
|
||||||
assert_public_ty(&db, "src/a.py", "x", r#"Literal["goodbyegoodbyegoodbye"]"#);
|
assert_public_type(&db, "src/a.py", "x", r#"Literal["goodbyegoodbyegoodbye"]"#);
|
||||||
assert_public_ty(
|
assert_public_type(
|
||||||
&db,
|
&db,
|
||||||
"src/a.py",
|
"src/a.py",
|
||||||
"y",
|
"y",
|
||||||
|
@ -6102,9 +6104,9 @@ mod tests {
|
||||||
"a".repeat(TypeInferenceBuilder::MAX_STRING_LITERAL_SIZE)
|
"a".repeat(TypeInferenceBuilder::MAX_STRING_LITERAL_SIZE)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
assert_public_ty(&db, "src/a.py", "z", "LiteralString");
|
assert_public_type(&db, "src/a.py", "z", "LiteralString");
|
||||||
assert_public_ty(&db, "src/a.py", "a", r#"Literal[""]"#);
|
assert_public_type(&db, "src/a.py", "a", r#"Literal[""]"#);
|
||||||
assert_public_ty(&db, "src/a.py", "b", r#"Literal[""]"#);
|
assert_public_type(&db, "src/a.py", "b", r#"Literal[""]"#);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6124,11 +6126,11 @@ mod tests {
|
||||||
);
|
);
|
||||||
db.write_dedented("src/a.py", &content)?;
|
db.write_dedented("src/a.py", &content)?;
|
||||||
|
|
||||||
assert_public_ty(&db, "src/a.py", "v", "LiteralString");
|
assert_public_type(&db, "src/a.py", "v", "LiteralString");
|
||||||
assert_public_ty(&db, "src/a.py", "w", "LiteralString");
|
assert_public_type(&db, "src/a.py", "w", "LiteralString");
|
||||||
assert_public_ty(&db, "src/a.py", "x", "LiteralString");
|
assert_public_type(&db, "src/a.py", "x", "LiteralString");
|
||||||
assert_public_ty(&db, "src/a.py", "z", r#"Literal[""]"#);
|
assert_public_type(&db, "src/a.py", "z", r#"Literal[""]"#);
|
||||||
assert_public_ty(&db, "src/a.py", "u", r#"Literal[""]"#);
|
assert_public_type(&db, "src/a.py", "u", r#"Literal[""]"#);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6145,8 +6147,8 @@ mod tests {
|
||||||
);
|
);
|
||||||
db.write_dedented("src/a.py", &content)?;
|
db.write_dedented("src/a.py", &content)?;
|
||||||
|
|
||||||
assert_public_ty(&db, "src/a.py", "w", "LiteralString");
|
assert_public_type(&db, "src/a.py", "w", "LiteralString");
|
||||||
assert_public_ty(&db, "src/a.py", "x", "LiteralString");
|
assert_public_type(&db, "src/a.py", "x", "LiteralString");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6165,10 +6167,10 @@ mod tests {
|
||||||
);
|
);
|
||||||
db.write_dedented("src/a.py", &content)?;
|
db.write_dedented("src/a.py", &content)?;
|
||||||
|
|
||||||
assert_public_ty(&db, "src/a.py", "v", "LiteralString");
|
assert_public_type(&db, "src/a.py", "v", "LiteralString");
|
||||||
assert_public_ty(&db, "src/a.py", "w", "LiteralString");
|
assert_public_type(&db, "src/a.py", "w", "LiteralString");
|
||||||
assert_public_ty(&db, "src/a.py", "x", "LiteralString");
|
assert_public_type(&db, "src/a.py", "x", "LiteralString");
|
||||||
assert_public_ty(&db, "src/a.py", "z", "LiteralString");
|
assert_public_type(&db, "src/a.py", "z", "LiteralString");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6217,7 +6219,7 @@ mod tests {
|
||||||
let statement = parsed.suite().first().unwrap().as_assign_stmt().unwrap();
|
let statement = parsed.suite().first().unwrap().as_assign_stmt().unwrap();
|
||||||
let model = SemanticModel::new(&db, a);
|
let model = SemanticModel::new(&db, a);
|
||||||
|
|
||||||
let literal_ty = statement.value.ty(&model);
|
let literal_ty = statement.value.inferred_type(&model);
|
||||||
|
|
||||||
assert_eq!(format!("{}", literal_ty.display(&db)), "Literal[10]");
|
assert_eq!(format!("{}", literal_ty.display(&db)), "Literal[10]");
|
||||||
|
|
||||||
|
@ -6230,7 +6232,7 @@ mod tests {
|
||||||
|
|
||||||
db.write_file("/src/a.py", "c = chr")?;
|
db.write_file("/src/a.py", "c = chr")?;
|
||||||
|
|
||||||
assert_public_ty(&db, "/src/a.py", "c", "Literal[chr]");
|
assert_public_type(&db, "/src/a.py", "c", "Literal[chr]");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6247,7 +6249,7 @@ mod tests {
|
||||||
.with_file("/typeshed/stdlib/VERSIONS", "builtins: 3.8-")
|
.with_file("/typeshed/stdlib/VERSIONS", "builtins: 3.8-")
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
assert_public_ty(&db, "/src/a.py", "c", "Literal[copyright]");
|
assert_public_type(&db, "/src/a.py", "c", "Literal[copyright]");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6261,7 +6263,7 @@ mod tests {
|
||||||
.with_file("/typeshed/stdlib/VERSIONS", "builtins: 3.8-")
|
.with_file("/typeshed/stdlib/VERSIONS", "builtins: 3.8-")
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
assert_public_ty(&db, "/src/a.py", "x", "Unknown");
|
assert_public_type(&db, "/src/a.py", "x", "Unknown");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6270,7 +6272,7 @@ mod tests {
|
||||||
fn str_builtin() -> anyhow::Result<()> {
|
fn str_builtin() -> anyhow::Result<()> {
|
||||||
let mut db = setup_db();
|
let mut db = setup_db();
|
||||||
db.write_file("/src/a.py", "x = str")?;
|
db.write_file("/src/a.py", "x = str")?;
|
||||||
assert_public_ty(&db, "/src/a.py", "x", "Literal[str]");
|
assert_public_type(&db, "/src/a.py", "x", "Literal[str]");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6303,7 +6305,7 @@ mod tests {
|
||||||
foo = get_foo()
|
foo = get_foo()
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
assert_public_ty(&db, "/src/stub.pyi", "foo", "Foo");
|
assert_public_type(&db, "/src/stub.pyi", "foo", "Foo");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6323,7 +6325,7 @@ mod tests {
|
||||||
foo = get_foo()
|
foo = get_foo()
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
assert_public_ty(&db, "/src/source.py", "foo", "Unknown");
|
assert_public_type(&db, "/src/source.py", "foo", "Unknown");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6342,7 +6344,7 @@ mod tests {
|
||||||
foo = get_foo()
|
foo = get_foo()
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
assert_public_ty(&db, "/src/source_with_future.py", "foo", "Foo");
|
assert_public_type(&db, "/src/source_with_future.py", "foo", "Foo");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6375,8 +6377,8 @@ mod tests {
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<listcomp>"], "x", "int");
|
assert_scope_type(&db, "src/a.py", &["foo", "<listcomp>"], "x", "int");
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<listcomp>"], "y", "IntIterable");
|
assert_scope_type(&db, "src/a.py", &["foo", "<listcomp>"], "y", "IntIterable");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6404,14 +6406,14 @@ mod tests {
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
assert_scope_ty(
|
assert_scope_type(
|
||||||
&db,
|
&db,
|
||||||
"src/a.py",
|
"src/a.py",
|
||||||
&["foo", "<listcomp>", "<listcomp>"],
|
&["foo", "<listcomp>", "<listcomp>"],
|
||||||
"x",
|
"x",
|
||||||
"int",
|
"int",
|
||||||
);
|
);
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<listcomp>"], "y", "int");
|
assert_scope_type(&db, "src/a.py", &["foo", "<listcomp>"], "y", "int");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6446,14 +6448,14 @@ mod tests {
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
assert_scope_ty(
|
assert_scope_type(
|
||||||
&db,
|
&db,
|
||||||
"src/a.py",
|
"src/a.py",
|
||||||
&["foo", "<listcomp>", "<listcomp>"],
|
&["foo", "<listcomp>", "<listcomp>"],
|
||||||
"x",
|
"x",
|
||||||
"int",
|
"int",
|
||||||
);
|
);
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<listcomp>"], "y", "IntIterable");
|
assert_scope_type(&db, "src/a.py", &["foo", "<listcomp>"], "y", "IntIterable");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -6468,7 +6470,7 @@ mod tests {
|
||||||
assert!(x.is_unbound());
|
assert!(x.is_unbound());
|
||||||
|
|
||||||
// Iterating over an unbound iterable yields `Unknown`:
|
// Iterating over an unbound iterable yields `Unknown`:
|
||||||
assert_scope_ty(&db, "src/a.py", &["<listcomp>"], "z", "Unknown");
|
assert_scope_type(&db, "src/a.py", &["<listcomp>"], "z", "Unknown");
|
||||||
|
|
||||||
assert_file_diagnostics(&db, "src/a.py", &["Name `x` used when not defined"]);
|
assert_file_diagnostics(&db, "src/a.py", &["Name `x` used when not defined"]);
|
||||||
|
|
||||||
|
@ -6495,8 +6497,8 @@ mod tests {
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<listcomp>"], "x", "int");
|
assert_scope_type(&db, "src/a.py", &["foo", "<listcomp>"], "x", "int");
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<listcomp>"], "z", "Unknown");
|
assert_scope_type(&db, "src/a.py", &["foo", "<listcomp>"], "z", "Unknown");
|
||||||
assert_file_diagnostics(&db, "src/a.py", &["Object of type `int` is not iterable"]);
|
assert_file_diagnostics(&db, "src/a.py", &["Object of type `int` is not iterable"]);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -6522,7 +6524,7 @@ mod tests {
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<dictcomp>"], "x", "int");
|
assert_scope_type(&db, "src/a.py", &["foo", "<dictcomp>"], "x", "int");
|
||||||
assert_file_diagnostics(&db, "src/a.py", &[]);
|
assert_file_diagnostics(&db, "src/a.py", &[]);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -6548,7 +6550,7 @@ mod tests {
|
||||||
",
|
",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<dictcomp>"], "x", "int");
|
assert_scope_type(&db, "src/a.py", &["foo", "<dictcomp>"], "x", "int");
|
||||||
assert_file_diagnostics(&db, "src/a.py", &[]);
|
assert_file_diagnostics(&db, "src/a.py", &[]);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -6577,7 +6579,7 @@ mod tests {
|
||||||
// We'll emit a diagnostic separately for invalid syntax,
|
// We'll emit a diagnostic separately for invalid syntax,
|
||||||
// but it's reasonably clear here what they *meant* to write,
|
// but it's reasonably clear here what they *meant* to write,
|
||||||
// so we'll still infer the correct type:
|
// so we'll still infer the correct type:
|
||||||
assert_scope_ty(&db, "src/a.py", &["foo", "<listcomp>"], "z", "int");
|
assert_scope_type(&db, "src/a.py", &["foo", "<listcomp>"], "z", "int");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6614,7 +6616,7 @@ mod tests {
|
||||||
fn comprehension_with_missing_for() -> anyhow::Result<()> {
|
fn comprehension_with_missing_for() -> anyhow::Result<()> {
|
||||||
let mut db = setup_db();
|
let mut db = setup_db();
|
||||||
db.write_dedented("src/a.py", "[z for z in]")?;
|
db.write_dedented("src/a.py", "[z for z in]")?;
|
||||||
assert_scope_ty(&db, "src/a.py", &["<listcomp>"], "z", "Unknown");
|
assert_scope_type(&db, "src/a.py", &["<listcomp>"], "z", "Unknown");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6622,7 +6624,7 @@ mod tests {
|
||||||
fn comprehension_with_missing_in_keyword_and_missing_iter() -> anyhow::Result<()> {
|
fn comprehension_with_missing_in_keyword_and_missing_iter() -> anyhow::Result<()> {
|
||||||
let mut db = setup_db();
|
let mut db = setup_db();
|
||||||
db.write_dedented("src/a.py", "[z for z]")?;
|
db.write_dedented("src/a.py", "[z for z]")?;
|
||||||
assert_scope_ty(&db, "src/a.py", &["<listcomp>"], "z", "Unknown");
|
assert_scope_type(&db, "src/a.py", &["<listcomp>"], "z", "Unknown");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6648,7 +6650,7 @@ mod tests {
|
||||||
|
|
||||||
// We currently return `Todo` for all async comprehensions,
|
// We currently return `Todo` for all async comprehensions,
|
||||||
// including comprehensions that have invalid syntax
|
// including comprehensions that have invalid syntax
|
||||||
assert_scope_ty(
|
assert_scope_type(
|
||||||
&db,
|
&db,
|
||||||
"src/a.py",
|
"src/a.py",
|
||||||
&["foo", "<listcomp>"],
|
&["foo", "<listcomp>"],
|
||||||
|
@ -6682,7 +6684,7 @@ mod tests {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// TODO async iterables/iterators! --Alex
|
// TODO async iterables/iterators! --Alex
|
||||||
assert_scope_ty(
|
assert_scope_type(
|
||||||
&db,
|
&db,
|
||||||
"src/a.py",
|
"src/a.py",
|
||||||
&["foo", "<listcomp>"],
|
&["foo", "<listcomp>"],
|
||||||
|
|
|
@ -76,7 +76,7 @@ impl<'db> Mro<'db> {
|
||||||
// This *could* theoretically be handled by the final branch below,
|
// This *could* theoretically be handled by the final branch below,
|
||||||
// but it's a common case (i.e., worth optimizing for),
|
// but it's a common case (i.e., worth optimizing for),
|
||||||
// and the `c3_merge` function requires lots of allocations.
|
// and the `c3_merge` function requires lots of allocations.
|
||||||
[single_base] => ClassBase::try_from_ty(db, *single_base).map_or_else(
|
[single_base] => ClassBase::try_from_type(db, *single_base).map_or_else(
|
||||||
|| Err(MroErrorKind::InvalidBases(Box::from([(0, *single_base)]))),
|
|| Err(MroErrorKind::InvalidBases(Box::from([(0, *single_base)]))),
|
||||||
|single_base| {
|
|single_base| {
|
||||||
Ok(std::iter::once(ClassBase::Class(class))
|
Ok(std::iter::once(ClassBase::Class(class))
|
||||||
|
@ -95,7 +95,7 @@ impl<'db> Mro<'db> {
|
||||||
let mut invalid_bases = vec![];
|
let mut invalid_bases = vec![];
|
||||||
|
|
||||||
for (i, base) in multiple_bases.iter().enumerate() {
|
for (i, base) in multiple_bases.iter().enumerate() {
|
||||||
match ClassBase::try_from_ty(db, *base) {
|
match ClassBase::try_from_type(db, *base) {
|
||||||
Some(valid_base) => valid_bases.push(valid_base),
|
Some(valid_base) => valid_bases.push(valid_base),
|
||||||
None => invalid_bases.push((i, *base)),
|
None => invalid_bases.push((i, *base)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,9 +322,9 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
|
||||||
|
|
||||||
for (op, (left, right)) in std::iter::zip(&**ops, comparator_tuples) {
|
for (op, (left, right)) in std::iter::zip(&**ops, comparator_tuples) {
|
||||||
let lhs_ty = last_rhs_ty.unwrap_or_else(|| {
|
let lhs_ty = last_rhs_ty.unwrap_or_else(|| {
|
||||||
inference.expression_ty(left.scoped_expression_id(self.db, scope))
|
inference.expression_type(left.scoped_expression_id(self.db, scope))
|
||||||
});
|
});
|
||||||
let rhs_ty = inference.expression_ty(right.scoped_expression_id(self.db, scope));
|
let rhs_ty = inference.expression_type(right.scoped_expression_id(self.db, scope));
|
||||||
last_rhs_ty = Some(rhs_ty);
|
last_rhs_ty = Some(rhs_ty);
|
||||||
|
|
||||||
match left {
|
match left {
|
||||||
|
@ -393,7 +393,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let callable_ty =
|
let callable_ty =
|
||||||
inference.expression_ty(callable.scoped_expression_id(self.db, scope));
|
inference.expression_type(callable.scoped_expression_id(self.db, scope));
|
||||||
|
|
||||||
if callable_ty
|
if callable_ty
|
||||||
.into_class_literal()
|
.into_class_literal()
|
||||||
|
@ -422,7 +422,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
|
||||||
let inference = infer_expression_types(self.db, expression);
|
let inference = infer_expression_types(self.db, expression);
|
||||||
|
|
||||||
let callable_ty =
|
let callable_ty =
|
||||||
inference.expression_ty(expr_call.func.scoped_expression_id(self.db, scope));
|
inference.expression_type(expr_call.func.scoped_expression_id(self.db, scope));
|
||||||
|
|
||||||
// TODO: add support for PEP 604 union types on the right hand side of `isinstance`
|
// TODO: add support for PEP 604 union types on the right hand side of `isinstance`
|
||||||
// and `issubclass`, for example `isinstance(x, str | (int | float))`.
|
// and `issubclass`, for example `isinstance(x, str | (int | float))`.
|
||||||
|
@ -441,7 +441,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
|
||||||
let symbol = self.symbols().symbol_id_by_name(id).unwrap();
|
let symbol = self.symbols().symbol_id_by_name(id).unwrap();
|
||||||
|
|
||||||
let class_info_ty =
|
let class_info_ty =
|
||||||
inference.expression_ty(class_info.scoped_expression_id(self.db, scope));
|
inference.expression_type(class_info.scoped_expression_id(self.db, scope));
|
||||||
|
|
||||||
function
|
function
|
||||||
.generate_constraint(self.db, class_info_ty)
|
.generate_constraint(self.db, class_info_ty)
|
||||||
|
@ -500,7 +500,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
|
||||||
let scope = self.scope();
|
let scope = self.scope();
|
||||||
let inference = infer_expression_types(self.db, cls);
|
let inference = infer_expression_types(self.db, cls);
|
||||||
let ty = inference
|
let ty = inference
|
||||||
.expression_ty(cls.node_ref(self.db).scoped_expression_id(self.db, scope))
|
.expression_type(cls.node_ref(self.db).scoped_expression_id(self.db, scope))
|
||||||
.to_instance(self.db);
|
.to_instance(self.db);
|
||||||
let mut constraints = NarrowingConstraints::default();
|
let mut constraints = NarrowingConstraints::default();
|
||||||
constraints.insert(symbol, ty);
|
constraints.insert(symbol, ty);
|
||||||
|
@ -524,7 +524,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
|
||||||
// filter our arms with statically known truthiness
|
// filter our arms with statically known truthiness
|
||||||
.filter(|expr| {
|
.filter(|expr| {
|
||||||
inference
|
inference
|
||||||
.expression_ty(expr.scoped_expression_id(self.db, scope))
|
.expression_type(expr.scoped_expression_id(self.db, scope))
|
||||||
.bool(self.db)
|
.bool(self.db)
|
||||||
!= match expr_bool_op.op {
|
!= match expr_bool_op.op {
|
||||||
BoolOp::And => Truthiness::AlwaysTrue,
|
BoolOp::And => Truthiness::AlwaysTrue,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{definition_expression_ty, Type};
|
use super::{definition_expression_type, Type};
|
||||||
use crate::Db;
|
use crate::Db;
|
||||||
use crate::{semantic_index::definition::Definition, types::todo_type};
|
use crate::{semantic_index::definition::Definition, types::todo_type};
|
||||||
use ruff_python_ast::{self as ast, name::Name};
|
use ruff_python_ast::{self as ast, name::Name};
|
||||||
|
@ -39,7 +39,7 @@ impl<'db> Signature<'db> {
|
||||||
if function_node.is_async {
|
if function_node.is_async {
|
||||||
todo_type!("generic types.CoroutineType")
|
todo_type!("generic types.CoroutineType")
|
||||||
} else {
|
} else {
|
||||||
definition_expression_ty(db, definition, returns.as_ref())
|
definition_expression_type(db, definition, returns.as_ref())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ impl<'db> Parameters<'db> {
|
||||||
parameter_with_default
|
parameter_with_default
|
||||||
.default
|
.default
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|default| definition_expression_ty(db, definition, default))
|
.map(|default| definition_expression_type(db, definition, default))
|
||||||
};
|
};
|
||||||
let positional_only = posonlyargs.iter().map(|arg| {
|
let positional_only = posonlyargs.iter().map(|arg| {
|
||||||
Parameter::from_node_and_kind(
|
Parameter::from_node_and_kind(
|
||||||
|
@ -245,7 +245,7 @@ impl<'db> Parameter<'db> {
|
||||||
annotated_ty: parameter
|
annotated_ty: parameter
|
||||||
.annotation
|
.annotation
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|annotation| definition_expression_ty(db, definition, annotation)),
|
.map(|annotation| definition_expression_type(db, definition, annotation)),
|
||||||
kind,
|
kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ impl<'db> Parameter<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Annotated type of the parameter, if annotated.
|
/// Annotated type of the parameter, if annotated.
|
||||||
pub(crate) fn annotated_ty(&self) -> Option<Type<'db>> {
|
pub(crate) fn annotated_type(&self) -> Option<Type<'db>> {
|
||||||
self.annotated_ty
|
self.annotated_ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ impl<'db> Parameter<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default-value type of the parameter, if any.
|
/// Default-value type of the parameter, if any.
|
||||||
pub(crate) fn default_ty(&self) -> Option<Type<'db>> {
|
pub(crate) fn default_type(&self) -> Option<Type<'db>> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ParameterKind::PositionalOnly { default_ty } => default_ty,
|
ParameterKind::PositionalOnly { default_ty } => default_ty,
|
||||||
ParameterKind::PositionalOrKeyword { default_ty } => default_ty,
|
ParameterKind::PositionalOrKeyword { default_ty } => default_ty,
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl<'db> Unpacker<'db> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut value_ty = infer_expression_types(self.db(), value.expression())
|
let mut value_ty = infer_expression_types(self.db(), value.expression())
|
||||||
.expression_ty(value.scoped_expression_id(self.db(), self.scope));
|
.expression_type(value.scoped_expression_id(self.db(), self.scope));
|
||||||
|
|
||||||
if value.is_assign()
|
if value.is_assign()
|
||||||
&& self.context.in_stub()
|
&& self.context.in_stub()
|
||||||
|
|
|
@ -294,8 +294,8 @@ impl<'db> VisibilityConstraints<'db> {
|
||||||
ConstraintNode::Expression(test_expr) => {
|
ConstraintNode::Expression(test_expr) => {
|
||||||
let inference = infer_expression_types(db, test_expr);
|
let inference = infer_expression_types(db, test_expr);
|
||||||
let scope = test_expr.scope(db);
|
let scope = test_expr.scope(db);
|
||||||
let ty =
|
let ty = inference
|
||||||
inference.expression_ty(test_expr.node_ref(db).scoped_expression_id(db, scope));
|
.expression_type(test_expr.node_ref(db).scoped_expression_id(db, scope));
|
||||||
|
|
||||||
ty.bool(db).negate_if(!constraint.is_positive)
|
ty.bool(db).negate_if(!constraint.is_positive)
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,7 @@ impl<'db> VisibilityConstraints<'db> {
|
||||||
let subject_expression = inner.subject(db);
|
let subject_expression = inner.subject(db);
|
||||||
let inference = infer_expression_types(db, *subject_expression);
|
let inference = infer_expression_types(db, *subject_expression);
|
||||||
let scope = subject_expression.scope(db);
|
let scope = subject_expression.scope(db);
|
||||||
let subject_ty = inference.expression_ty(
|
let subject_ty = inference.expression_type(
|
||||||
subject_expression
|
subject_expression
|
||||||
.node_ref(db)
|
.node_ref(db)
|
||||||
.scoped_expression_id(db, scope),
|
.scoped_expression_id(db, scope),
|
||||||
|
@ -312,8 +312,8 @@ impl<'db> VisibilityConstraints<'db> {
|
||||||
|
|
||||||
let inference = infer_expression_types(db, *value);
|
let inference = infer_expression_types(db, *value);
|
||||||
let scope = value.scope(db);
|
let scope = value.scope(db);
|
||||||
let value_ty =
|
let value_ty = inference
|
||||||
inference.expression_ty(value.node_ref(db).scoped_expression_id(db, scope));
|
.expression_type(value.node_ref(db).scoped_expression_id(db, scope));
|
||||||
|
|
||||||
if subject_ty.is_single_valued(db) {
|
if subject_ty.is_single_valued(db) {
|
||||||
let truthiness =
|
let truthiness =
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue