You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/0000-immovable-types.md
+2-42Lines changed: 2 additions & 42 deletions
Original file line number
Diff line number
Diff line change
@@ -30,49 +30,9 @@ You can freely move values which are known to implement `Move` after they are bo
30
30
31
31
Static variables allow types which do not implement `Move`.
32
32
33
-
## Borrowing immovable types
33
+
## Move checking
34
34
35
-
Borrowing values of types which do not implement `Move` is only allowed if the borrows lasts for the entire lifetime of the values, including the drop of the value, since `drop` takes a reference to it. Reborrows of such borrows follow existing rules.
36
-
37
-
This means that the following borrow would not be allowed:
38
-
```rust
39
-
letmutex=StaticMutex::new(0);
40
-
{
41
-
*mutex.lock() +=1;
42
-
}
43
-
letmoved=mutex;
44
-
*moved.lock() +=1;
45
-
```
46
-
Here `lock` borrows the `mutex` variable. The borrow only last until the end of the same statement. That means we'd be allowed to move `mutex` into a new variable `moved` and call `lock` on it, this time with an different address for `&self`!
47
-
48
-
We rely on the fact that borrows prevent moves. We cannot change the lifetime of the borrow to encompass the moving statement using the current borrow checker. This can be changed once we get non-lexical lifetime and we'd get an error on the move instead.
49
-
50
-
Conceptually we can think of borrows of `?Move` values as introducing 2 borrows:
51
-
- one borrow with as short lifetime as possible with normal restrictions
52
-
- one borrow which must match the lifetime of the borrowed value. The only restriction placed is that the value must not be moved out of.
53
-
54
-
This RFC suggests an approach where we use only the shorter borrow and require it to match the lifetime of the value. This is less flexible, but results in minimal implementation changes. A more flexible solution can be introduced with non-lexical lifetimes.
55
-
56
-
We can easily work around issues with this in code by using a single borrow of the immovable value and just reborrow.
57
-
58
-
Illegal:
59
-
```rust
60
-
letmutex=StaticMutex::new(0);
61
-
*mutex.lock() +=1;
62
-
*mutex.lock() +=1;
63
-
```
64
-
Workaround using reborrows:
65
-
```rust
66
-
letmutex=&StaticMutex::new(0);
67
-
*mutex.lock() +=1;
68
-
*mutex.lock() +=1;
69
-
```
70
-
71
-
A borrow such as `&var.field` where `field` is immovable will last as long as the lifetime of `var` to ensure it matches the lifetime of the field.
72
-
73
-
We need to prevent assignment to immovable types once they have been borrowed. This is because assignment actually moves the l-value before calling `Drop::drop`. If there are any restrictions on the l-value or if the l-value has a dereference operation, assignment to immovable types is not allowed.
74
-
75
-
Types which implement `Copy`, but not `Move` are allowed. You can still copy them around, but borrows follows the restrictions of `?Move` types.
35
+
To prevent values which may not implement `Move` that have been previously borrowed we introduce a MIR pass. We do a forward dataflow analysis on the MIR marking l-values that have been borrowed. For `a` we mark the path `a` as observed. For `a.b` we mark both `a.b` and the parent `a`, since if you observe `a.b` moving `a` will change the address of `a.b`. For `*a` we do nothing, as the address of `a` isn't observed. For slice indices `a[i]`, we mark `a` as observed. Finally we walk through every move in the MIR and give an error if the moved value could be observed at that point and the type of the value isn't known to implement `Move`.
0 commit comments