@@ -912,23 +912,43 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
912912
913913 let mut traits = FxIndexMap :: default ( ) ;
914914 let mut fn_traits = FxIndexMap :: default ( ) ;
915- let mut is_sized = false ;
915+ let mut sizedness = Sizedness :: Maybe ;
916916 let mut lifetimes = SmallVec :: < [ ty:: Region < ' tcx > ; 1 ] > :: new ( ) ;
917917
918+ enum Sizedness {
919+ Positive ,
920+ Negative ,
921+ Maybe ,
922+ }
923+
918924 for ( predicate, _) in bounds. iter_instantiated_copied ( tcx, args) {
919925 let bound_predicate = predicate. kind ( ) ;
920926
921927 match bound_predicate. skip_binder ( ) {
922928 ty:: ClauseKind :: Trait ( pred) => {
923929 let trait_ref = bound_predicate. rebind ( pred. trait_ref ) ;
924930
925- // Don't print + Sized, but rather + ?Sized if absent.
931+ // Don't print ` + Sized` , but rather ` + ?Sized` if absent.
926932 if Some ( trait_ref. def_id ( ) ) == tcx. lang_items ( ) . sized_trait ( ) {
927- is_sized = true ;
928- continue ;
933+ match pred. polarity {
934+ ty:: ImplPolarity :: Positive | ty:: ImplPolarity :: Reservation => {
935+ sizedness = Sizedness :: Positive ;
936+ continue ;
937+ }
938+ ty:: ImplPolarity :: Negative if let Sizedness :: Maybe = & sizedness => {
939+ sizedness = Sizedness :: Negative ;
940+ }
941+ _ => { }
942+ }
929943 }
930944
931- self . insert_trait_and_projection ( trait_ref, None , & mut traits, & mut fn_traits) ;
945+ self . insert_trait_and_projection (
946+ trait_ref,
947+ pred. polarity ,
948+ None ,
949+ & mut traits,
950+ & mut fn_traits,
951+ ) ;
932952 }
933953 ty:: ClauseKind :: Projection ( pred) => {
934954 let proj_ref = bound_predicate. rebind ( pred) ;
@@ -939,6 +959,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
939959
940960 self . insert_trait_and_projection (
941961 trait_ref,
962+ ty:: ImplPolarity :: Positive ,
942963 Some ( proj_ty) ,
943964 & mut traits,
944965 & mut fn_traits,
@@ -955,7 +976,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
955976
956977 let mut first = true ;
957978 // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
958- let paren_needed = fn_traits. len ( ) > 1 || traits. len ( ) > 0 || !is_sized;
979+ let paren_needed =
980+ fn_traits. len ( ) > 1 || traits. len ( ) > 0 || matches ! ( sizedness, Sizedness :: Maybe ) ;
959981
960982 for ( fn_once_trait_ref, entry) in fn_traits {
961983 write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
@@ -1002,18 +1024,21 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10021024 // trait_refs we collected in the OpaqueFnEntry as normal trait refs.
10031025 _ => {
10041026 if entry. has_fn_once {
1005- traits. entry ( fn_once_trait_ref) . or_default ( ) . extend (
1006- // Group the return ty with its def id, if we had one.
1007- entry
1008- . return_ty
1009- . map ( |ty| ( tcx. require_lang_item ( LangItem :: FnOnce , None ) , ty) ) ,
1010- ) ;
1027+ traits
1028+ . entry ( ( fn_once_trait_ref, ty:: ImplPolarity :: Positive ) )
1029+ . or_default ( )
1030+ . extend (
1031+ // Group the return ty with its def id, if we had one.
1032+ entry. return_ty . map ( |ty| {
1033+ ( tcx. require_lang_item ( LangItem :: FnOnce , None ) , ty)
1034+ } ) ,
1035+ ) ;
10111036 }
10121037 if let Some ( trait_ref) = entry. fn_mut_trait_ref {
1013- traits. entry ( trait_ref) . or_default ( ) ;
1038+ traits. entry ( ( trait_ref, ty :: ImplPolarity :: Positive ) ) . or_default ( ) ;
10141039 }
10151040 if let Some ( trait_ref) = entry. fn_trait_ref {
1016- traits. entry ( trait_ref) . or_default ( ) ;
1041+ traits. entry ( ( trait_ref, ty :: ImplPolarity :: Positive ) ) . or_default ( ) ;
10171042 }
10181043 }
10191044 }
@@ -1023,11 +1048,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10231048 }
10241049
10251050 // Print the rest of the trait types (that aren't Fn* family of traits)
1026- for ( trait_ref, assoc_items) in traits {
1051+ for ( ( trait_ref, polarity ) , assoc_items) in traits {
10271052 write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
10281053
10291054 self . wrap_binder ( & trait_ref, |trait_ref, cx| {
10301055 define_scoped_cx ! ( cx) ;
1056+
1057+ if polarity == ty:: ImplPolarity :: Negative {
1058+ p ! ( "!" ) ;
1059+ }
10311060 p ! ( print( trait_ref. print_only_trait_name( ) ) ) ;
10321061
10331062 let generics = tcx. generics_of ( trait_ref. def_id ) ;
@@ -1094,10 +1123,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10941123 } ) ?;
10951124 }
10961125
1097- if !is_sized {
1098- write ! ( self , "{}? Sized" , if first { "" } else { " + " } ) ? ;
1099- } else if first {
1100- write ! ( self , "Sized" ) ? ;
1126+ match sizedness {
1127+ Sizedness :: Positive if first => write ! ( self , "Sized" ) ? ,
1128+ Sizedness :: Maybe => write ! ( self , "{}?Sized" , if first { "" } else { " + " } ) ? ,
1129+ _ => { }
11011130 }
11021131
11031132 if !with_forced_trimmed_paths ( ) {
@@ -1128,9 +1157,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11281157 fn insert_trait_and_projection (
11291158 & mut self ,
11301159 trait_ref : ty:: PolyTraitRef < ' tcx > ,
1160+ polarity : ty:: ImplPolarity ,
11311161 proj_ty : Option < ( DefId , ty:: Binder < ' tcx , Term < ' tcx > > ) > ,
11321162 traits : & mut FxIndexMap <
1133- ty:: PolyTraitRef < ' tcx > ,
1163+ ( ty:: PolyTraitRef < ' tcx > , ty :: ImplPolarity ) ,
11341164 FxIndexMap < DefId , ty:: Binder < ' tcx , Term < ' tcx > > > ,
11351165 > ,
11361166 fn_traits : & mut FxIndexMap < ty:: PolyTraitRef < ' tcx > , OpaqueFnEntry < ' tcx > > ,
@@ -1139,7 +1169,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11391169
11401170 // If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
11411171 // super-trait ref and record it there.
1142- if let Some ( fn_once_trait) = self . tcx ( ) . lang_items ( ) . fn_once_trait ( ) {
1172+ // We skip negative Fn* bounds since they can't use parenthetical notation anyway.
1173+ if polarity == ty:: ImplPolarity :: Positive
1174+ && let Some ( fn_once_trait) = self . tcx ( ) . lang_items ( ) . fn_once_trait ( )
1175+ {
11431176 // If we have a FnOnce, then insert it into
11441177 if trait_def_id == fn_once_trait {
11451178 let entry = fn_traits. entry ( trait_ref) . or_default ( ) ;
@@ -1167,7 +1200,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11671200 }
11681201
11691202 // Otherwise, just group our traits and projection types.
1170- traits. entry ( trait_ref) . or_default ( ) . extend ( proj_ty) ;
1203+ traits. entry ( ( trait_ref, polarity ) ) . or_default ( ) . extend ( proj_ty) ;
11711204 }
11721205
11731206 fn pretty_print_inherent_projection (
0 commit comments