1
1
use hir:: def:: Namespace ;
2
2
use hir:: map:: DefPathData ;
3
3
use hir:: def_id:: { CrateNum , DefId , CRATE_DEF_INDEX , LOCAL_CRATE } ;
4
+ use middle:: region;
4
5
use ty:: { self , DefIdTree , Ty , TyCtxt , TypeFoldable } ;
5
6
use ty:: subst:: { Kind , Subst , Substs , UnpackedKind } ;
6
7
use middle:: cstore:: { ExternCrate , ExternCrateSource } ;
@@ -68,7 +69,7 @@ pub struct RegionHighlightMode {
68
69
/// This is used when you have a signature like `fn foo(x: &u32,
69
70
/// y: &'a u32)` and we want to give a name to the region of the
70
71
/// reference `x`.
71
- pub ( crate ) highlight_bound_region : Option < ( ty:: BoundRegion , usize ) > ,
72
+ highlight_bound_region : Option < ( ty:: BoundRegion , usize ) > ,
72
73
}
73
74
74
75
impl RegionHighlightMode {
@@ -116,7 +117,7 @@ impl RegionHighlightMode {
116
117
117
118
/// Returns `Some(n)` with the number to use for the given region,
118
119
/// if any.
119
- pub ( crate ) fn region_highlighted ( & self , region : ty:: Region < ' _ > ) -> Option < usize > {
120
+ fn region_highlighted ( & self , region : ty:: Region < ' _ > ) -> Option < usize > {
120
121
self
121
122
. highlight_regions
122
123
. iter ( )
@@ -252,6 +253,7 @@ pub trait Printer: Sized {
252
253
type Error ;
253
254
254
255
type Path ;
256
+ type Region ;
255
257
256
258
fn print_def_path (
257
259
self : PrintCx < ' _ , ' _ , ' tcx , Self > ,
@@ -273,6 +275,11 @@ pub trait Printer: Sized {
273
275
self . default_print_impl_path ( impl_def_id, substs, ns, self_ty, trait_ref)
274
276
}
275
277
278
+ fn print_region (
279
+ self : PrintCx < ' _ , ' _ , ' _ , Self > ,
280
+ region : ty:: Region < ' _ > ,
281
+ ) -> Result < Self :: Region , Self :: Error > ;
282
+
276
283
fn path_crate (
277
284
self : PrintCx < ' _ , ' _ , ' _ , Self > ,
278
285
cnum : CrateNum ,
@@ -312,7 +319,7 @@ pub trait Printer: Sized {
312
319
}
313
320
314
321
/// Trait for printers that pretty-print using `fmt::Write` to the printer.
315
- pub trait PrettyPrinter : Printer < Error = fmt:: Error , Path = Self > + fmt:: Write {
322
+ pub trait PrettyPrinter : Printer < Error = fmt:: Error , Path = Self , Region = Self > + fmt:: Write {
316
323
/// Enter a nested print context, for pretty-printing
317
324
/// nested components in some larger context.
318
325
fn nest < ' a , ' gcx , ' tcx , E > (
@@ -331,9 +338,26 @@ pub trait PrettyPrinter: Printer<Error = fmt::Error, Path = Self> + fmt::Write {
331
338
} )
332
339
}
333
340
334
- fn region_highlight_mode ( & self ) -> RegionHighlightMode {
335
- RegionHighlightMode :: default ( )
341
+ /// Return `true` if the region should be printed in path generic args
342
+ /// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`.
343
+ fn always_print_region_in_paths (
344
+ self : & PrintCx < ' _ , ' _ , ' _ , Self > ,
345
+ _region : ty:: Region < ' _ > ,
346
+ ) -> bool {
347
+ false
336
348
}
349
+
350
+ // HACK(eddyb) Trying to print a lifetime might not print anything, which
351
+ // may need special handling in the caller (of `ty::RegionKind::print`).
352
+ // To avoid printing to a temporary string (which isn't even supported),
353
+ // the `print_region_outputs_anything` method can instead be used to
354
+ // determine this, ahead of time.
355
+ //
356
+ // NB: this must be kept in sync with the implementation of `print_region`.
357
+ fn print_region_outputs_anything (
358
+ self : & PrintCx < ' _ , ' _ , ' _ , Self > ,
359
+ region : ty:: Region < ' _ > ,
360
+ ) -> bool ;
337
361
}
338
362
339
363
macro_rules! nest {
@@ -799,10 +823,13 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
799
823
800
824
let start = if ns == Namespace :: ValueNS { "::<" } else { "<" } ;
801
825
802
- // Don't print any regions if they're all erased .
826
+ // Don't print `'_` if there's no printed region .
803
827
let print_regions = params. iter ( ) . any ( |param| {
804
828
match substs[ param. index as usize ] . unpack ( ) {
805
- UnpackedKind :: Lifetime ( r) => * r != ty:: ReErased ,
829
+ UnpackedKind :: Lifetime ( r) => {
830
+ self . always_print_region_in_paths ( r) ||
831
+ self . print_region_outputs_anything ( r)
832
+ }
806
833
_ => false ,
807
834
}
808
835
} ) ;
@@ -830,7 +857,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
830
857
continue ;
831
858
}
832
859
start_or_continue ( & mut self , start, ", " ) ?;
833
- if !region . display_outputs_anything ( & self ) {
860
+ if !self . print_region_outputs_anything ( region ) {
834
861
// This happens when the value of the region
835
862
// parameter is not easily serialized. This may be
836
863
// because the user omitted it in the first place,
@@ -872,6 +899,7 @@ impl<F: fmt::Write> Printer for FmtPrinter<F> {
872
899
type Error = fmt:: Error ;
873
900
874
901
type Path = Self ;
902
+ type Region = Self ;
875
903
876
904
fn print_def_path (
877
905
mut self : PrintCx < ' _ , ' _ , ' tcx , Self > ,
@@ -928,6 +956,80 @@ impl<F: fmt::Write> Printer for FmtPrinter<F> {
928
956
self . default_print_def_path ( def_id, substs, ns, projections)
929
957
}
930
958
959
+ fn print_region (
960
+ mut self : PrintCx < ' _ , ' _ , ' _ , Self > ,
961
+ region : ty:: Region < ' _ > ,
962
+ ) -> Result < Self :: Region , Self :: Error > {
963
+ // Watch out for region highlights.
964
+ let highlight = self . printer . region_highlight_mode ;
965
+ if let Some ( n) = highlight. region_highlighted ( region) {
966
+ write ! ( self . printer, "'{}" , n) ?;
967
+ return Ok ( self . printer ) ;
968
+ }
969
+
970
+ if self . config . is_verbose {
971
+ return region. print_debug ( self ) ;
972
+ }
973
+
974
+ // These printouts are concise. They do not contain all the information
975
+ // the user might want to diagnose an error, but there is basically no way
976
+ // to fit that into a short string. Hence the recommendation to use
977
+ // `explain_region()` or `note_and_explain_region()`.
978
+ match * region {
979
+ ty:: ReEarlyBound ( ref data) => {
980
+ if data. name != "'_" {
981
+ write ! ( self . printer, "{}" , data. name) ?;
982
+ }
983
+ }
984
+ ty:: ReLateBound ( _, br) |
985
+ ty:: ReFree ( ty:: FreeRegion { bound_region : br, .. } ) |
986
+ ty:: RePlaceholder ( ty:: Placeholder { name : br, .. } ) => {
987
+ if let ty:: BrNamed ( _, name) = br {
988
+ if name != "" && name != "'_" {
989
+ write ! ( self . printer, "{}" , name) ?;
990
+ return Ok ( self . printer ) ;
991
+ }
992
+ }
993
+
994
+ if let Some ( ( region, counter) ) = highlight. highlight_bound_region {
995
+ if br == region {
996
+ write ! ( self . printer, "'{}" , counter) ?;
997
+ }
998
+ }
999
+ }
1000
+ ty:: ReScope ( scope) if self . config . identify_regions => {
1001
+ match scope. data {
1002
+ region:: ScopeData :: Node =>
1003
+ write ! ( self . printer, "'{}s" , scope. item_local_id( ) . as_usize( ) ) ?,
1004
+ region:: ScopeData :: CallSite =>
1005
+ write ! ( self . printer, "'{}cs" , scope. item_local_id( ) . as_usize( ) ) ?,
1006
+ region:: ScopeData :: Arguments =>
1007
+ write ! ( self . printer, "'{}as" , scope. item_local_id( ) . as_usize( ) ) ?,
1008
+ region:: ScopeData :: Destruction =>
1009
+ write ! ( self . printer, "'{}ds" , scope. item_local_id( ) . as_usize( ) ) ?,
1010
+ region:: ScopeData :: Remainder ( first_statement_index) => write ! ( self . printer,
1011
+ "'{}_{}rs" ,
1012
+ scope. item_local_id( ) . as_usize( ) ,
1013
+ first_statement_index. index( )
1014
+ ) ?,
1015
+ }
1016
+ }
1017
+ ty:: ReVar ( region_vid) if self . config . identify_regions => {
1018
+ write ! ( self . printer, "{:?}" , region_vid) ?;
1019
+ }
1020
+ ty:: ReVar ( _) => { }
1021
+ ty:: ReScope ( _) |
1022
+ ty:: ReErased => { }
1023
+ ty:: ReStatic => write ! ( self . printer, "'static" ) ?,
1024
+ ty:: ReEmpty => write ! ( self . printer, "'<empty>" ) ?,
1025
+
1026
+ // The user should never encounter these in unsubstituted form.
1027
+ ty:: ReClosureBound ( vid) => write ! ( self . printer, "{:?}" , vid) ?,
1028
+ }
1029
+
1030
+ Ok ( self . printer )
1031
+ }
1032
+
931
1033
fn path_crate (
932
1034
mut self : PrintCx < ' _ , ' _ , ' _ , Self > ,
933
1035
cnum : CrateNum ,
@@ -1017,7 +1119,59 @@ impl<F: fmt::Write> PrettyPrinter for FmtPrinter<F> {
1017
1119
} )
1018
1120
}
1019
1121
1020
- fn region_highlight_mode ( & self ) -> RegionHighlightMode {
1021
- self . region_highlight_mode
1122
+ fn always_print_region_in_paths (
1123
+ self : & PrintCx < ' _ , ' _ , ' _ , Self > ,
1124
+ region : ty:: Region < ' _ > ,
1125
+ ) -> bool {
1126
+ * region != ty:: ReErased
1127
+ }
1128
+
1129
+ fn print_region_outputs_anything (
1130
+ self : & PrintCx < ' _ , ' _ , ' _ , Self > ,
1131
+ region : ty:: Region < ' _ > ,
1132
+ ) -> bool {
1133
+ let highlight = self . printer . region_highlight_mode ;
1134
+ if highlight. region_highlighted ( region) . is_some ( ) {
1135
+ return true ;
1136
+ }
1137
+
1138
+ if self . config . is_verbose {
1139
+ return true ;
1140
+ }
1141
+
1142
+ match * region {
1143
+ ty:: ReEarlyBound ( ref data) => {
1144
+ data. name != "" && data. name != "'_"
1145
+ }
1146
+
1147
+ ty:: ReLateBound ( _, br) |
1148
+ ty:: ReFree ( ty:: FreeRegion { bound_region : br, .. } ) |
1149
+ ty:: RePlaceholder ( ty:: Placeholder { name : br, .. } ) => {
1150
+ if let ty:: BrNamed ( _, name) = br {
1151
+ if name != "" && name != "'_" {
1152
+ return true ;
1153
+ }
1154
+ }
1155
+
1156
+ if let Some ( ( region, _) ) = highlight. highlight_bound_region {
1157
+ if br == region {
1158
+ return true ;
1159
+ }
1160
+ }
1161
+
1162
+ false
1163
+ }
1164
+
1165
+ ty:: ReScope ( _) |
1166
+ ty:: ReVar ( _) if self . config . identify_regions => true ,
1167
+
1168
+ ty:: ReVar ( _) |
1169
+ ty:: ReScope ( _) |
1170
+ ty:: ReErased => false ,
1171
+
1172
+ ty:: ReStatic |
1173
+ ty:: ReEmpty |
1174
+ ty:: ReClosureBound ( _) => true ,
1175
+ }
1022
1176
}
1023
1177
}
0 commit comments