fe3b1e8b6a
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
Sessions 56–69: declarative macro! with rep/zip/literal/block and unhygienic var $name binders; partial field-move skip Drop; @[Release] polish; LSP type hierarchy; CI Nim cache + lean macOS + Windows smoke.
64 lines
1.8 KiB
Plaintext
64 lines
1.8 KiB
Plaintext
// Session 68 — partial field moves out of @[Drop] parents
|
|
// `return bag.items` / `let x = bag.items` must skip Bag_Drop (no double-free).
|
|
// Non-droppable fields (`bag.tag`) do not mark the parent moved.
|
|
import Std::Io::{PrintLine};
|
|
import Std::Array::{Array, Array_New, Array_Push, Array_Len, Array_Get};
|
|
import Std::String::{String_FromInt, String_Concat};
|
|
import Std::Test::{Test_AssertTrue, Test_Pass};
|
|
|
|
@[Drop]
|
|
struct Bag {
|
|
items: Array<int>,
|
|
tag: int
|
|
}
|
|
|
|
func Bag_Drop(self: *Bag) {
|
|
Array_Drop<int>(&self.items);
|
|
}
|
|
|
|
// Move droppable field out via return
|
|
func TakeItems() -> Array<int> {
|
|
var items: Array<int> = Array_New<int>(4);
|
|
Array_Push<int>(&items, 42);
|
|
let bag: Bag = Bag { items: items, tag: 7 };
|
|
return bag.items;
|
|
}
|
|
|
|
// Move droppable field via let; read non-droppable tag after
|
|
func PeekTagAndTake() -> int {
|
|
var items: Array<int> = Array_New<int>(2);
|
|
Array_Push<int>(&items, 1);
|
|
let bag: Bag = Bag { items: items, tag: 99 };
|
|
let moved: Array<int> = bag.items;
|
|
let t: int = bag.tag;
|
|
discard Array_Len<int>(&moved);
|
|
return t;
|
|
}
|
|
|
|
// Whole-struct return still moves bag (existing path)
|
|
func MakeBag() -> Bag {
|
|
var items: Array<int> = Array_New<int>(2);
|
|
Array_Push<int>(&items, 10);
|
|
Array_Push<int>(&items, 20);
|
|
let bag: Bag = Bag { items: items, tag: 3 };
|
|
return bag;
|
|
}
|
|
|
|
func Main() -> int {
|
|
let taken: Array<int> = TakeItems();
|
|
Test_AssertTrue(Array_Len<int>(&taken) == 1);
|
|
Test_AssertTrue(Array_Get<int>(&taken, 0) == 42);
|
|
|
|
let tag: int = PeekTagAndTake();
|
|
Test_AssertTrue(tag == 99);
|
|
|
|
let b: Bag = MakeBag();
|
|
Test_AssertTrue(Array_Len<int>(&b.items) == 2);
|
|
Test_AssertTrue(Array_Get<int>(&b.items, 0) == 10);
|
|
Test_AssertTrue(b.tag == 3);
|
|
|
|
PrintLine(String_Concat("ok=", String_FromInt(tag as int64)));
|
|
Test_Pass("move_field_partial");
|
|
return 0;
|
|
}
|