diff --git a/crates/red_knot_python_semantic/src/semantic_index.rs b/crates/red_knot_python_semantic/src/semantic_index.rs index c3c72cfe2812e..a2c766cccc570 100644 --- a/crates/red_knot_python_semantic/src/semantic_index.rs +++ b/crates/red_knot_python_semantic/src/semantic_index.rs @@ -246,7 +246,6 @@ impl<'db> SemanticIndex<'db> { } /// Returns an iterator over all ancestors of `scope`, starting with `scope` itself. - #[allow(unused)] pub(crate) fn ancestor_scopes(&self, scope: FileScopeId) -> AncestorsIter { AncestorsIter::new(self, scope) } diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 6a885af83f72b..69f1f0f080e05 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -1468,7 +1468,7 @@ impl<'db> Type<'db> { }; if let Ok(Type::BooleanLiteral(bool_val)) = bool_method - .call_bound(db, instance_ty, &CallArguments::positional([])) + .try_call_bound(db, instance_ty, &CallArguments::positional([])) .map(|outcome| outcome.return_type(db)) { bool_val.into() @@ -1541,12 +1541,15 @@ impl<'db> Type<'db> { return usize_len.try_into().ok().map(Type::IntLiteral); } - let return_ty = match self.call_dunder(db, "__len__", &CallArguments::positional([*self])) { - Ok(outcome) | Err(CallDunderError::PossiblyUnbound(outcome)) => outcome.return_type(db), + let return_ty = + match self.try_call_dunder(db, "__len__", &CallArguments::positional([*self])) { + Ok(outcome) | Err(CallDunderError::PossiblyUnbound(outcome)) => { + outcome.return_type(db) + } - // TODO: emit a diagnostic - Err(err) => err.return_type(db)?, - }; + // TODO: emit a diagnostic + Err(err) => err.return_type(db)?, + }; non_negative_int_literal(db, return_ty) } @@ -1554,7 +1557,7 @@ impl<'db> Type<'db> { /// Calls `self` /// /// Returns `Ok` if the call with the given arguments is successful and `Err` otherwise. - fn call( + fn try_call( self, db: &'db dyn Db, arguments: &CallArguments<'_, 'db>, @@ -1672,7 +1675,7 @@ impl<'db> Type<'db> { instance_ty @ Type::Instance(_) => { instance_ty - .call_dunder(db, "__call__", &arguments.with_self(instance_ty)) + .try_call_dunder(db, "__call__", &arguments.with_self(instance_ty)) .map_err(|err| match err { CallDunderError::Call(CallError::NotCallable { .. }) => { // Turn "`` not callable" into @@ -1712,7 +1715,7 @@ impl<'db> Type<'db> { Type::Dynamic(_) => Ok(CallOutcome::Single(CallBinding::from_return_type(self))), Type::Union(union) => { - CallOutcome::try_call_union(db, union, |element| element.call(db, arguments)) + CallOutcome::try_call_union(db, union, |element| element.try_call(db, arguments)) } Type::Intersection(_) => Ok(CallOutcome::Single(CallBinding::from_return_type( @@ -1731,7 +1734,7 @@ impl<'db> Type<'db> { /// `receiver_ty` must be `Type::Instance(_)` or `Type::ClassLiteral`. /// /// TODO: handle `super()` objects properly - fn call_bound( + fn try_call_bound( self, db: &'db dyn Db, receiver_ty: &Type<'db>, @@ -1743,16 +1746,16 @@ impl<'db> Type<'db> { Type::FunctionLiteral(..) => { // Functions are always descriptors, so this would effectively call // the function with the instance as the first argument - self.call(db, &arguments.with_self(*receiver_ty)) + self.try_call(db, &arguments.with_self(*receiver_ty)) } Type::Instance(_) | Type::ClassLiteral(_) => { // TODO descriptor protocol. For now, assume non-descriptor and call without `self` argument. - self.call(db, arguments) + self.try_call(db, arguments) } Type::Union(union) => CallOutcome::try_call_union(db, union, |element| { - element.call_bound(db, receiver_ty, arguments) + element.try_call_bound(db, receiver_ty, arguments) }), Type::Intersection(_) => Ok(CallOutcome::Single(CallBinding::from_return_type( @@ -1769,16 +1772,16 @@ impl<'db> Type<'db> { } /// Look up a dunder method on the meta type of `self` and call it. - fn call_dunder( + fn try_call_dunder( self, db: &'db dyn Db, name: &str, arguments: &CallArguments<'_, 'db>, ) -> Result, CallDunderError<'db>> { match self.to_meta_type(db).member(db, name) { - Symbol::Type(callable_ty, Boundness::Bound) => Ok(callable_ty.call(db, arguments)?), + Symbol::Type(callable_ty, Boundness::Bound) => Ok(callable_ty.try_call(db, arguments)?), Symbol::Type(callable_ty, Boundness::PossiblyUnbound) => { - let call = callable_ty.call(db, arguments)?; + let call = callable_ty.try_call(db, arguments)?; Err(CallDunderError::PossiblyUnbound(call)) } Symbol::Unbound => Err(CallDunderError::MethodNotAvailable), @@ -1801,12 +1804,12 @@ impl<'db> Type<'db> { } let dunder_iter_result = - self.call_dunder(db, "__iter__", &CallArguments::positional([self])); + self.try_call_dunder(db, "__iter__", &CallArguments::positional([self])); match &dunder_iter_result { Ok(outcome) | Err(CallDunderError::PossiblyUnbound(outcome)) => { let iterator_ty = outcome.return_type(db); - return match iterator_ty.call_dunder( + return match iterator_ty.try_call_dunder( db, "__next__", &CallArguments::positional([iterator_ty]), @@ -1855,7 +1858,7 @@ impl<'db> Type<'db> { // // TODO(Alex) this is only valid if the `__getitem__` method is annotated as // accepting `int` or `SupportsIndex` - match self.call_dunder( + match self.try_call_dunder( db, "__getitem__", &CallArguments::positional([self, KnownClass::Int.to_instance(db)]), @@ -2693,52 +2696,8 @@ pub enum KnownInstanceType<'db> { } impl<'db> KnownInstanceType<'db> { - pub const fn as_str(self) -> &'static str { - match self { - Self::Annotated => "Annotated", - Self::Literal => "Literal", - Self::LiteralString => "LiteralString", - Self::Optional => "Optional", - Self::Union => "Union", - Self::TypeVar(_) => "TypeVar", - Self::NoReturn => "NoReturn", - Self::Never => "Never", - Self::Any => "Any", - Self::Tuple => "Tuple", - Self::Type => "Type", - Self::TypeAliasType(_) => "TypeAliasType", - Self::TypingSelf => "Self", - Self::Final => "Final", - Self::ClassVar => "ClassVar", - Self::Callable => "Callable", - Self::Concatenate => "Concatenate", - Self::Unpack => "Unpack", - Self::Required => "Required", - Self::NotRequired => "NotRequired", - Self::TypeAlias => "TypeAlias", - Self::TypeGuard => "TypeGuard", - Self::TypeIs => "TypeIs", - Self::List => "List", - Self::Dict => "Dict", - Self::DefaultDict => "DefaultDict", - Self::Set => "Set", - Self::FrozenSet => "FrozenSet", - Self::Counter => "Counter", - Self::Deque => "Deque", - Self::ChainMap => "ChainMap", - Self::OrderedDict => "OrderedDict", - Self::ReadOnly => "ReadOnly", - Self::Unknown => "Unknown", - Self::AlwaysTruthy => "AlwaysTruthy", - Self::AlwaysFalsy => "AlwaysFalsy", - Self::Not => "Not", - Self::Intersection => "Intersection", - Self::TypeOf => "TypeOf", - } - } - /// Evaluate the known instance in boolean context - pub const fn bool(self) -> Truthiness { + pub(crate) const fn bool(self) -> Truthiness { match self { Self::Annotated | Self::Literal @@ -2783,7 +2742,7 @@ impl<'db> KnownInstanceType<'db> { } /// Return the repr of the symbol at runtime - pub fn repr(self, db: &'db dyn Db) -> &'db str { + pub(crate) fn repr(self, db: &'db dyn Db) -> &'db str { match self { Self::Annotated => "typing.Annotated", Self::Literal => "typing.Literal", @@ -2828,7 +2787,7 @@ impl<'db> KnownInstanceType<'db> { } /// Return the [`KnownClass`] which this symbol is an instance of - pub const fn class(self) -> KnownClass { + pub(crate) const fn class(self) -> KnownClass { match self { Self::Annotated => KnownClass::SpecialForm, Self::Literal => KnownClass::SpecialForm, @@ -2877,16 +2836,20 @@ impl<'db> KnownInstanceType<'db> { /// For example, the symbol `typing.Literal` is an instance of `typing._SpecialForm`, /// so `KnownInstanceType::Literal.instance_fallback(db)` /// returns `Type::Instance(InstanceType { class: })`. - pub fn instance_fallback(self, db: &dyn Db) -> Type { + pub(crate) fn instance_fallback(self, db: &dyn Db) -> Type { self.class().to_instance(db) } /// Return `true` if this symbol is an instance of `class`. - pub fn is_instance_of(self, db: &'db dyn Db, class: Class<'db>) -> bool { + pub(crate) fn is_instance_of(self, db: &'db dyn Db, class: Class<'db>) -> bool { self.class().is_subclass_of(db, class) } - pub fn try_from_file_and_name(db: &'db dyn Db, file: File, symbol_name: &str) -> Option { + pub(crate) fn try_from_file_and_name( + db: &'db dyn Db, + file: File, + symbol_name: &str, + ) -> Option { let candidate = match symbol_name { "Any" => Self::Any, "ClassVar" => Self::ClassVar, @@ -2937,7 +2900,7 @@ impl<'db> KnownInstanceType<'db> { /// /// Most variants can only exist in one module, which is the same as `self.class().canonical_module()`. /// Some variants could validly be defined in either `typing` or `typing_extensions`, however. - pub fn check_module(self, module: KnownModule) -> bool { + pub(crate) fn check_module(self, module: KnownModule) -> bool { match self { Self::Any | Self::ClassVar @@ -3668,7 +3631,7 @@ impl<'db> Class<'db> { // TODO: Other keyword arguments? let arguments = CallArguments::positional([name, bases, namespace]); - let return_ty_result = match metaclass.call(db, &arguments) { + let return_ty_result = match metaclass.try_call(db, &arguments) { Ok(outcome) => Ok(outcome.return_type(db)), Err(CallError::NotCallable { not_callable_ty }) => Err(MetaclassError { diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index b405b4c5cbe23..ef340126e3610 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -1616,7 +1616,7 @@ impl<'db> TypeInferenceBuilder<'db> { } let target_ty = enter_ty - .call(self.db(), &CallArguments::positional([context_expression_ty])) + .try_call(self.db(), &CallArguments::positional([context_expression_ty])) .map(|outcome| outcome.return_type(self.db())) .unwrap_or_else(|err| { // TODO: Use more specific error messages for the different error cases. @@ -1659,7 +1659,7 @@ impl<'db> TypeInferenceBuilder<'db> { } if exit_ty - .call( + .try_call( self.db(), &CallArguments::positional([ context_manager_ty, @@ -2209,7 +2209,7 @@ impl<'db> TypeInferenceBuilder<'db> { if let Symbol::Type(class_member, boundness) = class.class_member(self.db(), op.in_place_dunder()) { - let call = class_member.call( + let call = class_member.try_call( self.db(), &CallArguments::positional([target_type, value_type]), ); @@ -3247,7 +3247,7 @@ impl<'db> TypeInferenceBuilder<'db> { .unwrap_or_default(); let call_arguments = self.infer_arguments(arguments, parameter_expectations); - let call = function_type.call(self.db(), &call_arguments); + let call = function_type.try_call(self.db(), &call_arguments); match call { Ok(outcome) => { @@ -3747,7 +3747,7 @@ impl<'db> TypeInferenceBuilder<'db> { } }; - match operand_type.call_dunder( + match operand_type.try_call_dunder( self.db(), unary_dunder_method, &CallArguments::positional([operand_type]), @@ -3996,7 +3996,7 @@ impl<'db> TypeInferenceBuilder<'db> { && rhs_reflected != left_class.member(self.db(), reflected_dunder) { return right_ty - .call_dunder( + .try_call_dunder( self.db(), reflected_dunder, &CallArguments::positional([right_ty, left_ty]), @@ -4004,7 +4004,7 @@ impl<'db> TypeInferenceBuilder<'db> { .map(|outcome| outcome.return_type(self.db())) .or_else(|_| { left_ty - .call_dunder( + .try_call_dunder( self.db(), op.dunder(), &CallArguments::positional([left_ty, right_ty]), @@ -4020,7 +4020,7 @@ impl<'db> TypeInferenceBuilder<'db> { left_class.member(self.db(), op.dunder()) { class_member - .call(self.db(), &CallArguments::positional([left_ty, right_ty])) + .try_call(self.db(), &CallArguments::positional([left_ty, right_ty])) .map(|outcome| outcome.return_type(self.db())) .ok() } else { @@ -4036,7 +4036,10 @@ impl<'db> TypeInferenceBuilder<'db> { { // TODO: Use `call_dunder` class_member - .call(self.db(), &CallArguments::positional([right_ty, left_ty])) + .try_call( + self.db(), + &CallArguments::positional([right_ty, left_ty]), + ) .map(|outcome| outcome.return_type(self.db())) .ok() } else { @@ -4610,7 +4613,7 @@ impl<'db> TypeInferenceBuilder<'db> { // TODO: How do we want to handle possibly unbound dunder methods? match left.class.class_member(db, op.dunder()) { Symbol::Type(class_member_dunder, Boundness::Bound) => class_member_dunder - .call( + .try_call( db, &CallArguments::positional([Type::Instance(left), Type::Instance(right)]), ) @@ -4660,7 +4663,7 @@ impl<'db> TypeInferenceBuilder<'db> { Symbol::Type(contains_dunder, Boundness::Bound) => { // If `__contains__` is available, it is used directly for the membership test. contains_dunder - .call( + .try_call( db, &CallArguments::positional([Type::Instance(right), Type::Instance(left)]), ) @@ -4917,7 +4920,7 @@ impl<'db> TypeInferenceBuilder<'db> { // If the class defines `__getitem__`, return its return type. // // See: https://docs.python.org/3/reference/datamodel.html#class-getitem-versus-getitem - match value_ty.call_dunder( + match value_ty.try_call_dunder( self.db(), "__getitem__", &CallArguments::positional([value_ty, slice_ty]), @@ -4981,7 +4984,7 @@ impl<'db> TypeInferenceBuilder<'db> { } return ty - .call(self.db(), &CallArguments::positional([value_ty, slice_ty])) + .try_call(self.db(), &CallArguments::positional([value_ty, slice_ty])) .map(|outcome| outcome.return_type(self.db())) .unwrap_or_else(|err| { self.context.report_lint( diff --git a/crates/ruff_db/src/lib.rs b/crates/ruff_db/src/lib.rs index d98418e7c0e78..55a47d96d1f45 100644 --- a/crates/ruff_db/src/lib.rs +++ b/crates/ruff_db/src/lib.rs @@ -74,7 +74,6 @@ mod tests { /// /// ## Panics /// If there are pending database snapshots. - #[allow(unused)] pub(crate) fn take_salsa_events(&mut self) -> Vec { let inner = Arc::get_mut(&mut self.events) .expect("expected no pending salsa database snapshots."); @@ -86,7 +85,6 @@ mod tests { /// /// ## Panics /// If there are pending database snapshots. - #[allow(unused)] pub(crate) fn clear_salsa_events(&mut self) { self.take_salsa_events(); }