From 3140beb6a4e939cec51669840bfb5a070ad747fc Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Tue, 17 Sep 2024 13:25:47 -0700 Subject: [PATCH] WIP: start on passing context to call --- crates/red_knot_python_semantic/src/types.rs | 12 +++++----- .../src/types/infer.rs | 22 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index d606daa7d5..ab0319c016 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -482,14 +482,14 @@ impl<'db> Type<'db> { /// /// Returns `None` if `self` is not a callable type. #[must_use] - pub fn call(&self, db: &'db dyn Db) -> Option> { + fn call(&self, db: &'db dyn Db, _context: &mut TypeInferenceContext<'db>) -> Option> { match self { Type::Function(function_type) => Some(function_type.return_type(db)), // TODO annotated return type on `__new__` or metaclass `__call__` Type::Class(class) => Some(Type::Instance(*class)), - // TODO: handle classes which implement the Callable protocol + // TODO: handle classes which implement `__call__` Type::Instance(_instance_ty) => Some(Type::Unknown), // `Any` is callable, and its return type is also `Any`. @@ -497,7 +497,7 @@ impl<'db> Type<'db> { Type::Unknown => Some(Type::Unknown), - // TODO: union and intersection types, if they reduce to `Callable` + // TODO: union and intersection types Type::Union(_) => Some(Type::Unknown), Type::Intersection(_) => Some(Type::Unknown), @@ -529,13 +529,13 @@ impl<'db> Type<'db> { let dunder_iter_method = iterable_meta_type.member(db, "__iter__"); if !dunder_iter_method.is_unbound() { - let Some(iterator_ty) = dunder_iter_method.call(db) else { + let Some(iterator_ty) = dunder_iter_method.call(db, context) else { context.not_iterable_diagnostic(*self); return None; }; let dunder_next_method = iterator_ty.to_meta_type(db).member(db, "__next__"); - return dunder_next_method.call(db).or_else(|| { + return dunder_next_method.call(db, context).or_else(|| { context.not_iterable_diagnostic(*self); None }); @@ -549,7 +549,7 @@ impl<'db> Type<'db> { // accepting `int` or `SupportsIndex` let dunder_get_item_method = iterable_meta_type.member(db, "__getitem__"); - dunder_get_item_method.call(db).or_else(|| { + dunder_get_item_method.call(db, context).or_else(|| { context.not_iterable_diagnostic(*self); None }) diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 52f38db653..71b334c972 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -1949,16 +1949,18 @@ impl<'db> TypeInferenceBuilder<'db> { self.infer_arguments(arguments); let function_type = self.infer_expression(func); - function_type.call(self.db).unwrap_or_else(|| { - self.context.add_diagnostic( - "call-non-callable", - format_args!( - "Object of type '{}' is not callable", - function_type.display(self.db) - ), - ); - Type::Unknown - }) + function_type + .call(self.db, &mut self.context) + .unwrap_or_else(|| { + self.context.add_diagnostic( + "call-non-callable", + format_args!( + "Object of type '{}' is not callable", + function_type.display(self.db) + ), + ); + Type::Unknown + }) } fn infer_starred_expression(&mut self, starred: &'db ast::ExprStarred) -> Type<'db> {