@@ -557,66 +557,78 @@ fn symbol_from_bindings_impl<'db>(
557557 _ => Truthiness :: AlwaysFalse ,
558558 } ;
559559
560- let mut types = bindings_with_constraints. filter_map (
561- |BindingWithConstraints {
562- binding,
563- narrowing_constraint,
564- visibility_constraint,
565- } | {
566- let binding = binding?;
567-
568- if is_non_exported ( binding) {
569- return None ;
570- }
571-
572- let static_visibility =
573- visibility_constraints. evaluate ( db, constraints, visibility_constraint) ;
574-
575- if static_visibility. is_always_false ( ) {
576- return None ;
577- }
560+ let mut types: Vec < _ > = bindings_with_constraints
561+ . filter_map (
562+ |BindingWithConstraints {
563+ binding,
564+ narrowing_constraint,
565+ visibility_constraint,
566+ } | {
567+ let binding = binding?;
568+
569+ if is_non_exported ( binding) {
570+ return None ;
571+ }
578572
579- let constraint_tys: Vec < _ > = narrowing_constraint
580- . filter_map ( |constraint| infer_narrowing_constraint ( db, constraint, binding) )
581- . collect ( ) ;
573+ let static_visibility =
574+ visibility_constraints. evaluate ( db, constraints, visibility_constraint) ;
582575
583- let binding_ty = binding_type ( db, binding) ;
584- if constraint_tys. is_empty ( ) {
585- Some ( binding_ty)
586- } else {
587- let intersection_ty = constraint_tys
588- . into_iter ( )
589- . rev ( )
590- . fold (
591- IntersectionBuilder :: new ( db) . add_positive ( binding_ty) ,
592- IntersectionBuilder :: add_positive,
593- )
594- . build ( ) ;
595- Some ( intersection_ty)
596- }
597- } ,
598- ) ;
576+ if static_visibility. is_always_false ( ) {
577+ return None ;
578+ }
599579
600- if let Some ( first) = types. next ( ) {
601- let boundness = match unbound_visibility {
602- Truthiness :: AlwaysTrue => {
603- unreachable ! ( "If we have at least one binding, the scope-start should not be definitely visible" )
604- }
605- Truthiness :: AlwaysFalse => Boundness :: Bound ,
606- Truthiness :: Ambiguous => Boundness :: PossiblyUnbound ,
607- } ;
580+ let constraint_tys: Vec < _ > = narrowing_constraint
581+ . filter_map ( |constraint| infer_narrowing_constraint ( db, constraint, binding) )
582+ . collect ( ) ;
583+
584+ let binding_ty = binding_type ( db, binding) ;
585+ if constraint_tys. is_empty ( ) {
586+ Some ( binding_ty)
587+ } else {
588+ let intersection_ty = constraint_tys
589+ . into_iter ( )
590+ . rev ( )
591+ . fold (
592+ IntersectionBuilder :: new ( db) . add_positive ( binding_ty) ,
593+ IntersectionBuilder :: add_positive,
594+ )
595+ . build ( ) ;
596+ Some ( intersection_ty)
597+ }
598+ } ,
599+ )
600+ . collect ( ) ;
601+
602+ // The bindings iterator is in reverse order, so popping the last element from the collected
603+ // vector gives us the first binding.
604+ let Some ( first) = types. pop ( ) else {
605+ return Symbol :: Unbound ;
606+ } ;
608607
609- if let Some ( second ) = types . next ( ) {
610- Symbol :: Type (
611- UnionType :: from_elements ( db , [ first , second ] . into_iter ( ) . chain ( types ) ) ,
612- boundness ,
608+ let boundness = match unbound_visibility {
609+ Truthiness :: AlwaysTrue => {
610+ unreachable ! (
611+ "If we have at least one binding, the scope-start should not be definitely visible"
613612 )
614- } else {
615- Symbol :: Type ( first, boundness)
616613 }
617- } else {
618- Symbol :: Unbound
614+ Truthiness :: AlwaysFalse => Boundness :: Bound ,
615+ Truthiness :: Ambiguous => Boundness :: PossiblyUnbound ,
616+ } ;
617+
618+ if types. is_empty ( ) {
619+ return Symbol :: Type ( first, boundness) ;
619620 }
621+
622+ Symbol :: Type (
623+ types
624+ . into_iter ( )
625+ . rev ( )
626+ . fold ( UnionBuilder :: new ( db) . add ( first) , |builder, element| {
627+ builder. add ( element)
628+ } )
629+ . build ( ) ,
630+ boundness,
631+ )
620632}
621633
622634/// Implementation of [`symbol_from_declarations`].
@@ -647,70 +659,77 @@ fn symbol_from_declarations_impl<'db>(
647659 _ => Truthiness :: AlwaysFalse ,
648660 } ;
649661
650- let mut types = declarations. filter_map (
651- |DeclarationWithConstraint {
652- declaration,
653- visibility_constraint,
654- } | {
655- let declaration = declaration?;
662+ let mut types: Vec < _ > = declarations
663+ . filter_map (
664+ |DeclarationWithConstraint {
665+ declaration,
666+ visibility_constraint,
667+ } | {
668+ let declaration = declaration?;
656669
657- if is_non_exported ( declaration) {
658- return None ;
659- }
670+ if is_non_exported ( declaration) {
671+ return None ;
672+ }
660673
661- let static_visibility =
662- visibility_constraints. evaluate ( db, constraints, visibility_constraint) ;
674+ let static_visibility =
675+ visibility_constraints. evaluate ( db, constraints, visibility_constraint) ;
663676
664- if static_visibility. is_always_false ( ) {
665- None
666- } else {
667- Some ( declaration_type ( db, declaration) )
668- }
669- } ,
670- ) ;
671-
672- if let Some ( first) = types. next ( ) {
673- let mut conflicting: Vec < Type < ' db > > = vec ! [ ] ;
674- let declared_ty = if let Some ( second) = types. next ( ) {
675- let ty_first = first. inner_type ( ) ;
676- let mut qualifiers = first. qualifiers ( ) ;
677-
678- let mut builder = UnionBuilder :: new ( db) . add ( ty_first) ;
679- for other in std:: iter:: once ( second) . chain ( types) {
680- let other_ty = other. inner_type ( ) ;
681- if !ty_first. is_equivalent_to ( db, other_ty) {
682- conflicting. push ( other_ty) ;
677+ if static_visibility. is_always_false ( ) {
678+ None
679+ } else {
680+ Some ( declaration_type ( db, declaration) )
683681 }
684- builder = builder. add ( other_ty) ;
685- qualifiers = qualifiers. union ( other. qualifiers ( ) ) ;
686- }
687- TypeAndQualifiers :: new ( builder. build ( ) , qualifiers)
688- } else {
689- first
690- } ;
691- if conflicting. is_empty ( ) {
692- let boundness = match undeclared_visibility {
693- Truthiness :: AlwaysTrue => {
694- unreachable ! ( "If we have at least one declaration, the scope-start should not be definitely visible" )
695- }
696- Truthiness :: AlwaysFalse => Boundness :: Bound ,
697- Truthiness :: Ambiguous => Boundness :: PossiblyUnbound ,
698- } ;
682+ } ,
683+ )
684+ . collect ( ) ;
685+
686+ // The bindings iterator is in reverse order, so popping the last element from the collected
687+ // vector gives us the first binding.
688+ let Some ( first) = types. pop ( ) else {
689+ return Ok ( Symbol :: Unbound . into ( ) ) ;
690+ } ;
699691
700- Ok ( SymbolAndQualifiers (
701- Symbol :: Type ( declared_ty. inner_type ( ) , boundness) ,
702- declared_ty. qualifiers ( ) ,
703- ) )
704- } else {
705- Err ( (
706- declared_ty,
707- std:: iter:: once ( first. inner_type ( ) )
708- . chain ( conflicting)
709- . collect ( ) ,
710- ) )
692+ let boundness = match undeclared_visibility {
693+ Truthiness :: AlwaysTrue => {
694+ unreachable ! ( "If we have at least one declaration, the scope-start should not be definitely visible" )
695+ }
696+ Truthiness :: AlwaysFalse => Boundness :: Bound ,
697+ Truthiness :: Ambiguous => Boundness :: PossiblyUnbound ,
698+ } ;
699+
700+ if types. is_empty ( ) {
701+ return Ok ( SymbolAndQualifiers (
702+ Symbol :: Type ( first. inner_type ( ) , boundness) ,
703+ first. qualifiers ( ) ,
704+ ) ) ;
705+ }
706+
707+ let mut conflicting: Vec < Type < ' db > > = vec ! [ ] ;
708+ let ty_first = first. inner_type ( ) ;
709+ let mut qualifiers = first. qualifiers ( ) ;
710+
711+ let mut builder = UnionBuilder :: new ( db) . add ( ty_first) ;
712+ for other in types. into_iter ( ) . rev ( ) {
713+ let other_ty = other. inner_type ( ) ;
714+ if !ty_first. is_equivalent_to ( db, other_ty) {
715+ conflicting. push ( other_ty) ;
711716 }
717+ builder = builder. add ( other_ty) ;
718+ qualifiers = qualifiers. union ( other. qualifiers ( ) ) ;
719+ }
720+ let declared_ty = builder. build ( ) ;
721+
722+ if conflicting. is_empty ( ) {
723+ Ok ( SymbolAndQualifiers (
724+ Symbol :: Type ( declared_ty, boundness) ,
725+ qualifiers,
726+ ) )
712727 } else {
713- Ok ( Symbol :: Unbound . into ( ) )
728+ conflicting. insert ( 0 , ty_first) ;
729+ Err ( (
730+ TypeAndQualifiers :: new ( declared_ty, qualifiers) ,
731+ conflicting. into ( ) ,
732+ ) )
714733 }
715734}
716735
0 commit comments