Skip to content

Commit 73a2281

Browse files
committed
Auto merge of rust-lang#127658 - compiler-errors:precise-capturing-rustdoc-cross, r=fmease
Add cross-crate precise capturing support to rustdoc Follow-up to rust-lang#127632. Fixes rust-lang#127228. r? `@fmease` Tracking: * rust-lang#123432
2 parents 1afc5fd + da2054f commit 73a2281

File tree

8 files changed

+87
-17
lines changed

8 files changed

+87
-17
lines changed

compiler/rustc_hir_analysis/src/collect.rs

+21
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ pub fn provide(providers: &mut Providers) {
8484
coroutine_kind,
8585
coroutine_for_closure,
8686
is_type_alias_impl_trait,
87+
rendered_precise_capturing_args,
8788
..*providers
8889
};
8990
}
@@ -1882,3 +1883,23 @@ fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool
18821883
_ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
18831884
}
18841885
}
1886+
1887+
fn rendered_precise_capturing_args<'tcx>(
1888+
tcx: TyCtxt<'tcx>,
1889+
def_id: LocalDefId,
1890+
) -> Option<&'tcx [Symbol]> {
1891+
if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1892+
tcx.opt_rpitit_info(def_id.to_def_id())
1893+
{
1894+
return tcx.rendered_precise_capturing_args(opaque_def_id);
1895+
}
1896+
1897+
tcx.hir_node_by_def_id(def_id).expect_item().expect_opaque_ty().bounds.iter().find_map(
1898+
|bound| match bound {
1899+
hir::GenericBound::Use(args, ..) => {
1900+
Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| arg.name())))
1901+
}
1902+
_ => None,
1903+
},
1904+
)
1905+
}

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

+10
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>> ProcessQueryValue<'
7272
}
7373
}
7474

75+
impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>>
76+
ProcessQueryValue<'tcx, Option<&'tcx [T]>> for Option<DecodeIterator<'a, 'tcx, T>>
77+
{
78+
#[inline(always)]
79+
fn process_decoded(self, tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> Option<&'tcx [T]> {
80+
if let Some(iter) = self { Some(&*tcx.arena.alloc_from_iter(iter)) } else { None }
81+
}
82+
}
83+
7584
impl ProcessQueryValue<'_, Option<DeprecationEntry>> for Option<Deprecation> {
7685
#[inline(always)]
7786
fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<DeprecationEntry> {
@@ -249,6 +258,7 @@ provide! { tcx, def_id, other, cdata,
249258
.process_decoded(tcx, || panic!("{def_id:?} does not have coerce_unsized_info"))) }
250259
mir_const_qualif => { table }
251260
rendered_const => { table }
261+
rendered_precise_capturing_args => { table }
252262
asyncness => { table_direct }
253263
fn_arg_names => { table }
254264
coroutine_kind => { table_direct }

compiler/rustc_metadata/src/rmeta/encoder.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1496,6 +1496,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14961496
self.tables
14971497
.is_type_alias_impl_trait
14981498
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
1499+
self.encode_precise_capturing_args(def_id);
14991500
}
15001501
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
15011502
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
@@ -1635,13 +1636,22 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16351636
self.tables.assumed_wf_types_for_rpitit[def_id]
16361637
<- self.tcx.assumed_wf_types_for_rpitit(def_id)
16371638
);
1639+
self.encode_precise_capturing_args(def_id);
16381640
}
16391641
}
16401642
if item.is_effects_desugaring {
16411643
self.tables.is_effects_desugaring.set(def_id.index, true);
16421644
}
16431645
}
16441646

1647+
fn encode_precise_capturing_args(&mut self, def_id: DefId) {
1648+
let Some(precise_capturing_args) = self.tcx.rendered_precise_capturing_args(def_id) else {
1649+
return;
1650+
};
1651+
1652+
record_array!(self.tables.rendered_precise_capturing_args[def_id] <- precise_capturing_args);
1653+
}
1654+
16451655
fn encode_mir(&mut self) {
16461656
if self.is_proc_macro {
16471657
return;

compiler/rustc_metadata/src/rmeta/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ define_tables! {
442442
coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
443443
mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
444444
rendered_const: Table<DefIndex, LazyValue<String>>,
445+
rendered_precise_capturing_args: Table<DefIndex, LazyArray<Symbol>>,
445446
asyncness: Table<DefIndex, ty::Asyncness>,
446447
fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
447448
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,

compiler/rustc_middle/src/query/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1261,13 +1261,21 @@ rustc_queries! {
12611261
desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
12621262
separate_provide_extern
12631263
}
1264+
12641265
/// Gets the rendered value of the specified constant or associated constant.
12651266
/// Used by rustdoc.
12661267
query rendered_const(def_id: DefId) -> &'tcx String {
12671268
arena_cache
12681269
desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) }
12691270
separate_provide_extern
12701271
}
1272+
1273+
/// Gets the rendered precise capturing args for an opaque for use in rustdoc.
1274+
query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [Symbol]> {
1275+
desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) }
1276+
separate_provide_extern
1277+
}
1278+
12711279
query impl_parent(def_id: DefId) -> Option<DefId> {
12721280
desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) }
12731281
separate_provide_extern

