@@ -258,16 +258,20 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
258
258
debug ! ( "check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}" ,
259
259
typ, scope) ;
260
260
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
+ } ) ;
263
265
264
266
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
+ } ,
267
273
TypeContext :: Root ,
268
274
typ,
269
- span,
270
- scope,
271
275
0 ) ;
272
276
match result {
273
277
Ok ( ( ) ) => { }
@@ -324,55 +328,49 @@ enum TypeContext {
324
328
}
325
329
}
326
330
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 > ,
333
344
context : TypeContext ,
334
345
ty : Ty < ' tcx > ,
335
- span : Span ,
336
- scope : region:: CodeExtent ,
337
346
depth : usize ) -> Result < ( ) , Error < ' tcx > >
338
347
{
348
+ let tcx = cx. rcx . tcx ( ) ;
339
349
// Issue #22443: Watch out for overflow. While we are careful to
340
350
// 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 ( ) ;
342
352
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.
343
356
return Err ( Error :: Overflow ( context, ty) )
344
357
}
345
358
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 ( ) ;
347
360
348
361
// FIXME(arielb1): don't be O(n^2)
349
- if breadcrumbs. contains ( & ty) {
362
+ if cx . breadcrumbs . contains ( & ty) {
350
363
debug ! ( "iterate_over_potentially_unsafe_regions_in_type \
351
364
{}ty: {} scope: {:?} - cached",
352
365
( 0 ..depth) . map( |_| ' ' ) . collect:: <String >( ) ,
353
- ty, scope ) ;
366
+ ty, cx . parent_scope ) ;
354
367
return Ok ( ( ) ) ; // we already visited this type
355
368
}
356
- breadcrumbs. push ( ty) ;
369
+ cx . breadcrumbs . push ( ty) ;
357
370
debug ! ( "iterate_over_potentially_unsafe_regions_in_type \
358
371
{}ty: {} scope: {:?}",
359
372
( 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) ;
376
374
377
375
// If `typ` has a destructor, then we must ensure that all
378
376
// borrowed data reachable via `typ` must outlive the parent
@@ -402,38 +400,24 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
402
400
// type parameters are unbounded. If both conditions hold, we
403
401
// simply skip the `type_must_outlive` call entirely (but
404
402
// 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 ) {
406
404
debug ! ( "iterate_over_potentially_unsafe_regions_in_type \
407
405
{}ty: {} - is a dtorck type!",
408
406
( 0 ..depth) . map( |_| ' ' ) . collect:: <String >( ) ,
409
407
ty) ;
410
408
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 ) ,
427
411
ty,
428
- parent_region ) ;
412
+ ty :: ReScope ( cx . parent_scope ) ) ;
429
413
430
414
return Ok ( ( ) ) ;
431
415
}
432
416
433
417
debug ! ( "iterate_over_potentially_unsafe_regions_in_type \
434
418
{}ty: {} scope: {:?} - checking interior",
435
419
( 0 ..depth) . map( |_| ' ' ) . collect:: <String >( ) ,
436
- ty, scope ) ;
420
+ ty, cx . parent_scope ) ;
437
421
438
422
// We still need to ensure all referenced data is safe.
439
423
match ty. sty {
@@ -446,55 +430,48 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
446
430
ty:: TyBox ( ity) | ty:: TyArray ( ity, _) | ty:: TySlice ( ity) => {
447
431
// single-element containers, behave like their element
448
432
iterate_over_potentially_unsafe_regions_in_type (
449
- rcx , breadcrumbs , context, ity, span , scope , depth+1 )
433
+ cx , context, ity, depth+1 )
450
434
}
451
435
452
436
ty:: TyStruct ( did, substs) if Some ( did) == opt_phantom_data_def_id => {
453
437
// PhantomData<T> - behaves identically to T
454
438
let ity = * substs. types . get ( subst:: TypeSpace , 0 ) ;
455
439
iterate_over_potentially_unsafe_regions_in_type (
456
- rcx , breadcrumbs , context, ity, span , scope , depth+1 )
440
+ cx , context, ity, depth+1 )
457
441
}
458
442
459
443
ty:: TyStruct ( did, substs) => {
460
- let fields = rcx . tcx ( ) . lookup_struct_fields ( did) ;
444
+ let fields = tcx. lookup_struct_fields ( did) ;
461
445
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 ) ) ;
465
449
try!( iterate_over_potentially_unsafe_regions_in_type (
466
- rcx,
467
- breadcrumbs,
450
+ cx,
468
451
TypeContext :: Struct {
469
452
def_id : did,
470
453
field : field. name ,
471
454
} ,
472
- rcx. fcx . resolve_type_vars_if_possible (
473
- rcx. fcx . normalize_associated_types_in ( span, & field_type) ) ,
474
- span,
475
- scope,
455
+ fty,
476
456
depth+1 ) )
477
457
}
478
458
Ok ( ( ) )
479
459
}
480
460
481
461
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) ;
484
463
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) ) ;
486
467
try!( iterate_over_potentially_unsafe_regions_in_type (
487
- rcx,
488
- breadcrumbs,
468
+ cx,
489
469
TypeContext :: EnumVariant {
490
470
def_id : did,
491
471
variant : variant_info. name ,
492
472
arg_index : i,
493
473
} ,
494
- rcx. fcx . resolve_type_vars_if_possible (
495
- rcx. fcx . normalize_associated_types_in ( span, arg_type) ) ,
496
- span,
497
- scope,
474
+ fty,
498
475
depth+1 ) ) ;
499
476
}
500
477
}
@@ -505,7 +482,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
505
482
ty:: TyClosure ( _, box ty:: ClosureSubsts { upvar_tys : ref tys, .. } ) => {
506
483
for ty in tys {
507
484
try!( iterate_over_potentially_unsafe_regions_in_type (
508
- rcx , breadcrumbs , context, ty, span , scope , depth+1 ) )
485
+ cx , context, ty, depth+1 ) )
509
486
}
510
487
Ok ( ( ) )
511
488
}
@@ -524,7 +501,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
524
501
}
525
502
526
503
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" ) ;
528
505
Ok ( ( ) )
529
506
}
530
507
@@ -533,53 +510,18 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
533
510
}
534
511
}
535
512
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
-
550
513
fn has_dtor_of_interest < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
551
- dtor_kind : DtorKind ,
552
- typ : ty:: Ty < ' tcx > ,
514
+ ty : ty:: Ty < ' tcx > ,
553
515
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 ;
578
523
}
579
- }
580
- */
581
- }
582
- DtorKind :: KnownDropMethod ( dtor_method_did) => {
524
+ } ;
583
525
let impl_did = tcx. impl_of_method ( dtor_method_did)
584
526
. unwrap_or_else ( || {
585
527
tcx. sess . span_bug (
@@ -631,8 +573,8 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
631
573
632
574
if result {
633
575
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) ;
636
578
break ' items;
637
579
}
638
580
}
@@ -651,22 +593,25 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
651
593
let has_region_param_of_interest =
652
594
dtor_generics. has_region_params ( subst:: TypeSpace ) ;
653
595
654
- has_dtor_of_interest =
596
+ let has_dtor_of_interest =
655
597
has_region_param_of_interest ||
656
598
has_pred_of_interest;
657
599
658
600
if has_dtor_of_interest {
659
- debug ! ( "typ : {:?} has interesting dtor, due to \
601
+ debug ! ( "ty : {:?} has interesting dtor, due to \
660
602
region params: {} or pred: {}",
661
- typ ,
603
+ ty ,
662
604
has_region_param_of_interest,
663
605
has_pred_of_interest) ;
664
606
} else {
665
- debug ! ( "typ: {:?} has dtor, but it is uninteresting" ,
666
- typ) ;
607
+ debug ! ( "ty: {:?} has dtor, but it is uninteresting" , ty) ;
667
608
}
609
+ has_dtor_of_interest
668
610
}
611
+ ty:: TyTrait ( ..) | ty:: TyProjection ( ..) => {
612
+ debug ! ( "ty: {:?} isn't known, and therefore is a dropck type" , ty) ;
613
+ true
614
+ } ,
615
+ _ => false
669
616
}
670
-
671
- return has_dtor_of_interest;
672
617
}
0 commit comments