Skip to content

Commit 7f9953b

Browse files
committed
refactor has_dtor_of_interest
1 parent bfbc7bc commit 7f9953b

File tree

1 file changed

+75
-130
lines changed

1 file changed

+75
-130
lines changed

src/librustc_typeck/check/dropck.rs

Lines changed: 75 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,20 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
258258
debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
259259
typ, scope);
260260

261-
// types that have been traversed so far by `traverse_type_if_unseen`
262-
let mut breadcrumbs: Vec<Ty<'tcx>> = Vec::new();
261+
let parent_scope = rcx.tcx().region_maps.opt_encl_scope(scope).unwrap_or_else(|| {
262+
rcx.tcx().sess.span_bug(
263+
span, &format!("no enclosing scope found for scope: {:?}", scope))
264+
});
263265

264266
let result = iterate_over_potentially_unsafe_regions_in_type(
265-
rcx,
266-
&mut breadcrumbs,
267+
&mut DropckContext {
268+
rcx: rcx,
269+
span: span,
270+
parent_scope: parent_scope,
271+
breadcrumbs: vec![]
272+
},
267273
TypeContext::Root,
268274
typ,
269-
span,
270-
scope,
271275
0);
272276
match result {
273277
Ok(()) => {}
@@ -324,55 +328,49 @@ enum TypeContext {
324328
}
325329
}
326330

327-
// The `depth` counts the number of calls to this function;
328-
// the `xref_depth` counts the subset of such calls that go
329-
// across a `Box<T>` or `PhantomData<T>`.
330-
fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
331-
rcx: &mut Rcx<'a, 'tcx>,
332-
breadcrumbs: &mut Vec<Ty<'tcx>>,
331+
struct DropckContext<'a, 'b: 'a, 'tcx: 'b> {
332+
rcx: &'a mut Rcx<'b, 'tcx>,
333+
/// types that have already been traversed
334+
breadcrumbs: Vec<Ty<'tcx>>,
335+
/// span for error reporting
336+
span: Span,
337+
/// the scope reachable dtorck types must outlive
338+
parent_scope: region::CodeExtent
339+
}
340+
341+
// `context` is used for reporting overflow errors
342+
fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
343+
cx: &mut DropckContext<'a, 'b, 'tcx>,
333344
context: TypeContext,
334345
ty: Ty<'tcx>,
335-
span: Span,
336-
scope: region::CodeExtent,
337346
depth: usize) -> Result<(), Error<'tcx>>
338347
{
348+
let tcx = cx.rcx.tcx();
339349
// Issue #22443: Watch out for overflow. While we are careful to
340350
// handle regular types properly, non-regular ones cause problems.
341-
let recursion_limit = rcx.tcx().sess.recursion_limit.get();
351+
let recursion_limit = tcx.sess.recursion_limit.get();
342352
if depth / 4 >= recursion_limit {
353+
// This can get into rather deep recursion, especially in the
354+
// presence of things like Vec<T> -> Unique<T> -> PhantomData<T> -> T.
355+
// use a higher recursion limit to avoid errors.
343356
return Err(Error::Overflow(context, ty))
344357
}
345358

346-
let opt_phantom_data_def_id = rcx.tcx().lang_items.phantom_data();
359+
let opt_phantom_data_def_id = tcx.lang_items.phantom_data();
347360

348361
// FIXME(arielb1): don't be O(n^2)
349-
if breadcrumbs.contains(&ty) {
362+
if cx.breadcrumbs.contains(&ty) {
350363
debug!("iterate_over_potentially_unsafe_regions_in_type \
351364
{}ty: {} scope: {:?} - cached",
352365
(0..depth).map(|_| ' ').collect::<String>(),
353-
ty, scope);
366+
ty, cx.parent_scope);
354367
return Ok(()); // we already visited this type
355368
}
356-
breadcrumbs.push(ty);
369+
cx.breadcrumbs.push(ty);
357370
debug!("iterate_over_potentially_unsafe_regions_in_type \
358371
{}ty: {} scope: {:?}",
359372
(0..depth).map(|_| ' ').collect::<String>(),
360-
ty, scope);
361-
362-
// FIXME(arielb1): move into has_dtor_of_interest
363-
let dtor_kind = match ty.sty {
364-
ty::TyEnum(def_id, _) |
365-
ty::TyStruct(def_id, _) => {
366-
let destructor_for_type = rcx.tcx().destructor_for_type.borrow();
367-
match destructor_for_type.get(&def_id) {
368-
Some(def_id) => DtorKind::KnownDropMethod(*def_id),
369-
None => DtorKind::PureRecur,
370-
}
371-
}
372-
ty::TyTrait(..) | ty::TyProjection(..) => DtorKind::Unknown,
373-
_ => DtorKind::PureRecur,
374-
};
375-
373+
ty, cx.parent_scope);
376374

