11use ruff_db:: files:: File ;
2- use ruff_python_ast:: name :: Name ;
2+ use ruff_python_ast as ast ;
33
44use crate :: builtins:: builtins_scope;
5- use crate :: semantic_index:: definition:: Definition ;
5+ use crate :: semantic_index:: ast_ids:: HasScopedAstId ;
6+ use crate :: semantic_index:: definition:: { Definition , DefinitionKind } ;
67use crate :: semantic_index:: symbol:: { ScopeId , ScopedSymbolId } ;
78use crate :: semantic_index:: {
89 global_scope, semantic_index, symbol_table, use_def_map, DefinitionWithConstraints ,
@@ -14,7 +15,8 @@ use crate::{Db, FxOrderSet};
1415pub ( crate ) use self :: builder:: { IntersectionBuilder , UnionBuilder } ;
1516pub ( crate ) use self :: diagnostic:: TypeCheckDiagnostics ;
1617pub ( crate ) use self :: infer:: {
17- infer_definition_types, infer_expression_types, infer_scope_types, TypeInference ,
18+ infer_deferred_types, infer_definition_types, infer_expression_types, infer_scope_types,
19+ TypeInference ,
1820} ;
1921
2022mod builder;
@@ -88,6 +90,24 @@ pub(crate) fn definition_ty<'db>(db: &'db dyn Db, definition: Definition<'db>) -
8890 inference. definition_ty ( definition)
8991}
9092
93+ /// Infer the type of a (possibly deferred) sub-expression of a [`Definition`].
94+ ///
95+ /// ## Panics
96+ /// If the given expression is not a sub-expression of the given [`Definition`].
97+ pub ( crate ) fn definition_expression_ty < ' db > (
98+ db : & ' db dyn Db ,
99+ definition : Definition < ' db > ,
100+ expression : & ast:: Expr ,
101+ ) -> Type < ' db > {
102+ let expr_id = expression. scoped_ast_id ( db, definition. scope ( db) ) ;
103+ let inference = infer_definition_types ( db, definition) ;
104+ if let Some ( ty) = inference. try_expression_ty ( expr_id) {
105+ ty
106+ } else {
107+ infer_deferred_types ( db, definition) . expression_ty ( expr_id)
108+ }
109+ }
110+
91111/// Infer the combined type of an array of [`Definition`]s, plus one optional "unbound type".
92112///
93113/// Will return a union if there is more than one definition, or at least one plus an unbound
@@ -243,7 +263,7 @@ impl<'db> Type<'db> {
243263 /// us to explicitly consider whether to handle an error or propagate
244264 /// it up the call stack.
245265 #[ must_use]
246- pub fn member ( & self , db : & ' db dyn Db , name : & Name ) -> Type < ' db > {
266+ pub fn member ( & self , db : & ' db dyn Db , name : & ast :: name :: Name ) -> Type < ' db > {
247267 match self {
248268 Type :: Any => Type :: Any ,
249269 Type :: Never => {
@@ -314,7 +334,7 @@ impl<'db> Type<'db> {
314334#[ salsa:: interned]
315335pub struct FunctionType < ' db > {
316336 /// name of the function at definition
317- pub name : Name ,
337+ pub name : ast :: name :: Name ,
318338
319339 /// types of all decorators on this function
320340 decorators : Vec < Type < ' db > > ,
@@ -329,19 +349,33 @@ impl<'db> FunctionType<'db> {
329349#[ salsa:: interned]
330350pub struct ClassType < ' db > {
331351 /// Name of the class at definition
332- pub name : Name ,
352+ pub name : ast :: name :: Name ,
333353
334- /// Types of all class bases
335- bases : Vec < Type < ' db > > ,
354+ definition : Definition < ' db > ,
336355
337356 body_scope : ScopeId < ' db > ,
338357}
339358
340359impl < ' db > ClassType < ' db > {
360+ /// Return an iterator over the types of this class's bases.
361+ ///
362+ /// # Panics:
363+ /// If `definition` is not a `DefinitionKind::Class`.
364+ pub fn bases ( & self , db : & ' db dyn Db ) -> impl Iterator < Item = Type < ' db > > {
365+ let definition = self . definition ( db) ;
366+ let DefinitionKind :: Class ( class_stmt_node) = definition. node ( db) else {
367+ panic ! ( "Class type definition must have DefinitionKind::Class" ) ;
368+ } ;
369+ class_stmt_node
370+ . bases ( )
371+ . iter ( )
372+ . map ( move |base_expr| definition_expression_ty ( db, definition, base_expr) )
373+ }
374+
341375 /// Returns the class member of this class named `name`.
342376 ///
343377 /// The member resolves to a member of the class itself or any of its bases.
344- pub fn class_member ( self , db : & ' db dyn Db , name : & Name ) -> Type < ' db > {
378+ pub fn class_member ( self , db : & ' db dyn Db , name : & ast :: name :: Name ) -> Type < ' db > {
345379 let member = self . own_class_member ( db, name) ;
346380 if !member. is_unbound ( ) {
347381 return member;
@@ -351,12 +385,12 @@ impl<'db> ClassType<'db> {
351385 }
352386
353387 /// Returns the inferred type of the class member named `name`.
354- pub fn own_class_member ( self , db : & ' db dyn Db , name : & Name ) -> Type < ' db > {
388+ pub fn own_class_member ( self , db : & ' db dyn Db , name : & ast :: name :: Name ) -> Type < ' db > {
355389 let scope = self . body_scope ( db) ;
356390 symbol_ty_by_name ( db, scope, name)
357391 }
358392
359- pub fn inherited_class_member ( self , db : & ' db dyn Db , name : & Name ) -> Type < ' db > {
393+ pub fn inherited_class_member ( self , db : & ' db dyn Db , name : & ast :: name :: Name ) -> Type < ' db > {
360394 for base in self . bases ( db) {
361395 let member = base. member ( db, name) ;
362396 if !member. is_unbound ( ) {
0 commit comments