@@ -5,7 +5,7 @@ use rustc::ty::{self, TyCtxt, GenericParamDefKind};
5
5
use rustc:: ty:: util:: ExplicitSelf ;
6
6
use rustc:: traits:: { self , ObligationCause , ObligationCauseCode , Reveal } ;
7
7
use rustc:: ty:: error:: { ExpectedFound , TypeError } ;
8
- use rustc:: ty:: subst:: { Subst , InternalSubsts , SubstsRef } ;
8
+ use rustc:: ty:: subst:: { Subst , InternalSubsts } ;
9
9
use rustc:: util:: common:: ErrorReported ;
10
10
use errors:: { Applicability , DiagnosticId } ;
11
11
@@ -26,7 +26,7 @@ use rustc_error_codes::*;
26
26
/// - `trait_m`: the method in the trait
27
27
/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
28
28
29
- pub fn compare_impl_method < ' tcx > (
29
+ crate fn compare_impl_method < ' tcx > (
30
30
tcx : TyCtxt < ' tcx > ,
31
31
impl_m : & ty:: AssocItem ,
32
32
impl_m_span : Span ,
@@ -181,13 +181,14 @@ fn compare_predicate_entailment<'tcx>(
181
181
let trait_m_predicates = tcx. predicates_of ( trait_m. def_id ) ;
182
182
183
183
// 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
+ ) ?;
191
192
192
193
// Create obligations for each predicate declared by the impl
193
194
// definition in the context of the trait's parameter
@@ -361,25 +362,22 @@ fn compare_predicate_entailment<'tcx>(
361
362
} )
362
363
}
363
364
364
- fn check_region_bounds_on_impl_method < ' tcx > (
365
+ fn check_region_bounds_on_impl_item < ' tcx > (
365
366
tcx : TyCtxt < ' tcx > ,
366
367
span : Span ,
367
368
impl_m : & ty:: AssocItem ,
368
369
trait_m : & ty:: AssocItem ,
369
370
trait_generics : & ty:: Generics ,
370
371
impl_generics : & ty:: Generics ,
371
- trait_to_skol_substs : SubstsRef < ' tcx > ,
372
372
) -> Result < ( ) , ErrorReported > {
373
373
let trait_params = trait_generics. own_counts ( ) . lifetimes ;
374
374
let impl_params = impl_generics. own_counts ( ) . lifetimes ;
375
375
376
- debug ! ( "check_region_bounds_on_impl_method : \
376
+ debug ! ( "check_region_bounds_on_impl_item : \
377
377
trait_generics={:?} \
378
- impl_generics={:?} \
379
- trait_to_skol_substs={:?}",
378
+ impl_generics={:?}",
380
379
trait_generics,
381
- impl_generics,
382
- trait_to_skol_substs) ;
380
+ impl_generics) ;
383
381
384
382
// Must have same number of early-bound lifetime parameters.
385
383
// Unfortunately, if the user screws up the bounds, then this
@@ -391,20 +389,25 @@ fn check_region_bounds_on_impl_method<'tcx>(
391
389
// are zero. Since I don't quite know how to phrase things at
392
390
// the moment, give a kind of vague error message.
393
391
if trait_params != impl_params {
392
+ let item_kind = assoc_item_kind_str ( impl_m) ;
394
393
let def_span = tcx. sess . source_map ( ) . def_span ( span) ;
395
394
let span = tcx. hir ( ) . get_generics ( impl_m. def_id ) . map ( |g| g. span ) . unwrap_or ( def_span) ;
396
395
let mut err = struct_span_err ! (
397
396
tcx. sess,
398
397
span,
399
398
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,
401
401
impl_m. ident,
402
402
) ;
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 ) ) ;
404
404
if let Some ( sp) = tcx. hir ( ) . span_if_local ( trait_m. def_id ) {
405
405
let def_sp = tcx. sess . source_map ( ) . def_span ( sp) ;
406
406
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
+ ) ;
408
411
}
409
412
err. emit ( ) ;
410
413
return Err ( ErrorReported ) ;
@@ -603,6 +606,8 @@ fn compare_number_of_generics<'tcx>(
603
606
( "const" , trait_own_counts. consts , impl_own_counts. consts ) ,
604
607
] ;
605
608
609
+ let item_kind = assoc_item_kind_str ( impl_) ;
610
+
606
611
let mut err_occurred = false ;
607
612
for & ( kind, trait_count, impl_count) in & matchings {
608
613
if impl_count != trait_count {
@@ -647,8 +652,9 @@ fn compare_number_of_generics<'tcx>(
647
652
let mut err = tcx. sess . struct_span_err_with_code (
648
653
spans,
649
654
& format ! (
650
- "method `{}` has {} {kind} parameter{} but its trait \
655
+ "{} `{}` has {} {kind} parameter{} but its trait \
651
656
declaration has {} {kind} parameter{}",
657
+ item_kind,
652
658
trait_. ident,
653
659
impl_count,
654
660
pluralize!( impl_count) ,
@@ -961,7 +967,7 @@ fn compare_synthetic_generics<'tcx>(
961
967
}
962
968
}
963
969
964
- pub fn compare_const_impl < ' tcx > (
970
+ crate fn compare_const_impl < ' tcx > (
965
971
tcx : TyCtxt < ' tcx > ,
966
972
impl_c : & ty:: AssocItem ,
967
973
impl_c_span : Span ,
@@ -1059,3 +1065,131 @@ pub fn compare_const_impl<'tcx>(
1059
1065
fcx. regionck_item ( impl_c_hir_id, impl_c_span, & [ ] ) ;
1060
1066
} ) ;
1061
1067
}
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