377375
// If `typ` has a destructor, then we must ensure that all
378376
// borrowed data reachable via `typ` must outlive the parent
@@ -402,38 +400,24 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
402400
// type parameters are unbounded. If both conditions hold, we
403401
// simply skip the `type_must_outlive` call entirely (but
404402
// resume the recursive checking of the type-substructure).
405-
if has_dtor_of_interest(rcx.tcx(), dtor_kind, ty, span) {
403+
if has_dtor_of_interest(tcx, ty, cx.span) {
406404
debug!("iterate_over_potentially_unsafe_regions_in_type \
407405
{}ty: {} - is a dtorck type!",
408406
(0..depth).map(|_| ' ').collect::<String>(),
409407
ty);
410408

411-
// If `ty` is a dtorck type, then we must ensure that all
412-
// borrowed data reachable via `ty` must outlive the
413-
// parent of `scope`. (It does not suffice for it to
414-
// outlive `scope` because that could imply that the
415-
// borrowed data is torn down in between the end of
416-
// `scope` and when the destructor itself actually runs.)
417-
let parent_region =
418-
match rcx.tcx().region_maps.opt_encl_scope(scope) {
419-
Some(parent_scope) => ty::ReScope(parent_scope),
420-
None => rcx.tcx().sess.span_bug(
421-
span, &format!("no enclosing scope found for scope: {:?}",
422-
scope)),
423-
};
424-
425-
regionck::type_must_outlive(rcx,
426-
infer::SubregionOrigin::SafeDestructor(span),
409+
regionck::type_must_outlive(cx.rcx,
410+
infer::SubregionOrigin::SafeDestructor(cx.span),
427411
ty,
428-
parent_region);
412+
ty::ReScope(cx.parent_scope));
429413

430414
return Ok(());
431415
}
432416

433417
debug!("iterate_over_potentially_unsafe_regions_in_type \
434418
{}ty: {} scope: {:?} - checking interior",
435419
(0..depth).map(|_| ' ').collect::<String>(),
436-
ty, scope);
420+
ty, cx.parent_scope);
437421

438422
// We still need to ensure all referenced data is safe.
439423
match ty.sty {
@@ -446,55 +430,48 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
446430
ty::TyBox(ity) | ty::TyArray(ity, _) | ty::TySlice(ity) => {
447431
// single-element containers, behave like their element
448432
iterate_over_potentially_unsafe_regions_in_type(
449-
rcx, breadcrumbs, context, ity, span, scope, depth+1)
433+
cx, context, ity, depth+1)
450434
}
451435

452436
ty::TyStruct(did, substs) if Some(did) == opt_phantom_data_def_id => {
453437
// PhantomData<T> - behaves identically to T
454438
let ity = *substs.types.get(subst::TypeSpace, 0);
455439
iterate_over_potentially_unsafe_regions_in_type(
456-
rcx, breadcrumbs, context, ity, span, scope, depth+1)
440+
cx, context, ity, depth+1)
457441
}
458442

459443
ty::TyStruct(did, substs) => {
460-
let fields = rcx.tcx().lookup_struct_fields(did);
444+
let fields = tcx.lookup_struct_fields(did);
461445
for field in &fields {
462-
let field_type = rcx.tcx().lookup_field_type(did,
463-
field.id,
464-
substs);
446+
let fty = tcx.lookup_field_type(did, field.id, substs);
447+
let fty = cx.rcx.fcx.resolve_type_vars_if_possible(
448+
cx.rcx.fcx.normalize_associated_types_in(cx.span, &fty));
465449
try!(iterate_over_potentially_unsafe_regions_in_type(
466-
rcx,
467-
breadcrumbs,
450+
cx,
468451
TypeContext::Struct {
469452
def_id: did,
470453
field: field.name,
471454
},
472-
rcx.fcx.resolve_type_vars_if_possible(
473-
rcx.fcx.normalize_associated_types_in(span, &field_type)),
474-
span,
475-
scope,
455+
fty,
476456
depth+1))
477457
}
478458
Ok(())
479459
}
480460

481461
ty::TyEnum(did, substs) => {
482-
let all_variant_info =
483-
rcx.tcx().substd_enum_variants(did, substs);
462+
let all_variant_info = tcx.substd_enum_variants(did, substs);
484463
for variant_info in &all_variant_info {
485-
for (i, arg_type) in variant_info.args.iter().enumerate() {
464+
for (i, fty) in variant_info.args.iter().enumerate() {
465+
let fty = cx.rcx.fcx.resolve_type_vars_if_possible(
466+
cx.rcx.fcx.normalize_associated_types_in(cx.span, &fty));
486467
try!(iterate_over_potentially_unsafe_regions_in_type(
487-
rcx,
488-
breadcrumbs,
468+
cx,
489469
TypeContext::EnumVariant {
490470
def_id: did,
491471
variant: variant_info.name,
492472
arg_index: i,
493473
},
494-
rcx.fcx.resolve_type_vars_if_possible(
495-
rcx.fcx.normalize_associated_types_in(span, arg_type)),
496-
span,
497-
scope,
474+
fty,
498475
depth+1));
499476
}
500477
}
@@ -505,7 +482,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
505482
ty::TyClosure(_, box ty::ClosureSubsts { upvar_tys: ref tys, .. }) => {
506483
for ty in tys {
507484
try!(iterate_over_potentially_unsafe_regions_in_type(
508-
rcx, breadcrumbs, context, ty, span, scope, depth+1))
485+
cx, context, ty, depth+1))
509486
}
510487
Ok(())
511488
}
@@ -524,7 +501,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
524501
}
525502

