Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit b7afd35

Browse files
committed
Auto merge of rust-lang#127658 - compiler-errors:precise-capturing-rustdoc-cross, r=<try>
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 5d76a13 + a792b45 commit b7afd35

File tree

17 files changed

+140
-21
lines changed

17 files changed

+140
-21
lines changed

‎compiler/rustc_hir/src/hir.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,6 +2708,13 @@ impl PreciseCapturingArg<'_> {
27082708
PreciseCapturingArg::Param(param) => param.hir_id,
27092709
}
27102710
}
2711+
2712+
pub fn name(self) -> Symbol {
2713+
match self {
2714+
PreciseCapturingArg::Lifetime(lt) => lt.ident.name,
2715+
PreciseCapturingArg::Param(param) => param.ident.name,
2716+
}
2717+
}
27112718
}
27122719

27132720
/// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param

‎compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub fn provide(providers: &mut Providers) {
8686
coroutine_for_closure,
8787
is_type_alias_impl_trait,
8888
find_field,
89+
rendered_precise_capturing_args,
8990
..*providers
9091
};
9192
}
@@ -1899,3 +1900,23 @@ fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool
18991900
_ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
19001901
}
19011902
}
1903+
1904+
fn rendered_precise_capturing_args<'tcx>(
1905+
tcx: TyCtxt<'tcx>,
1906+
def_id: LocalDefId,
1907+
) -> Option<&'tcx [Symbol]> {
1908+
if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1909+
tcx.opt_rpitit_info(def_id.to_def_id())
1910+
{
1911+
return tcx.rendered_precise_capturing_args(opaque_def_id);
1912+
}
1913+
1914+
tcx.hir_node_by_def_id(def_id).expect_item().expect_opaque_ty().bounds.iter().find_map(
1915+
|bound| match bound {
1916+
hir::GenericBound::Use(args, ..) => {
1917+
Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| arg.name())))
1918+
}
1919+
_ => None,
1920+
},
1921+
)
1922+
}

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

Lines changed: 10 additions & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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)
@@ -1636,12 +1637,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16361637
<- self.tcx.assumed_wf_types_for_rpitit(def_id)
16371638
);
16381639
}
1640+
self.encode_precise_capturing_args(def_id);
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,13 +1261,20 @@ 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+
/// Gets the rendered precise capturing args for an opaque for use in rustdoc.
1273+
query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [Symbol]> {
1274+
desc { |tcx| "computing precise capturing args for `{}`", tcx.def_path_str(def_id) }
1275+
separate_provide_extern
1276+
}
1277+
12711278
query impl_parent(def_id: DefId) -> Option<DefId> {
12721279
desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) }
12731280
separate_provide_extern

‎rustfmt.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ ignore = [
2222
"/tests/rustdoc-ui/", # Some have syntax errors, some are whitespace-sensitive.
2323
"/tests/ui/", # Some have syntax errors, some are whitespace-sensitive.
2424
"/tests/ui-fulldeps/", # Some are whitespace-sensitive (e.g. `// ~ERROR` comments).
25+
# #[cfg(bootstrap)] so that t-release sees this when they search for it
26+
"/tests/rustdoc-json/impl-trait-precise-capturing.rs",
2527

2628
# Do not format submodules.
2729
# FIXME: sync submodule list with tidy/bootstrap/etc

‎src/librustdoc/clean/mod.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,9 @@ fn clean_generic_bound<'tcx>(
228228

229229
GenericBound::TraitBound(clean_poly_trait_ref(t, cx), modifier)
230230
}
231-
// FIXME(precise_capturing): Implement rustdoc support
232-
hir::GenericBound::Use(..) => return None,
231+
hir::GenericBound::Use(args, ..) => {
232+
GenericBound::Use(args.iter().map(|arg| arg.name()).collect())
233+
}
233234
})
234235
}
235236

