-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clarify clone, new_ref, duplicate and duplicate_deep semantics #712
Comments
There are some examples of internal reference-counting throughout the Rust ecosystem, e.g. wasmtime, though there aren't many (any?) in std. I have thought recently that there kind of should have been 4 distinctions in Rust for copy/clone semantics: cheaply trivially copyable (register load), trivially mem-copyable (a memcpy results in a valid standalone object, even if it's big), and deep-clone vs reference-counting. But alas, we're stuck with what we've got. The only function in std I know of that was designed to not take |
Also, there are a lot of users that get started with godot-rust by trying to convert GDScript code to Rust, so keeping the API close to what it is in GDScript has a lot of value. |
I don't see much benefit for register/memcpy differentiation, as this will also depend on the architecture and only differs in performance, not semantics. But for the others I agree, and additionally some types differ between deep- and shallow-clone (see below).
The same argument can be made for people already familiar with Rust, and picking up Godot as an engine. Furthermore, staying idiomatic in the target language usually leads to less rough edges than trying to port one language's idioms to another. But of course there are different opinions, a compromise makes sense here to reduce interop friction on both ends of Godot <-> godot-rust <-> Rust. My attempt at categorizing different copy semantics goes as follows: 1. Simple types (
|
It's not quite deep-copy with |
My personal opinion is that For collections, my opinion is a bit less clear. I'd almost want something like a collection-specific reference type, so |
|
The more I think about this, the more I think something akin to |
That's an interesting take. It would imply quite some refactoring of the type system though, as Might be doable with another type state, but definitely needs more thinking 💡 |
@Bromeon yeah, it's possible the refactoring effort alone would make it not worth the change. However, I am thinking a separate type that's similar to edit: to be clear, the new type would also have to have a name that reminded users of |
I'm not opposed to change if it makes the resulting type system simpler. The relation between It sometimes makes sense to reflect upon a design based on first principles, and see if components can be further decoupled. We should definitely try to reuse the knowledge that went into the current design. The current model is already great at isolating some behaviors:
Maybe there are more layers, or the existing ones can be arranged differently? |
I think the idea of using a wrapper type to indicate variant reference counting sounds interesting. The behavior of deep duplication wrt. objects is consistent with the cloning of Rust collections that contain The biggest issue with this approach seems to be the extra cognitive burden of learning "by heart" yet another Another possible point of contention I see is whether we should allow users to obtain bare versions of the values. This needs to be allowed if we want to implement |
From #711:
@Bromeon:
@toasteater:
I agree with the
Rc
consistency, but keep in mind that in the standard library, the boundary between value type and reference-counted type is much clearer than in Godot.Rc
's only function is to reference-count a value, it's even in the name. For something likeVariantArray
orDictionary
, it's more an implementation detail due to how Godot works, and it wouldn't surprise me if some users expected them to behave like standard collection types (i.e. values).So we make a choice by being consistent with either smart pointer types, or with collection types.
Dictionary
and friends seem to me closer to collections than to smart pointers.In the
Rc
documentation, it is even recommended to use the associated function call syntax, to make it clearer that no deep copy is performed:This indicates to me that the
Rc::clone()
method is indeed considered a special case, and thex.clone()
syntax generally means "copy the whole contents of x".The text was updated successfully, but these errors were encountered: