@@ -82,10 +82,12 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> {
82
82
fn visit_block ( & mut self , b : & Block , _: ( ) ) {
83
83
gather_loans_in_block ( self , b) ;
84
84
}
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
+
89
91
fn visit_stmt ( & mut self , s : & Stmt , _: ( ) ) {
90
92
visit:: walk_stmt ( self , s, ( ) ) ;
91
93
}
@@ -99,10 +101,20 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> {
99
101
// #7740: Do not visit items here, not even fn items nor methods
100
102
// of impl items; the outer loop in borrowck/mod will visit them
101
103
// 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, ( ) ) ;
103
115
}
104
116
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 )
106
118
-> ( IdRange , Vec < Loan > , move_data:: MoveData ) {
107
119
let mut glcx = GatherLoanCtxt {
108
120
bccx : bccx,
@@ -119,27 +131,6 @@ pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block)
119
131
( id_range, all_loans, move_data)
120
132
}
121
133
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
-
143
134
fn gather_loans_in_block ( this : & mut GatherLoanCtxt ,
144
135
blk : & ast:: Block ) {
145
136
this. id_range . add ( blk. id ) ;
@@ -171,6 +162,28 @@ fn gather_loans_in_local(this: &mut GatherLoanCtxt,
171
162
visit:: walk_local ( this, local, ( ) ) ;
172
163
}
173
164
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
+ }
174
187
175
188
fn gather_loans_in_expr ( this : & mut GatherLoanCtxt ,
176
189
ex : & ast:: Expr ) {
@@ -673,34 +686,45 @@ impl<'a> GatherLoanCtxt<'a> {
673
686
-> Result < ( ) , ( ) > {
674
687
//! Implements the A-* rules in doc.rs.
675
688
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` */
678
692
Ok ( ( ) )
679
693
}
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 ( ( ) )
688
706
}
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.
694
709
Ok ( ( ) )
695
710
}
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 (
698
721
borrow_span,
699
722
BorrowViolation ( loan_cause) ,
700
723
alias_cause) ;
701
- Err ( ( ) )
702
- }
703
- }
724
+ Err ( ( ) )
725
+ }
726
+ ( _, _) => {
727
+ Ok ( ( ) )
704
728
}
705
729
}
706
730
}
0 commit comments