@@ -14,8 +14,9 @@ use middle::infer;
14
14
use middle:: region;
15
15
use middle:: subst;
16
16
use middle:: ty:: { self , Ty } ;
17
- use util:: ppaux:: { Repr } ;
17
+ use util:: ppaux:: { Repr , UserString } ;
18
18
19
+ use syntax:: ast;
19
20
use syntax:: codemap:: Span ;
20
21
21
22
pub fn check_safety_of_destructor_if_necessary < ' a , ' tcx > ( rcx : & mut Rcx < ' a , ' tcx > ,
@@ -28,23 +29,85 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
28
29
// types that have been traversed so far by `traverse_type_if_unseen`
29
30
let mut breadcrumbs: Vec < Ty < ' tcx > > = Vec :: new ( ) ;
30
31
31
- iterate_over_potentially_unsafe_regions_in_type (
32
+ let result = iterate_over_potentially_unsafe_regions_in_type (
32
33
rcx,
33
34
& mut breadcrumbs,
35
+ TypeContext :: Root ,
34
36
typ,
35
37
span,
36
38
scope,
37
39
0 ) ;
40
+ match result {
41
+ Ok ( ( ) ) => { }
42
+ Err ( Error :: Overflow ( ref ctxt, ref detected_on_typ) ) => {
43
+ let tcx = rcx. tcx ( ) ;
44
+ span_err ! ( tcx. sess, span, E0320 ,
45
+ "overflow while adding drop-check rules for {}" ,
46
+ typ. user_string( rcx. tcx( ) ) ) ;
47
+ match * ctxt {
48
+ TypeContext :: Root => {
49
+ // no need for an additional note if the overflow
50
+ // was somehow on the root.
51
+ }
52
+ TypeContext :: EnumVariant { def_id, variant, arg_index } => {
53
+ // FIXME (pnkfelix): eventually lookup arg_name
54
+ // for the given index on struct variants.
55
+ span_note ! (
56
+ rcx. tcx( ) . sess,
57
+ span,
58
+ "overflowed on enum {} variant {} argument {} type: {}" ,
59
+ ty:: item_path_str( tcx, def_id) ,
60
+ variant,
61
+ arg_index,
62
+ detected_on_typ. user_string( rcx. tcx( ) ) ) ;
63
+ }
64
+ TypeContext :: Struct { def_id, field } => {
65
+ span_note ! (
66
+ rcx. tcx( ) . sess,
67
+ span,
68
+ "overflowed on struct {} field {} type: {}" ,
69
+ ty:: item_path_str( tcx, def_id) ,
70
+ field,
71
+ detected_on_typ. user_string( rcx. tcx( ) ) ) ;
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+
78
+ enum Error < ' tcx > {
79
+ Overflow ( TypeContext , ty:: Ty < ' tcx > ) ,
80
+ }
81
+
82
+ enum TypeContext {
83
+ Root ,
84
+ EnumVariant {
85
+ def_id : ast:: DefId ,
86
+ variant : ast:: Name ,
87
+ arg_index : usize ,
88
+ } ,
89
+ Struct {
90
+ def_id : ast:: DefId ,
91
+ field : ast:: Name ,
92
+ }
38
93
}
39
94
40
95
fn iterate_over_potentially_unsafe_regions_in_type < ' a , ' tcx > (
41
96
rcx : & mut Rcx < ' a , ' tcx > ,
42
97
breadcrumbs : & mut Vec < Ty < ' tcx > > ,
98
+ context : TypeContext ,
43
99
ty_root : ty:: Ty < ' tcx > ,
44
100
span : Span ,
45
101
scope : region:: CodeExtent ,
46
- depth : uint )
102
+ depth : uint ) -> Result < ( ) , Error < ' tcx > >
47
103
{
104
+ // Issue #22443: Watch out for overflow. While we are careful to
105
+ // handle regular types properly, non-regular ones cause problems.
106
+ let recursion_limit = rcx. tcx ( ) . sess . recursion_limit . get ( ) ;
107
+ if depth >= recursion_limit {
108
+ return Err ( Error :: Overflow ( context, ty_root) )
109
+ }
110
+
48
111
let origin = |& : | infer:: SubregionOrigin :: SafeDestructor ( span) ;
49
112
let mut walker = ty_root. walk ( ) ;
50
113
let opt_phantom_data_def_id = rcx. tcx ( ) . lang_items . phantom_data ( ) ;
@@ -240,13 +303,17 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
240
303
struct_did,
241
304
field. id ,
242
305
substs) ;
243
- iterate_over_potentially_unsafe_regions_in_type (
306
+ try! ( iterate_over_potentially_unsafe_regions_in_type (
244
307
rcx,
245
308
breadcrumbs,
309
+ TypeContext :: Struct {
310
+ def_id : struct_did,
311
+ field : field. name ,
312
+ } ,
246
313
field_type,
247
314
span,
248
315
scope,
249
- depth+1 )
316
+ depth+1 ) )
250
317
}
251
318
}
252
319
@@ -260,14 +327,19 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
260
327
enum_did,
261
328
substs) ;
262
329
for variant_info in all_variant_info. iter ( ) {
263
- for argument_type in variant_info. args . iter ( ) {
264
- iterate_over_potentially_unsafe_regions_in_type (
330
+ for ( i , arg_type ) in variant_info. args . iter ( ) . enumerate ( ) {
331
+ try! ( iterate_over_potentially_unsafe_regions_in_type (
265
332
rcx,
266
333
breadcrumbs,
267
- * argument_type,
334
+ TypeContext :: EnumVariant {
335
+ def_id : enum_did,
336
+ variant : variant_info. name ,
337
+ arg_index : i,
338
+ } ,
339
+ * arg_type,
268
340
span,
269
341
scope,
270
- depth+1 )
342
+ depth+1 ) ) ;
271
343
}
272
344
}
273
345
}
@@ -290,4 +362,6 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
290
362
// is done.
291
363
}
292
364
}
365
+
366
+ return Ok ( ( ) ) ;
293
367
}
0 commit comments