526503
ty::TyInfer(..) | ty::TyError => {
527-
rcx.tcx().sess.delay_span_bug(span, "unresolved type in regionck");
504+
tcx.sess.delay_span_bug(cx.span, "unresolved type in regionck");
528505
Ok(())
529506
}
530507

@@ -533,53 +510,18 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
533510
}
534511
}
535512

536-
enum DtorKind {
537-
// Type has an associated drop method with this def id
538-
KnownDropMethod(ast::DefId),
539-
540-
// Type has no destructor (or its dtor is known to be pure
541-
// with respect to lifetimes), though its *substructure*
542-
// may carry a destructor.
543-
PureRecur,
544-
545-
// Type may have impure destructor that is unknown;
546-
// e.g. `Box<Trait+'a>`
547-
Unknown,
548-
}
549-
550513
fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
551-
dtor_kind: DtorKind,
552-
typ: ty::Ty<'tcx>,
514+
ty: ty::Ty<'tcx>,
553515
span: Span) -> bool {
554-
let has_dtor_of_interest: bool;
555-
556-
match dtor_kind {
557-
DtorKind::PureRecur => {
558-
has_dtor_of_interest = false;
559-
debug!("typ: {:?} has no dtor, and thus is uninteresting",
560-
typ);
561-
}
562-
DtorKind::Unknown => {
563-
debug!("trait: {:?} is interesting", typ);
564-
has_dtor_of_interest = true;
565-
/*
566-
match bounds.region_bound {
567-
ty::ReStatic => {
568-
debug!("trait: {:?} has 'static bound, and thus is uninteresting",
569-
typ);
570-
has_dtor_of_interest = false;
571-
}
572-
ty::ReEmpty => {
573-
debug!("trait: {:?} has empty region bound, and thus is uninteresting",
574-
typ);
575-
has_dtor_of_interest = false;
576-
}
577-
r => {
516+
match ty.sty {
517+
ty::TyEnum(def_id, _) | ty::TyStruct(def_id, _) => {
518+
let dtor_method_did = match tcx.destructor_for_type.borrow().get(&def_id) {
519+
Some(def_id) => *def_id,
520+
None => {
521+
debug!("ty: {:?} has no dtor, and thus isn't a dropck type", ty);
522+
return false;
578523
}
579-
}
580-
*/
581-
}
582-
DtorKind::KnownDropMethod(dtor_method_did) => {
524+
};
583525
let impl_did = tcx.impl_of_method(dtor_method_did)
584526
.unwrap_or_else(|| {
585527
tcx.sess.span_bug(
@@ -631,8 +573,8 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
631573

632574
if result {
633575
has_pred_of_interest = true;
634-
debug!("typ: {:?} has interesting dtor due to generic preds, e.g. {:?}",
635-
typ, pred);
576+
debug!("ty: {:?} has interesting dtor due to generic preds, e.g. {:?}",
577+
ty, pred);
636578
break 'items;
637579
}
638580
}
@@ -651,22 +593,25 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
651593
let has_region_param_of_interest =
652594
dtor_generics.has_region_params(subst::TypeSpace);
653595

654-
has_dtor_of_interest =
596+
let has_dtor_of_interest =
655597
has_region_param_of_interest ||
656598
has_pred_of_interest;
657599

658600
if has_dtor_of_interest {
659-
debug!("typ: {:?} has interesting dtor, due to \
601+
debug!("ty: {:?} has interesting dtor, due to \
660602
region params: {} or pred: {}",
661-
typ,
603+
ty,
662604
has_region_param_of_interest,
663605
has_pred_of_interest);
664606
} else {
665-
debug!("typ: {:?} has dtor, but it is uninteresting",
666-
typ);
607+
debug!("ty: {:?} has dtor, but it is uninteresting", ty);
667608
}
609+
has_dtor_of_interest
668610
}
611+
ty::TyTrait(..) | ty::TyProjection(..) => {
612+
debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
613+
true
614+
},
615+
_ => false
669616
}
670-
671-
return has_dtor_of_interest;
672617
}

0 commit comments

Comments
 (0)