diff options
| author | León Orell Valerian Liehr <me@fmease.dev> | 2024-02-13 11:52:27 +0100 |
|---|---|---|
| committer | León Orell Valerian Liehr <me@fmease.dev> | 2024-02-15 01:40:38 +0100 |
| commit | a8d869e1d151d70137af8e7a03155cb6ac93139c (patch) | |
| tree | 00cfd2899efe26e94b1d682e96b6a69ec9e1766e /src/librustdoc/clean/inline.rs | |
| parent | 0a5b998c57a8681acc13206b5917340b053b3a30 (diff) | |
| download | rust-a8d869e1d151d70137af8e7a03155cb6ac93139c.tar.gz rust-a8d869e1d151d70137af8e7a03155cb6ac93139c.zip | |
rustdoc: cross-crate re-exports: correctly render late-bound params in source order even if early-bound params are present
Diffstat (limited to 'src/librustdoc/clean/inline.rs')
| -rw-r--r-- | src/librustdoc/clean/inline.rs | 50 |
1 files changed, 36 insertions, 14 deletions
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 23a059c6e03..e2f2c9a5e56 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -18,8 +18,8 @@ use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ - self, clean_bound_vars, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, - clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, + self, clean_bound_vars, clean_generics, clean_impl_item, clean_middle_assoc_item, + clean_middle_field, clean_middle_ty, clean_poly_fn_sig, clean_trait_ref_with_bindings, clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes, AttributesExt, ImplKind, ItemId, Type, }; @@ -72,7 +72,9 @@ pub(crate) fn try_inline( } Res::Def(DefKind::Fn, did) => { record_extern_fqn(cx, did, ItemType::Function); - cx.with_param_env(did, |cx| clean::FunctionItem(build_external_function(cx, did))) + cx.with_param_env(did, |cx| { + clean::enter_impl_trait(cx, |cx| clean::FunctionItem(build_function(cx, did))) + }) } Res::Def(DefKind::Struct, did) => { record_extern_fqn(cx, did, ItemType::Struct); @@ -274,18 +276,38 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds } } -fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box<clean::Function> { - let sig = cx.tcx.fn_sig(did).instantiate_identity(); - let predicates = cx.tcx.explicit_predicates_of(did); +pub(crate) fn build_function<'tcx>( + cx: &mut DocContext<'tcx>, + def_id: DefId, +) -> Box<clean::Function> { + let sig = cx.tcx.fn_sig(def_id).instantiate_identity(); + // The generics need to be cleaned before the signature. + let mut generics = + clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id)); + let bound_vars = clean_bound_vars(sig.bound_vars()); + + // At the time of writing early & late-bound params are stored separately in rustc, + // namely in `generics.params` and `bound_vars` respectively. + // + // To reestablish the original source code order of the generic parameters, we + // need to manually sort them by their definition span after concatenation. + // + // See also: + // * https://rustc-dev-guide.rust-lang.org/bound-vars-and-params.html + // * https://rustc-dev-guide.rust-lang.org/what-does-early-late-bound-mean.html + let has_early_bound_params = !generics.params.is_empty(); + let has_late_bound_params = !bound_vars.is_empty(); + generics.params.extend(bound_vars); + if has_early_bound_params && has_late_bound_params { + // If this ever becomes a performances bottleneck either due to the sorting + // or due to the query calls, consider inserting the late-bound lifetime params + // right after the last early-bound lifetime param followed by only sorting + // the slice of lifetime params. + generics.params.sort_by_key(|param| cx.tcx.def_ident_span(param.def_id).unwrap()); + } + + let decl = clean_poly_fn_sig(cx, Some(def_id), sig); - let (generics, decl) = clean::enter_impl_trait(cx, |cx| { - // NOTE: generics need to be cleaned before the decl! - let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); - // FIXME: This does not place parameters in source order (late-bound ones come last) - generics.params.extend(clean_bound_vars(sig.bound_vars())); - let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig); - (generics, decl) - }); Box::new(clean::Function { decl, generics }) } |
