@@ -151,14 +151,13 @@ that the value `(*x).f` may be mutated via the newly created reference
151
151
restrictions `RS` that accompany the loan.
152
152
153
153
The first restriction `((*x).f, [MUTATE, CLAIM, FREEZE])` states that
154
- the lender may not mutate nor freeze `(*x).f`. Mutation is illegal
155
- because `(*x).f` is only supposed to be mutated via the new reference,
156
- not by mutating the original path `(*x).f`. Freezing is
154
+ the lender may not mutate, freeze, nor alias `(*x).f`. Mutation is
155
+ illegal because `(*x).f` is only supposed to be mutated via the new
156
+ reference, not by mutating the original path `(*x).f`. Freezing is
157
157
illegal because the path now has an `&mut` alias; so even if we the
158
158
lender were to consider `(*x).f` to be immutable, it might be mutated
159
- via this alias. Both of these restrictions are temporary. They will be
160
- enforced for the lifetime `'a` of the loan. After the loan expires,
161
- the restrictions no longer apply.
159
+ via this alias. They will be enforced for the lifetime `'a` of the
160
+ loan. After the loan expires, the restrictions no longer apply.
162
161
163
162
The second restriction on `*x` is interesting because it does not
164
163
apply to the path that was lent (`(*x).f`) but rather to a prefix of
@@ -188,11 +187,9 @@ The kinds of expressions which in-scope loans can render illegal are:
188
187
against mutating `lv`;
189
188
- *moves*: illegal if there is any in-scope restriction on `lv` at all;
190
189
- *mutable borrows* (`&mut lv`): illegal there is an in-scope restriction
191
- against mutating `lv` or aliasing `lv`;
190
+ against claiming `lv`;
192
191
- *immutable borrows* (`&lv`): illegal there is an in-scope restriction
193
- against freezing `lv` or aliasing `lv`;
194
- - *read-only borrows* (`&const lv`): illegal there is an in-scope restriction
195
- against aliasing `lv`.
192
+ against freezing `lv`.
196
193
197
194
## Formal rules
198
195
@@ -238,19 +235,23 @@ live. (This is done via restrictions, read on.)
238
235
We start with the `gather_loans` pass, which walks the AST looking for
239
236
borrows. For each borrow, there are three bits of information: the
240
237
lvalue `LV` being borrowed and the mutability `MQ` and lifetime `LT`
241
- of the resulting pointer. Given those, `gather_loans` applies three
238
+ of the resulting pointer. Given those, `gather_loans` applies four
242
239
validity tests:
243
240
244
241
1. `MUTABILITY(LV, MQ)`: The mutability of the reference is
245
242
compatible with the mutability of `LV` (i.e., not borrowing immutable
246
243
data as mutable).
247
244
248
- 2. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed
245
+ 2. `ALIASABLE(LV, MQ)`: The aliasability of the reference is
246
+ compatible with the aliasability of `LV`. The goal is to prevent
247
+ `&mut` borrows of aliasability data.
248
+
249
+ 3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed
249
250
the lifetime of the value being borrowed. This pass is also
250
251
responsible for inserting root annotations to keep managed values
251
252
alive.
252
253
253
- 3 . `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the
254
+ 4 . `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the
254
255
restrictions to maintain memory safety. These are the restrictions
255
256
that will go into the final loan. We'll discuss in more detail below.
256
257
@@ -313,6 +314,47 @@ be borrowed if MQ is immutable or const:
313
314
MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut
314
315
TYPE(LV) = &mut Ty
315
316
317
+ ## Checking aliasability
318
+
319
+ The goal of the aliasability check is to ensure that we never permit
320
+ `&mut` borrows of aliasable data. Formally we define a predicate
321
+ `ALIASABLE(LV, MQ)` which if defined means that
322
+ "borrowing `LV` with mutability `MQ` is ok". The
323
+ Rust code corresponding to this predicate is the function
324
+ `check_aliasability()` in `middle::borrowck::gather_loans`.
325
+
326
+ ### Checking aliasability of variables
327
+
328
+ Local variables are never aliasable as they are accessible only within
329
+ the stack frame.
330
+
331
+ ALIASABLE(X, MQ) // M-Var-Mut
332
+
333
+ ### Checking aliasable of owned content
334
+
335
+ Owned content is aliasable if it is found in an aliasable location:
336
+
337
+ ALIASABLE(LV.f, MQ) // M-Field
338
+ ALIASABLE(LV, MQ)
339
+
340
+ ALIASABLE(*LV, MQ) // M-Deref-Unique
341
+ ALIASABLE(LV, MQ)
342
+
343
+ ### Checking mutability of immutable pointer types
344
+
345
+ Immutable pointer types like `&T` are aliasable, and hence can only be
346
+ borrowed immutably:
347
+
348
+ ALIASABLE(*LV, imm) // M-Deref-Borrowed-Imm
349
+ TYPE(LV) = &Ty
350
+
351
+ ### Checking mutability of mutable pointer types
352
+
353
+ `&mut T` can be frozen, so it is acceptable to borrow it as either imm or mut:
354
+
355
+ ALIASABLE(*LV, MQ) // M-Deref-Borrowed-Mut
356
+ TYPE(LV) = &mut Ty
357
+
316
358
## Checking lifetime
317
359
318
360
These rules aim to ensure that no data is borrowed for a scope that exceeds
0 commit comments