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