@@ -8,17 +8,18 @@ use crate::clean::{
8
8
} ;
9
9
use crate :: core:: DocContext ;
10
10
11
+ use itertools:: Itertools ;
11
12
use rustc:: hir;
12
13
use rustc:: hir:: def:: { DefKind , Res } ;
13
14
use rustc:: hir:: def_id:: { DefId , LOCAL_CRATE } ;
15
+ use rustc:: mir:: interpret:: { sign_extend, ConstValue , Scalar } ;
14
16
use rustc:: ty:: subst:: { GenericArgKind , SubstsRef } ;
15
17
use rustc:: ty:: { self , DefIdTree , Ty } ;
16
18
use rustc:: util:: nodemap:: FxHashSet ;
19
+ use std:: mem;
17
20
use syntax_pos;
18
21
use syntax_pos:: symbol:: { kw, sym, Symbol } ;
19
22
20
- use std:: mem;
21
-
22
23
pub fn krate ( mut cx : & mut DocContext < ' _ > ) -> Crate {
23
24
use crate :: visit_lib:: LibEmbargoVisitor ;
24
25
@@ -482,8 +483,78 @@ pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
482
483
}
483
484
}
484
485
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
+
485
548
pub 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 ) )
487
558
}
488
559
489
560
/// Given a type Path, resolve it to a Type using the TyCtxt
0 commit comments