Skip to content

Commit 076e627

Browse files
authored
Rollup merge of rust-lang#108141 - spastorino:add_rpitit_queries, r=compiler-errors
Add rpitit queries This is part of the changes we are making to lower RPITITs as an associated type. The rest of the stuff will follow under a `-Z` flag. I still need to add comments to the code, explain stuff and also I'd need to avoid encoding in metadata when rpitit queries return `&[]` r? `@compiler-errors`
2 parents e781a6f + 5e763b6 commit 076e627

File tree

11 files changed

+158
-13
lines changed

11 files changed

+158
-13
lines changed

compiler/rustc_hir/src/definitions.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ pub enum DefPathData {
280280
AnonConst,
281281
/// An `impl Trait` type node.
282282
ImplTrait,
283+
/// `impl Trait` generated associated type node.
284+
ImplTraitAssocTy,
283285
}
284286

285287
impl Definitions {
@@ -403,7 +405,7 @@ impl DefPathData {
403405
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
404406

405407
Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst
406-
| ImplTrait => None,
408+
| ImplTrait | ImplTraitAssocTy => None,
407409
}
408410
}
409411

@@ -422,7 +424,7 @@ impl DefPathData {
422424
ClosureExpr => DefPathDataName::Anon { namespace: sym::closure },
423425
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
424426
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
425-
ImplTrait => DefPathDataName::Anon { namespace: sym::opaque },
427+
ImplTrait | ImplTraitAssocTy => DefPathDataName::Anon { namespace: sym::opaque },
426428
}
427429
}
428430
}

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+2
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ provide! { tcx, def_id, other, cdata,
254254
.process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
255255
}
256256

257+
associated_items_for_impl_trait_in_trait => { table_defaulted_array }
258+
257259
visibility => { cdata.get_visibility(def_id.index) }
258260
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
259261
adt_destructor => {

compiler/rustc_metadata/src/rmeta/encoder.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,11 @@ fn should_encode_trait_impl_trait_tys(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
11291129
})
11301130
}
11311131

1132+
// Return `false` to avoid encoding impl trait in trait, while we don't use the query.
1133+
fn should_encode_fn_impl_trait_in_trait<'tcx>(_tcx: TyCtxt<'tcx>, _def_id: DefId) -> bool {
1134+
false
1135+
}
1136+
11321137
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11331138
fn encode_attrs(&mut self, def_id: LocalDefId) {
11341139
let tcx = self.tcx;
@@ -1137,8 +1142,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11371142
is_doc_hidden: false,
11381143
};
11391144
let attr_iter = tcx
1140-
.hir()
1141-
.attrs(tcx.hir().local_def_id_to_hir_id(def_id))
1145+
.opt_local_def_id_to_hir_id(def_id)
1146+
.map_or(Default::default(), |hir_id| tcx.hir().attrs(hir_id))
11421147
.iter()
11431148
.filter(|attr| analyze_attr(attr, &mut state));
11441149

@@ -1211,6 +1216,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
12111216
{
12121217
record!(self.tables.trait_impl_trait_tys[def_id] <- table);
12131218
}
1219+
if should_encode_fn_impl_trait_in_trait(tcx, def_id) {
1220+
let table = tcx.associated_items_for_impl_trait_in_trait(def_id);
1221+
record_defaulted_array!(self.tables.associated_items_for_impl_trait_in_trait[def_id] <- table);
1222+
}
12141223
}
12151224

