대여는 변수가 아니라 place 단위다
p.a 와 p.b 는 서로 다른 자리인데 한쪽을 대여하면 다른 쪽까지 잠겼다. 메서드가
하는 일의 대부분이 한 필드에 쓰면서 다른 필드를 읽는 것이라, std.map 의 keep 은
그것 때문에 함수 둘로 갈라져 있었고 파서도 같은 자리에서 걸렸다.
FeOwnState 가 필드별 칸을 넷 갖는다. 값으로 복사되는 구조체라 흐름 병합과
스냅샷은 손댈 것이 없었다. 전체를 대여하면 모든 필드와 충돌하고, 필드를
대여하면 전체 및 같은 필드와 충돌한다. 칸이 모자라면 전체 대여로 되돌아가
더 많이 보고할 뿐 놓치지 않는다.
읽기는 식별자에서 일어나는데 그 자리에서는 자기가 무엇의 밑동인지 알 수 없다.
그래서 투영이 내려가는 길에 어느 필드인지 적어두고 식별자가 그것을 집는다.
인덱스는 갈라지지 않는다 -- xs[i] 의 i 는 상수가 아닐 수 있고, 필드 이름은
상수다.
길에서 나온 것: mem.replace 가 목적지 대여를 가져가고 돌려주지 않았다. 일반
호출 인자는 문장 끝에 돌려주는데 intrinsic 경로에만 그것이 없었다. 전에는
그 자리가 어차피 거부돼서 드러나지 않았다.
var p = Pair{ a: 1, b: 2 };
let r = &mut p.a;
p.b = 3; // ok -- 전에는 에러
p.a = 3; // 에러
take(p); // 에러
SPEC §5 R6 을 고쳤고, 옛 규칙을 그대로 적어둔 문단과 예제를 갈아치웠다.
own/badrfld 는 이제 허용되는 코드였으므로 같은 필드를 건드리도록 다시 겨눴고
okrfld·badrall·badrsame·exec/fieldbrw 를 더했다.
228/228, 32/32.
This commit is contained in:
+14
-25
@@ -92,33 +92,22 @@ pub struct Map(V) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// Make sure `need` bytes fit, moving to a bigger buffer if they do not.
|
||||
///
|
||||
/// Kept apart from `keep` because the borrow that swaps the buffer in is
|
||||
/// a borrow of the whole of `self` -- borrowing is tracked at the root --
|
||||
/// and it has to be over before any field is read again.
|
||||
fn ensure_room(self: &mut Self, need: usize) -> !void {
|
||||
let have: usize = self.bytes.^.n;
|
||||
if need <= have { return; }
|
||||
var room: usize = have;
|
||||
while room < need { room = room * 2; }
|
||||
let bigger: ^[]mut u8 = try mem.alloc_slice(u8, room);
|
||||
var k: usize = 0;
|
||||
let filled: usize = self.used_bytes;
|
||||
while k < filled {
|
||||
bigger.^[k] = self.bytes.^[k];
|
||||
k = k + 1;
|
||||
}
|
||||
let old: ^[]mut u8 = mem.replace(&mut self.bytes, bigger);
|
||||
mem.destroy(old);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Copy `key` into the byte buffer and point the slot at it.
|
||||
/// Copy `key` into the byte buffer and point the slot at it, moving to a
|
||||
/// bigger buffer first if it does not fit.
|
||||
fn keep(self: &mut Self, key: []u8, slot: usize) -> !void {
|
||||
let at: usize = self.used_bytes;
|
||||
let need: usize = at + key.n;
|
||||
try self.ensure_room(need);
|
||||
if at + key.n > self.bytes.^.n {
|
||||
var room: usize = self.bytes.^.n;
|
||||
while room < at + key.n { room = room * 2; }
|
||||
let bigger: ^[]mut u8 = try mem.alloc_slice(u8, room);
|
||||
var k: usize = 0;
|
||||
while k < at {
|
||||
bigger.^[k] = self.bytes.^[k];
|
||||
k = k + 1;
|
||||
}
|
||||
let old: ^[]mut u8 = mem.replace(&mut self.bytes, bigger);
|
||||
mem.destroy(old);
|
||||
}
|
||||
var i: usize = 0;
|
||||
while i < key.n {
|
||||
self.bytes.^[at + i] = key[i];
|
||||
|
||||
Reference in New Issue
Block a user