10
10
11
11
use astconv:: AstConv ;
12
12
use check:: { FnCtxt , Inherited , blank_fn_ctxt, vtable, regionck} ;
13
+ use constrained_type_params:: identify_constrained_type_params;
13
14
use CrateCtxt ;
14
15
use middle:: region;
15
- use middle:: subst;
16
+ use middle:: subst:: { self , TypeSpace , FnSpace , ParamSpace , SelfSpace } ;
16
17
use middle:: traits;
17
18
use middle:: ty:: { self , Ty } ;
18
19
use middle:: ty:: liberate_late_bound_regions;
19
20
use middle:: ty_fold:: { TypeFolder , TypeFoldable , super_fold_ty} ;
20
- use util:: ppaux:: Repr ;
21
+ use util:: ppaux:: { Repr , UserString } ;
21
22
22
23
use std:: collections:: HashSet ;
23
24
use syntax:: ast;
24
25
use syntax:: ast_util:: { local_def} ;
25
26
use syntax:: attr;
26
27
use syntax:: codemap:: Span ;
27
- use syntax:: parse:: token;
28
+ use syntax:: parse:: token:: { self , special_idents } ;
28
29
use syntax:: visit;
29
30
use syntax:: visit:: Visitor ;
30
31
@@ -38,6 +39,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
38
39
CheckTypeWellFormedVisitor { ccx : ccx, cache : HashSet :: new ( ) }
39
40
}
40
41
42
+ fn tcx ( & self ) -> & ty:: ctxt < ' tcx > {
43
+ self . ccx . tcx
44
+ }
45
+
41
46
/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
42
47
/// well-formed, meaning that they do not require any constraints not declared in the struct
43
48
/// definition itself. For example, this definition would be illegal:
@@ -96,23 +101,29 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
96
101
ast:: ItemConst ( ..) => {
97
102
self . check_item_type ( item) ;
98
103
}
99
- ast:: ItemStruct ( ref struct_def, _ ) => {
104
+ ast:: ItemStruct ( ref struct_def, ref ast_generics ) => {
100
105
self . check_type_defn ( item, |fcx| {
101
106
vec ! [ struct_variant( fcx, & * * struct_def) ]
102
107
} ) ;
108
+
109
+ self . check_variances_for_type_defn ( item, ast_generics) ;
103
110
}
104
- ast:: ItemEnum ( ref enum_def, _ ) => {
111
+ ast:: ItemEnum ( ref enum_def, ref ast_generics ) => {
105
112
self . check_type_defn ( item, |fcx| {
106
113
enum_variants ( fcx, enum_def)
107
114
} ) ;
115
+
116
+ self . check_variances_for_type_defn ( item, ast_generics) ;
108
117
}
109
- ast:: ItemTrait ( .. ) => {
118
+ ast:: ItemTrait ( _ , ref ast_generics , _ , _ ) => {
110
119
let trait_predicates =
111
120
ty:: lookup_predicates ( ccx. tcx , local_def ( item. id ) ) ;
112
121
reject_non_type_param_bounds (
113
122
ccx. tcx ,
114
123
item. span ,
115
124
& trait_predicates) ;
125
+ self . check_variances ( item, ast_generics, & trait_predicates,
126
+ self . tcx ( ) . lang_items . phantom_fn ( ) ) ;
116
127
}
117
128
_ => { }
118
129
}
@@ -280,6 +291,123 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
280
291
}
281
292
} ) ;
282
293
}
294
+
295
+ fn check_variances_for_type_defn ( & self ,
296
+ item : & ast:: Item ,
297
+ ast_generics : & ast:: Generics )
298
+ {
299
+ let item_def_id = local_def ( item. id ) ;
300
+ let predicates = ty:: lookup_predicates ( self . tcx ( ) , item_def_id) ;
301
+ self . check_variances ( item,
302
+ ast_generics,
303
+ & predicates,
304
+ self . tcx ( ) . lang_items . phantom_data ( ) ) ;
305
+ }
306
+
307
+ fn check_variances ( & self ,
308
+ item : & ast:: Item ,
309
+ ast_generics : & ast:: Generics ,
310
+ ty_predicates : & ty:: GenericPredicates < ' tcx > ,
311
+ suggested_marker_id : Option < ast:: DefId > )
312
+ {
313
+ let variance_lang_items = & [
314
+ self . tcx ( ) . lang_items . phantom_fn ( ) ,
315
+ self . tcx ( ) . lang_items . phantom_data ( ) ,
316
+ ] ;
317
+
318
+ let item_def_id = local_def ( item. id ) ;
319
+ let is_lang_item = variance_lang_items. iter ( ) . any ( |n| * n == Some ( item_def_id) ) ;
320
+ if is_lang_item {
321
+ return ;
322
+ }
323
+
324
+ let variances = ty:: item_variances ( self . tcx ( ) , item_def_id) ;
325
+
326
+ let mut constrained_parameters: HashSet < _ > =
327
+ variances. types
328
+ . iter_enumerated ( )
329
+ . filter ( |& ( _, _, & variance) | variance != ty:: Bivariant )
330
+ . map ( |( space, index, _) | self . param_ty ( ast_generics, space, index) )
331
+ . collect ( ) ;
332
+
333
+ identify_constrained_type_params ( self . tcx ( ) ,
334
+ ty_predicates. predicates . as_slice ( ) ,
335
+ None ,
336
+ & mut constrained_parameters) ;
337
+
338
+ for ( space, index, _) in variances. types . iter_enumerated ( ) {
339
+ let param_ty = self . param_ty ( ast_generics, space, index) ;
340
+ if constrained_parameters. contains ( & param_ty) {
341
+ continue ;
342
+ }
343
+ let span = self . ty_param_span ( ast_generics, item, space, index) ;
344
+ self . report_bivariance ( span, param_ty. name , suggested_marker_id) ;
345
+ }
346
+
347
+ for ( space, index, & variance) in variances. regions . iter_enumerated ( ) {
348
+ if variance != ty:: Bivariant {
349
+ continue ;
350
+ }
351
+
352
+ assert_eq ! ( space, TypeSpace ) ;
353
+ let span = ast_generics. lifetimes [ index] . lifetime . span ;
354
+ let name = ast_generics. lifetimes [ index] . lifetime . name ;
355
+ self . report_bivariance ( span, name, suggested_marker_id) ;
356
+ }
357
+ }
358
+
359
+ fn param_ty ( & self ,
360
+ ast_generics : & ast:: Generics ,
361
+ space : ParamSpace ,
362
+ index : usize )
363
+ -> ty:: ParamTy
364
+ {
365
+ let name = match space {
366
+ TypeSpace => ast_generics. ty_params [ index] . ident . name ,
367
+ SelfSpace => special_idents:: type_self. name ,
368
+ FnSpace => self . tcx ( ) . sess . bug ( "Fn space occupied?" ) ,
369
+ } ;
370
+
371
+ ty:: ParamTy { space : space, idx : index as u32 , name : name }
372
+ }
373
+
374
+ fn ty_param_span ( & self ,
375
+ ast_generics : & ast:: Generics ,
376
+ item : & ast:: Item ,
377
+ space : ParamSpace ,
378
+ index : usize )
379
+ -> Span
380
+ {
381
+ match space {
382
+ TypeSpace => ast_generics. ty_params [ index] . span ,
383
+ SelfSpace => item. span ,
384
+ FnSpace => self . tcx ( ) . sess . span_bug ( item. span , "Fn space occupied?" ) ,
385
+ }
386
+ }
387
+
388
+ fn report_bivariance ( & self ,
389
+ span : Span ,
390
+ param_name : ast:: Name ,
391
+ suggested_marker_id : Option < ast:: DefId > )
392
+ {
393
+ self . tcx ( ) . sess . span_err (
394
+ span,
395
+ & format ! ( "parameter `{}` is never used" ,
396
+ param_name. user_string( self . tcx( ) ) ) [ ] ) ;
397
+
398
+ match suggested_marker_id {
399
+ Some ( def_id) => {
400
+ self . tcx ( ) . sess . span_help (
401
+ span,
402
+ format ! ( "consider removing `{}` or using a marker such as `{}`" ,
403
+ param_name. user_string( self . tcx( ) ) ,
404
+ ty:: item_path_str( self . tcx( ) , def_id) ) . as_slice ( ) ) ;
405
+ }
406
+ None => {
407
+ // no lang items, no help!
408
+ }
409
+ }
410
+ }
283
411
}
284
412
285
413
// Reject any predicates that do not involve a type parameter.
@@ -347,9 +475,9 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
347
475
match fk {
348
476
visit:: FkFnBlock | visit:: FkItemFn ( ..) => { }
349
477
visit:: FkMethod ( ..) => {
350
- match ty:: impl_or_trait_item ( self . ccx . tcx , local_def ( id) ) {
478
+ match ty:: impl_or_trait_item ( self . tcx ( ) , local_def ( id) ) {
351
479
ty:: ImplOrTraitItem :: MethodTraitItem ( ty_method) => {
352
- reject_shadowing_type_parameters ( self . ccx . tcx , span, & ty_method. generics )
480
+ reject_shadowing_type_parameters ( self . tcx ( ) , span, & ty_method. generics )
353
481
}
354
482
_ => { }
355
483
}
@@ -363,14 +491,14 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
363
491
& ast:: TraitItem :: ProvidedMethod ( _) |
364
492
& ast:: TraitItem :: TypeTraitItem ( _) => { } ,
365
493
& ast:: TraitItem :: RequiredMethod ( ref method) => {
366
- match ty:: impl_or_trait_item ( self . ccx . tcx , local_def ( method. id ) ) {
494
+ match ty:: impl_or_trait_item ( self . tcx ( ) , local_def ( method. id ) ) {
367
495
ty:: ImplOrTraitItem :: MethodTraitItem ( ty_method) => {
368
496
reject_non_type_param_bounds (
369
- self . ccx . tcx ,
497
+ self . tcx ( ) ,
370
498
method. span ,
371
499
& ty_method. predicates ) ;
372
500
reject_shadowing_type_parameters (
373
- self . ccx . tcx ,
501
+ self . tcx ( ) ,
374
502
method. span ,
375
503
& ty_method. generics ) ;
376
504
}
0 commit comments