Skip to content

Commit

Permalink
Rework rustdoc const type
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Mar 24, 2021
1 parent f5fe425 commit 0cde855
Show file tree
Hide file tree
Showing 11 changed files with 805 additions and 608 deletions.
19 changes: 6 additions & 13 deletions src/librustdoc/clean/inline.rs
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,24 +490,17 @@ 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 {
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))
}),
}
clean::Constant::Inline { type_: cx.tcx.type_of(did).clean(cx), did }
}

fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
Expand Down
23 changes: 8 additions & 15 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -393,14 +393,12 @@ impl Clean<Lifetime> for hir::GenericParam<'_> {

impl Clean<Constant> for hir::ConstArg {
fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
Constant {
Constant::Generic {
type_: cx
.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),
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(cx.tcx, self.def_id))
} else {
None
};
Expand Down Expand Up @@ -1745,12 +1743,8 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {

impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
Constant {
type_: self.ty.clean(cx),
expr: format!("{}", self),
value: None,
is_literal: false,
}
// FIXME: instead of storing `format!("{}", self)`, store `self` directly instead.
Constant::TyConst { type_: self.ty.clean(cx), expr: format!("{}", self) }
}
}

Expand Down Expand Up @@ -1951,11 +1945,10 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
ItemKind::Static(ty, mutability, body_id) => {
StaticItem(Static { type_: ty.clean(cx), mutability, expr: Some(body_id) })
}
ItemKind::Const(ty, body_id) => ConstantItem(Constant {
ItemKind::Const(ty, body_id) => ConstantItem(Constant::Const {
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),
body: body_id,
did: def_id,
}),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
bounds: ty.bounds.clean(cx),
Expand Down
66 changes: 60 additions & 6 deletions src/librustdoc/clean/types.rs
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 @@ -1986,11 +1987,64 @@ 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 enum Constant {
/// Typed constant value.
TyConst { type_: Type, 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.
Generic { type_: Type, body: BodyId },
/// Inlined constant (from another crate).
Inline { type_: Type, did: DefId },
/// const FOO: u32 = ...;
Const { type_: Type, did: DefId, body: BodyId },
}

impl Constant {
crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
match self {
Self::TyConst { expr, .. } => expr.clone(),
Self::Inline { did, .. } => print_inlined_const(tcx, *did),
Self::Const { body, .. } | Self::Generic { body, .. } => print_const_expr(tcx, *body),
}
}

crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
match self {
Self::TyConst { .. } | Self::Generic { .. } => None,
Self::Inline { did, .. } | Self::Const { did, .. } => print_evaluated_const(tcx, *did),
}
}

crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
match self {
Self::TyConst { .. } => false,
Self::Inline { did, .. } => did
.as_local()
.map_or(false, |did| is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(did))),
Self::Const { body, .. } | Self::Generic { body, .. } => {
is_literal_expr(tcx, body.hir_id)
}
}
}

crate fn type_(&self) -> &Type {
match *self {
Self::TyConst { ref type_, .. }
| Self::Inline { ref type_, .. }
| Self::Const { ref type_, .. }
| Self::Generic { ref type_, .. } => type_,
}
}

crate fn to_type(self) -> Type {
match self {
Self::TyConst { type_, .. }
| Self::Inline { type_, .. }
| Self::Const { type_, .. }
| Self::Generic { type_, .. } => type_,
}
}
}

#[derive(Clone, Debug)]
Expand Down
24 changes: 12 additions & 12 deletions src/librustdoc/clean/utils.rs
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

0 comments on commit 0cde855

Please sign in to comment.