@@ -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-
550513fn 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