@@ -16,8 +16,8 @@ use rustc_hir::definitions::{DefKey, DefPathDataName};
1616use rustc_macros:: { Lift , extension} ;
1717use rustc_session:: Limit ;
1818use rustc_session:: cstore:: { ExternCrate , ExternCrateSource } ;
19- use rustc_span:: FileNameDisplayPreference ;
2019use rustc_span:: symbol:: { Ident , Symbol , kw} ;
20+ use rustc_span:: { FileNameDisplayPreference , sym} ;
2121use rustc_type_ir:: { Upcast as _, elaborate} ;
2222use smallvec:: SmallVec ;
2323
@@ -26,8 +26,8 @@ use super::*;
2626use crate :: mir:: interpret:: { AllocRange , GlobalAlloc , Pointer , Provenance , Scalar } ;
2727use crate :: query:: { IntoQueryParam , Providers } ;
2828use crate :: ty:: {
29- ConstInt , Expr , GenericArgKind , ParamConst , ScalarInt , Term , TermKind , TypeFoldable ,
30- TypeSuperFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitableExt ,
29+ ConstInt , Expr , GenericArgKind , ParamConst , ScalarInt , Term , TermKind , TraitPredicate ,
30+ TypeFoldable , TypeSuperFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitableExt ,
3131} ;
3232
3333macro_rules! p {
@@ -1007,24 +1007,22 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10071007 }
10081008
10091009 self . insert_trait_and_projection (
1010- trait_ref,
1011- pred. polarity ,
1010+ bound_predicate. rebind ( pred) ,
10121011 None ,
10131012 & mut traits,
10141013 & mut fn_traits,
10151014 ) ;
10161015 }
10171016 ty:: ClauseKind :: Projection ( pred) => {
1018- let proj_ref = bound_predicate. rebind ( pred) ;
1019- let trait_ref = proj_ref . required_poly_trait_ref ( tcx ) ;
1020-
1021- // Projection type entry -- the def-id for naming, and the ty.
1022- let proj_ty = ( proj_ref . projection_def_id ( ) , proj_ref . term ( ) ) ;
1017+ let proj = bound_predicate. rebind ( pred) ;
1018+ let trait_ref = proj . map_bound ( |proj| TraitPredicate {
1019+ trait_ref : proj . projection_term . trait_ref ( tcx ) ,
1020+ polarity : ty :: PredicatePolarity :: Positive ,
1021+ } ) ;
10231022
10241023 self . insert_trait_and_projection (
10251024 trait_ref,
1026- ty:: PredicatePolarity :: Positive ,
1027- Some ( proj_ty) ,
1025+ Some ( ( proj. projection_def_id ( ) , proj. term ( ) ) ) ,
10281026 & mut traits,
10291027 & mut fn_traits,
10301028 ) ;
@@ -1042,88 +1040,63 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
10421040 // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
10431041 let paren_needed = fn_traits. len ( ) > 1 || traits. len ( ) > 0 || !has_sized_bound;
10441042
1045- for ( fn_once_trait_ref , entry) in fn_traits {
1043+ for ( bound_args , entry) in fn_traits {
10461044 write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
10471045 write ! ( self , "{}" , if paren_needed { "(" } else { "" } ) ?;
10481046
1049- self . wrap_binder ( & fn_once_trait_ref, |trait_ref, cx| {
1050- define_scoped_cx ! ( cx) ;
1051- // Get the (single) generic ty (the args) of this FnOnce trait ref.
1052- let generics = tcx. generics_of ( trait_ref. def_id ) ;
1053- let own_args = generics. own_args_no_defaults ( tcx, trait_ref. args ) ;
1054-
1055- match ( entry. return_ty , own_args[ 0 ] . expect_ty ( ) ) {
1056- // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
1057- // a return type.
1058- ( Some ( return_ty) , arg_tys) if matches ! ( arg_tys. kind( ) , ty:: Tuple ( _) ) => {
1059- let name = if entry. fn_trait_ref . is_some ( ) {
1060- "Fn"
1061- } else if entry. fn_mut_trait_ref . is_some ( ) {
1062- "FnMut"
1063- } else {
1064- "FnOnce"
1065- } ;
1066-
1067- p ! ( write( "{}(" , name) ) ;
1047+ let trait_def_id =
1048+ tcx. fn_trait_kind_to_def_id ( entry. kind ) . expect ( "expected Fn lang items" ) ;
10681049
1069- for ( idx, ty) in arg_tys. tuple_fields ( ) . iter ( ) . enumerate ( ) {
1070- if idx > 0 {
1071- p ! ( ", " ) ;
1072- }
1073- p ! ( print( ty) ) ;
1074- }
1050+ if let Some ( return_ty) = entry. return_ty {
1051+ self . wrap_binder ( & bound_args, |args, cx| {
1052+ define_scoped_cx ! ( cx) ;
1053+ p ! ( write( "{}" , tcx. item_name( trait_def_id) ) ) ;
1054+ p ! ( "(" ) ;
10751055
1076- p ! ( ")" ) ;
1077- if let Some ( ty) = return_ty. skip_binder ( ) . as_type ( ) {
1078- if !ty. is_unit ( ) {
1079- p ! ( " -> " , print( return_ty) ) ;
1080- }
1056+ for ( idx, ty) in args. iter ( ) . enumerate ( ) {
1057+ if idx > 0 {
1058+ p ! ( ", " ) ;
10811059 }
1082- p ! ( write( "{}" , if paren_needed { ")" } else { "" } ) ) ;
1083-
1084- first = false ;
1060+ p ! ( print( ty) ) ;
10851061 }
1086- // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the
1087- // trait_refs we collected in the OpaqueFnEntry as normal trait refs.
1088- _ => {
1089- if entry. has_fn_once {
1090- traits
1091- . entry ( ( fn_once_trait_ref, ty:: PredicatePolarity :: Positive ) )
1092- . or_default ( )
1093- . extend (
1094- // Group the return ty with its def id, if we had one.
1095- entry. return_ty . map ( |ty| {
1096- ( tcx. require_lang_item ( LangItem :: FnOnceOutput , None ) , ty)
1097- } ) ,
1098- ) ;
1099- }
1100- if let Some ( trait_ref) = entry. fn_mut_trait_ref {
1101- traits. entry ( ( trait_ref, ty:: PredicatePolarity :: Positive ) ) . or_default ( ) ;
1102- }
1103- if let Some ( trait_ref) = entry. fn_trait_ref {
1104- traits. entry ( ( trait_ref, ty:: PredicatePolarity :: Positive ) ) . or_default ( ) ;
1062+
1063+ p ! ( ")" ) ;
1064+ if let Some ( ty) = return_ty. skip_binder ( ) . as_type ( ) {
1065+ if !ty. is_unit ( ) {
1066+ p ! ( " -> " , print( return_ty) ) ;
11051067 }
11061068 }
1107- }
1069+ p ! ( write ( "{}" , if paren_needed { ")" } else { "" } ) ) ;
11081070
1109- Ok ( ( ) )
1110- } ) ?;
1071+ first = false ;
1072+ Ok ( ( ) )
1073+ } ) ?;
1074+ } else {
1075+ // Otherwise, render this like a regular trait.
1076+ traits. insert (
1077+ bound_args. map_bound ( |args| ty:: TraitPredicate {
1078+ polarity : ty:: PredicatePolarity :: Positive ,
1079+ trait_ref : ty:: TraitRef :: new ( tcx, trait_def_id, [ Ty :: new_tup ( tcx, args) ] ) ,
1080+ } ) ,
1081+ FxIndexMap :: default ( ) ,
1082+ ) ;
1083+ }
11111084 }
11121085
11131086 // Print the rest of the trait types (that aren't Fn* family of traits)
1114- for ( ( trait_ref , polarity ) , assoc_items) in traits {
1087+ for ( trait_pred , assoc_items) in traits {
11151088 write ! ( self , "{}" , if first { "" } else { " + " } ) ?;
11161089
1117- self . wrap_binder ( & trait_ref , |trait_ref , cx| {
1090+ self . wrap_binder ( & trait_pred , |trait_pred , cx| {
11181091 define_scoped_cx ! ( cx) ;
11191092
1120- if polarity == ty:: PredicatePolarity :: Negative {
1093+ if trait_pred . polarity == ty:: PredicatePolarity :: Negative {
11211094 p ! ( "!" ) ;
11221095 }
1123- p ! ( print( trait_ref. print_only_trait_name( ) ) ) ;
1096+ p ! ( print( trait_pred . trait_ref. print_only_trait_name( ) ) ) ;
11241097
1125- let generics = tcx. generics_of ( trait_ref . def_id ) ;
1126- let own_args = generics. own_args_no_defaults ( tcx, trait_ref. args ) ;
1098+ let generics = tcx. generics_of ( trait_pred . def_id ( ) ) ;
1099+ let own_args = generics. own_args_no_defaults ( tcx, trait_pred . trait_ref . args ) ;
11271100
11281101 if !own_args. is_empty ( ) || !assoc_items. is_empty ( ) {
11291102 let mut first = true ;
@@ -1230,51 +1203,37 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
12301203 /// traits map or fn_traits map, depending on if the trait is in the Fn* family of traits.
12311204 fn insert_trait_and_projection (
12321205 & mut self ,
1233- trait_ref : ty:: PolyTraitRef < ' tcx > ,
1234- polarity : ty:: PredicatePolarity ,
1206+ trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
12351207 proj_ty : Option < ( DefId , ty:: Binder < ' tcx , Term < ' tcx > > ) > ,
12361208 traits : & mut FxIndexMap <
1237- ( ty:: PolyTraitRef < ' tcx > , ty :: PredicatePolarity ) ,
1209+ ty:: PolyTraitPredicate < ' tcx > ,
12381210 FxIndexMap < DefId , ty:: Binder < ' tcx , Term < ' tcx > > > ,
12391211 > ,
1240- fn_traits : & mut FxIndexMap < ty:: PolyTraitRef < ' tcx > , OpaqueFnEntry < ' tcx > > ,
1212+ fn_traits : & mut FxIndexMap < ty:: Binder < ' tcx , & ' tcx ty :: List < Ty < ' tcx > > > , OpaqueFnEntry < ' tcx > > ,
12411213 ) {
1242- let trait_def_id = trait_ref. def_id ( ) ;
1214+ let tcx = self . tcx ( ) ;
1215+ let trait_def_id = trait_pred. def_id ( ) ;
12431216
1244- // If our trait_ref is FnOnce or any of its children, project it onto the parent FnOnce
1245- // super-trait ref and record it there.
1246- // We skip negative Fn* bounds since they can't use parenthetical notation anyway.
1247- if polarity == ty:: PredicatePolarity :: Positive
1248- && let Some ( fn_once_trait) = self . tcx ( ) . lang_items ( ) . fn_once_trait ( )
1217+ if trait_pred. polarity ( ) == ty:: PredicatePolarity :: Positive
1218+ && let Some ( kind) = tcx. fn_trait_kind_from_def_id ( trait_def_id)
1219+ && let ty:: Tuple ( types) = * trait_pred. skip_binder ( ) . trait_ref . args . type_at ( 1 ) . kind ( )
12491220 {
1250- // If we have a FnOnce, then insert it into
1251- if trait_def_id == fn_once_trait {
1252- let entry = fn_traits. entry ( trait_ref) . or_default ( ) ;
1253- // Optionally insert the return_ty as well.
1254- if let Some ( ( _, ty) ) = proj_ty {
1255- entry. return_ty = Some ( ty) ;
1256- }
1257- entry. has_fn_once = true ;
1258- return ;
1259- } else if self . tcx ( ) . is_lang_item ( trait_def_id, LangItem :: FnMut ) {
1260- let super_trait_ref = elaborate:: supertraits ( self . tcx ( ) , trait_ref)
1261- . find ( |super_trait_ref| super_trait_ref. def_id ( ) == fn_once_trait)
1262- . unwrap ( ) ;
1263-
1264- fn_traits. entry ( super_trait_ref) . or_default ( ) . fn_mut_trait_ref = Some ( trait_ref) ;
1265- return ;
1266- } else if self . tcx ( ) . is_lang_item ( trait_def_id, LangItem :: Fn ) {
1267- let super_trait_ref = elaborate:: supertraits ( self . tcx ( ) , trait_ref)
1268- . find ( |super_trait_ref| super_trait_ref. def_id ( ) == fn_once_trait)
1269- . unwrap ( ) ;
1270-
1271- fn_traits. entry ( super_trait_ref) . or_default ( ) . fn_trait_ref = Some ( trait_ref) ;
1272- return ;
1221+ let entry = fn_traits
1222+ . entry ( trait_pred. rebind ( types) )
1223+ . or_insert_with ( || OpaqueFnEntry { kind, return_ty : None } ) ;
1224+ if kind. extends ( entry. kind ) {
1225+ entry. kind = kind;
1226+ }
1227+ if let Some ( ( proj_def_id, proj_ty) ) = proj_ty
1228+ && tcx. item_name ( proj_def_id) == sym:: Output
1229+ {
1230+ entry. return_ty = Some ( proj_ty) ;
12731231 }
1232+ return ;
12741233 }
12751234
12761235 // Otherwise, just group our traits and projection types.
1277- traits. entry ( ( trait_ref , polarity ) ) . or_default ( ) . extend ( proj_ty) ;
1236+ traits. entry ( trait_pred ) . or_default ( ) . extend ( proj_ty) ;
12781237 }
12791238
12801239 fn pretty_print_inherent_projection (
@@ -3415,11 +3374,7 @@ pub fn provide(providers: &mut Providers) {
34153374 * providers = Providers { trimmed_def_paths, ..* providers } ;
34163375}
34173376
3418- #[ derive( Default ) ]
34193377pub struct OpaqueFnEntry < ' tcx > {
3420- // The trait ref is already stored as a key, so just track if we have it as a real predicate
3421- has_fn_once : bool ,
3422- fn_mut_trait_ref : Option < ty:: PolyTraitRef < ' tcx > > ,
3423- fn_trait_ref : Option < ty:: PolyTraitRef < ' tcx > > ,
3378+ kind : ty:: ClosureKind ,
34243379 return_ty : Option < ty:: Binder < ' tcx , Term < ' tcx > > > ,
34253380}
0 commit comments