12161225
let inherent_impls = tcx.with_stable_hashing_context(|hcx| {

compiler/rustc_metadata/src/rmeta/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ define_tables! {
354354
explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
355355
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
356356
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
357+
associated_items_for_impl_trait_in_trait: Table<DefIndex, LazyArray<DefId>>,
357358

358359
- optional:
359360
attributes: Table<DefIndex, LazyArray<ast::Attribute>>,

compiler/rustc_middle/src/hir/map/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,13 @@ impl<'hir> Map<'hir> {
849849
}
850850
}
851851

852+
pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> {
853+
match self.tcx.hir_owner(OwnerId { def_id }) {
854+
Some(Owner { node, .. }) => node.fn_decl().map(|fn_decl| &fn_decl.output),
855+
_ => None,
856+
}
857+
}
858+
852859
pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
853860
match self.find(id) {
854861
Some(Node::Variant(variant)) => variant,

compiler/rustc_middle/src/hir/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,13 @@ pub fn provide(providers: &mut Providers) {
121121
let node = owner.node();
122122
Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies })
123123
};
124-
providers.local_def_id_to_hir_id = |tcx, id| {
124+
providers.opt_local_def_id_to_hir_id = |tcx, id| {
125125
let owner = tcx.hir_crate(()).owners[id].map(|_| ());
126-
match owner {
126+
Some(match owner {
127127
MaybeOwner::Owner(_) => HirId::make_owner(id),
128128
MaybeOwner::Phantom => bug!("No HirId for {:?}", id),
129129
MaybeOwner::NonOwner(hir_id) => hir_id,
130-
}
130+
})
131131
};
132132
providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes);
133133
providers.hir_owner_parent = |tcx, id| {

compiler/rustc_middle/src/query/mod.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,10 @@ rustc_queries! {
8585
desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
8686
}
8787

88-
/// Gives access to the HIR ID for the given `LocalDefId` owner `key`.
88+
/// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any.
8989
///
90-
/// This can be conveniently accessed by methods on `tcx.hir()`.
91-
/// Avoid calling this query directly.
92-
query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId {
90+
/// Definitions that were generated with no HIR, would be feeded to return `None`.
91+
query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
9392
desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
9493
}
9594

@@ -767,6 +766,26 @@ rustc_queries! {
767766
desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) }
768767
}
769768

