Walk return-position impl trait in trait deeply in associated_item_def_ids

This commit is contained in:
Michael Goulet 2023-03-21 18:06:04 +00:00 committed by Santiago Pastorino
parent 478cbb42b7
commit 76b0cf812b
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF
3 changed files with 36 additions and 22 deletions

View file

@ -1,3 +1,4 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
@ -196,20 +197,26 @@ fn associated_types_for_impl_traits_in_associated_fn(
match tcx.def_kind(parent_def_id) { match tcx.def_kind(parent_def_id) {
DefKind::Trait => { DefKind::Trait => {
struct RPITVisitor { struct RPITVisitor<'tcx> {
rpits: Vec<LocalDefId>, rpits: FxIndexSet<LocalDefId>,
tcx: TyCtxt<'tcx>,
} }
impl<'v> Visitor<'v> for RPITVisitor { impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind { if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind
self.rpits.push(item_id.owner_id.def_id) && self.rpits.insert(item_id.owner_id.def_id)
{
let opaque_item = self.tcx.hir().expect_item(item_id.owner_id.def_id).expect_opaque_ty();
for bound in opaque_item.bounds {
intravisit::walk_param_bound(self, bound);
}
} }
intravisit::walk_ty(self, ty) intravisit::walk_ty(self, ty)
} }
} }
let mut visitor = RPITVisitor { rpits: Vec::new() }; let mut visitor = RPITVisitor { tcx, rpits: FxIndexSet::default() };
if let Some(output) = tcx.hir().get_fn_output(fn_def_id) { if let Some(output) = tcx.hir().get_fn_output(fn_def_id) {
visitor.visit_fn_ret_ty(output); visitor.visit_fn_ret_ty(output);
@ -227,13 +234,9 @@ fn associated_types_for_impl_traits_in_associated_fn(
tcx.arena.alloc_from_iter( tcx.arena.alloc_from_iter(
tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map( tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map(
move |trait_assoc_def_id| { move |&trait_assoc_def_id| {
associated_type_for_impl_trait_in_impl( associated_type_for_impl_trait_in_impl(tcx, trait_assoc_def_id, fn_def_id)
tcx, .to_def_id()
trait_assoc_def_id.expect_local(),
fn_def_id,
)
.to_def_id()
}, },
), ),
) )
@ -355,7 +358,7 @@ fn associated_type_for_impl_trait_in_trait(
/// that inherits properties that we infer from the method and the associated type. /// that inherits properties that we infer from the method and the associated type.
fn associated_type_for_impl_trait_in_impl( fn associated_type_for_impl_trait_in_impl(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
trait_assoc_def_id: LocalDefId, trait_assoc_def_id: DefId,
impl_fn_def_id: LocalDefId, impl_fn_def_id: LocalDefId,
) -> LocalDefId { ) -> LocalDefId {
let impl_local_def_id = tcx.local_parent(impl_fn_def_id); let impl_local_def_id = tcx.local_parent(impl_fn_def_id);
@ -380,7 +383,7 @@ fn associated_type_for_impl_trait_in_impl(
name: kw::Empty, name: kw::Empty,
kind: ty::AssocKind::Type, kind: ty::AssocKind::Type,
def_id, def_id,
trait_item_def_id: Some(trait_assoc_def_id.to_def_id()), trait_item_def_id: Some(trait_assoc_def_id),
container: ty::ImplContainer, container: ty::ImplContainer,
fn_has_self_parameter: false, fn_has_self_parameter: false,
opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }), opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),

View file

@ -2,12 +2,13 @@
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait)]
use std::ops::Deref;
pub trait Foo { pub trait Foo {
fn bar() -> impl Sized; fn bar() -> impl Deref<Target = impl Sized>;
} }
pub struct Foreign; pub struct Foreign;
impl Foo for Foreign { impl Foo for Foreign {
fn bar() {} fn bar() -> &'static () { &() }
} }

View file

@ -5,7 +5,17 @@
extern crate rpitit; extern crate rpitit;
fn main() { use std::sync::Arc;
// Witness an RPITIT from another crate
let () = <rpitit::Foreign as rpitit::Foo>::bar(); // Implement an RPITIT from another crate.
struct Local;
impl rpitit::Foo for Local {
fn bar() -> Arc<String> { Arc::new(String::new()) }
}
fn main() {
// Witness an RPITIT from another crate.
let &() = <rpitit::Foreign as rpitit::Foo>::bar();
let x: Arc<String> = <Local as rpitit::Foo>::bar();
} }