diff options
author | Son Ho | 2022-01-03 09:28:05 +0100 |
---|---|---|
committer | Son Ho | 2022-01-03 09:28:05 +0100 |
commit | 6a70f1467aff300eb2bc83033d8d9c3939448ff8 (patch) | |
tree | 48c4e2f0ec9df6a56a4e935f0ec812a3f269e63b /src | |
parent | 0185ef3957019ba9f150d051cf96c0d66fae371a (diff) |
Add a detailed example in the comments for drop_borrows_loans_at_place
Diffstat (limited to 'src')
-rw-r--r-- | src/Interpreter.ml | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/src/Interpreter.ml b/src/Interpreter.ml index 46b6c2b0..6f26152b 100644 --- a/src/Interpreter.ml +++ b/src/Interpreter.ml @@ -2416,14 +2416,52 @@ let rec drop_borrows_loans_at_lplace (config : C.config) (p : E.place) borrows). Because a loan inside the value may be linked to a borrow somewhere else *also inside* the value (it's possible with adts), we first end all the borrows we find - by using [Inner] to allow - ending inner borrows - then end all the loans we find. It is really - important to do this in two steps: the borrow linked to a loan may - be inside the value at place p, in which case this borrow may be + ending inner borrows - then end all the loans we find. + + It is really important to do this in two steps: the borrow linked to a + loan may be inside the value at place p, in which case this borrow may be an inner borrow that we *can* end, but it may also be outside this value, in which case we need to end all the outer borrows first... Also, whenever the context is updated, we need to re-inspect the value at place p *in two steps* again (end borrows, then end loans). + + Example: + ======= + We want to end the borrows/loans at `*x` in the following environment: + ``` + x -> mut_borrow l0 (mut_loan l1, mut_borrow l1 (Int 3), mut_loan l2) + y -> mut_borrow l2 (Bool true) + ``` + + We have to consider two things: + - the borrow `mut_borrow l1 (Int 3)` borrows a subvalue of `*x` + - the borrow corresponding to the loan `mut_loan l2` is outside of `*x` + + We first end all the *borrows* (not the loans) inside of `*x`, which gives: + ``` + x -> mut_borrow l0 (Int 3, ⊥, mut_loan l2) + y -> mut_borrow l2 (Bool true) + ``` + + Note that when ending the borrows, we can (and have to) ignore the outer + borrows (in this case `mut_borrow l0 ...`). Otherwise, we would have to end + the borrow `l0` which is incorrect (note that we might have to drop the + borrows/loans at `*x` if we evaluate, for instance, `*x = ...`). + It is ok to ignore outer borrows in this case because whenever + we end a borrow, it is an outer borrow locally to `*x` (i.e., we ignore + the outer borrows when accessing `*x`, but once examining the value at + `*x` we never dive into borrows: whenever we find one, we end it - it is thus + an outer borrow, in some way). + + Then, we end the loans at `*x`. Note that as at this point `*x` doesn't + contain borrows (only loans), the borrows corresponding to those loans + are thus necessarily outside of `*x`: we mustn't ignore outer borrows this + time. This gives: + ``` + x -> mut_borrow l0 (Int 3, ⊥, Bool true) + y -> ⊥ + ``` *) let obj = object |