@@ -8,17 +8,18 @@ use crate::clean::{
88} ;
99use crate :: core:: DocContext ;
1010
11+ use itertools:: Itertools ;
1112use rustc:: hir;
1213use rustc:: hir:: def:: { DefKind , Res } ;
1314use rustc:: hir:: def_id:: { DefId , LOCAL_CRATE } ;
15+ use rustc:: mir:: interpret:: { sign_extend, ConstValue , Scalar } ;
1416use rustc:: ty:: subst:: { GenericArgKind , SubstsRef } ;
1517use rustc:: ty:: { self , DefIdTree , Ty } ;
1618use rustc:: util:: nodemap:: FxHashSet ;
19+ use std:: mem;
1720use syntax_pos;
1821use syntax_pos:: symbol:: { kw, sym, Symbol } ;
1922
20- use std:: mem;
21-
2223pub fn krate ( mut cx : & mut DocContext < ' _ > ) -> Crate {
2324 use crate :: visit_lib:: LibEmbargoVisitor ;
2425
@@ -482,8 +483,78 @@ pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
482483 }
483484}
484485
486+ pub fn print_evaluated_const ( cx : & DocContext < ' _ > , def_id : DefId ) -> Option < String > {
487+ let value =
488+ cx. tcx . const_eval_poly ( def_id) . ok ( ) . and_then ( |value| match ( value. val , & value. ty . kind ) {
489+ ( _, ty:: Ref ( ..) ) => None ,
490+ ( ty:: ConstKind :: Value ( ConstValue :: Scalar ( _) ) , ty:: Adt ( _, _) ) => None ,
491+ ( ty:: ConstKind :: Value ( ConstValue :: Scalar ( _) ) , _) => {
492+ Some ( print_const_with_custom_print_scalar ( cx, value) )
493+ }
494+ _ => None ,
495+ } ) ;
496+
497+ value
498+ }
499+
500+ fn format_integer_with_underscore_sep ( num : & str ) -> String {
501+ let num_chars: Vec < _ > = num. chars ( ) . collect ( ) ;
502+ let num_start_index = if num_chars. get ( 0 ) == Some ( & '-' ) { 1 } else { 0 } ;
503+
504+ num_chars[ ..num_start_index]
505+ . iter ( )
506+ . chain ( num_chars[ num_start_index..] . rchunks ( 3 ) . rev ( ) . intersperse ( & [ '_' ] ) . flatten ( ) )
507+ . collect ( )
508+ }
509+
510+ fn print_const_with_custom_print_scalar ( cx : & DocContext < ' _ > , ct : & ' tcx ty:: Const < ' tcx > ) -> String {
511+ // Use a slightly different format for integer types which always shows the actual value.
512+ // For all other types, fallback to the original `pretty_print_const`.
513+ match ( ct. val , & ct. ty . kind ) {
514+ ( ty:: ConstKind :: Value ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) ) , ty:: Uint ( ui) ) => {
515+ format ! ( "{}{}" , format_integer_with_underscore_sep( & data. to_string( ) ) , ui. name_str( ) )
516+ }
517+ ( ty:: ConstKind :: Value ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) ) , ty:: Int ( i) ) => {
518+ let ty = cx. tcx . lift ( & ct. ty ) . unwrap ( ) ;
519+ let size = cx. tcx . layout_of ( ty:: ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) . size ;
520+ let sign_extended_data = sign_extend ( data, size) as i128 ;
521+
522+ format ! (
523+ "{}{}" ,
524+ format_integer_with_underscore_sep( & sign_extended_data. to_string( ) ) ,
525+ i. name_str( )
526+ )
527+ }
528+ _ => ct. to_string ( ) ,
529+ }
530+ }
531+
532+ pub fn is_literal_expr ( cx : & DocContext < ' _ > , hir_id : hir:: HirId ) -> bool {
533+ if let hir:: Node :: Expr ( expr) = cx. tcx . hir ( ) . get ( hir_id) {
534+ if let hir:: ExprKind :: Lit ( _) = & expr. kind {
535+ return true ;
536+ }
537+
538+ if let hir:: ExprKind :: Unary ( hir:: UnOp :: UnNeg , expr) = & expr. kind {
539+ if let hir:: ExprKind :: Lit ( _) = & expr. kind {
540+ return true ;
541+ }
542+ }
543+ }
544+
545+ false
546+ }
547+
485548pub fn print_const_expr ( cx : & DocContext < ' _ > , body : hir:: BodyId ) -> String {
486- cx. tcx . hir ( ) . hir_to_pretty_string ( body. hir_id )
549+ let value = & cx. tcx . hir ( ) . body ( body) . value ;
550+
551+ let snippet = if !value. span . from_expansion ( ) {
552+ cx. sess ( ) . source_map ( ) . span_to_snippet ( value. span ) . ok ( )
553+ } else {
554+ None
555+ } ;
556+
557+ snippet. unwrap_or_else ( || cx. tcx . hir ( ) . hir_to_pretty_string ( body. hir_id ) )
487558}
488559
489560/// Given a type Path, resolve it to a Type using the TyCtxt
0 commit comments