Skip to content

Commit

Permalink
Auto merge of #82873 - GuillaumeGomez:rustdoc-const-ty, r=jyn514
Browse files Browse the repository at this point in the history
Rework rustdoc const type

This PR is mostly about two things:
 1. Not storing some information in the `clean::Constant` type
 2. Using `TyCtxt` in the formatting (which we will need in any case as we move forward in any case).

Also: I'm very curious of the perf change in here.

Thanks a lot `@danielhenrymantilla` for your `Captures` idea! It allowed me to solve the lifetime issue completely. :)

r? `@jyn514`
  • Loading branch information
bors committed Mar 25, 2021
2 parents 52e3dff + 7b59089 commit 3debe9a
Show file tree
Hide file tree
Showing 11 changed files with 840 additions and 634 deletions.
20 changes: 8 additions & 12 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc_hir::Mutability;
use rustc_metadata::creader::LoadedMacro;
use rustc_middle::ty;
use rustc_middle::ty::{self, TyCtxt};
use rustc_mir::const_eval::is_min_const_fn;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
Expand Down Expand Up @@ -490,23 +490,19 @@ fn build_module(
clean::Module { items, is_crate: false }
}

crate fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
crate fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
if let Some(did) = did.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(did);
rustc_hir_pretty::id_to_string(&cx.tcx.hir(), hir_id)
let hir_id = tcx.hir().local_def_id_to_hir_id(did);
rustc_hir_pretty::id_to_string(&tcx.hir(), hir_id)
} else {
cx.tcx.rendered_const(did)
tcx.rendered_const(did)
}
}

fn build_const(cx: &mut DocContext<'_>, did: DefId) -> clean::Constant {
fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
clean::Constant {
type_: cx.tcx.type_of(did).clean(cx),
expr: print_inlined_const(cx, did),
value: clean::utils::print_evaluated_const(cx, did),
is_literal: did.as_local().map_or(false, |did| {
clean::utils::is_literal_expr(cx, cx.tcx.hir().local_def_id_to_hir_id(did))
}),
type_: cx.tcx.type_of(def_id).clean(cx),
kind: clean::ConstantKind::Extern { def_id },
}
}

Expand Down
15 changes: 5 additions & 10 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,7 @@ impl Clean<Constant> for hir::ConstArg {
.tcx
.type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id())
.clean(cx),
expr: print_const_expr(cx.tcx, self.value.body),
value: None,
is_literal: is_literal_expr(cx, self.value.body.hir_id),
kind: ConstantKind::Anonymous { body: self.value.body },
}
}
}
Expand Down Expand Up @@ -1135,7 +1133,7 @@ impl Clean<Item> for ty::AssocItem {
ty::AssocKind::Const => {
let ty = tcx.type_of(self.def_id);
let default = if self.defaultness.has_value() {
Some(inline::print_inlined_const(cx, self.def_id))
Some(inline::print_inlined_const(tcx, self.def_id))
} else {
None
};
Expand Down Expand Up @@ -1745,11 +1743,10 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {

impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
// FIXME: instead of storing the stringified expression, store `self` directly instead.
Constant {
type_: self.ty.clean(cx),
expr: format!("{}", self),
value: None,
is_literal: false,
kind: ConstantKind::TyConst { expr: self.to_string() },
}
}
}
Expand Down Expand Up @@ -1953,9 +1950,7 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
}
ItemKind::Const(ty, body_id) => ConstantItem(Constant {
type_: ty.clean(cx),
expr: print_const_expr(cx.tcx, body_id),
value: print_evaluated_const(cx, def_id),
is_literal: is_literal_expr(cx, body_id.hir_id),
kind: ConstantKind::Local { body: body_id, def_id },
}),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
bounds: ty.bounds.clean(cx),
Expand Down
58 changes: 54 additions & 4 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ use rustc_target::spec::abi::Abi;

use crate::clean::cfg::Cfg;
use crate::clean::external_path;
use crate::clean::inline;
use crate::clean::inline::{self, print_inlined_const};
use crate::clean::types::Type::{QPath, ResolvedPath};
use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
use crate::clean::Clean;
use crate::core::DocContext;
use crate::formats::cache::Cache;
Expand Down Expand Up @@ -1988,9 +1989,58 @@ crate struct Static {
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
crate struct Constant {
crate type_: Type,
crate expr: String,
crate value: Option<String>,
crate is_literal: bool,
crate kind: ConstantKind,
}

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
crate enum ConstantKind {
/// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a
/// `BodyId`, we need to handle it on its own.
///
/// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
/// by a DefId. So this field must be different from `Extern`.
TyConst { expr: String },
/// A constant (expression) that's not an item or associated item. These are usually found
/// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
/// used to define explicit discriminant values for enum variants.
Anonymous { body: BodyId },
/// A constant from a different crate.
Extern { def_id: DefId },
/// `const FOO: u32 = ...;`
Local { def_id: DefId, body: BodyId },
}

impl Constant {
crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
match self.kind {
ConstantKind::TyConst { ref expr } => expr.clone(),
ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
print_const_expr(tcx, body)
}
}
}

crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
match self.kind {
ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
print_evaluated_const(tcx, def_id)
}
}
}

crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
match self.kind {
ConstantKind::TyConst { .. } => false,
ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
}),
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
is_literal_expr(tcx, body.hir_id)
}
}
}
}

#[derive(Clone, Debug)]
Expand Down
24 changes: 12 additions & 12 deletions src/librustdoc/clean/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id))
} else {
inline::print_inlined_const(cx, def.did)
inline::print_inlined_const(cx.tcx, def.did)
};
if let Some(promoted) = promoted {
s.push_str(&format!("::{:?}", promoted))
Expand All @@ -324,15 +324,15 @@ crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
}
}

crate fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option<String> {
cx.tcx.const_eval_poly(def_id).ok().and_then(|val| {
let ty = cx.tcx.type_of(def_id);
crate fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
tcx.const_eval_poly(def_id).ok().and_then(|val| {
let ty = tcx.type_of(def_id);
match (val, ty.kind()) {
(_, &ty::Ref(..)) => None,
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
(ConstValue::Scalar(_), _) => {
let const_ = ty::Const::from_value(cx.tcx, val, ty);
Some(print_const_with_custom_print_scalar(cx, const_))
let const_ = ty::Const::from_value(tcx, val, ty);
Some(print_const_with_custom_print_scalar(tcx, const_))
}
_ => None,
}
Expand All @@ -349,16 +349,16 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
.collect()
}

fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const<'tcx>) -> String {
fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tcx>) -> 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.val, ct.ty.kind()) {
(ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Uint(ui)) => {
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
}
(ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Int(i)) => {
let ty = cx.tcx.lift(ct.ty).unwrap();
let size = cx.tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let ty = tcx.lift(ct.ty).unwrap();
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;

Expand All @@ -372,8 +372,8 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const
}
}

crate fn is_literal_expr(cx: &DocContext<'_>, hir_id: hir::HirId) -> bool {
if let hir::Node::Expr(expr) = cx.tcx.hir().get(hir_id) {
crate fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
if let hir::Node::Expr(expr) = tcx.hir().get(hir_id) {
if let hir::ExprKind::Lit(_) = &expr.kind {
return true;
}
Expand Down Expand Up @@ -411,7 +411,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty
return Generic(kw::SelfUpper);
}
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache))));
return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache, cx.tcx))));
}
Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
_ => false,
Expand Down
Loading

0 comments on commit 3debe9a

Please sign in to comment.