summaryrefslogtreecommitdiffstats
path: root/src/librustdoc/clean/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/clean/utils.rs')
-rw-r--r--src/librustdoc/clean/utils.rs116
1 files changed, 13 insertions, 103 deletions
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index a86bbcc76..61e653423 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -14,8 +14,8 @@ use rustc_ast::tokenstream::TokenTree;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_metadata::rendered_const;
use rustc_middle::mir;
-use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
use std::fmt::Write as _;
@@ -104,6 +104,10 @@ pub(crate) fn ty_args_to_args<'tcx>(
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))))
}
@@ -153,7 +157,7 @@ pub(super) fn external_path<'tcx>(
args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> Path {
let def_kind = cx.tcx.def_kind(did);
- let name = cx.tcx.item_name(did);
+ let name = cx.tcx.opt_item_name(did).unwrap_or(kw::Empty);
Path {
res: Res::Def(def_kind, did),
segments: thin_vec![PathSegment {
@@ -255,7 +259,7 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => {
let s = if let Some(def) = def.as_local() {
- print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def))
+ rendered_const(cx.tcx, cx.tcx.hir().body_owned_by(def))
} else {
inline::print_inlined_const(cx.tcx, def)
};
@@ -281,9 +285,9 @@ pub(crate) fn print_evaluated_const(
let ty = tcx.type_of(def_id).instantiate_identity();
match (val, ty.kind()) {
(_, &ty::Ref(..)) => None,
- (ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
- (ConstValue::Scalar(_), _) => {
- let const_ = mir::ConstantKind::from_value(val, ty);
+ (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))
}
_ => None,
@@ -319,20 +323,20 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
fn print_const_with_custom_print_scalar<'tcx>(
tcx: TyCtxt<'tcx>,
- ct: mir::ConstantKind<'tcx>,
+ ct: mir::Const<'tcx>,
underscores_and_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::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => {
+ (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())
} else {
int.to_string()
}
}
- (mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
+ (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);
@@ -367,100 +371,6 @@ pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
false
}
-/// Build a textual representation of an unevaluated constant expression.
-///
-/// If the const expression is too complex, an underscore `_` is returned.
-/// For const arguments, it's `{ _ }` to be precise.
-/// This means that the output is not necessarily valid Rust code.
-///
-/// Currently, only
-///
-/// * literals (optionally with a leading `-`)
-/// * unit `()`
-/// * blocks (`{ … }`) around simple expressions and
-/// * paths without arguments
-///
-/// are considered simple enough. Simple blocks are included since they are
-/// necessary to disambiguate unit from the unit type.
-/// This list might get extended in the future.
-///
-/// Without this censoring, in a lot of cases the output would get too large
-/// and verbose. Consider `match` expressions, blocks and deeply nested ADTs.
-/// Further, private and `doc(hidden)` fields of structs would get leaked
-/// since HIR datatypes like the `body` parameter do not contain enough
-/// semantic information for this function to be able to hide them –
-/// at least not without significant performance overhead.
-///
-/// Whenever possible, prefer to evaluate the constant first and try to
-/// use a different method for pretty-printing. Ideally this function
-/// should only ever be used as a fallback.
-pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String {
- let hir = tcx.hir();
- let value = &hir.body(body).value;
-
- #[derive(PartialEq, Eq)]
- enum Classification {
- Literal,
- Simple,
- Complex,
- }
-
- use Classification::*;
-
- fn classify(expr: &hir::Expr<'_>) -> Classification {
- match &expr.kind {
- hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
- if matches!(expr.kind, hir::ExprKind::Lit(_)) { Literal } else { Complex }
- }
- hir::ExprKind::Lit(_) => Literal,
- hir::ExprKind::Tup([]) => Simple,
- hir::ExprKind::Block(hir::Block { stmts: [], expr: Some(expr), .. }, _) => {
- if classify(expr) == Complex { Complex } else { Simple }
- }
- // Paths with a self-type or arguments are too “complex” following our measure since
- // they may leak private fields of structs (with feature `adt_const_params`).
- // Consider: `<Self as Trait<{ Struct { private: () } }>>::CONSTANT`.
- // Paths without arguments are definitely harmless though.
- hir::ExprKind::Path(hir::QPath::Resolved(_, hir::Path { segments, .. })) => {
- if segments.iter().all(|segment| segment.args.is_none()) { Simple } else { Complex }
- }
- // FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty
- // contains const arguments. Is there a *concise* way to check for this?
- hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple,
- // FIXME: Can they contain const arguments and thus leak private struct fields?
- hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple,
- _ => Complex,
- }
- }
-
- let classification = classify(value);
-
- if classification == Literal
- && !value.span.from_expansion()
- && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) {
- // For literals, we avoid invoking the pretty-printer and use the source snippet instead to
- // preserve certain stylistic choices the user likely made for the sake legibility like
- //
- // * hexadecimal notation
- // * underscores
- // * character escapes
- //
- // FIXME: This passes through `-/*spacer*/0` verbatim.
- snippet
- } else if classification == Simple {
- // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and
- // other formatting artifacts.
- rustc_hir_pretty::id_to_string(&hir, body.hir_id)
- } else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst {
- // FIXME: Omit the curly braces if the enclosing expression is an array literal
- // with a repeated element (an `ExprKind::Repeat`) as in such case it
- // would not actually need any disambiguation.
- "{ _ }".to_owned()
- } else {
- "_".to_owned()
- }
-}
-
/// Given a type Path, resolve it to a Type using the TyCtxt
pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
debug!("resolve_type({path:?})");