@@ -912,7 +912,8 @@ 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 has_sized_bound = false ;
916+ let mut has_negative_sized_bound = false ;
916917 let mut lifetimes = SmallVec :: < [ ty:: Region < ' tcx > ; 1 ] > :: new ( ) ;
917918
918919 for ( predicate, _) in bounds. iter_instantiated_copied ( tcx, args) {
@@ -922,13 +923,24 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
922923 ty:: ClauseKind :: Trait ( pred) => {
923924 let trait_ref = bound_predicate. rebind ( pred. trait_ref ) ;
924925
925- // Don't print + Sized, but rather + ?Sized if absent.
926+ // Don't print ` + Sized` , but rather ` + ?Sized` if absent.
926927 if Some ( trait_ref. def_id ( ) ) == tcx. lang_items ( ) . sized_trait ( ) {
927- is_sized = true ;
928- continue ;
928+ match pred. polarity {
929+ ty:: ImplPolarity :: Positive | ty:: ImplPolarity :: Reservation => {
930+ has_sized_bound = true ;
931+ continue ;
932+ }
933+ ty:: ImplPolarity :: Negative => has_negative_sized_bound = true ,
934+ }
929935 }
930936
931- self . insert_trait_and_projection ( trait_ref, None , & mut traits, & mut fn_traits) ;
937+ self . insert_trait_and_projection (
938+ trait_ref,
939+ pred. polarity ,
940+ None ,
941+ & mut traits,
942+ & mut fn_traits,
943+ ) ;
932944 }
933945 ty:: ClauseKind :: Projection ( pred) => {
934946 let proj_ref = bound_predicate. rebind ( pred) ;
@@ -939,6 +951,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
939951
940952 self . insert_trait_and_projection (
941953 trait_ref,
954+ ty:: ImplPolarity :: Positive ,
942955 Some ( proj_ty) ,
943956 & mut traits,
944957 & mut fn_traits,
@@ -955,7 +968,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
955968
956969 let mut first = true ;
957970 // 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 ;
971+ let paren_needed = fn_traits. len ( ) > 1 || traits. len ( ) > 0 || !has_sized_bound ;
959972
960973 for ( fn_once_trait_ref, entry) in fn_traits {
961974 write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
@@ -1002,18 +1015,21 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10021015 // trait_refs we collected in the OpaqueFnEntry as normal trait refs.
10031016 _ => {
10041017 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- ) ;
1018+ traits
1019+ . entry ( ( fn_once_trait_ref, ty:: ImplPolarity :: Positive ) )
1020+ . or_default ( )
1021+ . extend (
1022+ // Group the return ty with its def id, if we had one.
1023+ entry. return_ty . map ( |ty| {
1024+ ( tcx. require_lang_item ( LangItem :: FnOnce , None ) , ty)
1025+ } ) ,
1026+ ) ;
10111027 }
10121028 if let Some ( trait_ref) = entry. fn_mut_trait_ref {
1013- traits. entry ( trait_ref) . or_default ( ) ;
1029+ traits. entry ( ( trait_ref, ty :: ImplPolarity :: Positive ) ) . or_default ( ) ;
10141030 }
10151031 if let Some ( trait_ref) = entry. fn_trait_ref {
1016- traits. entry ( trait_ref) . or_default ( ) ;
1032+ traits. entry ( ( trait_ref, ty :: ImplPolarity :: Positive ) ) . or_default ( ) ;
10171033 }
10181034 }
10191035 }
@@ -1023,11 +1039,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10231039 }
10241040
10251041 // Print the rest of the trait types (that aren't Fn* family of traits)
1026- for ( trait_ref, assoc_items) in traits {
1042+ for ( ( trait_ref, polarity ) , assoc_items) in traits {
10271043 write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
10281044
10291045 self . wrap_binder ( & trait_ref, |trait_ref, cx| {
10301046 define_scoped_cx ! ( cx) ;
1047+
1048+ if polarity == ty:: ImplPolarity :: Negative {
1049+ p ! ( "!" ) ;
1050+ }
10311051 p ! ( print( trait_ref. print_only_trait_name( ) ) ) ;
10321052
10331053 let generics = tcx. generics_of ( trait_ref. def_id ) ;
@@ -1094,9 +1114,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10941114 } ) ?;
10951115 }
10961116
1097- if !is_sized {
1098- write ! ( self , "{}?Sized" , if first { "" } else { " + " } ) ?;
1099- } else if first {
1117+ let add_sized = has_sized_bound && ( first || has_negative_sized_bound) ;
1118+ let add_maybe_sized = !has_sized_bound && !has_negative_sized_bound;
1119+ if add_sized || add_maybe_sized {
1120+ if !first {
1121+ write ! ( self , " + " ) ?;
1122+ }
1123+ if add_maybe_sized {
1124+ write ! ( self , "?" ) ?;
1125+ }
11001126 write ! ( self , "Sized" ) ?;
11011127 }
11021128
@@ -1128,9 +1154,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11281154 fn insert_trait_and_projection (
11291155 & mut self ,
11301156 trait_ref : ty:: PolyTraitRef < ' tcx > ,
1157+ polarity : ty:: ImplPolarity ,
11311158 proj_ty : Option < ( DefId , ty:: Binder < ' tcx , Term < ' tcx > > ) > ,
11321159 traits : & mut FxIndexMap <
1133- ty:: PolyTraitRef < ' tcx > ,
1160+ ( ty:: PolyTraitRef < ' tcx > , ty :: ImplPolarity ) ,
11341161 FxIndexMap < DefId , ty:: Binder < ' tcx , Term < ' tcx > > > ,
11351162 > ,
11361163 fn_traits : & mut FxIndexMap < ty:: PolyTraitRef < ' tcx > , OpaqueFnEntry < ' tcx > > ,
@@ -1139,7 +1166,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11391166
11401167 // If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
11411168 // super-trait ref and record it there.
1142- if let Some ( fn_once_trait) = self . tcx ( ) . lang_items ( ) . fn_once_trait ( ) {
1169+ // We skip negative Fn* bounds since they can't use parenthetical notation anyway.
1170+ if polarity == ty:: ImplPolarity :: Positive
1171+ && let Some ( fn_once_trait) = self . tcx ( ) . lang_items ( ) . fn_once_trait ( )
1172+ {
11431173 // If we have a FnOnce, then insert it into
11441174 if trait_def_id == fn_once_trait {
11451175 let entry = fn_traits. entry ( trait_ref) . or_default ( ) ;
@@ -1167,7 +1197,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11671197 }
11681198
11691199 // Otherwise, just group our traits and projection types.
1170- traits. entry ( trait_ref) . or_default ( ) . extend ( proj_ty) ;
1200+ traits. entry ( ( trait_ref, polarity ) ) . or_default ( ) . extend ( proj_ty) ;
11711201 }
11721202
11731203 fn pretty_print_inherent_projection (
0 commit comments