src/librustdoc/clean/mod.rs

+17-17
Original file line numberDiff line numberDiff line change
@@ -468,13 +468,7 @@ fn clean_projection<'tcx>(
468468
def_id: Option<DefId>,
469469
) -> Type {
470470
if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) {
471-
let bounds = cx
472-
.tcx
473-
.explicit_item_bounds(ty.skip_binder().def_id)
474-
.iter_instantiated_copied(cx.tcx, ty.skip_binder().args)
475-
.map(|(pred, _)| pred)
476-
.collect::<Vec<_>>();
477-
return clean_middle_opaque_bounds(cx, bounds);
471+
return clean_middle_opaque_bounds(cx, ty.skip_binder().def_id, ty.skip_binder().args);
478472
}
479473

480474
let trait_ = clean_trait_ref_with_constraints(
@@ -2260,13 +2254,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
22602254
*cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
22612255
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
22622256
// by looking up the bounds associated with the def_id.
2263-
let bounds = cx
2264-
.tcx
2265-
.explicit_item_bounds(def_id)
2266-
.iter_instantiated_copied(cx.tcx, args)
2267-
.map(|(bound, _)| bound)
2268-
.collect::<Vec<_>>();
2269-
let ty = clean_middle_opaque_bounds(cx, bounds);
2257+
let ty = clean_middle_opaque_bounds(cx, def_id, args);
22702258
if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
22712259
*count -= 1;
22722260
if *count == 0 {
@@ -2289,12 +2277,20 @@ pub(crate) fn clean_middle_ty<'tcx>(
22892277

22902278
fn clean_middle_opaque_bounds<'tcx>(
22912279
cx: &mut DocContext<'tcx>,
2292-
bounds: Vec<ty::Clause<'tcx>>,
2280+
impl_trait_def_id: DefId,
2281+
args: ty::GenericArgsRef<'tcx>,
22932282
) -> Type {
22942283
let mut has_sized = false;
2284+
2285+
let bounds: Vec<_> = cx
2286+
.tcx
2287+
.explicit_item_bounds(impl_trait_def_id)
2288+
.iter_instantiated_copied(cx.tcx, args)
2289+
.collect();
2290+
22952291
let mut bounds = bounds
22962292
.iter()
2297-
.filter_map(|bound| {
2293+
.filter_map(|(bound, _)| {
22982294
let bound_predicate = bound.kind();
22992295
let trait_ref = match bound_predicate.skip_binder() {
23002296
ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
@@ -2313,7 +2309,7 @@ fn clean_middle_opaque_bounds<'tcx>(
23132309

23142310
let bindings: ThinVec<_> = bounds
23152311
.iter()
2316-
.filter_map(|bound| {
2312+
.filter_map(|(bound, _)| {
23172313
if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
23182314
if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() {
23192315
Some(AssocItemConstraint {
@@ -2353,6 +2349,10 @@ fn clean_middle_opaque_bounds<'tcx>(
23532349
bounds.insert(0, GenericBound::sized(cx));
23542350
}
23552351

2352+
if let Some(args) = cx.tcx.rendered_precise_capturing_args(impl_trait_def_id) {
2353+
bounds.push(GenericBound::Use(args.to_vec()));
2354+
}
2355+
23562356
ImplTrait(bounds)
23572357
}
23582358

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(precise_capturing)]
2+
3+
pub fn cross_crate_empty() -> impl Sized + use<> {}
4+
5+
pub fn cross_crate_missing() -> impl Sized {}
6+
7+
pub fn cross_crate_args<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}

tests/rustdoc/impl-trait-precise-capturing.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
//@ aux-build:precise-capturing.rs
2+
13
#![crate_name = "foo"]
24
#![feature(precise_capturing)]
35

6+
extern crate precise_capturing;
7+
48
//@ has foo/fn.two.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'b, 'a>"
59
pub fn two<'a, 'b, 'c>() -> impl Sized + use<'b, 'a /* no 'c */> {}
610

@@ -12,3 +16,12 @@ pub fn none() -> impl Sized + use<> {}
1216

1317
//@ has foo/fn.first.html '//section[@id="main-content"]//pre' "-> impl use<> + Sized"
1418
pub fn first() -> impl use<> + Sized {}
19+
20+
//@ has foo/fn.cross_crate_empty.html '//section[@id="main-content"]//pre' "-> impl Sized + use<>"
21+
pub use precise_capturing::cross_crate_empty;
22+
23+
//@ matches foo/fn.cross_crate_missing.html '//section[@id="main-content"]//pre' "-> impl Sized$"
24+
pub use precise_capturing::cross_crate_missing;
25+
26+
//@ has foo/fn.cross_crate_args.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'a, T, N>"
27+
pub use precise_capturing::cross_crate_args;

0 commit comments

Comments
 (0)