@@ -82,10 +82,12 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> {
8282 fn visit_block ( & mut self , b : & Block , _: ( ) ) {
8383 gather_loans_in_block ( self , b) ;
8484 }
85- fn visit_fn ( & mut self , fk : & FnKind , fd : & FnDecl , b : & Block ,
86- s : Span , n : NodeId , _: ( ) ) {
87- gather_loans_in_fn ( self , fk, fd, b, s, n) ;
88- }
85+
86+ /// Do not visit closures or fn items here, the outer loop in
87+ /// borrowck/mod will visit them for us in turn.
88+ fn visit_fn ( & mut self , _: & FnKind , _: & FnDecl , _: & Block ,
89+ _: Span , _: NodeId , _: ( ) ) { }
90+
8991 fn visit_stmt ( & mut self , s : & Stmt , _: ( ) ) {
9092 visit:: walk_stmt ( self , s, ( ) ) ;
9193 }
@@ -99,10 +101,20 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> {
99101 // #7740: Do not visit items here, not even fn items nor methods
100102 // of impl items; the outer loop in borrowck/mod will visit them
101103 // for us in turn. Thus override visit_item's walk with a no-op.
102- fn visit_item ( & mut self , _: & ast:: Item , _: ( ) ) { }
104+ fn visit_item ( & mut self , _: & ast:: Item , _: ( ) ) { }
105+ }
106+
107+ fn add_pat_to_id_range ( this : & mut GatherLoanCtxt ,
108+ p : & ast:: Pat ) {
109+ // NB: This visitor function just adds the pat ids into the id
110+ // range. We gather loans that occur in patterns using the
111+ // `gather_pat()` method below. Eventually these two should be
112+ // brought together.
113+ this. id_range . add ( p. id ) ;
114+ visit:: walk_pat ( this, p, ( ) ) ;
103115}
104116
105- pub fn gather_loans ( bccx : & BorrowckCtxt , decl : & ast:: FnDecl , body : & ast:: Block )
117+ pub fn gather_loans_in_fn ( bccx : & BorrowckCtxt , decl : & ast:: FnDecl , body : & ast:: Block )
106118 -> ( IdRange , Vec < Loan > , move_data:: MoveData ) {
107119 let mut glcx = GatherLoanCtxt {
108120 bccx : bccx,
@@ -119,27 +131,6 @@ pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block)
119131 ( id_range, all_loans, move_data)
120132}
121133
122- fn add_pat_to_id_range ( this : & mut GatherLoanCtxt ,
123- p : & ast:: Pat ) {
124- // NB: This visitor function just adds the pat ids into the id
125- // range. We gather loans that occur in patterns using the
126- // `gather_pat()` method below. Eventually these two should be
127- // brought together.
128- this. id_range . add ( p. id ) ;
129- visit:: walk_pat ( this, p, ( ) ) ;
130- }
131-
132- fn gather_loans_in_fn ( _v : & mut GatherLoanCtxt ,
133- _fk : & FnKind ,
134- _decl : & ast:: FnDecl ,
135- _body : & ast:: Block ,
136- _sp : Span ,
137- _id : ast:: NodeId ) {
138- // Do not visit closures or fn items here, the outer loop in
139- // borrowck/mod will visit them for us in turn.
140- return ;
141- }
142-
143134fn gather_loans_in_block ( this : & mut GatherLoanCtxt ,
144135 blk : & ast:: Block ) {
145136 this. id_range . add ( blk. id ) ;
@@ -171,6 +162,28 @@ fn gather_loans_in_local(this: &mut GatherLoanCtxt,
171162 visit:: walk_local ( this, local, ( ) ) ;
172163}
173164
165+ pub fn gather_loans_in_static_initializer ( bccx : & mut BorrowckCtxt , expr : & ast:: Expr ) {
166+
167+ debug ! ( "gather_loans_in_item(expr={})" , expr. repr( bccx. tcx) ) ;
168+
169+ let mut glcx = GatherLoanCtxt {
170+ bccx : bccx,
171+ id_range : IdRange :: max ( ) ,
172+ all_loans : Vec :: new ( ) ,
173+ item_ub : expr. id ,
174+ repeating_ids : vec ! ( expr. id) ,
175+ move_data : MoveData :: new ( )
176+ } ;
177+
178+ // FIXME #13005 This should also walk the
179+ // expression.
180+ match expr. node {
181+ ast:: ExprAddrOf ( ..) => {
182+ glcx. visit_expr ( expr, ( ) ) ;
183+ }
184+ _ => { }
185+ }
186+ }
174187
175188fn gather_loans_in_expr ( this : & mut GatherLoanCtxt ,
176189 ex : & ast:: Expr ) {
@@ -673,34 +686,45 @@ impl<'a> GatherLoanCtxt<'a> {
673686 -> Result < ( ) , ( ) > {
674687 //! Implements the A-* rules in doc.rs.
675688
676- match req_kind {
677- ty:: ImmBorrow => {
689+ match ( cmt. freely_aliasable ( bccx. tcx ) , req_kind) {
690+ ( None , _) => {
691+ /* Uniquely accessible path -- OK for `&` and `&mut` */
678692 Ok ( ( ) )
679693 }
680-
681- ty:: UniqueImmBorrow | ty:: MutBorrow => {
682- // Check for those cases where we cannot control
683- // the aliasing and make sure that we are not
684- // being asked to.
685- match cmt. freely_aliasable ( ) {
686- None => {
687- Ok ( ( ) )
694+ ( Some ( mc:: AliasableStatic ( safety) ) , ty:: ImmBorrow ) => {
695+ // Borrow of an immutable static item:
696+ match safety {
697+ mc:: InteriorUnsafe => {
698+ // If the static item contains an Unsafe<T>, it has interior mutability.
699+ // In such cases, we cannot permit it to be borrowed, because the
700+ // static item resides in immutable memory and mutating it would
701+ // cause segfaults.
702+ bccx. tcx . sess . span_err ( borrow_span,
703+ format ! ( "borrow of immutable static items with \
704+ unsafe interior is not allowed") ) ;
705+ Err ( ( ) )
688706 }
689- Some ( mc:: AliasableStaticMut ) => {
690- // This is nasty, but we ignore the
691- // aliasing rules if the data is based in
692- // a `static mut`, since those are always
693- // unsafe. At your own peril and all that.
707+ mc:: InteriorSafe => {
708+ // Immutable static can be borrowed, no problem.
694709 Ok ( ( ) )
695710 }
696- Some ( alias_cause) => {
697- bccx. report_aliasability_violation (
711+ }
712+ }
713+ ( Some ( mc:: AliasableStaticMut ( ..) ) , _) => {
714+ // Even touching a static mut is considered unsafe. We assume the
715+ // user knows what they're doing in these cases.
716+ Ok ( ( ) )
717+ }
718+ ( Some ( alias_cause) , ty:: UniqueImmBorrow ) |
719+ ( Some ( alias_cause) , ty:: MutBorrow ) => {
720+ bccx. report_aliasability_violation (
698721 borrow_span,
699722 BorrowViolation ( loan_cause) ,
700723 alias_cause) ;
701- Err ( ( ) )
702- }
703- }
724+ Err ( ( ) )
725+ }
726+ ( _, _) => {
727+ Ok ( ( ) )
704728 }
705729 }
706730 }
0 commit comments