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