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