Auto merge of #127658 - compiler-errors:precise-capturing-rustdoc-cross, r=fmease
Add cross-crate precise capturing support to rustdoc Follow-up to #127632. Fixes #127228. r? `@fmease` Tracking: * https://github.com/rust-lang/rust/issues/123432
This commit is contained in:
commit
73a228116a
@ -84,6 +84,7 @@ pub fn provide(providers: &mut Providers) {
|
|||||||
coroutine_kind,
|
coroutine_kind,
|
||||||
coroutine_for_closure,
|
coroutine_for_closure,
|
||||||
is_type_alias_impl_trait,
|
is_type_alias_impl_trait,
|
||||||
|
rendered_precise_capturing_args,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1882,3 +1883,23 @@ fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool
|
|||||||
_ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
|
_ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rendered_precise_capturing_args<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: LocalDefId,
|
||||||
|
) -> Option<&'tcx [Symbol]> {
|
||||||
|
if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
|
||||||
|
tcx.opt_rpitit_info(def_id.to_def_id())
|
||||||
|
{
|
||||||
|
return tcx.rendered_precise_capturing_args(opaque_def_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
tcx.hir_node_by_def_id(def_id).expect_item().expect_opaque_ty().bounds.iter().find_map(
|
||||||
|
|bound| match bound {
|
||||||
|
hir::GenericBound::Use(args, ..) => {
|
||||||
|
Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| arg.name())))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -72,6 +72,15 @@ fn process_decoded(self, tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> &'tcx [T] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>>
|
||||||
|
ProcessQueryValue<'tcx, Option<&'tcx [T]>> for Option<DecodeIterator<'a, 'tcx, T>>
|
||||||
|
{
|
||||||
|
#[inline(always)]
|
||||||
|
fn process_decoded(self, tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> Option<&'tcx [T]> {
|
||||||
|
if let Some(iter) = self { Some(&*tcx.arena.alloc_from_iter(iter)) } else { None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ProcessQueryValue<'_, Option<DeprecationEntry>> for Option<Deprecation> {
|
impl ProcessQueryValue<'_, Option<DeprecationEntry>> for Option<Deprecation> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<DeprecationEntry> {
|
fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<DeprecationEntry> {
|
||||||
@ -249,6 +258,7 @@ fn into_args(self) -> (DefId, SimplifiedType) {
|
|||||||
.process_decoded(tcx, || panic!("{def_id:?} does not have coerce_unsized_info"))) }
|
.process_decoded(tcx, || panic!("{def_id:?} does not have coerce_unsized_info"))) }
|
||||||
mir_const_qualif => { table }
|
mir_const_qualif => { table }
|
||||||
rendered_const => { table }
|
rendered_const => { table }
|
||||||
|
rendered_precise_capturing_args => { table }
|
||||||
asyncness => { table_direct }
|
asyncness => { table_direct }
|
||||||
fn_arg_names => { table }
|
fn_arg_names => { table }
|
||||||
coroutine_kind => { table_direct }
|
coroutine_kind => { table_direct }
|
||||||
|
@ -1496,6 +1496,7 @@ fn encode_def_ids(&mut self) {
|
|||||||
self.tables
|
self.tables
|
||||||
.is_type_alias_impl_trait
|
.is_type_alias_impl_trait
|
||||||
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
|
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
|
||||||
|
self.encode_precise_capturing_args(def_id);
|
||||||
}
|
}
|
||||||
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
|
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
|
||||||
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
|
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
|
||||||
@ -1635,6 +1636,7 @@ fn encode_info_for_assoc_item(&mut self, def_id: DefId) {
|
|||||||
self.tables.assumed_wf_types_for_rpitit[def_id]
|
self.tables.assumed_wf_types_for_rpitit[def_id]
|
||||||
<- self.tcx.assumed_wf_types_for_rpitit(def_id)
|
<- self.tcx.assumed_wf_types_for_rpitit(def_id)
|
||||||
);
|
);
|
||||||
|
self.encode_precise_capturing_args(def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if item.is_effects_desugaring {
|
if item.is_effects_desugaring {
|
||||||
@ -1642,6 +1644,14 @@ fn encode_info_for_assoc_item(&mut self, def_id: DefId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_precise_capturing_args(&mut self, def_id: DefId) {
|
||||||
|
let Some(precise_capturing_args) = self.tcx.rendered_precise_capturing_args(def_id) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
record_array!(self.tables.rendered_precise_capturing_args[def_id] <- precise_capturing_args);
|
||||||
|
}
|
||||||
|
|
||||||
fn encode_mir(&mut self) {
|
fn encode_mir(&mut self) {
|
||||||
if self.is_proc_macro {
|
if self.is_proc_macro {
|
||||||
return;
|
return;
|
||||||
|
@ -442,6 +442,7 @@ fn encode(&self, buf: &mut FileEncoder) -> LazyTables {
|
|||||||
coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
|
coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
|
||||||
mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
|
mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
|
||||||
rendered_const: Table<DefIndex, LazyValue<String>>,
|
rendered_const: Table<DefIndex, LazyValue<String>>,
|
||||||
|
rendered_precise_capturing_args: Table<DefIndex, LazyArray<Symbol>>,
|
||||||
asyncness: Table<DefIndex, ty::Asyncness>,
|
asyncness: Table<DefIndex, ty::Asyncness>,
|
||||||
fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
|
fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
|
||||||
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
|
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
|
||||||
|
@ -1261,6 +1261,7 @@
|
|||||||
desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the rendered value of the specified constant or associated constant.
|
/// Gets the rendered value of the specified constant or associated constant.
|
||||||
/// Used by rustdoc.
|
/// Used by rustdoc.
|
||||||
query rendered_const(def_id: DefId) -> &'tcx String {
|
query rendered_const(def_id: DefId) -> &'tcx String {
|
||||||
@ -1268,6 +1269,13 @@
|
|||||||
desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the rendered precise capturing args for an opaque for use in rustdoc.
|
||||||
|
query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [Symbol]> {
|
||||||
|
desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) }
|
||||||
|
separate_provide_extern
|
||||||
|
}
|
||||||
|
|
||||||
query impl_parent(def_id: DefId) -> Option<DefId> {
|
query impl_parent(def_id: DefId) -> Option<DefId> {
|
||||||
desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
|
@ -468,13 +468,7 @@ fn clean_projection<'tcx>(
|
|||||||
def_id: Option<DefId>,
|
def_id: Option<DefId>,
|
||||||
) -> Type {
|
) -> Type {
|
||||||
if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) {
|
if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) {
|
||||||
let bounds = cx
|
return clean_middle_opaque_bounds(cx, ty.skip_binder().def_id, ty.skip_binder().args);
|
||||||
.tcx
|
|
||||||
.explicit_item_bounds(ty.skip_binder().def_id)
|
|
||||||
.iter_instantiated_copied(cx.tcx, ty.skip_binder().args)
|
|
||||||
.map(|(pred, _)| pred)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
return clean_middle_opaque_bounds(cx, bounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let trait_ = clean_trait_ref_with_constraints(
|
let trait_ = clean_trait_ref_with_constraints(
|
||||||
@ -2260,13 +2254,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
|||||||
*cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
|
*cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
|
||||||
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
|
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
|
||||||
// by looking up the bounds associated with the def_id.
|
// by looking up the bounds associated with the def_id.
|
||||||
let bounds = cx
|
let ty = clean_middle_opaque_bounds(cx, def_id, args);
|
||||||
.tcx
|
|
||||||
.explicit_item_bounds(def_id)
|
|
||||||
.iter_instantiated_copied(cx.tcx, args)
|
|
||||||
.map(|(bound, _)| bound)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let ty = clean_middle_opaque_bounds(cx, bounds);
|
|
||||||
if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
|
if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
|
||||||
*count -= 1;
|
*count -= 1;
|
||||||
if *count == 0 {
|
if *count == 0 {
|
||||||
@ -2289,12 +2277,20 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
|||||||
|
|
||||||
fn clean_middle_opaque_bounds<'tcx>(
|
fn clean_middle_opaque_bounds<'tcx>(
|
||||||
cx: &mut DocContext<'tcx>,
|
cx: &mut DocContext<'tcx>,
|
||||||
bounds: Vec<ty::Clause<'tcx>>,
|
impl_trait_def_id: DefId,
|
||||||
|
args: ty::GenericArgsRef<'tcx>,
|
||||||
) -> Type {
|
) -> Type {
|
||||||
let mut has_sized = false;
|
let mut has_sized = false;
|
||||||
|
|
||||||
|
let bounds: Vec<_> = cx
|
||||||
|
.tcx
|
||||||
|
.explicit_item_bounds(impl_trait_def_id)
|
||||||
|
.iter_instantiated_copied(cx.tcx, args)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut bounds = bounds
|
let mut bounds = bounds
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|bound| {
|
.filter_map(|(bound, _)| {
|
||||||
let bound_predicate = bound.kind();
|
let bound_predicate = bound.kind();
|
||||||
let trait_ref = match bound_predicate.skip_binder() {
|
let trait_ref = match bound_predicate.skip_binder() {
|
||||||
ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
|
ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
|
||||||
@ -2313,7 +2309,7 @@ fn clean_middle_opaque_bounds<'tcx>(
|
|||||||
|
|
||||||
let bindings: ThinVec<_> = bounds
|
let bindings: ThinVec<_> = bounds
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|bound| {
|
.filter_map(|(bound, _)| {
|
||||||
if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
|
if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() {
|
||||||
if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() {
|
if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() {
|
||||||
Some(AssocItemConstraint {
|
Some(AssocItemConstraint {
|
||||||
@ -2353,6 +2349,10 @@ fn clean_middle_opaque_bounds<'tcx>(
|
|||||||
bounds.insert(0, GenericBound::sized(cx));
|
bounds.insert(0, GenericBound::sized(cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(args) = cx.tcx.rendered_precise_capturing_args(impl_trait_def_id) {
|
||||||
|
bounds.push(GenericBound::Use(args.to_vec()));
|
||||||
|
}
|
||||||
|
|
||||||
ImplTrait(bounds)
|
ImplTrait(bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
tests/rustdoc/auxiliary/precise-capturing.rs
Normal file
7
tests/rustdoc/auxiliary/precise-capturing.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#![feature(precise_capturing)]
|
||||||
|
|
||||||
|
pub fn cross_crate_empty() -> impl Sized + use<> {}
|
||||||
|
|
||||||
|
pub fn cross_crate_missing() -> impl Sized {}
|
||||||
|
|
||||||
|
pub fn cross_crate_args<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}
|
@ -1,6 +1,10 @@
|
|||||||
|
//@ aux-build:precise-capturing.rs
|
||||||
|
|
||||||
#![crate_name = "foo"]
|
#![crate_name = "foo"]
|
||||||
#![feature(precise_capturing)]
|
#![feature(precise_capturing)]
|
||||||
|
|
||||||
|
extern crate precise_capturing;
|
||||||
|
|
||||||
//@ has foo/fn.two.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'b, 'a>"
|
//@ has foo/fn.two.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'b, 'a>"
|
||||||
pub fn two<'a, 'b, 'c>() -> impl Sized + use<'b, 'a /* no 'c */> {}
|
pub fn two<'a, 'b, 'c>() -> impl Sized + use<'b, 'a /* no 'c */> {}
|
||||||
|
|
||||||
@ -12,3 +16,12 @@ pub fn none() -> impl Sized + use<> {}
|
|||||||
|
|
||||||
//@ has foo/fn.first.html '//section[@id="main-content"]//pre' "-> impl use<> + Sized"
|
//@ has foo/fn.first.html '//section[@id="main-content"]//pre' "-> impl use<> + Sized"
|
||||||
pub fn first() -> impl use<> + Sized {}
|
pub fn first() -> impl use<> + Sized {}
|
||||||
|
|
||||||
|
//@ has foo/fn.cross_crate_empty.html '//section[@id="main-content"]//pre' "-> impl Sized + use<>"
|
||||||
|
pub use precise_capturing::cross_crate_empty;
|
||||||
|
|
||||||
|
//@ matches foo/fn.cross_crate_missing.html '//section[@id="main-content"]//pre' "-> impl Sized$"
|
||||||
|
pub use precise_capturing::cross_crate_missing;
|
||||||
|
|
||||||
|
//@ has foo/fn.cross_crate_args.html '//section[@id="main-content"]//pre' "-> impl Sized + use<'a, T, N>"
|
||||||
|
pub use precise_capturing::cross_crate_args;
|
||||||
|
Loading…
Reference in New Issue
Block a user