@@ -912,7 +912,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
912
912
913
913
let mut traits = FxIndexMap :: default ( ) ;
914
914
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 ;
916
917
let mut lifetimes = SmallVec :: < [ ty:: Region < ' tcx > ; 1 ] > :: new ( ) ;
917
918
918
919
for ( predicate, _) in bounds. iter_instantiated_copied ( tcx, args) {
@@ -922,13 +923,24 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
922
923
ty:: ClauseKind :: Trait ( pred) => {
923
924
let trait_ref = bound_predicate. rebind ( pred. trait_ref ) ;
924
925
925
- // Don't print + Sized, but rather + ?Sized if absent.
926
+ // Don't print ` + Sized` , but rather ` + ?Sized` if absent.
926
927
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
+ }
929
935
}
930
936
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
+ ) ;
932
944
}
933
945
ty:: ClauseKind :: Projection ( pred) => {
934
946
let proj_ref = bound_predicate. rebind ( pred) ;
@@ -939,6 +951,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
939
951
940
952
self . insert_trait_and_projection (
941
953
trait_ref,
954
+ ty:: ImplPolarity :: Positive ,
942
955
Some ( proj_ty) ,
943
956
& mut traits,
944
957
& mut fn_traits,
@@ -955,7 +968,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
955
968
956
969
let mut first = true ;
957
970
// 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 ;
959
972
960
973
for ( fn_once_trait_ref, entry) in fn_traits {
961
974
write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
@@ -1002,18 +1015,21 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1002
1015
// trait_refs we collected in the OpaqueFnEntry as normal trait refs.
1003
1016
_ => {
1004
1017
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
+ ) ;
1011
1027
}
1012
1028
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 ( ) ;
1014
1030
}
1015
1031
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 ( ) ;
1017
1033
}
1018
1034
}
1019
1035
}
@@ -1023,11 +1039,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1023
1039
}
1024
1040
1025
1041
// 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 {
1027
1043
write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
1028
1044
1029
1045
self . wrap_binder ( & trait_ref, |trait_ref, cx| {
1030
1046
define_scoped_cx ! ( cx) ;
1047
+
1048
+ if polarity == ty:: ImplPolarity :: Negative {
1049
+ p ! ( "!" ) ;
1050
+ }
1031
1051
p ! ( print( trait_ref. print_only_trait_name( ) ) ) ;
1032
1052
1033
1053
let generics = tcx. generics_of ( trait_ref. def_id ) ;
@@ -1094,9 +1114,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1094
1114
} ) ?;
1095
1115
}
1096
1116
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
+ }
1100
1126
write ! ( self , "Sized" ) ?;
1101
1127
}
1102
1128
@@ -1128,9 +1154,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1128
1154
fn insert_trait_and_projection (
1129
1155
& mut self ,
1130
1156
trait_ref : ty:: PolyTraitRef < ' tcx > ,
1157
+ polarity : ty:: ImplPolarity ,
1131
1158
proj_ty : Option < ( DefId , ty:: Binder < ' tcx , Term < ' tcx > > ) > ,
1132
1159
traits : & mut FxIndexMap <
1133
- ty:: PolyTraitRef < ' tcx > ,
1160
+ ( ty:: PolyTraitRef < ' tcx > , ty :: ImplPolarity ) ,
1134
1161
FxIndexMap < DefId , ty:: Binder < ' tcx , Term < ' tcx > > > ,
1135
1162
> ,
1136
1163
fn_traits : & mut FxIndexMap < ty:: PolyTraitRef < ' tcx > , OpaqueFnEntry < ' tcx > > ,
@@ -1139,7 +1166,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1139
1166
1140
1167
// If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
1141
1168
// 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
+ {
1143
1173
// If we have a FnOnce, then insert it into
1144
1174
if trait_def_id == fn_once_trait {
1145
1175
let entry = fn_traits. entry ( trait_ref) . or_default ( ) ;
@@ -1167,7 +1197,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1167
1197
}
1168
1198
1169
1199
// 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) ;
1171
1201
}
1172
1202
1173
1203
fn pretty_print_inherent_projection (
0 commit comments