@@ -460,13 +461,7 @@ fn clean_projection<'tcx>(
460461
def_id: Option<DefId>,
461462
) -> Type {
462463
if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) {
463-
let bounds = cx
464-
.tcx
465-
.explicit_item_bounds(ty.skip_binder().def_id)
466-
.iter_instantiated_copied(cx.tcx, ty.skip_binder().args)
467-
.map(|(pred, _)| pred)
468-
.collect::<Vec<_>>();
469-
return clean_middle_opaque_bounds(cx, bounds);
464+
return clean_middle_opaque_bounds(cx, ty.skip_binder().def_id, ty.skip_binder().args);
470465
}
471466

472467
let trait_ = clean_trait_ref_with_constraints(
@@ -2242,13 +2237,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
22422237
*cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
22432238
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
22442239
// by looking up the bounds associated with the def_id.
2245-
let bounds = cx
2246-
.tcx
2247-
.explicit_item_bounds(def_id)
2248-
.iter_instantiated_copied(cx.tcx, args)
2249-
.map(|(bound, _)| bound)
2250-
.collect::<Vec<_>>();
2251-
let ty = clean_middle_opaque_bounds(cx, bounds);
2240+
let ty = clean_middle_opaque_bounds(cx, def_id, args);
22522241
if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
22532242
*count -= 1;
22542243
if *count == 0 {
@@ -2271,12 +2260,20 @@ pub(crate) fn clean_middle_ty<'tcx>(
22712260

22722261
fn clean_middle_opaque_bounds<'tcx>(
22732262
cx: &mut DocContext<'tcx>,
2274-
bounds: Vec<ty::Clause<'tcx>>,
2263+
impl_trait_def_id: DefId,
2264+
args: ty::GenericArgsRef<'tcx>,
22752265
) -> Type {
22762266
let mut has_sized = false;
2267+
2268+
let bounds: Vec<_> = cx
2269+
.tcx
2270+
.explicit_item_bounds(impl_trait_def_id)
2271+
.iter_instantiated_copied(cx.tcx, args)
2272+
.collect();
2273+
22772274
let mut bounds = bounds
22782275
.iter()
2279-
.filter_map(|bound| {
2276+
.filter_map(|(bound, _)| {
22802277
let bound_predicate = bound.kind();
22812278
let trait_ref = match bound_predicate.skip_binder() {
22822279
ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
@@ -2295,7 +2292,7 @@ fn clean_middle_opaque_bounds<'tcx>(
22952292

22962293
let bindings: ThinVec<_> = bounds
22972294
.iter()
2298-
.filter_map(|bound| {
2295+
.filter_map(|(bound, _)| {
22992296
if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
23002297
if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() {
23012298
Some(AssocItemConstraint {
@@ -2335,6 +2332,10 @@ fn clean_middle_opaque_bounds<'tcx>(
23352332
bounds.insert(0, GenericBound::sized(cx));
23362333
}
23372334

2335+
if let Some(args) = cx.tcx.rendered_precise_capturing_args(impl_trait_def_id) {
2336+
bounds.push(GenericBound::Use(args.to_vec()));
2337+
}
2338+
23382339
ImplTrait(bounds)
23392340
}
23402341

‎src/librustdoc/clean/simplify.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ pub(crate) fn merge_bounds(
7979
!bounds.iter_mut().any(|b| {
8080
let trait_ref = match *b {
8181
clean::GenericBound::TraitBound(ref mut tr, _) => tr,
82-
clean::GenericBound::Outlives(..) => return false,
82+
clean::GenericBound::Outlives(..) | clean::GenericBound::Use(_)=> return false,
8383
};
8484
// If this QPath's trait `trait_did` is the same as, or a supertrait
8585
// of, the bound's trait `did` then we can keep going, otherwise

‎src/librustdoc/clean/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,8 @@ impl Eq for Attributes {}
12441244
pub(crate) enum GenericBound {
12451245
TraitBound(PolyTrait, hir::TraitBoundModifier),
12461246
Outlives(Lifetime),
1247+
/// `use<'a, T>` precise-capturing bound syntax
1248+
Use(Vec<Symbol>),
12471249
}
12481250

12491251
impl GenericBound {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /