@@ -53,12 +53,15 @@ use rustc_data_structures::captures::Captures;
5353use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
5454use rustc_hir:: def_id:: { DefId , DefIdSet } ;
5555use rustc_hir:: Mutability ;
56+ use rustc_infer:: infer:: TyCtxtInferExt ;
57+ use rustc_infer:: traits:: { Obligation , ObligationCause } ;
5658use rustc_middle:: middle:: stability;
57- use rustc_middle:: ty:: TyCtxt ;
59+ use rustc_middle:: ty:: { ParamEnv , TyCtxt } ;
5860use rustc_span:: {
5961 symbol:: { sym, Symbol } ,
6062 BytePos , FileName , RealFileName ,
6163} ;
64+ use rustc_trait_selection:: traits:: ObligationCtxt ;
6265use serde:: ser:: { SerializeMap , SerializeSeq } ;
6366use serde:: { Serialize , Serializer } ;
6467
@@ -1112,28 +1115,76 @@ fn render_assoc_items<'a, 'cx: 'a>(
11121115 containing_item : & ' a clean:: Item ,
11131116 it : DefId ,
11141117 what : AssocItemRender < ' a > ,
1118+ aliased_type : Option < DefId > ,
11151119) -> impl fmt:: Display + ' a + Captures < ' cx > {
11161120 let mut derefs = DefIdSet :: default ( ) ;
11171121 derefs. insert ( it) ;
11181122 display_fn ( move |f| {
1119- render_assoc_items_inner ( f, cx, containing_item, it, what, & mut derefs) ;
1123+ render_assoc_items_inner ( f, cx, containing_item, it, what, & mut derefs, aliased_type ) ;
11201124 Ok ( ( ) )
11211125 } )
11221126}
11231127
1128+ /// Check whether `impl_def_id` may apply to *some instantiation* of `item_def_id`.
1129+ fn is_valid_impl_for ( tcx : TyCtxt < ' _ > , item_def_id : DefId , impl_def_id : DefId ) -> bool {
1130+ let infcx = tcx. infer_ctxt ( ) . intercrate ( true ) . build ( ) ;
1131+ let ocx = ObligationCtxt :: new ( & infcx) ;
1132+ let param_env = ParamEnv :: empty ( ) ;
1133+
1134+ let alias_substs = infcx. fresh_substs_for_item ( rustc_span:: DUMMY_SP , item_def_id) ;
1135+ let alias_ty = tcx. type_of ( item_def_id) . subst ( tcx, alias_substs) ;
1136+ let alias_bounds = tcx. predicates_of ( item_def_id) . instantiate ( tcx, alias_substs) ;
1137+
1138+ let impl_substs = infcx. fresh_substs_for_item ( rustc_span:: DUMMY_SP , impl_def_id) ;
1139+ let impl_self_ty = tcx. type_of ( impl_def_id) . subst ( tcx, impl_substs) ;
1140+ let impl_bounds = tcx. predicates_of ( impl_def_id) . instantiate ( tcx, impl_substs) ;
1141+
1142+ if ocx. eq ( & ObligationCause :: dummy ( ) , param_env, impl_self_ty, alias_ty) . is_err ( ) {
1143+ return false ;
1144+ }
1145+ ocx. register_obligations (
1146+ alias_bounds
1147+ . iter ( )
1148+ . chain ( impl_bounds)
1149+ . map ( |( p, _) | Obligation :: new ( tcx, ObligationCause :: dummy ( ) , param_env, p) ) ,
1150+ ) ;
1151+
1152+ let errors = ocx. select_where_possible ( ) ;
1153+ errors. is_empty ( )
1154+ }
1155+
1156+ // If `aliased_type` is `Some`, it means `it` is a type alias and `aliased_type` is the "actual"
1157+ // type aliased behind `it`. It is used to check whether or not the implementation of the aliased
1158+ // type can be displayed on the alias doc page.
11241159fn render_assoc_items_inner (
11251160 mut w : & mut dyn fmt:: Write ,
11261161 cx : & mut Context < ' _ > ,
11271162 containing_item : & clean:: Item ,
11281163 it : DefId ,
11291164 what : AssocItemRender < ' _ > ,
11301165 derefs : & mut DefIdSet ,
1166+ aliased_type : Option < DefId > ,
11311167) {
11321168 info ! ( "Documenting associated items of {:?}" , containing_item. name) ;
11331169 let shared = Rc :: clone ( & cx. shared ) ;
11341170 let cache = & shared. cache ;
1135- let Some ( v) = cache. impls . get ( & it) else { return } ;
1136- let ( non_trait, traits) : ( Vec < _ > , _ ) = v. iter ( ) . partition ( |i| i. inner_impl ( ) . trait_ . is_none ( ) ) ;
1171+ let empty = Vec :: new ( ) ;
1172+ let v = match cache. impls . get ( & it) {
1173+ Some ( v) => v,
1174+ None => & empty,
1175+ } ;
1176+ let v2 = match aliased_type {
1177+ Some ( aliased_type) => cache. impls . get ( & aliased_type) . unwrap_or ( & empty) ,
1178+ None => & empty,
1179+ } ;
1180+ if v. is_empty ( ) && v2. is_empty ( ) {
1181+ return ;
1182+ }
1183+ let mut saw_impls = FxHashSet :: default ( ) ;
1184+ let ( non_trait, traits) : ( Vec < _ > , _ ) =
1185+ v. iter ( ) . chain ( v2) . partition ( |i| i. inner_impl ( ) . trait_ . is_none ( ) ) ;
1186+ let tcx = cx. tcx ( ) ;
1187+ let is_alias = aliased_type. is_some ( ) ;
11371188 if !non_trait. is_empty ( ) {
11381189 let mut tmp_buf = Buffer :: html ( ) ;
11391190 let ( render_mode, id, class_html) = match what {
@@ -1165,6 +1216,12 @@ fn render_assoc_items_inner(
11651216 } ;
11661217 let mut impls_buf = Buffer :: html ( ) ;
11671218 for i in & non_trait {
1219+ if !saw_impls. insert ( i. def_id ( ) ) {
1220+ continue ;
1221+ }
1222+ if is_alias && !is_valid_impl_for ( tcx, it, i. def_id ( ) ) {
1223+ continue ;
1224+ }
11681225 render_impl (
11691226 & mut impls_buf,
11701227 cx,
@@ -1193,9 +1250,14 @@ fn render_assoc_items_inner(
11931250 if !traits. is_empty ( ) {
11941251 let deref_impl =
11951252 traits. iter ( ) . find ( |t| t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_trait ( ) ) ;
1196- if let Some ( impl_) = deref_impl {
1253+ if let Some ( impl_) = deref_impl &&
1254+ ( !is_alias || is_valid_impl_for ( tcx, it, impl_. def_id ( ) ) )
1255+ {
11971256 let has_deref_mut =
1198- traits. iter ( ) . any ( |t| t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_mut_trait ( ) ) ;
1257+ traits. iter ( ) . any ( |t| {
1258+ t. trait_did ( ) == cx. tcx ( ) . lang_items ( ) . deref_mut_trait ( ) &&
1259+ ( !is_alias || is_valid_impl_for ( tcx, it, t. def_id ( ) ) )
1260+ } ) ;
11991261 render_deref_methods ( & mut w, cx, impl_, containing_item, has_deref_mut, derefs) ;
12001262 }
12011263
@@ -1205,10 +1267,14 @@ fn render_assoc_items_inner(
12051267 return ;
12061268 }
12071269
1208- let ( synthetic, concrete) : ( Vec < & Impl > , Vec < & Impl > ) =
1209- traits. into_iter ( ) . partition ( |t| t. inner_impl ( ) . kind . is_auto ( ) ) ;
1210- let ( blanket_impl, concrete) : ( Vec < & Impl > , _ ) =
1211- concrete. into_iter ( ) . partition ( |t| t. inner_impl ( ) . kind . is_blanket ( ) ) ;
1270+ let ( synthetic, concrete) : ( Vec < & Impl > , Vec < & Impl > ) = traits
1271+ . into_iter ( )
1272+ . filter ( |t| saw_impls. insert ( t. def_id ( ) ) )
1273+ . partition ( |t| t. inner_impl ( ) . kind . is_auto ( ) ) ;
1274+ let ( blanket_impl, concrete) : ( Vec < & Impl > , _ ) = concrete
1275+ . into_iter ( )
1276+ . filter ( |t| !is_alias || is_valid_impl_for ( tcx, it, t. def_id ( ) ) )
1277+ . partition ( |t| t. inner_impl ( ) . kind . is_blanket ( ) ) ;
12121278
12131279 render_all_impls ( w, cx, containing_item, & concrete, & synthetic, & blanket_impl) ;
12141280 }
@@ -1247,10 +1313,10 @@ fn render_deref_methods(
12471313 return ;
12481314 }
12491315 }
1250- render_assoc_items_inner ( & mut w, cx, container_item, did, what, derefs) ;
1316+ render_assoc_items_inner ( & mut w, cx, container_item, did, what, derefs, None ) ;
12511317 } else if let Some ( prim) = target. primitive_type ( ) {
12521318 if let Some ( & did) = cache. primitive_locations . get ( & prim) {
1253- render_assoc_items_inner ( & mut w, cx, container_item, did, what, derefs) ;
1319+ render_assoc_items_inner ( & mut w, cx, container_item, did, what, derefs, None ) ;
12541320 }
12551321 }
12561322}
0 commit comments