|
|
Log in / Subscribe / Register

sa_family

sa_family

Posted Nov 16, 2025 22:40 UTC (Sun) by randomguy3 (subscriber, #71063)
In reply to: sa_family by da4089
Parent article: A struct sockaddr sequel

In C terms, a Rust enum is most similar to a union (plus a value to tell you which union variant is active). Imagine the potential issues with allowing new union variants to be added at runtime - most notably, how would you safely destroy such a value?

Of course (as with most things in software), this could be solved, but it would cost you (in performance, ergonomics, safety and/or another axis of flexibility).


to post comments

sa_family

Posted Nov 17, 2025 8:29 UTC (Mon) by taladar (subscriber, #68407) [Link] (1 responses)

Destruction would be the least of the issues. Every location that uses it and matches on the variant and does something for each of them would be incomplete.

sa_family

Posted Nov 17, 2025 20:23 UTC (Mon) by NYKevin (subscriber, #129325) [Link]

Simple code compatibility can be guarded with #[non_exhaustive], if you anticipate the problem when you define the enum.[1]

But the type system assumes that you will tell it about all of the variants at compile time. Layout optimizations are made under this assumption, so it cannot reasonably be unwound at runtime, even with #[non_exhaustive] (which is primarily meant as a backcompat lint).

If the set of possible types is unbounded at runtime, probably you need to use a dyn-compatible trait instead of an enum. Then we can define methods on addresses and dynamically dispatch to them (or statically dispatch if the type is known). But this has a number of downsides, including all the usual DST restrictions (see [2]), as well as various annoying restrictions on the method signatures.[3]

In contexts where it is acceptable to generate code handling each address type separately, the trait does not need to be dyn-compatible, because you can use ordinary enerics for that (specializations will be monomorphized and compiled at the same time as the rest of the module). But that doesn't work for cases where you want a single data structure that directly or indirectly contains instances of mixed types (e.g. the file descriptor table).

It should also be emphasized that Rust is a systems programming language. If you don't like dyn Trait, you are allowed to manually re-implement your own version of it with unsafe code. There is no strict aliasing rule, so you can unsafely cast between different types as long as the object representations are valid at all of those types, and there's nothing stopping you from building a safe abstraction around that operation. This is probably not a great idea in most situations, but the language doesn't rule it out, and indeed it even provides primitives to help you do it correctly (e.g. std::any::TypeId). This might be appropriate in contexts where you only need a very small subset of dyn Trait functionality and don't want to live with all of its restrictions.

[1]: https://doc.rust-lang.org/reference/attributes/type_syste...
[2]: https://doc.rust-lang.org/reference/dynamically-sized-typ...
[3]: https://doc.rust-lang.org/reference/items/traits.html#dyn...


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds