about summary refs log tree commit diff
path: root/compiler/rustc_ty_utils
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2023-02-16 18:12:53 -0300
committerSantiago Pastorino <spastorino@gmail.com>2023-02-19 11:57:38 -0300
commit45b0d9da6b463c73cf1f816e9cbe9483ebc84a6d (patch)
tree8a1a7a764b80c9b69273f021be236b024bcc09fe /compiler/rustc_ty_utils
parentb7dd609d9c3a6a336091e502caee8a10948cc2c3 (diff)
downloadrust-45b0d9da6b463c73cf1f816e9cbe9483ebc84a6d.tar.gz
rust-45b0d9da6b463c73cf1f816e9cbe9483ebc84a6d.zip
Make associated_items_for_impl_trait_in_trait handle impl traits on impls
Diffstat (limited to 'compiler/rustc_ty_utils')
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs78
1 files changed, 60 insertions, 18 deletions
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index ef725c48da6..0c3322d48f0 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -119,29 +119,58 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
 }
 
 fn associated_items_for_impl_trait_in_trait(tcx: TyCtxt<'_>, fn_def_id: DefId) -> &'_ [DefId] {
-    struct RPITVisitor {
-        rpits: Vec<LocalDefId>,
-    }
+    let parent_def_id = tcx.parent(fn_def_id);
 
-    impl<'v> Visitor<'v> for RPITVisitor {
-        fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
-            if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind {
-                self.rpits.push(item_id.owner_id.def_id)
+    match tcx.def_kind(parent_def_id) {
+        DefKind::Trait => {
+            struct RPITVisitor {
+                rpits: Vec<LocalDefId>,
             }
-            intravisit::walk_ty(self, ty)
-        }
-    }
 
-    let mut visitor = RPITVisitor { rpits: Vec::new() };
+            impl<'v> Visitor<'v> for RPITVisitor {
+                fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
+                    if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind {
+                        self.rpits.push(item_id.owner_id.def_id)
+                    }
+                    intravisit::walk_ty(self, ty)
+                }
+            }
 
-    if let Some(output) = tcx.hir().get_fn_output(fn_def_id.expect_local()) {
-        visitor.visit_fn_ret_ty(output);
+            let mut visitor = RPITVisitor { rpits: Vec::new() };
 
-        tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| {
-            tcx.associated_item_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id()
-        }))
-    } else {
-        &[]
+            if let Some(output) = tcx.hir().get_fn_output(fn_def_id.expect_local()) {
+                visitor.visit_fn_ret_ty(output);
+
+                tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| {
+                    tcx.associated_item_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id()
+                }))
+            } else {
+                &[]
+            }
+        }
+
+        DefKind::Impl { .. } => {
+            let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { return &[] };
+
+            tcx.arena.alloc_from_iter(
+                tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id).iter().map(
+                    move |trait_assoc_def_id| {
+                        impl_associated_item_for_impl_trait_in_trait(
+                            tcx,
+                            trait_assoc_def_id.expect_local(),
+                            fn_def_id.expect_local(),
+                        )
+                        .to_def_id()
+                    },
+                ),
+            )
+        }
+
+        def_kind => bug!(
+            "associated_items_for_impl_trait_in_trait: {:?} should be Trait or Impl but is {:?}",
+            parent_def_id,
+            def_kind
+        ),
     }
 }
 
@@ -158,3 +187,16 @@ fn associated_item_for_impl_trait_in_trait(
         tcx.at(span).create_def(trait_def_id.expect_local(), DefPathData::ImplTraitAssocTy);
     trait_assoc_ty.def_id()
 }
+
+fn impl_associated_item_for_impl_trait_in_trait(
+    tcx: TyCtxt<'_>,
+    trait_assoc_def_id: LocalDefId,
+    impl_fn_def_id: LocalDefId,
+) -> LocalDefId {
+    let impl_def_id = tcx.local_parent(impl_fn_def_id);
+
+    let span = tcx.def_span(trait_assoc_def_id);
+    let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy);
+
+    impl_assoc_ty.def_id()
+}