|
|
|
|
|
by verdagon
758 days ago
|
|
I'm glad you brought inheritance up! This rule has solved it nicely in my experience: if a struct is linear, then it can only inherit linear interfaces. And implementation inheritance works because it's really just a combination of interface inheritance + composition + method forwarding, none of which seem to have any particular trouble with linear types. Even if a language really wanted to have linear types in reference-counted objects, I don't think we'd see cycles in practice. Generally, for a reference-counted object to contain a linear type, we'd need exactly one reference to be the special "linear reference" (think a linear flavor of unique_ptr) which has ultimate responsibility for "consuming" (albeit not deleting) the contents. Making a unique_ptr cycle is much harder than making a regular RC cycle, so I'm not too worried, even if it is theoretically possible. Re: trivial moves, I'm not sure what you mean. The system works through the entire program, not just local variables. Also, the `onException` method would also handle panics. Hope that helps! |
|
You don't need RC to have a cycle - it already occurs with a pair of structs that refer to each other using `mut Option[Unique[T]]`. Rust seems to have settled for "document it aggressively, and otherwise ignore it" ... yet code very similar to this is actually very useful, so (with a few extra layers of nesting) it often does appear spontaneously in the wild. But the whole point of linear types is that you can no longer just say "leaks are okay I guess".
Moving even a small 64KB buffer isn't actually trivial even if your type system thinks it is by composition, but most linear-ish type systems seem to aggressively use destructuring (possibly via pattern-matching) which relies on moving the members. Not to mention all the other actually-useful things C++ move constructors can do (update peer objects, for example). While "move-by-default" is a definite winner, "trivial-move-only" is not. The question of "what exactly happens so I can move out of a language-defined Option[T], leaving None ... vs how can a user-defined variant type choose to do something similar" is significantly complicated by nontrivial moves.