Show value for consts in the documentation
This commit is contained in:
parent
625375400c
commit
811bdeee00
@ -3869,6 +3869,7 @@ dependencies = [
|
||||
name = "rustdoc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.8.0",
|
||||
"minifier",
|
||||
"pulldown-cmark 0.5.3",
|
||||
"rustc-rayon",
|
||||
|
@ -30,7 +30,7 @@ pub const DIGITS: u32 = 6;
|
||||
///
|
||||
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const EPSILON: f32 = 1.19209290e-07_f32;
|
||||
pub const EPSILON: f32 = 1.1920929e-7_f32;
|
||||
|
||||
/// Smallest finite `f32` value.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -15,3 +15,4 @@ rayon = { version = "0.3.0", package = "rustc-rayon" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tempfile = "3"
|
||||
itertools = "0.8"
|
||||
|
@ -450,7 +450,16 @@ pub fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
|
||||
}
|
||||
|
||||
fn build_const(cx: &DocContext<'_>, did: DefId) -> clean::Constant {
|
||||
clean::Constant { type_: cx.tcx.type_of(did).clean(cx), expr: print_inlined_const(cx, did) }
|
||||
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: cx
|
||||
.tcx
|
||||
.hir()
|
||||
.as_local_hir_id(did)
|
||||
.map_or(false, |hir_id| clean::utils::is_literal_expr(cx, hir_id)),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_static(cx: &DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
|
||||
|
@ -435,6 +435,8 @@ impl Clean<Constant> for hir::ConstArg {
|
||||
Constant {
|
||||
type_: cx.tcx.type_of(cx.tcx.hir().body_owner_def_id(self.value.body)).clean(cx),
|
||||
expr: print_const_expr(cx, self.value.body),
|
||||
value: None,
|
||||
is_literal: is_literal_expr(cx, self.value.body.hir_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1717,7 +1719,12 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
|
||||
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
|
||||
fn clean(&self, cx: &DocContext<'_>) -> Constant {
|
||||
Constant { type_: self.ty.clean(cx), expr: format!("{}", self) }
|
||||
Constant {
|
||||
type_: self.ty.clean(cx),
|
||||
expr: format!("{}", self),
|
||||
value: None,
|
||||
is_literal: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2062,17 +2069,21 @@ impl Clean<Item> for doctree::Static<'_> {
|
||||
|
||||
impl Clean<Item> for doctree::Constant<'_> {
|
||||
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||
let def_id = cx.tcx.hir().local_def_id(self.id);
|
||||
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
attrs: self.attrs.clean(cx),
|
||||
source: self.whence.clean(cx),
|
||||
def_id: cx.tcx.hir().local_def_id(self.id),
|
||||
def_id,
|
||||
visibility: self.vis.clean(cx),
|
||||
stability: cx.stability(self.id).clean(cx),
|
||||
deprecation: cx.deprecation(self.id).clean(cx),
|
||||
inner: ConstantItem(Constant {
|
||||
type_: self.type_.clean(cx),
|
||||
expr: print_const_expr(cx, self.expr),
|
||||
value: print_evaluated_const(cx, def_id),
|
||||
is_literal: is_literal_expr(cx, self.expr.hir_id),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -1460,6 +1460,8 @@ pub struct Static {
|
||||
pub struct Constant {
|
||||
pub type_: Type,
|
||||
pub expr: String,
|
||||
pub value: Option<String>,
|
||||
pub is_literal: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
|
@ -8,17 +8,18 @@ use crate::clean::{
|
||||
};
|
||||
use crate::core::DocContext;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def::{DefKind, Res};
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::mir::interpret::{sign_extend, ConstValue, Scalar};
|
||||
use rustc::ty::subst::{GenericArgKind, SubstsRef};
|
||||
use rustc::ty::{self, DefIdTree, Ty};
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use std::mem;
|
||||
use syntax_pos;
|
||||
use syntax_pos::symbol::{kw, sym, Symbol};
|
||||
|
||||
use std::mem;
|
||||
|
||||
pub fn krate(mut cx: &mut DocContext<'_>) -> Crate {
|
||||
use crate::visit_lib::LibEmbargoVisitor;
|
||||
|
||||
@ -482,8 +483,78 @@ pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option<String> {
|
||||
let value =
|
||||
cx.tcx.const_eval_poly(def_id).ok().and_then(|value| match (value.val, &value.ty.kind) {
|
||||
(_, ty::Ref(..)) => None,
|
||||
(ty::ConstKind::Value(ConstValue::Scalar(_)), ty::Adt(_, _)) => None,
|
||||
(ty::ConstKind::Value(ConstValue::Scalar(_)), _) => {
|
||||
Some(print_const_with_custom_print_scalar(cx, value))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
fn format_integer_with_underscore_sep(num: &str) -> String {
|
||||
let num_chars: Vec<_> = num.chars().collect();
|
||||
let num_start_index = if num_chars.get(0) == Some(&'-') { 1 } else { 0 };
|
||||
|
||||
num_chars[..num_start_index]
|
||||
.iter()
|
||||
.chain(num_chars[num_start_index..].rchunks(3).rev().intersperse(&['_']).flatten())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, 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(Scalar::Raw { data, .. })), ty::Uint(ui)) => {
|
||||
format!("{}{}", format_integer_with_underscore_sep(&data.to_string()), ui.name_str())
|
||||
}
|
||||
(ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data, .. })), 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 sign_extended_data = sign_extend(data, size) as i128;
|
||||
|
||||
format!(
|
||||
"{}{}",
|
||||
format_integer_with_underscore_sep(&sign_extended_data.to_string()),
|
||||
i.name_str()
|
||||
)
|
||||
}
|
||||
_ => ct.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_literal_expr(cx: &DocContext<'_>, hir_id: hir::HirId) -> bool {
|
||||
if let hir::Node::Expr(expr) = cx.tcx.hir().get(hir_id) {
|
||||
if let hir::ExprKind::Lit(_) = &expr.kind {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let hir::ExprKind::Unary(hir::UnOp::UnNeg, expr) = &expr.kind {
|
||||
if let hir::ExprKind::Lit(_) = &expr.kind {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn print_const_expr(cx: &DocContext<'_>, body: hir::BodyId) -> String {
|
||||
cx.tcx.hir().hir_to_pretty_string(body.hir_id)
|
||||
let value = &cx.tcx.hir().body(body).value;
|
||||
|
||||
let snippet = if !value.span.from_expansion() {
|
||||
cx.sess().source_map().span_to_snippet(value.span).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
snippet.unwrap_or_else(|| cx.tcx.hir().hir_to_pretty_string(body.hir_id))
|
||||
}
|
||||
|
||||
/// Given a type Path, resolve it to a Type using the TyCtxt
|
||||
|
@ -2272,14 +2272,36 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
|
||||
fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Constant) {
|
||||
write!(w, "<pre class='rust const'>");
|
||||
render_attributes(w, it, false);
|
||||
|
||||
write!(
|
||||
w,
|
||||
"{vis}const \
|
||||
{name}: {typ}</pre>",
|
||||
{name}: {typ}",
|
||||
vis = it.visibility.print_with_space(),
|
||||
name = it.name.as_ref().unwrap(),
|
||||
typ = c.type_.print()
|
||||
typ = c.type_.print(),
|
||||
);
|
||||
|
||||
if c.value.is_some() || c.is_literal {
|
||||
write!(w, " = {expr};", expr = c.expr);
|
||||
} else {
|
||||
write!(w, ";");
|
||||
}
|
||||
|
||||
if let Some(value) = &c.value {
|
||||
if !c.is_literal {
|
||||
let value_lowercase = value.to_lowercase();
|
||||
let expr_lowercase = c.expr.to_lowercase();
|
||||
|
||||
if value_lowercase != expr_lowercase
|
||||
&& value_lowercase.trim_end_matches("i32") != expr_lowercase
|
||||
{
|
||||
write!(w, " // {value}", value = value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write!(w, "</pre>");
|
||||
document(w, cx, it)
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@ pub struct VSet<T, const ORDER: Order> {
|
||||
inner: Vec<T>,
|
||||
}
|
||||
|
||||
// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, { Order::Sorted }>'
|
||||
// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, {Order::Sorted}>'
|
||||
impl <T> VSet<T, {Order::Sorted}> {
|
||||
pub fn new() -> Self {
|
||||
Self { inner: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, { Order::Unsorted }>'
|
||||
// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, {Order::Unsorted}>'
|
||||
impl <T> VSet<T, {Order::Unsorted}> {
|
||||
pub fn new() -> Self {
|
||||
Self { inner: Vec::new() }
|
||||
|
@ -1,5 +0,0 @@
|
||||
// Test that the contents of constants are not displayed as part of the
|
||||
// documentation.
|
||||
|
||||
// @!has dont_show_const_contents/constant.CONST_S.html 'dont show this'
|
||||
pub const CONST_S: &'static str = "dont show this";
|
64
src/test/rustdoc/show-const-contents.rs
Normal file
64
src/test/rustdoc/show-const-contents.rs
Normal file
@ -0,0 +1,64 @@
|
||||
// Test that the contents of constants are displayed as part of the
|
||||
// documentation.
|
||||
|
||||
// @has show_const_contents/constant.CONST_S.html 'show this'
|
||||
// @!has show_const_contents/constant.CONST_S.html '; //'
|
||||
pub const CONST_S: &'static str = "show this";
|
||||
|
||||
// @has show_const_contents/constant.CONST_I32.html '= 42;'
|
||||
// @!has show_const_contents/constant.CONST_I32.html '; //'
|
||||
pub const CONST_I32: i32 = 42;
|
||||
|
||||
// @has show_const_contents/constant.CONST_I32_HEX.html '= 0x42;'
|
||||
// @!has show_const_contents/constant.CONST_I32_HEX.html '; //'
|
||||
pub const CONST_I32_HEX: i32 = 0x42;
|
||||
|
||||
// @has show_const_contents/constant.CONST_NEG_I32.html '= -42;'
|
||||
// @!has show_const_contents/constant.CONST_NEG_I32.html '; //'
|
||||
pub const CONST_NEG_I32: i32 = -42;
|
||||
|
||||
// @has show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '= 42i32;'
|
||||
// @!has show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '// 42i32'
|
||||
pub const CONST_EQ_TO_VALUE_I32: i32 = 42i32;
|
||||
|
||||
// @has show_const_contents/constant.CONST_CALC_I32.html '= 42 + 1; // 43i32'
|
||||
pub const CONST_CALC_I32: i32 = 42 + 1;
|
||||
|
||||
// @!has show_const_contents/constant.CONST_REF_I32.html '= &42;'
|
||||
// @!has show_const_contents/constant.CONST_REF_I32.html '; //'
|
||||
pub const CONST_REF_I32: &'static i32 = &42;
|
||||
|
||||
// @has show_const_contents/constant.CONST_I32_MAX.html '= i32::max_value(); // 2_147_483_647i32'
|
||||
pub const CONST_I32_MAX: i32 = i32::max_value();
|
||||
|
||||
// @!has show_const_contents/constant.UNIT.html '= ();'
|
||||
// @!has show_const_contents/constant.UNIT.html '; //'
|
||||
pub const UNIT: () = ();
|
||||
|
||||
pub struct MyType(i32);
|
||||
|
||||
// @!has show_const_contents/constant.MY_TYPE.html '= MyType(42);'
|
||||
// @!has show_const_contents/constant.MY_TYPE.html '; //'
|
||||
pub const MY_TYPE: MyType = MyType(42);
|
||||
|
||||
pub struct MyTypeWithStr(&'static str);
|
||||
|
||||
// @!has show_const_contents/constant.MY_TYPE_WITH_STR.html '= MyTypeWithStr("show this");'
|
||||
// @!has show_const_contents/constant.MY_TYPE_WITH_STR.html '; //'
|
||||
pub const MY_TYPE_WITH_STR: MyTypeWithStr = MyTypeWithStr("show this");
|
||||
|
||||
// @has show_const_contents/constant.EPSILON.html '1.1920929e-7f32;'
|
||||
// @!has show_const_contents/constant.EPSILON.html '; //'
|
||||
pub use std::f32::EPSILON;
|
||||
|
||||
// @has show_const_contents/constant.MAX.html '= i32::max_value(); // 2_147_483_647i32'
|
||||
pub use std::i32::MAX;
|
||||
|
||||
macro_rules! int_module {
|
||||
($T:ident) => (
|
||||
pub const MIN: $T = $T::min_value();
|
||||
)
|
||||
}
|
||||
|
||||
// @has show_const_contents/constant.MIN.html '= i16::min_value(); // -32_768i16'
|
||||
int_module!(i16);
|
Loading…
Reference in New Issue
Block a user