@@ -10,7 +10,7 @@ use rustc_data_structures::sso::SsoHashSet;
10
10
use rustc_hir as hir;
11
11
use rustc_hir:: def:: { self , CtorKind , DefKind , Namespace } ;
12
12
use rustc_hir:: def_id:: { DefId , DefIdSet , CRATE_DEF_ID , LOCAL_CRATE } ;
13
- use rustc_hir:: definitions:: { DefPathData , DefPathDataName , DisambiguatedDefPathData } ;
13
+ use rustc_hir:: definitions:: { DefKey , DefPathData , DefPathDataName , DisambiguatedDefPathData } ;
14
14
use rustc_hir:: LangItem ;
15
15
use rustc_session:: config:: TrimmedDefPaths ;
16
16
use rustc_session:: cstore:: { ExternCrate , ExternCrateSource } ;
@@ -63,6 +63,7 @@ thread_local! {
63
63
static FORCE_IMPL_FILENAME_LINE : Cell <bool > = const { Cell :: new( false ) } ;
64
64
static SHOULD_PREFIX_WITH_CRATE : Cell <bool > = const { Cell :: new( false ) } ;
65
65
static NO_TRIMMED_PATH : Cell <bool > = const { Cell :: new( false ) } ;
66
+ static FORCE_TRIMMED_PATH : Cell <bool > = const { Cell :: new( false ) } ;
66
67
static NO_QUERIES : Cell <bool > = const { Cell :: new( false ) } ;
67
68
static NO_VISIBLE_PATH : Cell <bool > = const { Cell :: new( false ) } ;
68
69
}
@@ -116,6 +117,7 @@ define_helper!(
116
117
/// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
117
118
/// if no other `Vec` is found.
118
119
fn with_no_trimmed_paths( NoTrimmedGuard , NO_TRIMMED_PATH ) ;
120
+ fn with_forced_trimmed_paths( ForceTrimmedGuard , FORCE_TRIMMED_PATH ) ;
119
121
/// Prevent selection of visible paths. `Display` impl of DefId will prefer
120
122
/// visible (public) reexports of types as paths.
121
123
fn with_no_visible_paths( NoVisibleGuard , NO_VISIBLE_PATH ) ;
@@ -295,11 +297,89 @@ pub trait PrettyPrinter<'tcx>:
295
297
self . try_print_visible_def_path_recur ( def_id, & mut callers)
296
298
}
297
299
300
+ // Given a `DefId`, produce a short name. For types and traits, it prints *only* its name,
301
+ // For associated items on traits it prints out the trait's name and the associated item's name.
302
+ // For enum variants, if they have an unique name, then we only print the name, otherwise we
303
+ // print the enum name and the variant name. Otherwise, we do not print anything and let the
304
+ // caller use the `print_def_path` fallback.
305
+ fn force_print_trimmed_def_path (
306
+ mut self ,
307
+ def_id : DefId ,
308
+ ) -> Result < ( Self :: Path , bool ) , Self :: Error > {
309
+ let key = self . tcx ( ) . def_key ( def_id) ;
310
+ let visible_parent_map = self . tcx ( ) . visible_parent_map ( ( ) ) ;
311
+ let kind = self . tcx ( ) . def_kind ( def_id) ;
312
+
313
+ let get_local_name = |this : & Self , name, def_id, key : DefKey | {
314
+ if let Some ( visible_parent) = visible_parent_map. get ( & def_id)
315
+ && let actual_parent = this. tcx ( ) . opt_parent ( def_id)
316
+ && let DefPathData :: TypeNs ( _) = key. disambiguated_data . data
317
+ && Some ( * visible_parent) != actual_parent
318
+ {
319
+ this
320
+ . tcx ( )
321
+ . module_children ( visible_parent)
322
+ . iter ( )
323
+ . filter ( |child| child. res . opt_def_id ( ) == Some ( def_id) )
324
+ . find ( |child| child. vis . is_public ( ) && child. ident . name != kw:: Underscore )
325
+ . map ( |child| child. ident . name )
326
+ . unwrap_or ( name)
327
+ } else {
328
+ name
329
+ }
330
+ } ;
331
+ if let DefKind :: Variant = kind
332
+ && let Some ( symbol) = self . tcx ( ) . trimmed_def_paths ( ( ) ) . get ( & def_id)
333
+ {
334
+ // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`.
335
+ self . write_str ( get_local_name ( & self , * symbol, def_id, key) . as_str ( ) ) ?;
336
+ return Ok ( ( self , true ) ) ;
337
+ }
338
+ if let Some ( symbol) = key. get_opt_name ( ) {
339
+ if let DefKind :: AssocConst | DefKind :: AssocFn | DefKind :: AssocTy = kind
340
+ && let Some ( parent) = self . tcx ( ) . opt_parent ( def_id)
341
+ && let parent_key = self . tcx ( ) . def_key ( parent)
342
+ && let Some ( symbol) = parent_key. get_opt_name ( )
343
+ {
344
+ // Trait
345
+ self . write_str ( get_local_name ( & self , symbol, parent, parent_key) . as_str ( ) ) ?;
346
+ self . write_str ( "::" ) ?;
347
+ } else if let DefKind :: Variant = kind
348
+ && let Some ( parent) = self . tcx ( ) . opt_parent ( def_id)
349
+ && let parent_key = self . tcx ( ) . def_key ( parent)
350
+ && let Some ( symbol) = parent_key. get_opt_name ( )
351
+ {
352
+ // Enum
353
+
354
+ // For associated items and variants, we want the "full" path, namely, include
355
+ // the parent type in the path. For example, `Iterator::Item`.
356
+ self . write_str ( get_local_name ( & self , symbol, parent, parent_key) . as_str ( ) ) ?;
357
+ self . write_str ( "::" ) ?;
358
+ } else if let DefKind :: Struct | DefKind :: Union | DefKind :: Enum | DefKind :: Trait
359
+ | DefKind :: TyAlias | DefKind :: Fn | DefKind :: Const | DefKind :: Static ( _) = kind
360
+ {
361
+ } else {
362
+ // If not covered above, like for example items out of `impl` blocks, fallback.
363
+ return Ok ( ( self , false ) ) ;
364
+ }
365
+ self . write_str ( get_local_name ( & self , symbol, def_id, key) . as_str ( ) ) ?;
366
+ return Ok ( ( self , true ) ) ;
367
+ }
368
+ Ok ( ( self , false ) )
369
+ }
370
+
298
371
/// Try to see if this path can be trimmed to a unique symbol name.
299
372
fn try_print_trimmed_def_path (
300
373
mut self ,
301
374
def_id : DefId ,
302
375
) -> Result < ( Self :: Path , bool ) , Self :: Error > {
376
+ if FORCE_TRIMMED_PATH . with ( |flag| flag. get ( ) ) {
377
+ let ( s, trimmed) = self . force_print_trimmed_def_path ( def_id) ?;
378
+ if trimmed {
379
+ return Ok ( ( s, true ) ) ;
380
+ }
381
+ self = s;
382
+ }
303
383
if !self . tcx ( ) . sess . opts . unstable_opts . trim_diagnostic_paths
304
384
|| matches ! ( self . tcx( ) . sess. opts. trimmed_def_paths, TrimmedDefPaths :: Never )
305
385
|| NO_TRIMMED_PATH . with ( |flag| flag. get ( ) )
0 commit comments