Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[red-knot] Add type inference for basic for loops #13195

Merged
merged 5 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Renamings
  • Loading branch information
AlexWaygood committed Sep 4, 2024
commit 6d62ac2d5fbc36296397b2205cd093327f45f7e4
2 changes: 1 addition & 1 deletion crates/red_knot_python_semantic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use python_version::PythonVersion;
pub use semantic_model::{HasTy, SemanticModel};

pub mod ast_node_ref;
mod core_stdlib_modules;
mod stdlib;
mod db;
mod module_name;
mod module_resolver;
Expand Down
14 changes: 7 additions & 7 deletions crates/red_knot_python_semantic/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use ruff_db::files::File;
use ruff_python_ast as ast;

use crate::core_stdlib_modules::{builtins_scope, types_scope, typeshed_scope};
use crate::semantic_index::ast_ids::HasScopedAstId;
use crate::semantic_index::definition::{Definition, DefinitionKind};
use crate::semantic_index::symbol::{ScopeId, ScopedSymbolId};
use crate::semantic_index::{
global_scope, semantic_index, symbol_table, use_def_map, DefinitionWithConstraints,
DefinitionWithConstraintsIterator,
};
use crate::stdlib::{builtins_scope, types_scope, typeshed_scope};
use crate::types::narrow::narrowing_constraint;
use crate::{Db, FxOrderSet};

Expand Down Expand Up @@ -76,8 +76,6 @@ pub(crate) fn global_symbol_ty_by_name<'db>(db: &'db dyn Db, file: File, name: &
}

/// Enumeration of various core stdlib modules, for which we have dedicated Salsa queries.
///
/// Things will start getting very strange during type-checking if one of these doesn't exist.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum CoreStdlibModule {
AlexWaygood marked this conversation as resolved.
Show resolved Hide resolved
Builtins,
Expand Down Expand Up @@ -338,7 +336,7 @@ impl<'db> Type<'db> {
match self {
Type::Unbound => replacement,
Type::Union(union) => {
union.transform(db, |element| element.replace_unbound_with(db, replacement))
union.map(db, |element| element.replace_unbound_with(db, replacement))
}
ty => *ty,
}
Expand Down Expand Up @@ -381,7 +379,7 @@ impl<'db> Type<'db> {
// TODO MRO? get_own_instance_member, get_instance_member
Type::Unknown
}
Type::Union(union) => union.transform(db, |element| element.member(db, name)),
Type::Union(union) => union.map(db, |element| element.member(db, name)),
Type::Intersection(_) => {
// TODO perform the get_member on each type in the intersection
// TODO return the intersection of those results
Expand Down Expand Up @@ -450,12 +448,14 @@ impl<'db> Type<'db> {
// `self` represents the type of the iterable;
// `__iter__` and `__next__` are both looked up on the class of the iterable:
let type_of_class = self.to_type_of_class(db);

let dunder_iter_method = type_of_class.member(db, "__iter__");
if !dunder_iter_method.is_unbound() {
let iterator_ty = dunder_iter_method.call(db)?;
let dunder_next_method = iterator_ty.to_type_of_class(db).member(db, "__next__");
return dunder_next_method.call(db);
}

// Although it's not considered great practice,
// classes that define `__getitem__` are also iterable,
// even if they do not define `__iter__`.
Expand Down Expand Up @@ -484,7 +484,7 @@ impl<'db> Type<'db> {
Type::Unbound => Type::Unbound,
Type::Never => Type::Never,
Type::Instance(class) => Type::Class(*class),
Type::Union(union) => union.transform(db, |ty| ty.to_type_of_class(db)),
Type::Union(union) => union.map(db, |ty| ty.to_type_of_class(db)),
Type::BooleanLiteral(_) => builtins_symbol_ty_by_name(db, "bool"),
Type::BytesLiteral(_) => builtins_symbol_ty_by_name(db, "bytes"),
Type::IntLiteral(_) => builtins_symbol_ty_by_name(db, "int"),
Expand Down Expand Up @@ -624,7 +624,7 @@ impl<'db> UnionType<'db> {

/// Apply a transformation function to all elements of the union,
/// and create a new union from the resulting set of types
pub fn transform(
pub fn map(
AlexWaygood marked this conversation as resolved.
Show resolved Hide resolved
&self,
db: &'db dyn Db,
mut transform_fn: impl FnMut(&Type<'db>) -> Type<'db>,
Expand Down
4 changes: 2 additions & 2 deletions crates/red_knot_python_semantic/src/types/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use ruff_db::parsed::parsed_module;
use ruff_python_ast::{self as ast, AnyNodeRef, ExprContext, UnaryOp};
use ruff_text_size::Ranged;

use crate::core_stdlib_modules::builtins_scope;
use crate::stdlib::builtins_scope;
use crate::module_name::ModuleName;
use crate::module_resolver::{file_to_module, resolve_module};
use crate::semantic_index::ast_ids::{HasScopedAstId, HasScopedUseId, ScopedExpressionId};
Expand Down Expand Up @@ -2378,7 +2378,7 @@ mod tests {
use ruff_db::testing::assert_function_query_was_not_run;
use ruff_python_ast::name::Name;

use crate::core_stdlib_modules::builtins_scope;
use crate::stdlib::builtins_scope;
use crate::db::tests::TestDb;
use crate::program::{Program, SearchPathSettings};
use crate::python_version::PythonVersion;
Expand Down