@@ -53,12 +53,15 @@ use rustc_data_structures::captures::Captures;
53
53
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
54
54
use rustc_hir:: def_id:: { DefId , DefIdSet } ;
55
55
use rustc_hir:: Mutability ;
56
+ use rustc_infer:: infer:: TyCtxtInferExt ;
57
+ use rustc_infer:: traits:: { Obligation , ObligationCause } ;
56
58
use rustc_middle:: middle:: stability;
57
- use rustc_middle:: ty:: TyCtxt ;
59
+ use rustc_middle:: ty:: { ParamEnv , TyCtxt } ;
58
60
use rustc_span:: {
59
61
symbol:: { sym, Symbol } ,
60
62
BytePos , FileName , RealFileName ,
61
63
} ;
64
+ use rustc_trait_selection:: traits:: ObligationCtxt ;
62
65
use serde:: ser:: { SerializeMap , SerializeSeq } ;
63
66
use serde:: { Serialize , Serializer } ;
64
67
@@ -1112,28 +1115,76 @@ fn render_assoc_items<'a, 'cx: 'a>(
1112
1115
containing_item : & ' a clean:: Item ,
1113
1116
it : DefId ,
1114
1117
what : AssocItemRender < ' a > ,
1118
+ aliased_type : Option < DefId > ,
1115
1119
) -> impl fmt:: Display + ' a + Captures < ' cx > {
1116
1120
let mut derefs = DefIdSet :: default ( ) ;
1117
1121
derefs. insert ( it) ;
1118
1122
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 ) ;
1120
1124
Ok ( ( ) )
1121
1125
} )
1122
1126
}
1123
1127
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.
1124
1159
fn render_assoc_items_inner (
1125
1160
mut w : & mut dyn fmt:: Write ,
1126
1161
cx : & mut Context < ' _ > ,
1127
1162
containing_item : & clean:: Item ,
1128
1163
it : DefId ,
1129
1164
what : AssocItemRender < ' _ > ,
1130
1165
derefs : & mut DefIdSet ,
1166
+ aliased_type : Option < DefId > ,
1131
1167
) {
1132
1168
info ! ( "Documenting associated items of {:?}" , containing_item. name) ;
1133
1169
let shared = Rc :: clone ( & cx. shared ) ;
1134
1170
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 ( ) ;
1137
1188
if !non_trait. is_empty ( ) {
1138
1189
let mut tmp_buf = Buffer :: html ( ) ;
1139
1190
let ( render_mode, id, class_html) = match what {
@@ -1165,6 +1216,12 @@ fn render_assoc_items_inner(
1165
1216
} ;
1166
1217
let mut impls_buf = Buffer :: html ( ) ;
1167
1218
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
+ }
1168
1225
render_impl (
1169
1226
& mut impls_buf,
1170
1227
cx,
@@ -1193,9 +1250,14 @@ fn render_assoc_items_inner(
1193
1250
if !traits. is_empty ( ) {
1194
1251
let deref_impl =
1195
1252
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
+ {
1197
1256
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
+ } ) ;
1199
1261
render_deref_methods ( & mut w, cx, impl_, containing_item, has_deref_mut, derefs) ;
1200
1262
}
1201
1263
@@ -1205,10 +1267,14 @@ fn render_assoc_items_inner(
1205
1267
return ;
1206
1268
}
1207
1269
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 ( ) ) ;
1212
1278
1213
1279
render_all_impls ( w, cx, containing_item, & concrete, & synthetic, & blanket_impl) ;
1214
1280
}
@@ -1247,10 +1313,10 @@ fn render_deref_methods(
1247
1313
return ;
1248
1314
}
1249
1315
}
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 ) ;
1251
1317
} else if let Some ( prim) = target. primitive_type ( ) {
1252
1318
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 ) ;
1254
1320
}
1255
1321
}
1256
1322
}
0 commit comments