@@ -4,15 +4,17 @@ use rustc_hir::def::{DefKind, Res};
4
4
use rustc_hir:: intravisit;
5
5
use rustc_hir:: { GenericParamKind , ImplItemKind , TraitItemKind } ;
6
6
use rustc_infer:: infer:: { self , InferOk , TyCtxtInferExt } ;
7
+ use rustc_middle:: ty;
7
8
use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
8
- use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
9
+ use rustc_middle:: ty:: subst:: { InternalSubsts , Subst , SubstsRef } ;
9
10
use rustc_middle:: ty:: util:: ExplicitSelf ;
10
- use rustc_middle:: ty:: { self , GenericParamDefKind , TyCtxt } ;
11
+ use rustc_middle:: ty:: { GenericParamDefKind , ToPredicate , TyCtxt , WithConstness } ;
11
12
use rustc_span:: Span ;
12
13
use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt ;
13
14
use rustc_trait_selection:: traits:: { self , ObligationCause , ObligationCauseCode , Reveal } ;
14
15
15
16
use super :: { potentially_plural_count, FnCtxt , Inherited } ;
17
+ use std:: iter;
16
18
17
19
/// Checks that a method from an impl conforms to the signature of
18
20
/// the same method as declared in the trait.
@@ -1053,13 +1055,15 @@ crate fn compare_ty_impl<'tcx>(
1053
1055
let _: Result < ( ) , ErrorReported > = ( || {
1054
1056
compare_number_of_generics ( tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span) ?;
1055
1057
1056
- compare_type_predicate_entailment ( tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)
1058
+ compare_type_predicate_entailment ( tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref) ?;
1059
+
1060
+ compare_projection_bounds ( tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
1057
1061
} ) ( ) ;
1058
1062
}
1059
1063
1060
1064
/// The equivalent of [compare_predicate_entailment], but for associated types
1061
1065
/// instead of associated functions.
1062
- fn compare_type_predicate_entailment (
1066
+ fn compare_type_predicate_entailment < ' tcx > (
1063
1067
tcx : TyCtxt < ' tcx > ,
1064
1068
impl_ty : & ty:: AssocItem ,
1065
1069
impl_ty_span : Span ,
@@ -1161,6 +1165,152 @@ fn compare_type_predicate_entailment(
1161
1165
} )
1162
1166
}
1163
1167
1168
+ /// Validate that `ProjectionCandidate`s created for this associated type will
1169
+ /// be valid.
1170
+ ///
1171
+ /// Usually given
1172
+ ///
1173
+ /// trait X { type Y: Copy } impl X for T { type Y = S; }
1174
+ ///
1175
+ /// We are able to normalize `<T as X>::U` to `S`, and so when we check the
1176
+ /// impl is well-formed we have to prove `S: Copy`.
1177
+ ///
1178
+ /// For default associated types the normalization is not possible (the value
1179
+ /// from the impl could be overridden). We also can't normalize generic
1180
+ /// associated types (yet) because they contain bound parameters.
1181
+ fn compare_projection_bounds < ' tcx > (
1182
+ tcx : TyCtxt < ' tcx > ,
1183
+ trait_ty : & ty:: AssocItem ,
1184
+ impl_ty : & ty:: AssocItem ,
1185
+ impl_ty_span : Span ,
1186
+ impl_trait_ref : ty:: TraitRef < ' tcx > ,
1187
+ ) -> Result < ( ) , ErrorReported > {
1188
+ let is_gat = !tcx. generics_of ( impl_ty. def_id ) . params . is_empty ( ) ;
1189
+ if impl_ty. defaultness . is_final ( ) && !is_gat {
1190
+ // For "final", non-generic associate type implementations, we
1191
+ // don't need this as described above.
1192
+ return Ok ( ( ) ) ;
1193
+ }
1194
+
1195
+ let param_env = tcx. param_env ( impl_ty. def_id ) ;
1196
+
1197
+ let impl_substs = InternalSubsts :: identity_for_item ( tcx, impl_ty. container . id ( ) ) ;
1198
+ let impl_ty_value = tcx. type_of ( impl_ty. def_id ) ;
1199
+
1200
+ // Map the predicate from the trait to the corresponding one for the impl.
1201
+ // For example:
1202
+ //
1203
+ // trait X<A> { type Y<'a>: PartialEq<A> } impl X for T { type Y<'a> = &'a S; }
1204
+ // impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; }
1205
+ //
1206
+ // For the `for<'a> <<Self as X<A>>::Y<'a>: PartialEq<A>` bound, this
1207
+ // function would translate and partially normalize
1208
+ // `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`.
1209
+ let translate_predicate_substs = move |predicate_substs : SubstsRef < ' tcx > | {
1210
+ let normalized_self = if !is_gat {
1211
+ // projection_predicates only includes projections where the
1212
+ // substs of the trait ref are exactly the trait's identity
1213
+ // substs, so we can simply return the value from the impl.
1214
+ impl_ty_value
1215
+ } else {
1216
+ let predicate_self_ty = predicate_substs. type_at ( 0 ) ;
1217
+ let impl_ty_substs = if let ty:: Projection ( p) = predicate_self_ty. kind {
1218
+ assert ! (
1219
+ p. item_def_id == trait_ty. def_id,
1220
+ "projection_predicates returned predicate for the wrong type: {}" ,
1221
+ predicate_self_ty,
1222
+ ) ;
1223
+ p. substs . rebase_onto ( tcx, impl_trait_ref. def_id , impl_substs)
1224
+ } else {
1225
+ bug ! (
1226
+ "projection_predicates returned predicate for the wrong type `{}`" ,
1227
+ predicate_self_ty,
1228
+ ) ;
1229
+ } ;
1230
+ impl_ty_value. subst ( tcx, impl_ty_substs)
1231
+ } ;
1232
+
1233
+ tcx. mk_substs (
1234
+ iter:: once ( normalized_self. into ( ) )
1235
+ . chain ( predicate_substs[ 1 ..] . iter ( ) . map ( |s| s. subst ( tcx, impl_trait_ref. substs ) ) ) ,
1236
+ )
1237
+ } ;
1238
+
1239
+ tcx. infer_ctxt ( ) . enter ( move |infcx| {
1240
+ let inh = Inherited :: new ( infcx, impl_ty. def_id . expect_local ( ) ) ;
1241
+ let infcx = & inh. infcx ;
1242
+ let mut selcx = traits:: SelectionContext :: new ( & infcx) ;
1243
+
1244
+ let impl_ty_hir_id = tcx. hir ( ) . as_local_hir_id ( impl_ty. def_id . expect_local ( ) ) ;
1245
+ let normalize_cause = traits:: ObligationCause :: misc ( impl_ty_span, impl_ty_hir_id) ;
1246
+ let cause = ObligationCause {
1247
+ span : impl_ty_span,
1248
+ body_id : impl_ty_hir_id,
1249
+ code : ObligationCauseCode :: ItemObligation ( impl_trait_ref. def_id ) ,
1250
+ } ;
1251
+
1252
+ let predicates = tcx. projection_predicates ( trait_ty. def_id ) ;
1253
+
1254
+ debug ! ( "compare_projection_bounds: projection_predicates={:?}" , predicates) ;
1255
+
1256
+ for predicate in predicates {
1257
+ let concrete_ty_predicate = match predicate. kind ( ) {
1258
+ ty:: PredicateKind :: Trait ( poly_tr, c) => poly_tr
1259
+ . map_bound ( |tr| {
1260
+ let trait_substs = translate_predicate_substs ( tr. trait_ref . substs ) ;
1261
+ ty:: TraitRef { def_id : tr. def_id ( ) , substs : trait_substs }
1262
+ } )
1263
+ . with_constness ( * c)
1264
+ . to_predicate ( tcx) ,
1265
+ ty:: PredicateKind :: Projection ( poly_projection) => poly_projection
1266
+ . map_bound ( |projection| {
1267
+ let projection_substs =
1268
+ translate_predicate_substs ( projection. projection_ty . substs ) ;
1269
+ ty:: ProjectionPredicate {
1270
+ projection_ty : ty:: ProjectionTy {
1271
+ substs : projection_substs,
1272
+ item_def_id : projection. projection_ty . item_def_id ,
1273
+ } ,
1274
+ ty : projection. ty . subst ( tcx, impl_trait_ref. substs ) ,
1275
+ }
1276
+ } )
1277
+ . to_predicate ( tcx) ,
1278
+ _ => bug ! ( "unexepected projection predicate kind: `{:?}`" , predicate) ,
1279
+ } ;
1280
+
1281
+ let traits:: Normalized { value : normalized_predicate, obligations } = traits:: normalize (
1282
+ & mut selcx,
1283
+ param_env,
1284
+ normalize_cause. clone ( ) ,
1285
+ & concrete_ty_predicate,
1286
+ ) ;
1287
+
1288
+ debug ! ( "compare_projection_bounds: normalized predicate = {:?}" , normalized_predicate) ;
1289
+
1290
+ inh. register_predicates ( obligations) ;
1291
+ inh. register_predicate ( traits:: Obligation :: new (
1292
+ cause. clone ( ) ,
1293
+ param_env,
1294
+ normalized_predicate,
1295
+ ) ) ;
1296
+ }
1297
+
1298
+ // Check that all obligations are satisfied by the implementation's
1299
+ // version.
1300
+ if let Err ( ref errors) = inh. fulfillment_cx . borrow_mut ( ) . select_all_or_error ( & infcx) {
1301
+ infcx. report_fulfillment_errors ( errors, None , false ) ;
1302
+ return Err ( ErrorReported ) ;
1303
+ }
1304
+
1305
+ // Finally, resolve all regions. This catches wily misuses of
1306
+ // lifetime parameters.
1307
+ let fcx = FnCtxt :: new ( & inh, param_env, impl_ty_hir_id) ;
1308
+ fcx. regionck_item ( impl_ty_hir_id, impl_ty_span, & [ ] ) ;
1309
+
1310
+ Ok ( ( ) )
1311
+ } )
1312
+ }
1313
+
1164
1314
fn assoc_item_kind_str ( impl_item : & ty:: AssocItem ) -> & ' static str {
1165
1315
match impl_item. kind {
1166
1316
ty:: AssocKind :: Const => "const" ,
0 commit comments