@@ -54,6 +54,7 @@ thread_local! {
54
54
static FORCE_IMPL_FILENAME_LINE : Cell <bool > = Cell :: new( false ) ;
55
55
static SHOULD_PREFIX_WITH_CRATE : Cell <bool > = Cell :: new( false ) ;
56
56
static NO_QUERIES : Cell <bool > = Cell :: new( false ) ;
57
+ static NO_CONST_PATH : Cell <bool > = Cell :: new( false ) ;
57
58
}
58
59
59
60
/// Avoids running any queries during any prints that occur
@@ -72,6 +73,15 @@ pub fn with_no_queries<F: FnOnce() -> R, R>(f: F) -> R {
72
73
} )
73
74
}
74
75
76
+ pub fn with_no_const_path < F : FnOnce ( ) -> R , R > ( f : F ) -> R {
77
+ NO_CONST_PATH . with ( |no_const_path| {
78
+ let old = no_const_path. replace ( true ) ;
79
+ let result = f ( ) ;
80
+ no_const_path. set ( old) ;
81
+ result
82
+ } )
83
+ }
84
+
75
85
/// Force us to name impls with just the filename/line number. We
76
86
/// normally try to use types. But at some points, notably while printing
77
87
/// cycle errors, this can result in extra or suboptimal error output,
@@ -858,7 +868,9 @@ pub trait PrettyPrinter<'tcx>:
858
868
) -> Result < Self :: Const , Self :: Error > {
859
869
define_scoped_cx ! ( self ) ;
860
870
861
- if self . tcx ( ) . sess . verbose ( ) {
871
+ // See the call to `with_no_const_path` inside the
872
+ // `ty::ConstKind::Unevaluated` for why we check `NO_CONST_PATH`
873
+ if self . tcx ( ) . sess . verbose ( ) || NO_CONST_PATH . with ( |q| q. get ( ) ) {
862
874
p ! ( write( "Const({:?}: {:?})" , ct. val, ct. ty) ) ;
863
875
return Ok ( self ) ;
864
876
}
@@ -882,29 +894,39 @@ pub trait PrettyPrinter<'tcx>:
882
894
883
895
match ct. val {
884
896
ty:: ConstKind :: Unevaluated ( did, substs, promoted) => {
885
- if let Some ( promoted) = promoted {
886
- p ! ( print_value_path( did, substs) ) ;
887
- p ! ( write( "::{:?}" , promoted) ) ;
888
- } else {
889
- match self . tcx ( ) . def_kind ( did) {
890
- DefKind :: Static | DefKind :: Const | DefKind :: AssocConst => {
891
- p ! ( print_value_path( did, substs) )
892
- }
893
- _ => {
894
- if did. is_local ( ) {
895
- let span = self . tcx ( ) . def_span ( did) ;
896
- if let Ok ( snip) = self . tcx ( ) . sess . source_map ( ) . span_to_snippet ( span)
897
- {
898
- p ! ( write( "{}" , snip) )
897
+ // Don't re-entrantly enter this code path: that is,
898
+ // don't try to print the DefPath of an unevaluated const
899
+ // while we're already printing the DefPath of an unevaluated
900
+ // const. This ensures that we never end up trying to recursively
901
+ // print a const that we're already printing.
902
+ // See issue #68104 for more details
903
+ self = with_no_const_path ( || {
904
+ if let Some ( promoted) = promoted {
905
+ p ! ( print_value_path( did, substs) ) ;
906
+ p ! ( write( "::{:?}" , promoted) ) ;
907
+ } else {
908
+ match self . tcx ( ) . def_kind ( did) {
909
+ DefKind :: Static | DefKind :: Const | DefKind :: AssocConst => {
910
+ p ! ( print_value_path( did, substs) )
911
+ }
912
+ _ => {
913
+ if did. is_local ( ) {
914
+ let span = self . tcx ( ) . def_span ( did) ;
915
+ if let Ok ( snip) =
916
+ self . tcx ( ) . sess . source_map ( ) . span_to_snippet ( span)
917
+ {
918
+ p ! ( write( "{}" , snip) )
919
+ } else {
920
+ print_underscore ! ( )
921
+ }
899
922
} else {
900
923
print_underscore ! ( )
901
924
}
902
- } else {
903
- print_underscore ! ( )
904
925
}
905
926
}
906
927
}
907
- }
928
+ Ok ( self )
929
+ } ) ?;
908
930
}
909
931
ty:: ConstKind :: Infer ( ..) => print_underscore ! ( ) ,
910
932
ty:: ConstKind :: Param ( ParamConst { name, .. } ) => p ! ( write( "{}" , name) ) ,
0 commit comments