diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 94ff773413..cafc60b561 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -95,7 +95,8 @@ fn symbol<'db>(db: &'db dyn Db, scope: ScopeId<'db>, name: &str) -> Symbol<'db> // on inference from bindings. let declarations = use_def.public_declarations(symbol); - let declared = declarations_ty(db, declarations).map(|SymbolAndQualifiers(ty, _)| ty); + let declared = + symbol_from_declarations(db, declarations).map(|SymbolAndQualifiers(ty, _)| ty); match declared { // Symbol is declared, trust the declared type @@ -103,7 +104,7 @@ fn symbol<'db>(db: &'db dyn Db, scope: ScopeId<'db>, name: &str) -> Symbol<'db> // Symbol is possibly declared Ok(Symbol::Type(declared_ty, Boundness::PossiblyUnbound)) => { let bindings = use_def.public_bindings(symbol); - let inferred = bindings_ty(db, bindings); + let inferred = symbol_from_bindings(db, bindings); match inferred { // Symbol is possibly undeclared and definitely unbound @@ -123,7 +124,7 @@ fn symbol<'db>(db: &'db dyn Db, scope: ScopeId<'db>, name: &str) -> Symbol<'db> // Symbol is undeclared, return the inferred type Ok(Symbol::Unbound) => { let bindings = use_def.public_bindings(symbol); - bindings_ty(db, bindings) + symbol_from_bindings(db, bindings) } // Symbol is possibly undeclared Err((declared_ty, _)) => { @@ -284,10 +285,11 @@ fn definition_expression_ty<'db>( } } -/// Infer the combined type of an iterator of bindings. +/// Infer the combined type from an iterator of bindings, and return it +/// together with boundness information in a [`Symbol`]. /// -/// Will return a union if there is more than one binding. -fn bindings_ty<'db>( +/// The type will be a union if there are multiple bindings with different types. +fn symbol_from_bindings<'db>( db: &'db dyn Db, bindings_with_constraints: BindingWithConstraintsIterator<'_, 'db>, ) -> Symbol<'db> { @@ -391,8 +393,8 @@ impl<'db> From> for SymbolAndQualifiers<'db> { } } -/// The result of looking up a declared type from declarations; see [`declarations_ty`]. -type DeclaredTypeResult<'db> = +/// The result of looking up a declared type from declarations; see [`symbol_from_declarations`]. +type SymbolFromDeclarationsResult<'db> = Result, (TypeAndQualifiers<'db>, Box<[Type<'db>]>)>; /// Build a declared type from a [`DeclarationsIterator`]. @@ -403,10 +405,10 @@ type DeclaredTypeResult<'db> = /// /// This function also returns declaredness information (see [`Symbol`]) and a set of /// [`TypeQualifiers`] that have been specified on the declaration(s). -fn declarations_ty<'db>( +fn symbol_from_declarations<'db>( db: &'db dyn Db, declarations: DeclarationsIterator<'_, 'db>, -) -> DeclaredTypeResult<'db> { +) -> SymbolFromDeclarationsResult<'db> { let visibility_constraints = declarations.visibility_constraints; let mut declarations = declarations.peekable(); @@ -4098,7 +4100,7 @@ impl<'db> Class<'db> { let declarations = use_def.public_declarations(symbol); - match declarations_ty(db, declarations) { + match symbol_from_declarations(db, declarations) { Ok(SymbolAndQualifiers(Symbol::Type(declared_ty, _), qualifiers)) => { if let Some(function) = declared_ty.into_function_literal() { // TODO: Eventually, we are going to process all decorators correctly. This is @@ -4115,9 +4117,9 @@ impl<'db> Class<'db> { } Ok(SymbolAndQualifiers(Symbol::Unbound, qualifiers)) => { let bindings = use_def.public_bindings(symbol); - let inferred_ty = bindings_ty(db, bindings); + let inferred = symbol_from_bindings(db, bindings); - match inferred_ty { + match inferred { Symbol::Type(ty, _) => SymbolAndQualifiers( Symbol::Type( UnionType::from_elements(db, [Type::unknown(), ty]), diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 576cde3832..9f6fb8b39d 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -62,13 +62,13 @@ use crate::types::diagnostic::{ use crate::types::mro::MroErrorKind; use crate::types::unpacker::{UnpackResult, Unpacker}; use crate::types::{ - bindings_ty, builtins_symbol, declarations_ty, global_symbol, symbol, todo_type, - typing_extensions_symbol, Boundness, CallDunderResult, Class, ClassLiteralType, DynamicType, - FunctionType, InstanceType, IntersectionBuilder, IntersectionType, IterationOutcome, - KnownClass, KnownFunction, KnownInstanceType, MetaclassCandidate, MetaclassErrorKind, - SliceLiteralType, SubclassOfType, Symbol, SymbolAndQualifiers, Truthiness, TupleType, Type, - TypeAliasType, TypeAndQualifiers, TypeArrayDisplay, TypeQualifiers, TypeVarBoundOrConstraints, - TypeVarInstance, UnionBuilder, UnionType, + builtins_symbol, global_symbol, symbol, symbol_from_bindings, symbol_from_declarations, + todo_type, typing_extensions_symbol, Boundness, CallDunderResult, Class, ClassLiteralType, + DynamicType, FunctionType, InstanceType, IntersectionBuilder, IntersectionType, + IterationOutcome, KnownClass, KnownFunction, KnownInstanceType, MetaclassCandidate, + MetaclassErrorKind, SliceLiteralType, SubclassOfType, Symbol, SymbolAndQualifiers, Truthiness, + TupleType, Type, TypeAliasType, TypeAndQualifiers, TypeArrayDisplay, TypeQualifiers, + TypeVarBoundOrConstraints, TypeVarInstance, UnionBuilder, UnionType, }; use crate::unpack::Unpack; use crate::util::subscript::{PyIndex, PySlice}; @@ -859,7 +859,7 @@ impl<'db> TypeInferenceBuilder<'db> { let use_def = self.index.use_def_map(binding.file_scope(self.db())); let declarations = use_def.declarations_at_binding(binding); let mut bound_ty = ty; - let declared_ty = declarations_ty(self.db(), declarations) + let declared_ty = symbol_from_declarations(self.db(), declarations) .map(|SymbolAndQualifiers(s, _)| s.ignore_possibly_unbound().unwrap_or(Type::unknown())) .unwrap_or_else(|(ty, conflicting)| { // TODO point out the conflicting declarations in the diagnostic? @@ -894,7 +894,7 @@ impl<'db> TypeInferenceBuilder<'db> { let use_def = self.index.use_def_map(declaration.file_scope(self.db())); let prior_bindings = use_def.bindings_at_declaration(declaration); // unbound_ty is Never because for this check we don't care about unbound - let inferred_ty = bindings_ty(self.db(), prior_bindings) + let inferred_ty = symbol_from_bindings(self.db(), prior_bindings) .ignore_possibly_unbound() .unwrap_or(Type::Never); let ty = if inferred_ty.is_assignable_to(self.db(), ty.inner_ty()) { @@ -3310,9 +3310,9 @@ impl<'db> TypeInferenceBuilder<'db> { let use_def = self.index.use_def_map(file_scope_id); // If we're inferring types of deferred expressions, always treat them as public symbols - let bindings_ty = if self.is_deferred() { + let inferred = if self.is_deferred() { if let Some(symbol) = self.index.symbol_table(file_scope_id).symbol_id_by_name(id) { - bindings_ty(self.db(), use_def.public_bindings(symbol)) + symbol_from_bindings(self.db(), use_def.public_bindings(symbol)) } else { assert!( self.deferred_state.in_string_annotation(), @@ -3322,10 +3322,10 @@ impl<'db> TypeInferenceBuilder<'db> { } } else { let use_id = name.scoped_use_id(self.db(), self.scope()); - bindings_ty(self.db(), use_def.bindings_at_use(use_id)) + symbol_from_bindings(self.db(), use_def.bindings_at_use(use_id)) }; - if let Symbol::Type(ty, Boundness::Bound) = bindings_ty { + if let Symbol::Type(ty, Boundness::Bound) = inferred { ty } else { match self.lookup_name(name) { @@ -3334,12 +3334,12 @@ impl<'db> TypeInferenceBuilder<'db> { report_possibly_unresolved_reference(&self.context, name); } - bindings_ty + inferred .ignore_possibly_unbound() .map(|ty| UnionType::from_elements(self.db(), [ty, looked_up_ty])) .unwrap_or(looked_up_ty) } - Symbol::Unbound => match bindings_ty { + Symbol::Unbound => match inferred { Symbol::Type(ty, Boundness::PossiblyUnbound) => { report_possibly_unresolved_reference(&self.context, name); ty