about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs142
1 files changed, 74 insertions, 68 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 8265108513a..74f381d2661 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -2070,12 +2070,19 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                                 )
                             });
 
-                        let one_bound = bounds.next();
+                        let Some((bound_vars, assoc_item)) = bounds.next() else {
+                            // This will error in HIR lowering.
+                            self.tcx
+                                .dcx()
+                                .span_delayed_bug(path.span, "no resolution for RTN path");
+                            return;
+                        };
 
                         // Don't bail if we have identical bounds, which may be collected from
                         // something like `T: Bound + Bound`, or via elaborating supertraits.
-                        for second_bound in bounds {
-                            if Some(&second_bound) != one_bound.as_ref() {
+                        for (second_vars, second_assoc_item) in bounds {
+                            if second_vars != bound_vars || second_assoc_item != assoc_item {
+                                // This will error in HIR lowering.
                                 self.tcx.dcx().span_delayed_bug(
                                     path.span,
                                     "ambiguous resolution for RTN path",
@@ -2084,13 +2091,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                             }
                         }
 
-                        let Some((bound_vars, assoc_item)) = one_bound else {
-                            self.tcx
-                                .dcx()
-                                .span_delayed_bug(path.span, "no resolution for RTN path");
-                            return;
-                        };
-
                         (bound_vars, assoc_item.def_id, item_segment)
                     }
                     // If we have a self type alias (in an impl), try to resolve an
@@ -2166,75 +2166,81 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         std::iter::from_coroutine(
             #[coroutine]
             move || {
-                let mut next_scope = Some(self.scope);
-                while let Some(current_scope) = next_scope {
-                    next_scope = None;
-                    let hir_id = match *current_scope {
-                        Scope::Binder { s, hir_id, .. } => {
-                            next_scope = Some(s);
-                            hir_id
-                        }
-                        Scope::Body { s, .. }
-                        | Scope::ObjectLifetimeDefault { s, .. }
-                        | Scope::Supertrait { s, .. }
-                        | Scope::TraitRefBoundary { s }
-                        | Scope::LateBoundary { s, .. }
-                        | Scope::Opaque { s, .. } => {
-                            next_scope = Some(s);
-                            continue;
-                        }
-                        Scope::Root { opt_parent_item } => {
-                            if let Some(parent_id) = opt_parent_item {
-                                self.tcx.local_def_id_to_hir_id(parent_id)
-                            } else {
-                                continue;
-                            }
+                let mut scope = self.scope;
+                loop {
+                    let hir_id = match *scope {
+                        Scope::Binder { hir_id, .. } => Some(hir_id),
+                        Scope::Root { opt_parent_item: Some(parent_def_id) } => {
+                            Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
                         }
+                        Scope::Body { .. }
+                        | Scope::ObjectLifetimeDefault { .. }
+                        | Scope::Supertrait { .. }
+                        | Scope::TraitRefBoundary { .. }
+                        | Scope::LateBoundary { .. }
+                        | Scope::Opaque { .. }
+                        | Scope::Root { opt_parent_item: None } => None,
                     };
-                    let node = self.tcx.hir_node(hir_id);
-                    // If this is a `Self` bound in a trait, yield the trait itself.
-                    // Specifically, we don't need to look at any supertraits since
-                    // we already do that in `BoundVarContext::supertrait_hrtb_vars`.
-                    if let Res::SelfTyParam { trait_: _ } = expected_res
-                        && let hir::Node::Item(item) = node
-                        && let hir::ItemKind::Trait(..) = item.kind
-                    {
-                        // Yield the trait's def id. Supertraits will be
-                        // elaborated from that.
-                        yield item.owner_id.def_id.to_def_id();
-                    } else if let Some(generics) = node.generics() {
-                        for pred in generics.predicates {
-                            let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
-                                continue;
-                            };
-                            let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
-                                pred.bounded_ty.kind
-                            else {
-                                continue;
-                            };
-                            // Match the expected res.
-                            if bounded_path.res != expected_res {
-                                continue;
-                            }
-                            for pred in pred.bounds {
-                                match pred {
-                                    hir::GenericBound::Trait(poly_trait_ref) => {
-                                        if let Some(def_id) =
-                                            poly_trait_ref.trait_ref.trait_def_id()
-                                        {
-                                            yield def_id;
+
+                    if let Some(hir_id) = hir_id {
+                        let node = self.tcx.hir_node(hir_id);
+                        // If this is a `Self` bound in a trait, yield the trait itself.
+                        // Specifically, we don't need to look at any supertraits since
+                        // we already do that in `BoundVarContext::supertrait_hrtb_vars`.
+                        if let Res::SelfTyParam { trait_: _ } = expected_res
+                            && let hir::Node::Item(item) = node
+                            && let hir::ItemKind::Trait(..) = item.kind
+                        {
+                            // Yield the trait's def id. Supertraits will be
+                            // elaborated from that.
+                            yield item.owner_id.def_id.to_def_id();
+                        } else if let Some(generics) = node.generics() {
+                            for pred in generics.predicates {
+                                let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind
+                                else {
+                                    continue;
+                                };
+                                let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
+                                    pred.bounded_ty.kind
+                                else {
+                                    continue;
+                                };
+                                // Match the expected res.
+                                if bounded_path.res != expected_res {
+                                    continue;
+                                }
+                                for pred in pred.bounds {
+                                    match pred {
+                                        hir::GenericBound::Trait(poly_trait_ref) => {
+                                            if let Some(def_id) =
+                                                poly_trait_ref.trait_ref.trait_def_id()
+                                            {
+                                                yield def_id;
+                                            }
                                         }
+                                        hir::GenericBound::Outlives(_)
+                                        | hir::GenericBound::Use(_, _) => {}
                                     }
-                                    hir::GenericBound::Outlives(_)
-                                    | hir::GenericBound::Use(_, _) => {}
                                 }
                             }
                         }
                     }
+
+                    match *scope {
+                        Scope::Binder { s, .. }
+                        | Scope::Body { s, .. }
+                        | Scope::ObjectLifetimeDefault { s, .. }
+                        | Scope::Supertrait { s, .. }
+                        | Scope::TraitRefBoundary { s }
+                        | Scope::LateBoundary { s, .. }
+                        | Scope::Opaque { s, .. } => {
+                            scope = s;
+                        }
+                        Scope::Root { .. } => break,
+                    }
                 }
             },
         )
-        .fuse()
     }
 }