about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-07-30 20:31:27 +0000
committerMichael Goulet <michael@errs.io>2023-07-30 20:31:27 +0000
commit23776619a84260536c3fbd39acbcf4c712736557 (patch)
tree8cc1d1e05179a859e42a57619a277f2d50a080c6
parenta8be6e070f02fca6e5ab851e10e29d45c3a0217c (diff)
downloadrust-23776619a84260536c3fbd39acbcf4c712736557.tar.gz
rust-23776619a84260536c3fbd39acbcf4c712736557.zip
Remap explicit item bounds of RPITIT's opaque back to ty::Opaque
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs48
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr24
3 files changed, 47 insertions, 27 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 758e9dc7230..4b7743fae53 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -3,7 +3,7 @@ use crate::astconv::{AstConv, PredicateFilter};
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::Span;
 
@@ -113,7 +113,7 @@ pub(super) fn explicit_item_bounds(
             ..
         }) => associated_type_bounds(tcx, def_id, bounds, *span),
         hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
+            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: false, .. }),
             span,
             ..
         }) => {
@@ -121,6 +121,27 @@ pub(super) fn explicit_item_bounds(
             let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
             opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
         }
+        // Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking
+        // for the item bounds of the *opaques* in a trait's default method signature, we
+        // need to map these projections back to opaques.
+        hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: true, origin, .. }),
+            span,
+            ..
+        }) => {
+            let (hir::OpaqueTyOrigin::FnReturn(fn_def_id)
+            | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) = *origin
+            else {
+                bug!()
+            };
+            let args = GenericArgs::identity_for_item(tcx, def_id);
+            let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
+            tcx.arena.alloc_slice(
+                &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
+                    .to_vec()
+                    .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
+            )
+        }
         hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
         _ => bug!("item_bounds called on {:?}", def_id),
     };
@@ -135,3 +156,26 @@ pub(super) fn item_bounds(
         tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
     })
 }
+
+struct AssocTyToOpaque<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    fn_def_id: DefId,
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTyToOpaque<'tcx> {
+    fn interner(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if let ty::Alias(ty::Projection, projection_ty) = ty.kind()
+            && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. })
+                = self.tcx.opt_rpitit_info(projection_ty.def_id)
+            && fn_def_id == self.fn_def_id
+        {
+            self.tcx.type_of(projection_ty.def_id).instantiate(self.tcx, projection_ty.args)
+        } else {
+            ty
+        }
+    }
+}
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
index 0558d95128f..25133214dc6 100644
--- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -1,5 +1,5 @@
 // edition:2021
-// known-bug: #108304
+// check-pass
 
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr
deleted file mode 100644
index b5fc9d44d36..00000000000
--- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/default-body-with-rpit.rs:11:9
-   |
-LL |         ""
-   |         ^^ expected `impl Debug`, got `&'static str`
-   |
-note: previous use here
-  --> $DIR/default-body-with-rpit.rs:10:39
-   |
-LL |       async fn baz(&self) -> impl Debug {
-   |  _______________________________________^
-LL | |         ""
-LL | |     }
-   | |_____^
-
-error[E0720]: cannot resolve opaque type
-  --> $DIR/default-body-with-rpit.rs:10:28
-   |
-LL |     async fn baz(&self) -> impl Debug {
-   |                            ^^^^^^^^^^ cannot resolve opaque type
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0720`.