@@ -30,58 +30,57 @@ fn place_context<'a, 'tcx, D>(
3030) -> ( Option < region:: Scope > , hir:: Mutability )
3131 where D : HasLocalDecls < ' tcx >
3232{
33- if let ( base_place, Some ( projection) ) = place. final_projection ( tcx) {
34- match projection {
35- ProjectionElem :: Deref => {
36- // Computing the inside the recursion makes this quadratic.
37- // We don't expect deep paths though.
38- let ty = base_place. ty ( local_decls, tcx) . to_ty ( tcx) ;
39- // A Deref projection may restrict the context, this depends on the type
40- // being deref'd.
41- let context = match ty. sty {
42- ty:: TyRef ( re, _, mutbl) => {
43- let re = match re {
44- & RegionKind :: ReScope ( ce) => Some ( ce) ,
45- & RegionKind :: ReErased =>
46- bug ! ( "AddValidation pass must be run before erasing lifetimes" ) ,
47- _ => None
48- } ;
49- ( re, mutbl)
33+ let mut place_context = match place. base {
34+ PlaceBase :: Local { .. } => ( None , hir:: MutMutable ) ,
35+ PlaceBase :: Promoted ( _)
36+ | PlaceBase :: Static ( _) => ( None , hir:: MutImmutable ) ,
37+ } ;
38+
39+ if !place. has_no_projection ( ) {
40+ let mut base_ty = place. base . ty ( local_decls) ;
41+ let mut base_context = place_context;
42+ for elem in place. elems . iter ( ) {
43+ match elem {
44+ ProjectionElem :: Deref => {
45+ // A Deref projection may restrict the context, this depends on the type
46+ // being deref'd.
47+ place_context = match base_ty. sty {
48+ ty:: TyRef ( re, _, mutbl) => {
49+ let re = match re {
50+ & RegionKind :: ReScope ( ce) => Some ( ce) ,
51+ & RegionKind :: ReErased =>
52+ bug ! ( "AddValidation pass must be run before erasing lifetimes" ) ,
53+ _ => None
54+ } ;
55+ ( re, mutbl)
56+ }
57+ ty:: TyRawPtr ( _) =>
58+ // There is no guarantee behind even a mutable raw pointer,
59+ // no write locks are acquired there, so we also don't want to
60+ // release any.
61+ ( None , hir:: MutImmutable ) ,
62+ ty:: TyAdt ( adt, _) if adt. is_box ( ) => ( None , hir:: MutMutable ) ,
63+ _ => bug ! ( "Deref on a non-pointer type {:?}" , base_ty) ,
64+ } ;
65+ // "Intersect" this restriction with proj.base.
66+ if let ( Some ( _) , hir:: MutImmutable ) = place_context {
67+ // This is already as restricted as it gets, no need to even recurse
68+ } else {
69+ let re = place_context. 0 . or ( base_context. 0 ) ;
70+ let mutbl = place_context. 1 . and ( base_context. 1 ) ;
71+ place_context = ( re, mutbl) ;
5072 }
51- ty:: TyRawPtr ( _) =>
52- // There is no guarantee behind even a mutable raw pointer,
53- // no write locks are acquired there, so we also don't want to
54- // release any.
55- ( None , hir:: MutImmutable ) ,
56- ty:: TyAdt ( adt, _) if adt. is_box ( ) => ( None , hir:: MutMutable ) ,
57- _ => bug ! ( "Deref on a non-pointer type {:?}" , ty) ,
58- } ;
59- // "Intersect" this restriction with proj.base.
60- if let ( Some ( _) , hir:: MutImmutable ) = context {
61- // This is already as restricted as it gets, no need to even recurse
62- context
63- } else {
64- let base_context = place_context ( & place. projection_base ( tcx) , local_decls, tcx) ;
65- // The region of the outermost Deref is always most restrictive.
66- let re = context. 0 . or ( base_context. 0 ) ;
67- let mutbl = context. 1 . and ( base_context. 1 ) ;
68- ( re, mutbl)
69- }
70- } ,
71- _ => place_context ( & base_place, local_decls, tcx) ,
72- }
73- } else {
74- match place. base {
75- PlaceBase :: Local { .. } => ( None , hir:: MutMutable ) ,
76- PlaceBase :: Promoted ( _)
77- | PlaceBase :: Static ( _) => ( None , hir:: MutImmutable ) ,
73+
74+ } ,
75+ _ => { } ,
76+ }
77+ base_ty = tcx:: PlaceTy :: from ( base_ty)
78+ . projection_ty ( tcx, elem)
79+ . to_ty ( tcx) ;
80+ base_context = place_context;
7881 }
7982 }
80- // let mut place_context = match place.base {
81- // PlaceBase::Local { .. } => (None, hir::MutMutable),
82- // PlaceBase::Promoted(_)
83- // | PlaceBase::Static(_) => (None, hir::MutImmutable),
84- // };
83+ place_context
8584}
8685
8786/// Check if this function contains an unsafe block or is an unsafe function.
0 commit comments