@@ -902,9 +902,10 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
902
902
tcx. impl_trait_refs . borrow_mut ( ) . insert ( it. id , trait_ref) ;
903
903
}
904
904
905
- enforce_impl_ty_params_are_constrained ( tcx,
906
- generics,
907
- local_def ( it. id ) ) ;
905
+ enforce_impl_params_are_constrained ( tcx,
906
+ generics,
907
+ local_def ( it. id ) ,
908
+ impl_items) ;
908
909
} ,
909
910
ast:: ItemTrait ( _, _, _, ref trait_items) => {
910
911
let trait_def = trait_def_of_item ( ccx, it) ;
@@ -2188,9 +2189,10 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
2188
2189
}
2189
2190
2190
2191
/// Checks that all the type parameters on an impl
2191
- fn enforce_impl_ty_params_are_constrained < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
2192
- ast_generics : & ast:: Generics ,
2193
- impl_def_id : ast:: DefId )
2192
+ fn enforce_impl_params_are_constrained < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
2193
+ ast_generics : & ast:: Generics ,
2194
+ impl_def_id : ast:: DefId ,
2195
+ impl_items : & [ P < ast:: ImplItem > ] )
2194
2196
{
2195
2197
let impl_scheme = ty:: lookup_item_type ( tcx, impl_def_id) ;
2196
2198
let impl_predicates = ty:: lookup_predicates ( tcx, impl_def_id) ;
@@ -2216,11 +2218,67 @@ fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
2216
2218
let param_ty = ty:: ParamTy { space : TypeSpace ,
2217
2219
idx : index as u32 ,
2218
2220
name : ty_param. ident . name } ;
2219
- if !input_parameters. contains ( & param_ty) {
2220
- span_err ! ( tcx. sess, ty_param. span, E0207 ,
2221
- "the type parameter `{}` is not constrained by the \
2222
- impl trait, self type, or predicates",
2223
- param_ty. user_string( tcx) ) ;
2221
+ if !input_parameters. contains ( & ctp:: Parameter :: Type ( param_ty) ) {
2222
+ report_unused_parameter ( tcx, ty_param. span , "type" , & param_ty. user_string ( tcx) ) ;
2223
+ }
2224
+ }
2225
+
2226
+ // Every lifetime used in an associated type must be constrained.
2227
+
2228
+ let lifetimes_in_associated_types: HashSet < _ > =
2229
+ impl_items. iter ( )
2230
+ . filter_map ( |item| match item. node {
2231
+ ast:: TypeImplItem ( ..) => Some ( ty:: node_id_to_type ( tcx, item. id ) ) ,
2232
+ ast:: MethodImplItem ( ..) | ast:: MacImplItem ( ..) => None ,
2233
+ } )
2234
+ . flat_map ( |ty| ctp:: parameters_for_type ( ty) . into_iter ( ) )
2235
+ . filter_map ( |p| match p {
2236
+ ctp:: Parameter :: Type ( _) => None ,
2237
+ ctp:: Parameter :: Region ( r) => Some ( r) ,
2238
+ } )
2239
+ . collect ( ) ;
2240
+
2241
+ for ( index, lifetime_def) in ast_generics. lifetimes . iter ( ) . enumerate ( ) {
2242
+ let region = ty:: EarlyBoundRegion { param_id : lifetime_def. lifetime . id ,
2243
+ space : TypeSpace ,
2244
+ index : index as u32 ,
2245
+ name : lifetime_def. lifetime . name } ;
2246
+ if
2247
+ lifetimes_in_associated_types. contains ( & region) && // (*)
2248
+ !input_parameters. contains ( & ctp:: Parameter :: Region ( region) )
2249
+ {
2250
+ report_unused_parameter ( tcx, lifetime_def. lifetime . span ,
2251
+ "lifetime" , & region. name . user_string ( tcx) ) ;
2224
2252
}
2225
2253
}
2254
+
2255
+ // (*) This is a horrible concession to reality. I think it'd be
2256
+ // better to just ban unconstrianed lifetimes outright, but in
2257
+ // practice people do non-hygenic macros like:
2258
+ //
2259
+ // ```
2260
+ // macro_rules! __impl_slice_eq1 {
2261
+ // ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
2262
+ // impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
2263
+ // ....
2264
+ // }
2265
+ // }
2266
+ // }
2267
+ // ```
2268
+ //
2269
+ // In a concession to backwards compatbility, we continue to
2270
+ // permit those, so long as the lifetimes aren't used in
2271
+ // associated types. I believe this is sound, because lifetimes
2272
+ // used elsewhere are not projected back out.
2273
+ }
2274
+
2275
+ fn report_unused_parameter ( tcx : & ty:: ctxt ,
2276
+ span : Span ,
2277
+ kind : & str ,
2278
+ name : & str )
2279
+ {
2280
+ span_err ! ( tcx. sess, span, E0207 ,
2281
+ "the {} parameter `{}` is not constrained by the \
2282
+ impl trait, self type, or predicates",
2283
+ kind, name) ;
2226
2284
}
0 commit comments