Skip to content

Commit c3b8125

Browse files
committed
Add check for unbounded due to non-regular types in dropck.
(Regression tests are in followup commit.)
1 parent 41f8b1e commit c3b8125

File tree

2 files changed

+85
-10
lines changed

2 files changed

+85
-10
lines changed

src/librustc_typeck/check/dropck.rs

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ use middle::infer;
1414
use middle::region;
1515
use middle::subst;
1616
use middle::ty::{self, Ty};
17-
use util::ppaux::{Repr};
17+
use util::ppaux::{Repr, UserString};
1818

19+
use syntax::ast;
1920
use syntax::codemap::Span;
2021

2122
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>
2829
// types that have been traversed so far by `traverse_type_if_unseen`
2930
let mut breadcrumbs: Vec<Ty<'tcx>> = Vec::new();
3031

31-
iterate_over_potentially_unsafe_regions_in_type(
32+
let result = iterate_over_potentially_unsafe_regions_in_type(
3233
rcx,
3334
&mut breadcrumbs,
35+
TypeContext::Root,
3436
typ,
3537
span,
3638
scope,
3739
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+
}
3893
}
3994

4095
fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
4196
rcx: &mut Rcx<'a, 'tcx>,
4297
breadcrumbs: &mut Vec<Ty<'tcx>>,
98+
context: TypeContext,
4399
ty_root: ty::Ty<'tcx>,
44100
span: Span,
45101
scope: region::CodeExtent,
46-
depth: uint)
102+
depth: uint) -> Result<(), Error<'tcx>>
47103
{
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+
48111
let origin = |&:| infer::SubregionOrigin::SafeDestructor(span);
49112
let mut walker = ty_root.walk();
50113
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>(
240303
struct_did,
241304
field.id,
242305
substs);
243-
iterate_over_potentially_unsafe_regions_in_type(
306+
try!(iterate_over_potentially_unsafe_regions_in_type(
244307
rcx,
245308
breadcrumbs,
309+
TypeContext::Struct {
310+
def_id: struct_did,
311+
field: field.name,
312+
},
246313
field_type,
247314
span,
248315
scope,
249-
depth+1)
316+
depth+1))
250317
}
251318
}
252319

@@ -260,14 +327,19 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
260327
enum_did,
261328
substs);
262329
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(
265332
rcx,
266333
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,
268340
span,
269341
scope,
270-
depth+1)
342+
depth+1));
271343
}
272344
}
273345
}
@@ -290,4 +362,6 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
290362
// is done.
291363
}
292364
}
365+
366+
return Ok(());
293367
}

src/librustc_typeck/diagnostics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ register_diagnostics! {
174174
E0249, // expected constant expr for array length
175175
E0250, // expected constant expr for array length
176176
E0318, // can't create default impls for traits outside their crates
177-
E0319 // trait impls for defaulted traits allowed just for structs/enums
177+
E0319, // trait impls for defaulted traits allowed just for structs/enums
178+
E0320 // recursive overflow during dropck
178179
}
179180

180181
__build_diagnostic_array! { DIAGNOSTICS }

0 commit comments

Comments
 (0)