769+
/// Given `fn_def_id` of a trait or of an impl that implements a given trait:
770+
/// if `fn_def_id` is the def id of a function defined inside a trait, then it creates and returns
771+
/// the associated items that correspond to each impl trait in return position for that trait.
772+
/// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it
773+
/// creates and returns the associated items that correspond to each impl trait in return position
774+
/// of the implemented trait.
775+
query associated_items_for_impl_trait_in_trait(fn_def_id: DefId) -> &'tcx [DefId] {
776+
desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) }
777+
cache_on_disk_if { fn_def_id.is_local() }
778+
separate_provide_extern
779+
}
780+
781+
/// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
782+
/// associated item.
783+
query associated_item_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
784+
desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
785+
cache_on_disk_if { true }
786+
separate_provide_extern
787+
}
788+
770789
/// Given an `impl_id`, return the trait it implements.
771790
/// Return `None` if this is an inherent impl.
772791
query impl_trait_ref(impl_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {

compiler/rustc_middle/src/ty/context.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2451,6 +2451,10 @@ impl<'tcx> TyCtxt<'tcx> {
24512451
)
24522452
}
24532453

2454+
pub fn local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId {
2455+
self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
2456+
}
2457+
24542458
pub fn trait_solver_next(self) -> bool {
24552459
self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
24562460
}

compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
396396
hir::definitions::DefPathData::CrateRoot
397397
| hir::definitions::DefPathData::Use
398398
| hir::definitions::DefPathData::GlobalAsm
399+
| hir::definitions::DefPathData::ImplTraitAssocTy
399400
| hir::definitions::DefPathData::MacroNs(..)
400401
| hir::definitions::DefPathData::LifetimeNs(..) => {
401402
bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);

compiler/rustc_symbol_mangling/src/v0.rs

+1
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
791791
| DefPathData::Use
792792
| DefPathData::GlobalAsm
793793
| DefPathData::Impl
794+
| DefPathData::ImplTraitAssocTy
794795
| DefPathData::MacroNs(_)
795796
| DefPathData::LifetimeNs(_) => {
796797
bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)

compiler/rustc_ty_utils/src/assoc.rs

+101-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_hir as hir;
3-
use rustc_hir::def_id::DefId;
4-
use rustc_middle::ty::{self, TyCtxt};
3+
use rustc_hir::def::DefKind;
4+
use rustc_hir::def_id::{DefId, LocalDefId};
5+
use rustc_hir::definitions::DefPathData;
6+
use rustc_hir::intravisit::{self, Visitor};
7+
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
58

69
pub fn provide(providers: &mut ty::query::Providers) {
710
*providers = ty::query::Providers {
811
associated_item,
912
associated_item_def_ids,
1013
associated_items,
14+
associated_items_for_impl_trait_in_trait,
15+
associated_item_for_impl_trait_in_trait,
1116
impl_item_implementor_ids,
1217
..*providers
1318
};
@@ -112,3 +117,97 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
112117
fn_has_self_parameter: has_self,
113118
}
114119
}
120+
121+
/// Given an `fn_def_id` of a trait or of an impl that implements a given trait:
122+
/// if `fn_def_id` is the def id of a function defined inside a trait, then it creates and returns
123+
/// the associated items that correspond to each impl trait in return position for that trait.
124+
/// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it
125+
/// creates and returns the associated items that correspond to each impl trait in return position
126+
/// of the implemented trait.
127+
fn associated_items_for_impl_trait_in_trait(tcx: TyCtxt<'_>, fn_def_id: DefId) -> &'_ [DefId] {
128+
let parent_def_id = tcx.parent(fn_def_id);
129+
130+
match tcx.def_kind(parent_def_id) {
131+
DefKind::Trait => {
132+
struct RPITVisitor {
133+
rpits: Vec<LocalDefId>,
134+
}
135+
136+
impl<'v> Visitor<'v> for RPITVisitor {
137+
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
138+
if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind {
139+
self.rpits.push(item_id.owner_id.def_id)
140+
}
141+
intravisit::walk_ty(self, ty)
142+
}
143+
}
144+
145+
let mut visitor = RPITVisitor { rpits: Vec::new() };
146+
147+
if let Some(output) = tcx.hir().get_fn_output(fn_def_id.expect_local()) {
148+
visitor.visit_fn_ret_ty(output);
149+
150+
tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| {
151+
tcx.associated_item_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id()
152+
}))
153+
} else {
154+
&[]
155+
}
156+
}
157+
158+
DefKind::Impl { .. } => {
159+
let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { return &[] };
160+
161+
tcx.arena.alloc_from_iter(
162+
tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id).iter().map(
163+
move |trait_assoc_def_id| {
164+
impl_associated_item_for_impl_trait_in_trait(
165+
tcx,
166+
trait_assoc_def_id.expect_local(),
167+
fn_def_id.expect_local(),
168+
)
169+
.to_def_id()
170+
},
171+
),
172+
)
173+
}
174+
175+
def_kind => bug!(
176+
"associated_items_for_impl_trait_in_trait: {:?} should be Trait or Impl but is {:?}",
177+
parent_def_id,
178+
def_kind
179+
),
180+
}
181+
}
182+
183+
/// Given an `opaque_ty_def_id` corresponding to an impl trait in trait, create and return the
184+
/// corresponding associated item.
185+
fn associated_item_for_impl_trait_in_trait(
186+
tcx: TyCtxt<'_>,
187+
opaque_ty_def_id: LocalDefId,
188+
) -> LocalDefId {
189+
let fn_def_id = tcx.impl_trait_in_trait_parent(opaque_ty_def_id.to_def_id());
190+
let trait_def_id = tcx.parent(fn_def_id);
191+
assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
192+
193+
let span = tcx.def_span(opaque_ty_def_id);
194+
let trait_assoc_ty =
195+
tcx.at(span).create_def(trait_def_id.expect_local(), DefPathData::ImplTraitAssocTy);
196+
trait_assoc_ty.def_id()
197+
}
198+
199+
/// Given an `trait_assoc_def_id` that corresponds to a previously synthethized impl trait in trait
200+
/// into an associated type and an `impl_def_id` corresponding to an impl block, create and return
201+
/// the corresponding associated item inside the impl block.
202+
fn impl_associated_item_for_impl_trait_in_trait(
203+
tcx: TyCtxt<'_>,
204+
trait_assoc_def_id: LocalDefId,
205+
impl_fn_def_id: LocalDefId,
206+
) -> LocalDefId {
207+
let impl_def_id = tcx.local_parent(impl_fn_def_id);
208+
209+
let span = tcx.def_span(trait_assoc_def_id);
210+
let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy);
211+
212+
impl_assoc_ty.def_id()
213+
}

0 commit comments

Comments
 (0)