@@ -5,7 +5,7 @@ use rustc::ty::{self, TyCtxt, GenericParamDefKind};
55use rustc:: ty:: util:: ExplicitSelf ;
66use rustc:: traits:: { self , ObligationCause , ObligationCauseCode , Reveal } ;
77use rustc:: ty:: error:: { ExpectedFound , TypeError } ;
8- use rustc:: ty:: subst:: { Subst , InternalSubsts , SubstsRef } ;
8+ use rustc:: ty:: subst:: { Subst , InternalSubsts } ;
99use rustc:: util:: common:: ErrorReported ;
1010use errors:: { Applicability , DiagnosticId } ;
1111
@@ -26,7 +26,7 @@ use rustc_error_codes::*;
2626/// - `trait_m`: the method in the trait
2727/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
2828
29- pub fn compare_impl_method < ' tcx > (
29+ crate fn compare_impl_method < ' tcx > (
3030 tcx : TyCtxt < ' tcx > ,
3131 impl_m : & ty:: AssocItem ,
3232 impl_m_span : Span ,
@@ -181,13 +181,14 @@ fn compare_predicate_entailment<'tcx>(
181181 let trait_m_predicates = tcx. predicates_of ( trait_m. def_id ) ;
182182
183183 // Check region bounds.
184- check_region_bounds_on_impl_method ( tcx,
185- impl_m_span,
186- impl_m,
187- trait_m,
188- & trait_m_generics,
189- & impl_m_generics,
190- trait_to_skol_substs) ?;
184+ check_region_bounds_on_impl_item (
185+ tcx,
186+ impl_m_span,
187+ impl_m,
188+ trait_m,
189+ & trait_m_generics,
190+ & impl_m_generics,
191+ ) ?;
191192
192193 // Create obligations for each predicate declared by the impl
193194 // definition in the context of the trait's parameter
@@ -361,25 +362,22 @@ fn compare_predicate_entailment<'tcx>(
361362 } )
362363}
363364
364- fn check_region_bounds_on_impl_method < ' tcx > (
365+ fn check_region_bounds_on_impl_item < ' tcx > (
365366 tcx : TyCtxt < ' tcx > ,
366367 span : Span ,
367368 impl_m : & ty:: AssocItem ,
368369 trait_m : & ty:: AssocItem ,
369370 trait_generics : & ty:: Generics ,
370371 impl_generics : & ty:: Generics ,
371- trait_to_skol_substs : SubstsRef < ' tcx > ,
372372) -> Result < ( ) , ErrorReported > {
373373 let trait_params = trait_generics. own_counts ( ) . lifetimes ;
374374 let impl_params = impl_generics. own_counts ( ) . lifetimes ;
375375
376- debug ! ( "check_region_bounds_on_impl_method : \
376+ debug ! ( "check_region_bounds_on_impl_item : \
377377 trait_generics={:?} \
378- impl_generics={:?} \
379- trait_to_skol_substs={:?}",
378+ impl_generics={:?}",
380379 trait_generics,
381- impl_generics,
382- trait_to_skol_substs) ;
380+ impl_generics) ;
383381
384382 // Must have same number of early-bound lifetime parameters.
385383 // Unfortunately, if the user screws up the bounds, then this
@@ -391,20 +389,25 @@ fn check_region_bounds_on_impl_method<'tcx>(
391389 // are zero. Since I don't quite know how to phrase things at
392390 // the moment, give a kind of vague error message.
393391 if trait_params != impl_params {
392+ let item_kind = assoc_item_kind_str ( impl_m) ;
394393 let def_span = tcx. sess . source_map ( ) . def_span ( span) ;
395394 let span = tcx. hir ( ) . get_generics ( impl_m. def_id ) . map ( |g| g. span ) . unwrap_or ( def_span) ;
396395 let mut err = struct_span_err ! (
397396 tcx. sess,
398397 span,
399398 E0195 ,
400- "lifetime parameters or bounds on method `{}` do not match the trait declaration" ,
399+ "lifetime parameters or bounds on {} `{}` do not match the trait declaration" ,
400+ item_kind,
401401 impl_m. ident,
402402 ) ;
403- err. span_label ( span, "lifetimes do not match method in trait" ) ;
403+ err. span_label ( span, & format ! ( "lifetimes do not match {} in trait" , item_kind ) ) ;
404404 if let Some ( sp) = tcx. hir ( ) . span_if_local ( trait_m. def_id ) {
405405 let def_sp = tcx. sess . source_map ( ) . def_span ( sp) ;
406406 let sp = tcx. hir ( ) . get_generics ( trait_m. def_id ) . map ( |g| g. span ) . unwrap_or ( def_sp) ;
407- err. span_label ( sp, "lifetimes in impl do not match this method in trait" ) ;
407+ err. span_label (
408+ sp,
409+ & format ! ( "lifetimes in impl do not match this {} in trait" , item_kind) ,
410+ ) ;
408411 }
409412 err. emit ( ) ;
410413 return Err ( ErrorReported ) ;
@@ -603,6 +606,8 @@ fn compare_number_of_generics<'tcx>(
603606 ( "const" , trait_own_counts. consts , impl_own_counts. consts ) ,
604607 ] ;
605608
609+ let item_kind = assoc_item_kind_str ( impl_) ;
610+
606611 let mut err_occurred = false ;
607612 for & ( kind, trait_count, impl_count) in & matchings {
608613 if impl_count != trait_count {
@@ -647,8 +652,9 @@ fn compare_number_of_generics<'tcx>(
647652 let mut err = tcx. sess . struct_span_err_with_code (
648653 spans,
649654 & format ! (
650- "method `{}` has {} {kind} parameter{} but its trait \
655+ "{} `{}` has {} {kind} parameter{} but its trait \
651656 declaration has {} {kind} parameter{}",
657+ item_kind,
652658 trait_. ident,
653659 impl_count,
654660 pluralize!( impl_count) ,
@@ -961,7 +967,7 @@ fn compare_synthetic_generics<'tcx>(
961967 }
962968}
963969
964- pub fn compare_const_impl < ' tcx > (
970+ crate fn compare_const_impl < ' tcx > (
965971 tcx : TyCtxt < ' tcx > ,
966972 impl_c : & ty:: AssocItem ,
967973 impl_c_span : Span ,
@@ -1059,3 +1065,131 @@ pub fn compare_const_impl<'tcx>(
10591065 fcx. regionck_item ( impl_c_hir_id, impl_c_span, & [ ] ) ;
10601066 } ) ;
10611067}
1068+
1069+ crate fn compare_ty_impl < ' tcx > (
1070+ tcx : TyCtxt < ' tcx > ,
1071+ impl_ty : & ty:: AssocItem ,
1072+ impl_ty_span : Span ,
1073+ trait_ty : & ty:: AssocItem ,
1074+ impl_trait_ref : ty:: TraitRef < ' tcx > ,
1075+ trait_item_span : Option < Span > ,
1076+ ) {
1077+ debug ! ( "compare_impl_type(impl_trait_ref={:?})" , impl_trait_ref) ;
1078+
1079+ let _: Result < ( ) , ErrorReported > = ( || {
1080+ compare_number_of_generics ( tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span) ?;
1081+
1082+ compare_type_predicate_entailment ( tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)
1083+ } ) ( ) ;
1084+ }
1085+
1086+ /// The equivalent of [compare_predicate_entailment], but for associated types
1087+ /// instead of associated functions.
1088+ fn compare_type_predicate_entailment (
1089+ tcx : TyCtxt < ' tcx > ,
1090+ impl_ty : & ty:: AssocItem ,
1091+ impl_ty_span : Span ,
1092+ trait_ty : & ty:: AssocItem ,
1093+ impl_trait_ref : ty:: TraitRef < ' tcx > ,
1094+ ) -> Result < ( ) , ErrorReported > {
1095+ let impl_substs = InternalSubsts :: identity_for_item ( tcx, impl_ty. def_id ) ;
1096+ let trait_to_impl_substs = impl_substs. rebase_onto ( tcx,
1097+ impl_ty. container . id ( ) ,
1098+ impl_trait_ref. substs ) ;
1099+
1100+ let impl_ty_generics = tcx. generics_of ( impl_ty. def_id ) ;
1101+ let trait_ty_generics = tcx. generics_of ( trait_ty. def_id ) ;
1102+ let impl_ty_predicates = tcx. predicates_of ( impl_ty. def_id ) ;
1103+ let trait_ty_predicates = tcx. predicates_of ( trait_ty. def_id ) ;
1104+
1105+ check_region_bounds_on_impl_item (
1106+ tcx,
1107+ impl_ty_span,
1108+ impl_ty,
1109+ trait_ty,
1110+ & trait_ty_generics,
1111+ & impl_ty_generics,
1112+ ) ?;
1113+
1114+ let impl_ty_own_bounds = impl_ty_predicates. instantiate_own ( tcx, impl_substs) ;
1115+
1116+ if impl_ty_own_bounds. is_empty ( ) {
1117+ // Nothing to check.
1118+ return Ok ( ( ) ) ;
1119+ }
1120+
1121+ // This `HirId` should be used for the `body_id` field on each
1122+ // `ObligationCause` (and the `FnCtxt`). This is what
1123+ // `regionck_item` expects.
1124+ let impl_ty_hir_id = tcx. hir ( ) . as_local_hir_id ( impl_ty. def_id ) . unwrap ( ) ;
1125+ let cause = ObligationCause {
1126+ span : impl_ty_span,
1127+ body_id : impl_ty_hir_id,
1128+ code : ObligationCauseCode :: CompareImplTypeObligation {
1129+ item_name : impl_ty. ident . name ,
1130+ impl_item_def_id : impl_ty. def_id ,
1131+ trait_item_def_id : trait_ty. def_id ,
1132+ } ,
1133+ } ;
1134+
1135+ debug ! ( "compare_type_predicate_entailment: trait_to_impl_substs={:?}" , trait_to_impl_substs) ;
1136+
1137+ // The predicates declared by the impl definition, the trait and the
1138+ // associated type in the trait are assumed.
1139+ let impl_predicates = tcx. predicates_of ( impl_ty_predicates. parent . unwrap ( ) ) ;
1140+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) ;
1141+ hybrid_preds. predicates . extend (
1142+ trait_ty_predicates. instantiate_own ( tcx, trait_to_impl_substs) . predicates ) ;
1143+
1144+ debug ! ( "compare_type_predicate_entailment: bounds={:?}" , hybrid_preds) ;
1145+
1146+ let normalize_cause = traits:: ObligationCause :: misc ( impl_ty_span, impl_ty_hir_id) ;
1147+ let param_env = ty:: ParamEnv :: new (
1148+ tcx. intern_predicates ( & hybrid_preds. predicates ) ,
1149+ Reveal :: UserFacing ,
1150+ None
1151+ ) ;
1152+ let param_env = traits:: normalize_param_env_or_error ( tcx,
1153+ impl_ty. def_id ,
1154+ param_env,
1155+ normalize_cause. clone ( ) ) ;
1156+ tcx. infer_ctxt ( ) . enter ( |infcx| {
1157+ let inh = Inherited :: new ( infcx, impl_ty. def_id ) ;
1158+ let infcx = & inh. infcx ;
1159+
1160+ debug ! ( "compare_type_predicate_entailment: caller_bounds={:?}" ,
1161+ param_env. caller_bounds) ;
1162+
1163+ let mut selcx = traits:: SelectionContext :: new ( & infcx) ;
1164+
1165+ for predicate in impl_ty_own_bounds. predicates {
1166+ let traits:: Normalized { value : predicate, obligations } =
1167+ traits:: normalize ( & mut selcx, param_env, normalize_cause. clone ( ) , & predicate) ;
1168+
1169+ inh. register_predicates ( obligations) ;
1170+ inh. register_predicate ( traits:: Obligation :: new ( cause. clone ( ) , param_env, predicate) ) ;
1171+ }
1172+
1173+ // Check that all obligations are satisfied by the implementation's
1174+ // version.
1175+ if let Err ( ref errors) = inh. fulfillment_cx . borrow_mut ( ) . select_all_or_error ( & infcx) {
1176+ infcx. report_fulfillment_errors ( errors, None , false ) ;
1177+ return Err ( ErrorReported ) ;
1178+ }
1179+
1180+ // Finally, resolve all regions. This catches wily misuses of
1181+ // lifetime parameters.
1182+ let fcx = FnCtxt :: new ( & inh, param_env, impl_ty_hir_id) ;
1183+ fcx. regionck_item ( impl_ty_hir_id, impl_ty_span, & [ ] ) ;
1184+
1185+ Ok ( ( ) )
1186+ } )
1187+ }
1188+
1189+ fn assoc_item_kind_str ( impl_item : & ty:: AssocItem ) -> & ' static str {
1190+ match impl_item. kind {
1191+ ty:: AssocKind :: Const => "const" ,
1192+ ty:: AssocKind :: Method => "method" ,
1193+ ty:: AssocKind :: Type | ty:: AssocKind :: OpaqueTy => "type" ,
1194+ }
1195+ }
0 commit comments