@@ -600,6 +600,22 @@ impl<'db> TypeInferenceBuilder<'db> {
600600 }
601601 }
602602
603+ /// Check if a given AST node is reachable.
604+ ///
605+ /// Note that this only works if reachability is explicitly tracked for this specific
606+ /// type of node (see `node_reachability` in the use-def map).
607+ fn is_reachable < ' a , N > ( & self , node : N ) -> bool
608+ where
609+ N : Into < AnyNodeRef < ' a > > ,
610+ {
611+ let file_scope_id = self . scope ( ) . file_scope_id ( self . db ( ) ) ;
612+ self . index . is_node_reachable (
613+ self . db ( ) ,
614+ file_scope_id,
615+ self . enclosing_node_key ( node. into ( ) ) ,
616+ )
617+ }
618+
603619 fn in_stub ( & self ) -> bool {
604620 self . context . in_stub ( )
605621 }
@@ -781,6 +797,12 @@ impl<'db> TypeInferenceBuilder<'db> {
781797 MroErrorKind :: InvalidBases ( bases) => {
782798 let base_nodes = class_node. bases ( ) ;
783799 for ( index, base_ty) in bases {
800+ if base_ty. is_never ( ) {
801+ // A class base of type `Never` can appear in unreachable code. It
802+ // does not indicate a problem, since the actual construction of the
803+ // class will never happen.
804+ continue ;
805+ }
784806 self . context . report_lint_old (
785807 & INVALID_BASE ,
786808 & base_nodes[ * index] ,
@@ -802,7 +824,7 @@ impl<'db> TypeInferenceBuilder<'db> {
802824 )
803825 }
804826 }
805- Ok ( _) => check_class_slots ( & self . context , class, class_node)
827+ Ok ( _) => check_class_slots ( & self . context , class, class_node) ,
806828 }
807829
808830 // (4) Check that the class's metaclass can be determined without error.
@@ -3120,15 +3142,12 @@ impl<'db> TypeInferenceBuilder<'db> {
31203142
31213143 fn report_unresolved_import (
31223144 & self ,
3123- import_node : NodeKey ,
3145+ import_node : AnyNodeRef < ' _ > ,
31243146 range : TextRange ,
31253147 level : u32 ,
31263148 module : Option < & str > ,
31273149 ) {
3128- let file_scope_id = self . scope ( ) . file_scope_id ( self . db ( ) ) ;
3129- let is_import_reachable =
3130- self . index
3131- . is_node_reachable ( self . db ( ) , file_scope_id, import_node) ;
3150+ let is_import_reachable = self . is_reachable ( import_node) ;
31323151
31333152 if !is_import_reachable {
31343153 return ;
@@ -3166,7 +3185,7 @@ impl<'db> TypeInferenceBuilder<'db> {
31663185
31673186 // Resolve the module being imported.
31683187 let Some ( full_module_ty) = self . module_type_from_name ( & full_module_name) else {
3169- self . report_unresolved_import ( NodeKey :: from_node ( node) , alias. range ( ) , 0 , Some ( name) ) ;
3188+ self . report_unresolved_import ( node. into ( ) , alias. range ( ) , 0 , Some ( name) ) ;
31703189 self . add_unknown_declaration_with_binding ( alias. into ( ) , definition) ;
31713190 return ;
31723191 } ;
@@ -3280,8 +3299,6 @@ impl<'db> TypeInferenceBuilder<'db> {
32803299 ) -> Option < ( ModuleName , Type < ' db > ) > {
32813300 let ast:: StmtImportFrom { module, level, .. } = import_from;
32823301
3283- let node_key = NodeKey :: from_node ( import_from) ;
3284-
32853302 // For diagnostics, we want to highlight the unresolvable
32863303 // module and not the entire `from ... import ...` statement.
32873304 let module_ref = module
@@ -3310,7 +3327,12 @@ impl<'db> TypeInferenceBuilder<'db> {
33103327 "Relative module resolution `{}` failed: too many leading dots" ,
33113328 format_import_from_module( * level, module) ,
33123329 ) ;
3313- self . report_unresolved_import ( node_key, module_ref. range ( ) , * level, module) ;
3330+ self . report_unresolved_import (
3331+ import_from. into ( ) ,
3332+ module_ref. range ( ) ,
3333+ * level,
3334+ module,
3335+ ) ;
33143336 return None ;
33153337 }
33163338 Err ( ModuleNameResolutionError :: UnknownCurrentModule ) => {
@@ -3319,13 +3341,18 @@ impl<'db> TypeInferenceBuilder<'db> {
33193341 format_import_from_module( * level, module) ,
33203342 self . file( ) . path( self . db( ) )
33213343 ) ;
3322- self . report_unresolved_import ( node_key, module_ref. range ( ) , * level, module) ;
3344+ self . report_unresolved_import (
3345+ import_from. into ( ) ,
3346+ module_ref. range ( ) ,
3347+ * level,
3348+ module,
3349+ ) ;
33233350 return None ;
33243351 }
33253352 } ;
33263353
33273354 let Some ( module_ty) = self . module_type_from_name ( & module_name) else {
3328- self . report_unresolved_import ( node_key , module_ref. range ( ) , * level, module) ;
3355+ self . report_unresolved_import ( import_from . into ( ) , module_ref. range ( ) , * level, module) ;
33293356 return None ;
33303357 } ;
33313358
@@ -3410,12 +3437,7 @@ impl<'db> TypeInferenceBuilder<'db> {
34103437 }
34113438
34123439 if & alias. name != "*" {
3413- let file_scope_id = self . scope ( ) . file_scope_id ( self . db ( ) ) ;
3414- let is_import_reachable = self . index . is_node_reachable (
3415- self . db ( ) ,
3416- file_scope_id,
3417- NodeKey :: from_node ( import_from) ,
3418- ) ;
3440+ let is_import_reachable = self . is_reachable ( import_from) ;
34193441
34203442 if is_import_reachable {
34213443 self . context . report_lint_old (
@@ -4503,24 +4525,16 @@ impl<'db> TypeInferenceBuilder<'db> {
45034525 } )
45044526 } ) ;
45054527
4506- let report_unresolved_usage = || {
4507- self . index . is_node_reachable (
4508- db,
4509- file_scope_id,
4510- self . enclosing_node_key ( name_node. into ( ) ) ,
4511- )
4512- } ;
4513-
45144528 symbol
45154529 . unwrap_with_diagnostic ( |lookup_error| match lookup_error {
45164530 LookupError :: Unbound ( qualifiers) => {
4517- if report_unresolved_usage ( ) {
4531+ if self . is_reachable ( name_node ) {
45184532 report_unresolved_reference ( & self . context , name_node) ;
45194533 }
45204534 TypeAndQualifiers :: new ( Type :: unknown ( ) , qualifiers)
45214535 }
45224536 LookupError :: PossiblyUnbound ( type_when_bound) => {
4523- if report_unresolved_usage ( ) {
4537+ if self . is_reachable ( name_node ) {
45244538 report_possibly_unresolved_reference ( & self . context , name_node) ;
45254539 }
45264540 type_when_bound
@@ -4553,13 +4567,7 @@ impl<'db> TypeInferenceBuilder<'db> {
45534567 . member ( db, & attr. id )
45544568 . unwrap_with_diagnostic ( |lookup_error| match lookup_error {
45554569 LookupError :: Unbound ( _) => {
4556- let report_unresolved_attribute = self
4557- . index
4558- . is_node_reachable (
4559- db,
4560- self . scope ( ) . file_scope_id ( db) ,
4561- self . enclosing_node_key ( attribute. into ( ) ) ,
4562- ) ;
4570+ let report_unresolved_attribute = self . is_reachable ( attribute) ;
45634571
45644572 if report_unresolved_attribute {
45654573 let bound_on_instance = match value_type {
@@ -6334,7 +6342,11 @@ impl<'db> TypeInferenceBuilder<'db> {
63346342 _ => name_expr_ty
63356343 . in_type_expression ( self . db ( ) )
63366344 . unwrap_or_else ( |error| {
6337- error. into_fallback_type ( & self . context , annotation)
6345+ error. into_fallback_type (
6346+ & self . context ,
6347+ annotation,
6348+ self . is_reachable ( annotation) ,
6349+ )
63386350 } )
63396351 . into ( ) ,
63406352 }
@@ -6499,7 +6511,13 @@ impl<'db> TypeInferenceBuilder<'db> {
64996511 ast:: ExprContext :: Load => self
65006512 . infer_name_expression ( name)
65016513 . in_type_expression ( self . db ( ) )
6502- . unwrap_or_else ( |error| error. into_fallback_type ( & self . context , expression) ) ,
6514+ . unwrap_or_else ( |error| {
6515+ error. into_fallback_type (
6516+ & self . context ,
6517+ expression,
6518+ self . is_reachable ( expression) ,
6519+ )
6520+ } ) ,
65036521 ast:: ExprContext :: Invalid => Type :: unknown ( ) ,
65046522 ast:: ExprContext :: Store | ast:: ExprContext :: Del => {
65056523 todo_type ! ( "Name expression annotation in Store/Del context" )
@@ -6510,7 +6528,13 @@ impl<'db> TypeInferenceBuilder<'db> {
65106528 ast:: ExprContext :: Load => self
65116529 . infer_attribute_expression ( attribute_expression)
65126530 . in_type_expression ( self . db ( ) )
6513- . unwrap_or_else ( |error| error. into_fallback_type ( & self . context , expression) ) ,
6531+ . unwrap_or_else ( |error| {
6532+ error. into_fallback_type (
6533+ & self . context ,
6534+ expression,
6535+ self . is_reachable ( expression) ,
6536+ )
6537+ } ) ,
65146538 ast:: ExprContext :: Invalid => Type :: unknown ( ) ,
65156539 ast:: ExprContext :: Store | ast:: ExprContext :: Del => {
65166540 todo_type ! ( "Attribute expression annotation in Store/Del context" )
0 commit comments