@@ -10,7 +10,7 @@ use rustc_data_structures::sso::SsoHashSet;
1010use rustc_hir as hir;
1111use rustc_hir:: def:: { self , CtorKind , DefKind , Namespace } ;
1212use 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 } ;
1414use rustc_hir:: LangItem ;
1515use rustc_session:: config:: TrimmedDefPaths ;
1616use rustc_session:: cstore:: { ExternCrate , ExternCrateSource } ;
@@ -63,6 +63,7 @@ thread_local! {
6363 static FORCE_IMPL_FILENAME_LINE : Cell <bool > = const { Cell :: new( false ) } ;
6464 static SHOULD_PREFIX_WITH_CRATE : Cell <bool > = const { Cell :: new( false ) } ;
6565 static NO_TRIMMED_PATH : Cell <bool > = const { Cell :: new( false ) } ;
66+ static FORCE_TRIMMED_PATH : Cell <bool > = const { Cell :: new( false ) } ;
6667 static NO_QUERIES : Cell <bool > = const { Cell :: new( false ) } ;
6768 static NO_VISIBLE_PATH : Cell <bool > = const { Cell :: new( false ) } ;
6869}
@@ -116,6 +117,7 @@ define_helper!(
116117 /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
117118 /// if no other `Vec` is found.
118119 fn with_no_trimmed_paths( NoTrimmedGuard , NO_TRIMMED_PATH ) ;
120+ fn with_forced_trimmed_paths( ForceTrimmedGuard , FORCE_TRIMMED_PATH ) ;
119121 /// Prevent selection of visible paths. `Display` impl of DefId will prefer
120122 /// visible (public) reexports of types as paths.
121123 fn with_no_visible_paths( NoVisibleGuard , NO_VISIBLE_PATH ) ;
@@ -295,11 +297,89 @@ pub trait PrettyPrinter<'tcx>:
295297 self . try_print_visible_def_path_recur ( def_id, & mut callers)
296298 }
297299
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+
298371 /// Try to see if this path can be trimmed to a unique symbol name.
299372 fn try_print_trimmed_def_path (
300373 mut self ,
301374 def_id : DefId ,
302375 ) -> 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+ }
303383 if !self . tcx ( ) . sess . opts . unstable_opts . trim_diagnostic_paths
304384 || matches ! ( self . tcx( ) . sess. opts. trimmed_def_paths, TrimmedDefPaths :: Never )
305385 || NO_TRIMMED_PATH . with ( |flag| flag. get ( ) )
0 commit comments