summaryrefslogtreecommitdiffstats
path: root/src/librustdoc/clean
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /src/librustdoc/clean
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/librustdoc/clean')
-rw-r--r--src/librustdoc/clean/auto_trait.rs7
-rw-r--r--src/librustdoc/clean/inline.rs37
-rw-r--r--src/librustdoc/clean/mod.rs209
-rw-r--r--src/librustdoc/clean/simplify.rs21
-rw-r--r--src/librustdoc/clean/types.rs98
-rw-r--r--src/librustdoc/clean/types/tests.rs3
-rw-r--r--src/librustdoc/clean/utils.rs164
7 files changed, 322 insertions, 217 deletions
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index a06f31a93..bdf6a0f6b 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -551,8 +551,8 @@ where
WherePredicate::RegionPredicate { lifetime, bounds } => {
lifetime_to_bounds.entry(lifetime).or_default().extend(bounds);
}
- WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
- match *lhs {
+ WherePredicate::EqPredicate { lhs, rhs } => {
+ match lhs {
Type::QPath(box QPathData {
ref assoc,
ref self_type,
@@ -590,14 +590,13 @@ where
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
bindings.push(TypeBinding {
assoc: assoc.clone(),
- kind: TypeBindingKind::Equality { term: *rhs },
+ kind: TypeBindingKind::Equality { term: rhs },
});
}
GenericArgs::Parenthesized { .. } => {
existing_predicates.push(WherePredicate::EqPredicate {
lhs: lhs.clone(),
rhs,
- bound_params,
});
continue; // If something other than a Fn ends up
// with parentheses, leave it alone
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index fcbcfbf5c..974ba1e3b 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -18,14 +18,16 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
use crate::clean::{
- self, 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, clean_ty,
- clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
+ 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,
+ clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
AttributesExt, ImplKind, ItemId, Type,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
+use super::Item;
+
/// Attempt to inline a definition into this AST.
///
/// This function will fetch the definition specified, and if it is
@@ -83,7 +85,7 @@ pub(crate) fn try_inline(
Res::Def(DefKind::TyAlias, did) => {
record_extern_fqn(cx, did, ItemType::TypeAlias);
build_impls(cx, did, attrs_without_docs, &mut ret);
- clean::TypeAliasItem(build_type_alias(cx, did))
+ clean::TypeAliasItem(build_type_alias(cx, did, &mut ret))
}
Res::Def(DefKind::Enum, did) => {
record_extern_fqn(cx, did, ItemType::Enum);
@@ -239,20 +241,13 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box<clean::Function> {
let sig = cx.tcx.fn_sig(did).instantiate_identity();
-
- let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
- ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => {
- Some(clean::GenericParamDef::lifetime(name))
- }
- _ => None,
- });
-
let predicates = cx.tcx.explicit_predicates_of(did);
+
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(late_bound_regions);
+ generics.params.extend(clean_bound_vars(sig.bound_vars()));
let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig);
(generics, decl)
});
@@ -288,11 +283,15 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
clean::Union { generics, fields }
}
-fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::TypeAlias> {
+fn build_type_alias(
+ cx: &mut DocContext<'_>,
+ did: DefId,
+ ret: &mut Vec<Item>,
+) -> Box<clean::TypeAlias> {
let predicates = cx.tcx.explicit_predicates_of(did);
let ty = cx.tcx.type_of(did).instantiate_identity();
let type_ = clean_middle_ty(ty::Binder::dummy(ty), cx, Some(did), None);
- let inner_type = clean_ty_alias_inner_type(ty, cx);
+ let inner_type = clean_ty_alias_inner_type(ty, cx, ret);
Box::new(clean::TypeAlias {
type_,
@@ -600,7 +599,7 @@ fn build_module_items(
let prim_ty = clean::PrimitiveType::from(p);
items.push(clean::Item {
name: None,
- attrs: Box::new(clean::Attributes::default()),
+ attrs: Box::default(),
// We can use the item's `DefId` directly since the only information ever used
// from it is `DefId.krate`.
item_id: ItemId::DefId(did),
@@ -648,13 +647,13 @@ fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
clean::simplify::move_bounds_to_generic_parameters(&mut generics);
clean::Constant {
- type_: clean_middle_ty(
+ type_: Box::new(clean_middle_ty(
ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
cx,
Some(def_id),
None,
- ),
- generics: Box::new(generics),
+ )),
+ generics,
kind: clean::ConstantKind::Extern { def_id },
}
}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0caa92e44..1b7ca7bf7 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -232,20 +232,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
poly_trait_ref: ty::PolyTraitRef<'tcx>,
bindings: ThinVec<TypeBinding>,
) -> GenericBound {
- // collect any late bound regions
- let late_bound_regions: Vec<_> = cx
- .tcx
- .collect_referenced_late_bound_regions(&poly_trait_ref)
- .into_iter()
- .filter_map(|br| match br {
- ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
- _ => None,
- })
- .collect();
-
- let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
GenericBound::TraitBound(
- PolyTrait { trait_, generic_params: late_bound_regions },
+ PolyTrait {
+ trait_: clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings),
+ generic_params: clean_bound_vars(poly_trait_ref.bound_vars()),
+ },
hir::TraitBoundModifier::None,
)
}
@@ -268,13 +259,13 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
Constant {
- type_: clean_middle_ty(
+ type_: Box::new(clean_middle_ty(
ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
cx,
Some(def_id),
None,
- ),
- generics: Box::new(Generics::default()),
+ )),
+ generics: Generics::default(),
kind: ConstantKind::Anonymous { body: constant.value.body },
}
}
@@ -285,8 +276,8 @@ pub(crate) fn clean_middle_const<'tcx>(
) -> Constant {
// FIXME: instead of storing the stringified expression, store `self` directly instead.
Constant {
- type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None),
- generics: Box::new(Generics::default()),
+ type_: Box::new(clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None)),
+ generics: Generics::default(),
kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
}
}
@@ -338,9 +329,8 @@ fn clean_where_predicate<'tcx>(
},
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
- lhs: Box::new(clean_ty(wrp.lhs_ty, cx)),
- rhs: Box::new(clean_ty(wrp.rhs_ty, cx).into()),
- bound_params: Vec::new(),
+ lhs: clean_ty(wrp.lhs_ty, cx),
+ rhs: clean_ty(wrp.rhs_ty, cx).into(),
},
})
}
@@ -436,20 +426,9 @@ fn clean_projection_predicate<'tcx>(
pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
cx: &mut DocContext<'tcx>,
) -> WherePredicate {
- let late_bound_regions = cx
- .tcx
- .collect_referenced_late_bound_regions(&pred)
- .into_iter()
- .filter_map(|br| match br {
- ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
- _ => None,
- })
- .collect();
-
WherePredicate::EqPredicate {
- lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
- rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
- bound_params: late_bound_regions,
+ lhs: clean_projection(pred.map_bound(|p| p.projection_ty), cx, None),
+ rhs: clean_middle_term(pred.map_bound(|p| p.term), cx),
}
}
@@ -496,8 +475,9 @@ fn projection_to_path_segment<'tcx>(
ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
cx: &mut DocContext<'tcx>,
) -> PathSegment {
- let item = cx.tcx.associated_item(ty.skip_binder().def_id);
- let generics = cx.tcx.generics_of(ty.skip_binder().def_id);
+ let def_id = ty.skip_binder().def_id;
+ let item = cx.tcx.associated_item(def_id);
+ let generics = cx.tcx.generics_of(def_id);
PathSegment {
name: item.name,
args: GenericArgs::AngleBracketed {
@@ -505,7 +485,7 @@ fn projection_to_path_segment<'tcx>(
cx,
ty.map_bound(|ty| &ty.args[generics.parent_count..]),
false,
- None,
+ def_id,
)
.into(),
bindings: Default::default(),
@@ -519,7 +499,7 @@ fn clean_generic_param_def<'tcx>(
) -> GenericParamDef {
let (name, kind) = match def.kind {
ty::GenericParamDefKind::Lifetime => {
- (def.name, GenericParamDefKind::Lifetime { outlives: vec![] })
+ (def.name, GenericParamDefKind::Lifetime { outlives: ThinVec::new() })
}
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
let default = if has_default {
@@ -536,7 +516,7 @@ fn clean_generic_param_def<'tcx>(
def.name,
GenericParamDefKind::Type {
did: def.def_id,
- bounds: vec![], // These are filled in from the where-clauses.
+ bounds: ThinVec::new(), // These are filled in from the where-clauses.
default: default.map(Box::new),
synthetic,
},
@@ -588,7 +568,7 @@ fn clean_generic_param<'tcx>(
})
.collect()
} else {
- Vec::new()
+ ThinVec::new()
};
(param.name.ident().name, GenericParamDefKind::Lifetime { outlives })
}
@@ -601,7 +581,7 @@ fn clean_generic_param<'tcx>(
.filter_map(|x| clean_generic_bound(x, cx))
.collect()
} else {
- Vec::new()
+ ThinVec::new()
};
(
param.name.ident().name,
@@ -657,7 +637,7 @@ pub(crate) fn clean_generics<'tcx>(
match param.kind {
GenericParamDefKind::Lifetime { .. } => unreachable!(),
GenericParamDefKind::Type { did, ref bounds, .. } => {
- cx.impl_trait_bounds.insert(did.into(), bounds.clone());
+ cx.impl_trait_bounds.insert(did.into(), bounds.to_vec());
}
GenericParamDefKind::Const { .. } => unreachable!(),
}
@@ -705,8 +685,8 @@ pub(crate) fn clean_generics<'tcx>(
}
}
}
- WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
- eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs, bound_params });
+ WherePredicate::EqPredicate { lhs, rhs } => {
+ eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs });
}
}
}
@@ -800,11 +780,9 @@ fn clean_ty_generics<'tcx>(
})
.collect::<ThinVec<GenericParamDef>>();
- // param index -> [(trait DefId, associated type name & generics, term, higher-ranked params)]
- let mut impl_trait_proj = FxHashMap::<
- u32,
- Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>, Vec<GenericParamDef>)>,
- >::default();
+ // param index -> [(trait DefId, associated type name & generics, term)]
+ let mut impl_trait_proj =
+ FxHashMap::<u32, Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>)>>::default();
let where_predicates = preds
.predicates
@@ -856,11 +834,6 @@ fn clean_ty_generics<'tcx>(
trait_did,
name,
proj.map_bound(|p| p.term),
- pred.get_bound_params()
- .into_iter()
- .flatten()
- .cloned()
- .collect(),
));
}
@@ -896,9 +869,9 @@ fn clean_ty_generics<'tcx>(
let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() };
if let Some(proj) = impl_trait_proj.remove(&idx) {
- for (trait_did, name, rhs, bound_params) in proj {
+ for (trait_did, name, rhs) in proj {
let rhs = clean_middle_term(rhs, cx);
- simplify::merge_bounds(cx, &mut bounds, bound_params, trait_did, name, &rhs);
+ simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
}
}
@@ -962,11 +935,16 @@ fn clean_ty_generics<'tcx>(
fn clean_ty_alias_inner_type<'tcx>(
ty: Ty<'tcx>,
cx: &mut DocContext<'tcx>,
+ ret: &mut Vec<Item>,
) -> Option<TypeAliasInnerType> {
let ty::Adt(adt_def, args) = ty.kind() else {
return None;
};
+ if !adt_def.did().is_local() {
+ inline::build_impls(cx, adt_def.did(), None, ret);
+ }
+
Some(if adt_def.is_enum() {
let variants: rustc_index::IndexVec<_, _> = adt_def
.variants()
@@ -974,6 +952,10 @@ fn clean_ty_alias_inner_type<'tcx>(
.map(|variant| clean_variant_def_with_args(variant, args, cx))
.collect();
+ if !adt_def.did().is_local() {
+ inline::record_extern_fqn(cx, adt_def.did(), ItemType::Enum);
+ }
+
TypeAliasInnerType::Enum {
variants,
is_non_exhaustive: adt_def.is_variant_list_non_exhaustive(),
@@ -989,8 +971,14 @@ fn clean_ty_alias_inner_type<'tcx>(
clean_variant_def_with_args(variant, args, cx).kind.inner_items().cloned().collect();
if adt_def.is_struct() {
+ if !adt_def.did().is_local() {
+ inline::record_extern_fqn(cx, adt_def.did(), ItemType::Struct);
+ }
TypeAliasInnerType::Struct { ctor_kind: variant.ctor_kind(), fields }
} else {
+ if !adt_def.did().is_local() {
+ inline::record_extern_fqn(cx, adt_def.did(), ItemType::Union);
+ }
TypeAliasInnerType::Union { fields }
}
})
@@ -1244,14 +1232,14 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
hir::TraitItemKind::Const(ty, Some(default)) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
AssocConstItem(
- Box::new(generics),
- clean_ty(ty, cx),
+ generics,
+ Box::new(clean_ty(ty, cx)),
ConstantKind::Local { def_id: local_did, body: default },
)
}
hir::TraitItemKind::Const(ty, None) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
- TyAssocConstItem(Box::new(generics), clean_ty(ty, cx))
+ TyAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
@@ -1300,7 +1288,7 @@ pub(crate) fn clean_impl_item<'tcx>(
hir::ImplItemKind::Const(ty, expr) => {
let generics = clean_generics(impl_.generics, cx);
let default = ConstantKind::Local { def_id: local_did, body: expr };
- AssocConstItem(Box::new(generics), clean_ty(ty, cx), default)
+ AssocConstItem(generics, Box::new(clean_ty(ty, cx)), default)
}
hir::ImplItemKind::Fn(ref sig, body) => {
let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body));
@@ -1339,18 +1327,18 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
let tcx = cx.tcx;
let kind = match assoc_item.kind {
ty::AssocKind::Const => {
- let ty = clean_middle_ty(
+ let ty = Box::new(clean_middle_ty(
ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()),
cx,
Some(assoc_item.def_id),
None,
- );
+ ));
- let mut generics = Box::new(clean_ty_generics(
+ let mut generics = clean_ty_generics(
cx,
tcx.generics_of(assoc_item.def_id),
tcx.explicit_predicates_of(assoc_item.def_id),
- ));
+ );
simplify::move_bounds_to_generic_parameters(&mut generics);
let provided = match assoc_item.container {
@@ -1365,23 +1353,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
}
ty::AssocKind::Fn => {
let sig = tcx.fn_sig(assoc_item.def_id).instantiate_identity();
-
- let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
- ty::BoundVariableKind::Region(ty::BrNamed(_, name))
- if name != kw::UnderscoreLifetime =>
- {
- Some(GenericParamDef::lifetime(name))
- }
- _ => None,
- });
-
let mut generics = clean_ty_generics(
cx,
tcx.generics_of(assoc_item.def_id),
tcx.explicit_predicates_of(assoc_item.def_id),
);
// FIXME: This does not place parameters in source order (late-bound ones come last)
- generics.params.extend(late_bound_regions);
+ generics.params.extend(clean_bound_vars(sig.bound_vars()));
let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig);
@@ -2117,9 +2095,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
// FIXME: should we merge the outer and inner binders somehow?
let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
+ let generic_params = clean_bound_vars(sig.bound_vars());
+
BareFunction(Box::new(BareFunctionDecl {
unsafety: sig.unsafety(),
- generic_params: Vec::new(),
+ generic_params,
decl,
abi: sig.abi(),
}))
@@ -2195,8 +2175,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
let late_bound_regions: FxIndexSet<_> = obj
.iter()
- .flat_map(|pb| pb.bound_vars())
- .filter_map(|br| match br {
+ .flat_map(|pred| pred.bound_vars())
+ .filter_map(|var| match var {
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
if name != kw::UnderscoreLifetime =>
{
@@ -2221,18 +2201,19 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
ty::Alias(ty::Inherent, alias_ty) => {
+ let def_id = alias_ty.def_id;
let alias_ty = bound_ty.rebind(alias_ty);
let self_type = clean_middle_ty(alias_ty.map_bound(|ty| ty.self_ty()), cx, None, None);
Type::QPath(Box::new(QPathData {
assoc: PathSegment {
- name: cx.tcx.associated_item(alias_ty.skip_binder().def_id).name,
+ name: cx.tcx.associated_item(def_id).name,
args: GenericArgs::AngleBracketed {
args: ty_args_to_args(
cx,
alias_ty.map_bound(|ty| ty.args.as_slice()),
true,
- None,
+ def_id,
)
.into(),
bindings: Default::default(),
@@ -2270,6 +2251,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
}
+ ty::Bound(_, ref ty) => match ty.kind {
+ ty::BoundTyKind::Param(_, name) => Generic(name),
+ ty::BoundTyKind::Anon => panic!("unexpected anonymous bound type variable"),
+ },
+
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
// If it's already in the same alias, don't get an infinite loop.
if cx.current_type_aliases.contains_key(&def_id) {
@@ -2297,10 +2283,9 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
ty::Closure(..) => panic!("Closure"),
- ty::Generator(..) => panic!("Generator"),
- ty::Bound(..) => panic!("Bound"),
+ ty::Coroutine(..) => panic!("Coroutine"),
ty::Placeholder(..) => panic!("Placeholder"),
- ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
+ ty::CoroutineWitness(..) => panic!("CoroutineWitness"),
ty::Infer(..) => panic!("Infer"),
ty::Error(_) => rustc_errors::FatalError.raise(),
}
@@ -2549,7 +2534,8 @@ fn clean_generic_args<'tcx>(
}
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)),
- // FIXME(effects): This will still emit `<true>` for non-const impls of const traits
+ // Checking for `#[rustc_host]` on the `AnonConst` not only accounts for the case
+ // where the argument is `host` but for all possible cases (e.g., `true`, `false`).
hir::GenericArg::Const(ct)
if cx.tcx.has_attr(ct.value.def_id, sym::rustc_host) =>
{
@@ -2750,8 +2736,8 @@ fn clean_maybe_renamed_item<'tcx>(
StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
}
ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant {
- type_: clean_ty(ty, cx),
- generics: Box::new(clean_generics(generics, cx)),
+ type_: Box::new(clean_ty(ty, cx)),
+ generics: clean_generics(generics, cx),
kind: ConstantKind::Local { body: body_id, def_id },
}),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
@@ -2776,14 +2762,24 @@ fn clean_maybe_renamed_item<'tcx>(
}
let ty = cx.tcx.type_of(def_id).instantiate_identity();
- let inner_type = clean_ty_alias_inner_type(ty, cx);
- TypeAliasItem(Box::new(TypeAlias {
- generics,
- inner_type,
- type_: rustdoc_ty,
- item_type: Some(type_),
- }))
+ let mut ret = Vec::new();
+ let inner_type = clean_ty_alias_inner_type(ty, cx, &mut ret);
+
+ ret.push(generate_item_with_correct_attrs(
+ cx,
+ TypeAliasItem(Box::new(TypeAlias {
+ generics,
+ inner_type,
+ type_: rustdoc_ty,
+ item_type: Some(type_),
+ })),
+ item.owner_id.def_id.to_def_id(),
+ name,
+ import_id,
+ renamed,
+ ));
+ return ret;
}
ItemKind::Enum(ref def, generics) => EnumItem(Enum {
variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
@@ -3137,3 +3133,30 @@ fn clean_type_binding<'tcx>(
},
}
}
+
+fn clean_bound_vars<'tcx>(
+ bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
+) -> Vec<GenericParamDef> {
+ bound_vars
+ .into_iter()
+ .filter_map(|var| match var {
+ ty::BoundVariableKind::Region(ty::BrNamed(_, name))
+ if name != kw::UnderscoreLifetime =>
+ {
+ Some(GenericParamDef::lifetime(name))
+ }
+ ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(did, name)) => Some(GenericParamDef {
+ name,
+ kind: GenericParamDefKind::Type {
+ did,
+ bounds: ThinVec::new(),
+ default: None,
+ synthetic: false,
+ },
+ }),
+ // FIXME(non_lifetime_binders): Support higher-ranked const parameters.
+ ty::BoundVariableKind::Const => None,
+ _ => None,
+ })
+ .collect()
+}
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 7b8f20326..627f15e67 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -40,18 +40,18 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
WP::RegionPredicate { lifetime, bounds } => {
lifetimes.push((lifetime, bounds));
}
- WP::EqPredicate { lhs, rhs, bound_params } => equalities.push((lhs, rhs, bound_params)),
+ WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)),
}
}
// Look for equality predicates on associated types that can be merged into
// general bound predicates.
- equalities.retain(|(lhs, rhs, bound_params)| {
+ equalities.retain(|(lhs, rhs)| {
let Some((ty, trait_did, name)) = lhs.projection() else {
return true;
};
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
- merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs)
+ merge_bounds(cx, bounds, trait_did, name, rhs)
});
// And finally, let's reassemble everything
@@ -64,18 +64,13 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
bounds,
bound_params,
}));
- clauses.extend(equalities.into_iter().map(|(lhs, rhs, bound_params)| WP::EqPredicate {
- lhs,
- rhs,
- bound_params,
- }));
+ clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
clauses
}
pub(crate) fn merge_bounds(
cx: &clean::DocContext<'_>,
bounds: &mut Vec<clean::GenericBound>,
- mut bound_params: Vec<clean::GenericParamDef>,
trait_did: DefId,
assoc: clean::PathSegment,
rhs: &clean::Term,
@@ -93,12 +88,6 @@ pub(crate) fn merge_bounds(
}
let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
- trait_ref.generic_params.append(&mut bound_params);
- // Sort parameters (likely) originating from a hashset alphabetically to
- // produce predictable output (and to allow for full deduplication).
- trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str()));
- trait_ref.generic_params.dedup_by_key(|p| p.name);
-
match last.args {
PP::AngleBracketed { ref mut bindings, .. } => {
bindings.push(clean::TypeBinding {
@@ -156,7 +145,7 @@ pub(crate) fn move_bounds_to_generic_parameters(generics: &mut clean::Generics)
..
}) = generics.params.iter_mut().find(|param| &param.name == arg)
{
- param_bounds.append(bounds);
+ param_bounds.extend(bounds.drain(..));
} else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred
&& let Some(GenericParamDef {
kind: GenericParamDefKind::Lifetime { outlives: param_bounds },
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 4256e7b51..88ee4e3a2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -12,7 +12,7 @@ use thin_vec::ThinVec;
use rustc_ast as ast;
use rustc_ast_pretty::pprust;
-use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
+use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel, StableSince};
use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
@@ -585,14 +585,14 @@ impl Item {
})
}
- pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<Symbol> {
+ pub(crate) fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
match self.stability(tcx)?.level {
StabilityLevel::Stable { since, .. } => Some(since),
StabilityLevel::Unstable { .. } => None,
}
}
- pub(crate) fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<Symbol> {
+ pub(crate) fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<StableSince> {
match self.const_stability(tcx)?.level {
StabilityLevel::Stable { since, .. } => Some(since),
StabilityLevel::Unstable { .. } => None,
@@ -713,12 +713,16 @@ impl Item {
Some(tcx.visibility(def_id))
}
- pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, keep_as_is: bool) -> Vec<String> {
+ pub(crate) fn attributes(
+ &self,
+ tcx: TyCtxt<'_>,
+ cache: &Cache,
+ keep_as_is: bool,
+ ) -> Vec<String> {
const ALLOWED_ATTRIBUTES: &[Symbol] =
- &[sym::export_name, sym::link_section, sym::no_mangle, sym::repr, sym::non_exhaustive];
+ &[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive];
use rustc_abi::IntegerType;
- use rustc_middle::ty::ReprFlags;
let mut attrs: Vec<String> = self
.attrs
@@ -739,20 +743,38 @@ impl Item {
}
})
.collect();
- if let Some(def_id) = self.def_id() &&
- !def_id.is_local() &&
- // This check is needed because `adt_def` will panic if not a compatible type otherwise...
- matches!(self.type_(), ItemType::Struct | ItemType::Enum | ItemType::Union)
+ if !keep_as_is
+ && let Some(def_id) = self.def_id()
+ && let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_()
{
- let repr = tcx.adt_def(def_id).repr();
+ let adt = tcx.adt_def(def_id);
+ let repr = adt.repr();
let mut out = Vec::new();
- if repr.flags.contains(ReprFlags::IS_C) {
+ if repr.c() {
out.push("C");
}
- if repr.flags.contains(ReprFlags::IS_TRANSPARENT) {
- out.push("transparent");
+ if repr.transparent() {
+ // Render `repr(transparent)` iff the non-1-ZST field is public or at least one
+ // field is public in case all fields are 1-ZST fields.
+ let render_transparent = cache.document_private
+ || adt
+ .all_fields()
+ .find(|field| {
+ let ty =
+ field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
+ tcx.layout_of(tcx.param_env(field.did).and(ty))
+ .is_ok_and(|layout| !layout.is_1zst())
+ })
+ .map_or_else(
+ || adt.all_fields().any(|field| field.vis.is_public()),
+ |field| field.vis.is_public(),
+ );
+
+ if render_transparent {
+ out.push("transparent");
+ }
}
- if repr.flags.contains(ReprFlags::IS_SIMD) {
+ if repr.simd() {
out.push("simd");
}
let pack_s;
@@ -777,10 +799,9 @@ impl Item {
};
out.push(&int_s);
}
- if out.is_empty() {
- return Vec::new();
+ if !out.is_empty() {
+ attrs.push(format!("#[repr({})]", out.join(", ")));
}
- attrs.push(format!("#[repr({})]", out.join(", ")));
}
attrs
}
@@ -831,9 +852,9 @@ pub(crate) enum ItemKind {
ProcMacroItem(ProcMacro),
PrimitiveItem(PrimitiveType),
/// A required associated constant in a trait declaration.
- TyAssocConstItem(Box<Generics>, Type),
+ TyAssocConstItem(Generics, Box<Type>),
/// An associated constant in a trait impl or a provided one in a trait declaration.
- AssocConstItem(Box<Generics>, Type, ConstantKind),
+ AssocConstItem(Generics, Box<Type>, ConstantKind),
/// A required associated type in a trait declaration.
///
/// The bounds may be non-empty if there is a `where` clause.
@@ -1289,7 +1310,7 @@ impl Lifetime {
pub(crate) enum WherePredicate {
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
- EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<GenericParamDef> },
+ EqPredicate { lhs: Type, rhs: Term },
}
impl WherePredicate {
@@ -1300,21 +1321,13 @@ impl WherePredicate {
_ => None,
}
}
-
- pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> {
- match self {
- Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
- Some(bound_params)
- }
- _ => None,
- }
- }
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) enum GenericParamDefKind {
- Lifetime { outlives: Vec<Lifetime> },
- Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
+ Lifetime { outlives: ThinVec<Lifetime> },
+ Type { did: DefId, bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
+ // Option<Box<String>> makes this type smaller than `Option<String>` would.
Const { ty: Box<Type>, default: Option<Box<String>>, is_host_effect: bool },
}
@@ -1332,7 +1345,7 @@ pub(crate) struct GenericParamDef {
impl GenericParamDef {
pub(crate) fn lifetime(name: Symbol) -> Self {
- Self { name, kind: GenericParamDefKind::Lifetime { outlives: Vec::new() } }
+ Self { name, kind: GenericParamDefKind::Lifetime { outlives: ThinVec::new() } }
}
pub(crate) fn is_synthetic_param(&self) -> bool {
@@ -1443,6 +1456,9 @@ impl Trait {
pub(crate) fn unsafety(&self, tcx: TyCtxt<'_>) -> hir::Unsafety {
tcx.trait_def(self.def_id).unsafety
}
+ pub(crate) fn is_object_safe(&self, tcx: TyCtxt<'_>) -> bool {
+ tcx.check_is_object_safe(self.def_id)
+ }
}
#[derive(Clone, Debug)]
@@ -2094,9 +2110,8 @@ impl Discriminant {
pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> {
self.expr.map(|body| rendered_const(tcx, body))
}
- /// Will always be a machine readable number, without underscores or suffixes.
- pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String {
- print_evaluated_const(tcx, self.value, false).unwrap()
+ pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String {
+ print_evaluated_const(tcx, self.value, with_underscores, false).unwrap()
}
}
@@ -2271,8 +2286,8 @@ pub(crate) struct Static {
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct Constant {
- pub(crate) type_: Type,
- pub(crate) generics: Box<Generics>,
+ pub(crate) type_: Box<Type>,
+ pub(crate) generics: Generics,
pub(crate) kind: ConstantKind,
}
@@ -2341,7 +2356,7 @@ impl ConstantKind {
match *self {
ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
- print_evaluated_const(tcx, def_id, true)
+ print_evaluated_const(tcx, def_id, true, true)
}
}
}
@@ -2510,11 +2525,10 @@ mod size_asserts {
static_assert_size!(DocFragment, 32);
static_assert_size!(GenericArg, 32);
static_assert_size!(GenericArgs, 32);
- static_assert_size!(GenericParamDef, 56);
+ static_assert_size!(GenericParamDef, 40);
static_assert_size!(Generics, 16);
static_assert_size!(Item, 56);
- // FIXME(generic_const_items): Further reduce the size.
- static_assert_size!(ItemKind, 72);
+ static_assert_size!(ItemKind, 56);
static_assert_size!(PathSegment, 40);
static_assert_size!(Type, 32);
// tidy-alphabetical-end
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
index 4907a5527..ee7c0068e 100644
--- a/src/librustdoc/clean/types/tests.rs
+++ b/src/librustdoc/clean/types/tests.rs
@@ -1,9 +1,8 @@
use super::*;
use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragment, DocFragmentKind};
-use rustc_span::create_default_session_globals_then;
-use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::Symbol;
+use rustc_span::{create_default_session_globals_then, DUMMY_SP};
fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
vec![DocFragment {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 61e653423..9ff00c194 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -17,6 +17,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_metadata::rendered_const;
use rustc_middle::mir;
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt};
+use rustc_middle::ty::{TypeVisitable, TypeVisitableExt};
use rustc_span::symbol::{kw, sym, Symbol};
use std::fmt::Write as _;
use std::mem;
@@ -76,44 +77,119 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
pub(crate) fn ty_args_to_args<'tcx>(
cx: &mut DocContext<'tcx>,
- args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
+ ty_args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
has_self: bool,
- container: Option<DefId>,
+ owner: DefId,
) -> Vec<GenericArg> {
- let mut skip_first = has_self;
- let mut ret_val =
- Vec::with_capacity(args.skip_binder().len().saturating_sub(if skip_first { 1 } else { 0 }));
-
- ret_val.extend(args.iter().enumerate().filter_map(|(index, kind)| {
- match kind.skip_binder().unpack() {
- GenericArgKind::Lifetime(lt) => {
- Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
- }
- GenericArgKind::Type(_) if skip_first => {
- skip_first = false;
- None
+ if ty_args.skip_binder().is_empty() {
+ // Fast path which avoids executing the query `generics_of`.
+ return Vec::new();
+ }
+
+ let params = &cx.tcx.generics_of(owner).params;
+ let mut elision_has_failed_once_before = false;
+
+ let offset = if has_self { 1 } else { 0 };
+ let mut args = Vec::with_capacity(ty_args.skip_binder().len().saturating_sub(offset));
+
+ let ty_arg_to_arg = |(index, arg): (usize, &ty::GenericArg<'tcx>)| match arg.unpack() {
+ GenericArgKind::Lifetime(lt) => {
+ Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
+ }
+ GenericArgKind::Type(_) if has_self && index == 0 => None,
+ GenericArgKind::Type(ty) => {
+ if !elision_has_failed_once_before
+ && let Some(default) = params[index].default_value(cx.tcx)
+ {
+ let default =
+ ty_args.map_bound(|args| default.instantiate(cx.tcx, args).expect_ty());
+
+ if can_elide_generic_arg(ty_args.rebind(ty), default) {
+ return None;
+ }
+
+ elision_has_failed_once_before = true;
}
- GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(
- kind.rebind(ty),
+
+ Some(GenericArg::Type(clean_middle_ty(
+ ty_args.rebind(ty),
cx,
None,
- container.map(|container| crate::clean::ContainerTy::Regular {
- ty: container,
- args,
+ Some(crate::clean::ContainerTy::Regular {
+ ty: owner,
+ args: ty_args,
has_self,
arg: index,
}),
- ))),
- // FIXME(effects): this relies on the host effect being called `host`, which users could also name
- // their const generics.
- // FIXME(effects): this causes `host = true` and `host = false` generics to also be emitted.
- GenericArgKind::Const(ct) if let ty::ConstKind::Param(p) = ct.kind() && p.name == sym::host => None,
- GenericArgKind::Const(ct) => {
- Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
+ )))
+ }
+ GenericArgKind::Const(ct) => {
+ if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } = params[index].kind
+ {
+ return None;
+ }
+
+ if !elision_has_failed_once_before
+ && let Some(default) = params[index].default_value(cx.tcx)
+ {
+ let default =
+ ty_args.map_bound(|args| default.instantiate(cx.tcx, args).expect_const());
+
+ if can_elide_generic_arg(ty_args.rebind(ct), default) {
+ return None;
+ }
+
+ elision_has_failed_once_before = true;
}
+
+ Some(GenericArg::Const(Box::new(clean_middle_const(ty_args.rebind(ct), cx))))
}
- }));
- ret_val
+ };
+
+ args.extend(ty_args.skip_binder().iter().enumerate().rev().filter_map(ty_arg_to_arg));
+ args.reverse();
+ args
+}
+
+/// Check if the generic argument `actual` coincides with the `default` and can therefore be elided.
+///
+/// This uses a very conservative approach for performance and correctness reasons, meaning for
+/// several classes of terms it claims that they cannot be elided even if they theoretically could.
+/// This is absolutely fine since it mostly concerns edge cases.
+fn can_elide_generic_arg<'tcx, Term>(
+ actual: ty::Binder<'tcx, Term>,
+ default: ty::Binder<'tcx, Term>,
+) -> bool
+where
+ Term: Eq + TypeVisitable<TyCtxt<'tcx>>,
+{
+ // In practice, we shouldn't have any inference variables at this point.
+ // However to be safe, we bail out if we do happen to stumble upon them.
+ if actual.has_infer() || default.has_infer() {
+ return false;
+ }
+
+ // Since we don't properly keep track of bound variables in rustdoc (yet), we don't attempt to
+ // make any sense out of escaping bound variables. We simply don't have enough context and it
+ // would be incorrect to try to do so anyway.
+ if actual.has_escaping_bound_vars() || default.has_escaping_bound_vars() {
+ return false;
+ }
+
+ // Theoretically we could now check if either term contains (non-escaping) late-bound regions or
+ // projections, relate the two using an `InferCtxt` and check if the resulting obligations hold.
+ // Having projections means that the terms can potentially be further normalized thereby possibly
+ // revealing that they are equal after all. Regarding late-bound regions, they could to be
+ // liberated allowing us to consider more types to be equal by ignoring the names of binders
+ // (e.g., `for<'a> TYPE<'a>` and `for<'b> TYPE<'b>`).
+ //
+ // However, we are mostly interested in “reeliding” generic args, i.e., eliding generic args that
+ // were originally elided by the user and later filled in by the compiler contrary to eliding
+ // arbitrary generic arguments if they happen to semantically coincide with the default (of course,
+ // we cannot possibly distinguish these two cases). Therefore and for performance reasons, it
+ // suffices to only perform a syntactic / structural check by comparing the memory addresses of
+ // the interned arguments.
+ actual.skip_binder() == default.skip_binder()
}
fn external_generic_args<'tcx>(
@@ -123,7 +199,7 @@ fn external_generic_args<'tcx>(
bindings: ThinVec<TypeBinding>,
ty_args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> GenericArgs {
- let args = ty_args_to_args(cx, ty_args.map_bound(|args| &args[..]), has_self, Some(did));
+ let args = ty_args_to_args(cx, ty_args.map_bound(|args| &args[..]), has_self, did);
if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
let ty = ty_args
@@ -279,7 +355,8 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
pub(crate) fn print_evaluated_const(
tcx: TyCtxt<'_>,
def_id: DefId,
- underscores_and_type: bool,
+ with_underscores: bool,
+ with_type: bool,
) -> Option<String> {
tcx.const_eval_poly(def_id).ok().and_then(|val| {
let ty = tcx.type_of(def_id).instantiate_identity();
@@ -288,7 +365,7 @@ pub(crate) fn print_evaluated_const(
(mir::ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
(mir::ConstValue::Scalar(_), _) => {
let const_ = mir::Const::from_value(val, ty);
- Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
+ Some(print_const_with_custom_print_scalar(tcx, const_, with_underscores, with_type))
}
_ => None,
}
@@ -324,32 +401,37 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
fn print_const_with_custom_print_scalar<'tcx>(
tcx: TyCtxt<'tcx>,
ct: mir::Const<'tcx>,
- underscores_and_type: bool,
+ with_underscores: bool,
+ with_type: bool,
) -> String {
// Use a slightly different format for integer types which always shows the actual value.
// For all other types, fallback to the original `pretty_print_const`.
match (ct, ct.ty().kind()) {
(mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Uint(ui)) => {
- if underscores_and_type {
- format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
+ let mut output = if with_underscores {
+ format_integer_with_underscore_sep(&int.to_string())
} else {
int.to_string()
+ };
+ if with_type {
+ output += ui.name_str();
}
+ output
}
(mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => {
let ty = ct.ty();
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let data = int.assert_bits(size);
let sign_extended_data = size.sign_extend(data) as i128;
- if underscores_and_type {
- format!(
- "{}{}",
- format_integer_with_underscore_sep(&sign_extended_data.to_string()),
- i.name_str()
- )
+ let mut output = if with_underscores {
+ format_integer_with_underscore_sep(&sign_extended_data.to_string())
} else {
sign_extended_data.to_string()
+ };
+ if with_type {
+ output += i.name_str();
}
+ output
}
_ => ct.to_string(),
}
@@ -502,7 +584,7 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool {
/// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL");
pub(crate) static DOC_CHANNEL: Lazy<&'static str> =
- Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap());
+ Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit('/').filter(|c| !c.is_empty()).next().unwrap());
/// Render a sequence of macro arms in a format suitable for displaying to the user
/// as part of an item declaration.