@@ -2686,7 +2686,7 @@ impl<'db> ClassLiteral<'db> {
26862686 // that attribute. We include `Unknown` in that union to account for the fact that the
26872687 // attribute might be externally modified.
26882688 let mut union_of_inferred_types = UnionBuilder :: new ( db) ;
2689- let mut qualifiers = TypeQualifiers :: empty ( ) ;
2689+ let mut qualifiers = TypeQualifiers :: IMPLICIT_INSTANCE_ATTRIBUTE ;
26902690
26912691 let mut is_attribute_bound = false ;
26922692
@@ -2736,20 +2736,11 @@ impl<'db> ClassLiteral<'db> {
27362736 // self.name: <annotation>
27372737 // self.name: <annotation> = …
27382738
2739- let reachability = use_def_map ( db, method_scope)
2740- . declaration_reachability ( db, & attribute_declaration) ;
2741-
2742- if reachability. is_always_false ( ) {
2743- continue ;
2744- }
2745-
27462739 let annotation = declaration_type ( db, declaration) ;
2747- let mut annotation =
2748- Place :: bound ( annotation. inner ) . with_qualifiers ( annotation. qualifiers ) ;
2740+ let annotation = Place :: bound ( annotation. inner ) . with_qualifiers (
2741+ annotation. qualifiers | TypeQualifiers :: IMPLICIT_INSTANCE_ATTRIBUTE ,
2742+ ) ;
27492743
2750- if reachability. is_ambiguous ( ) {
2751- annotation. qualifiers |= TypeQualifiers :: POSSIBLY_UNBOUND_IMPLICIT_ATTRIBUTE ;
2752- }
27532744 if let Some ( all_qualifiers) = annotation. is_bare_final ( ) {
27542745 if let Some ( value) = assignment. value ( & module) {
27552746 // If we see an annotated assignment with a bare `Final` as in
@@ -2781,8 +2772,6 @@ impl<'db> ClassLiteral<'db> {
27812772 continue ;
27822773 }
27832774
2784- let method_map = use_def_map ( db, method_scope) ;
2785-
27862775 // The attribute assignment inherits the reachability of the method which contains it
27872776 let is_method_reachable =
27882777 if let Some ( method_def) = method_scope. node ( db) . as_function ( & module) {
@@ -2802,53 +2791,16 @@ impl<'db> ClassLiteral<'db> {
28022791 continue ;
28032792 }
28042793
2805- // Storage for the implicit `DefinitionState::Undefined` binding. If present, it
2806- // will be the first binding in the `attribute_assignments` iterator.
2807- let mut unbound_binding = None ;
2808-
28092794 for attribute_assignment in attribute_assignments {
28102795 if let DefinitionState :: Undefined = attribute_assignment. binding {
2811- // Store the implicit unbound binding here so that we can delay the
2812- // computation of `unbound_reachability` to the point when we actually
2813- // need it. This is an optimization for the common case where the
2814- // `unbound` binding is the only binding of the `name` attribute,
2815- // i.e. if there is no `self.name = …` assignment in this method.
2816- unbound_binding = Some ( attribute_assignment) ;
28172796 continue ;
28182797 }
28192798
28202799 let DefinitionState :: Defined ( binding) = attribute_assignment. binding else {
28212800 continue ;
28222801 } ;
2823- match method_map
2824- . binding_reachability ( db, & attribute_assignment)
2825- . and ( is_method_reachable)
2826- {
2827- Truthiness :: AlwaysTrue => {
2828- is_attribute_bound = true ;
2829- }
2830- Truthiness :: Ambiguous => {
2831- is_attribute_bound = true ;
2832- qualifiers |= TypeQualifiers :: POSSIBLY_UNBOUND_IMPLICIT_ATTRIBUTE ;
2833- }
2834- Truthiness :: AlwaysFalse => {
2835- continue ;
2836- }
2837- }
2838-
2839- // There is at least one attribute assignment that may be reachable, so if `unbound_reachability` is
2840- // always false then this attribute is considered bound.
2841- // TODO: this is incomplete logic since the attributes bound after termination are considered reachable.
2842- let unbound_reachability = unbound_binding
2843- . as_ref ( )
2844- . map ( |binding| method_map. binding_reachability ( db, binding) )
2845- . unwrap_or ( Truthiness :: AlwaysFalse ) ;
28462802
2847- if unbound_reachability
2848- . negate ( )
2849- . and ( is_method_reachable)
2850- . is_always_true ( )
2851- {
2803+ if !is_method_reachable. is_always_false ( ) {
28522804 is_attribute_bound = true ;
28532805 }
28542806
0 commit comments