diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 84452979aa589..73627a818e5df 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -576,7 +576,6 @@ fn find_and_apply_rpit_args<'tcx>( struct Visitor<'tcx> { tcx: TyCtxt<'tcx>, opaque: DefId, - function: DefId, seen: FxHashSet, } impl<'tcx> ty::TypeVisitor> for Visitor<'tcx> { @@ -601,19 +600,6 @@ fn find_and_apply_rpit_args<'tcx>( } } } - ty::Alias(ty::Projection, alias) => { - if self.tcx.is_impl_trait_in_trait(alias.def_id) - && self.tcx.impl_trait_in_trait_parent_fn(alias.def_id) == self.function - { - // If we're lowering to associated item, install the opaque type which is just - // the `type_of` of the trait's associated item. If we're using the old lowering - // strategy, then just reinterpret the associated type like an opaque :^) - self.tcx - .type_of(alias.def_id) - .instantiate(self.tcx, alias.args) - .visit_with(self)?; - } - } ty::Alias(ty::Weak, alias) => { self.tcx .type_of(alias.def_id) @@ -627,7 +613,7 @@ fn find_and_apply_rpit_args<'tcx>( } } if let ControlFlow::Break(args) = - ret.visit_with(&mut Visitor { tcx, function, opaque, seen: Default::default() }) + ret.visit_with(&mut Visitor { tcx, opaque, seen: Default::default() }) { trace!(?args); trace!("expected: {hidden_ty:#?}"); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 758e9dc723047..4b7743fae53b9 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> 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/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 119ed2fa4082a..d5f03a6aaed12 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -558,10 +558,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let pred = clause.kind().rebind(match clause.kind().skip_binder() { ty::ClauseKind::Trait(trait_pred) => { - // FIXME(rpitit): This will need to be fixed when we move to associated types assert!(matches!( *trait_pred.trait_ref.self_ty().kind(), - ty::Alias(_, ty::AliasTy { def_id, args: alias_args, .. }) + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args: alias_args, .. }) if def_id == rpit_def_id && args == alias_args )); ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty)) @@ -569,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ClauseKind::Projection(mut proj_pred) => { assert!(matches!( *proj_pred.projection_ty.self_ty().kind(), - ty::Alias(_, ty::AliasTy { def_id, args: alias_args, .. }) + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args: alias_args, .. }) if def_id == rpit_def_id && args == alias_args )); proj_pred = proj_pred.with_self_ty(self.tcx, ty); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index ca3b595d238e1..0624a4baf79db 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -723,11 +723,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter_instantiated_copied(self.tcx, args) .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, ty::Error(_) => return None, - ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self - .tcx - .explicit_item_bounds(proj.def_id) - .iter_instantiated_copied(self.tcx, proj.args) - .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, _ => span_bug!( self.tcx.def_span(expr_def_id), "async fn generator return type not an inference variable: {ret_ty}" diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 945136fbff2e9..9c90b7045862f 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -619,13 +619,6 @@ impl<'tcx> InferCtxt<'tcx> { { hidden_ty } - // FIXME(RPITIT): This can go away when we move to associated types - // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too. - ty::Alias(ty::Projection, ty::AliasTy { def_id: def_id2, args: args2, .. }) - if def_id == def_id2 && args == args2 => - { - hidden_ty - } _ => ty, }, lt_op: |lt| lt, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 329de02a9b5f9..2b4c834f766b9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2625,19 +2625,6 @@ impl<'tcx> TyCtxt<'tcx> { matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait)) } - pub fn impl_trait_in_trait_parent_fn(self, mut def_id: DefId) -> DefId { - match self.opt_rpitit_info(def_id) { - Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) - | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id, - None => { - while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn { - def_id = self.parent(def_id); - } - def_id - } - } - } - /// Returns the `DefId` of the item within which the `impl Trait` is declared. /// For type-alias-impl-trait this is the `type` alias. /// For impl-trait-in-assoc-type this is the assoc type. diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 4c896712b1b92..791a1f4fa99a2 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -181,8 +181,10 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind() - && self.tcx.is_impl_trait_in_trait(unshifted_alias_ty.def_id) - && self.tcx.impl_trait_in_trait_parent_fn(unshifted_alias_ty.def_id) == self.fn_def_id + && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. } + | ty::ImplTraitInTraitData::Impl { fn_def_id, .. }) + = self.tcx.opt_rpitit_info(unshifted_alias_ty.def_id) + && fn_def_id == self.fn_def_id && self.seen.insert(unshifted_alias_ty.def_id) { // We have entered some binders as we've walked into the 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 0558d95128f4a..25133214dc624 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 b5fc9d44d3687..0000000000000 --- 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`.