@@ -912,23 +912,43 @@ 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 sizedness = Sizedness :: Maybe ;
916
916
let mut lifetimes = SmallVec :: < [ ty:: Region < ' tcx > ; 1 ] > :: new ( ) ;
917
917
918
+ enum Sizedness {
919
+ Positive ,
920
+ Negative ,
921
+ Maybe ,
922
+ }
923
+
918
924
for ( predicate, _) in bounds. iter_instantiated_copied ( tcx, args) {
919
925
let bound_predicate = predicate. kind ( ) ;
920
926
921
927
match bound_predicate. skip_binder ( ) {
922
928
ty:: ClauseKind :: Trait ( pred) => {
923
929
let trait_ref = bound_predicate. rebind ( pred. trait_ref ) ;
924
930
925
- // Don't print + Sized, but rather + ?Sized if absent.
931
+ // Don't print ` + Sized` , but rather ` + ?Sized` if absent.
926
932
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
+ }
929
943
}
930
944
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
+ ) ;
932
952
}
933
953
ty:: ClauseKind :: Projection ( pred) => {
934
954
let proj_ref = bound_predicate. rebind ( pred) ;
@@ -939,6 +959,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
939
959
940
960
self . insert_trait_and_projection (
941
961
trait_ref,
962
+ ty:: ImplPolarity :: Positive ,
942
963
Some ( proj_ty) ,
943
964
& mut traits,
944
965
& mut fn_traits,
@@ -955,7 +976,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
955
976
956
977
let mut first = true ;
957
978
// 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 ) ;
959
981
960
982
for ( fn_once_trait_ref, entry) in fn_traits {
961
983
write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
@@ -1002,18 +1024,21 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1002
1024
// trait_refs we collected in the OpaqueFnEntry as normal trait refs.
1003
1025
_ => {
1004
1026
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
+ ) ;
1011
1036
}
1012
1037
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 ( ) ;
1014
1039
}
1015
1040
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 ( ) ;
1017
1042
}
1018
1043
}
1019
1044
}
@@ -1023,11 +1048,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1023
1048
}
1024
1049
1025
1050
// 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 {
1027
1052
write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
1028
1053
1029
1054
self . wrap_binder ( & trait_ref, |trait_ref, cx| {
1030
1055
define_scoped_cx ! ( cx) ;
1056
+
1057
+ if polarity == ty:: ImplPolarity :: Negative {
1058
+ p ! ( "!" ) ;
1059
+ }
1031
1060
p ! ( print( trait_ref. print_only_trait_name( ) ) ) ;
1032
1061
1033
1062
let generics = tcx. generics_of ( trait_ref. def_id ) ;
@@ -1094,10 +1123,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1094
1123
} ) ?;
1095
1124
}
1096
1125
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
+ _ => { }
1101
1130
}
1102
1131
1103
1132
if !with_forced_trimmed_paths ( ) {
@@ -1128,9 +1157,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1128
1157
fn insert_trait_and_projection (
1129
1158
& mut self ,
1130
1159
trait_ref : ty:: PolyTraitRef < ' tcx > ,
1160
+ polarity : ty:: ImplPolarity ,
1131
1161
proj_ty : Option < ( DefId , ty:: Binder < ' tcx , Term < ' tcx > > ) > ,
1132
1162
traits : & mut FxIndexMap <
1133
- ty:: PolyTraitRef < ' tcx > ,
1163
+ ( ty:: PolyTraitRef < ' tcx > , ty :: ImplPolarity ) ,
1134
1164
FxIndexMap < DefId , ty:: Binder < ' tcx , Term < ' tcx > > > ,
1135
1165
> ,
1136
1166
fn_traits : & mut FxIndexMap < ty:: PolyTraitRef < ' tcx > , OpaqueFnEntry < ' tcx > > ,
@@ -1139,7 +1169,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1139
1169
1140
1170
// If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
1141
1171
// 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
+ {
1143
1176
// If we have a FnOnce, then insert it into
1144
1177
if trait_def_id == fn_once_trait {
1145
1178
let entry = fn_traits. entry ( trait_ref) . or_default ( ) ;
@@ -1167,7 +1200,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
1167
1200
}
1168
1201
1169
1202
// 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) ;
1171
1204
}
1172
1205
1173
1206
fn pretty_print_inherent_projection (
0 commit comments