Object Safety is a terrible term

To users of high-level OOP interfaces, perhaps, but for anyone who has implemented or worked with or implemented low-level OOP interfaces (think GObject or manual C vtables), the parallels are pretty clear. even without full inheritance, it's still a vtable-based object with dynamic dispatch.

I don't think "dyn types" is very clear. it sounds like it sounds too similar to "dynamic typing", perhaps leading people to believe rust has some sort of gradual typing system (which it does not). the closest thing to dynamic typing that rust has is dyn Any, which is only a subset of trait objects.

3 Likes

The point is to have unified terminology for the trait property ("dyn-compatible traits") and types which rely on it ("dyn types"). "Object" is too vague for this purpose. Yes, because of its vagueness in some areas it's used with the meaning close to Rust's "trait object", but it does not cancel the original vagueness.

For new Rust users this terminology will be introduced together with the dyn keyword, while experienced Rust users already know the keyword. Plus, we can explain it as a shortened version of "dyn(amic dispatch) types". This proposal intentionally introduces Rust-specific terminology without relying on parallels with other languages, so I don't think there is much room for confusion here.

I know overloading the term "safe" further isn't great, but informally I've been using "dyn-safe" to refer to the class of object-safe traits. It's not a complete bastardization of the safety concept, though, as any attempt to make a non-dyn-safe trait into a dyn Trait "object" requires some amount of unsafe. That may still be trivially encapsulated behind just some Box and more dynamic dispatch that doesn't require you to write unsafe, but the fact that someone needed to do some unsafe in the bridge is how I justify calling it dyn-safety despite being part of the UCG and attempting to narrowly define safety as a useful term.

I'm not against finding a better term to use in docs that try to remain formally correct, and am favorably included towards "dyn-compatible," but I fully expect that at least "dyn-safety" will stick around in contexts less concerned with being fully correct in their term usage.

As for what to call dyn trait types other than "objects," well, I just call them as "dyn trait" and let sentence structure dictate whether more words are even necessary to be clear about what's being discussed.


Opsem does discuss some things in terms of an "allocated object," which refers to the entire chunk of memory created by allocation, whether dynamic or stack. I don't recall that term getting put into any documentation yet, but it's certainly unfortunate how "object" is overloaded due to being a good word for "a thing" without implying further context.

(Member of T-opsem but not speaking on behalf of the team)

2 Likes

I agree, that's why I recommended the option of always using the more specific "trait object"

That hasn't been my experience.[1]

One never makes a trait into a dyn Trait, so that error is poorly worded independent of any "object" language.

I'm guilty of this too.

Perhaps "dyn-capable"?

the trait $Trait is not dyn-capable

The reference also uses "dispatchable" and for methods (and "explicitly non-dispatchable" for the Self: Sized opt-out on methods). And doesn't yet talk about associated types/GATs, which can now also have the opt-out. "dispatchable" wouldn't work for associated types, but "dyn-capable" could work for both.


  1. Unless it went straight over my head somehow. ↩︎

1 Like

I think "dyn-compatible trait" is just as clear and not repetitive.

I personally think "dyn-compatible" is the clearer term to use instead of "trait-object-safe", both because it avoids overloading the meaning of "safe" and because it directly makes it clear that the issue is being compatible with dyn.

20 Likes

I like "dynamic type", both because it avoids "object" and because it seems pretty apt to me: the point of dyn Trait is to make the actual type of the underlying value a dynamic property rather than a static one. So this fits pretty well with the static vs dynamic terminology in PL: it statically encodes the information "the type of this value is only known dynamically, but we know it implements this trait".

A more theoretically founded term would be "existential type", since that's the fundamental PL concept this corresponds to, but that is too obscure so I don't think it worst as a Rust term.

One could also try to draw an analogy with erasure (the actual type is erased, the only point that is retained is that this trait is implemented). But I think that's also worse than "dynamic type".

4 Likes

Not to mention that “existential type” could also refer to impl Trait types, so that’s another reason against using it to describe dyn-types.

1 Like

impl Trait are static existential types, dyn Trait are dynamic existential types. Normal type theory only really has the latter.

2 Likes

Out of curiosity, I just grabbed the C specification from open-std.org, and searching for "object" finds 728 references (in "only" 550 pages!) - "object" being defined as:

region of data storage in the execution environment, the contents of which can represent values

I guess it's not really an issue there because nobody reads the specification :yum:

2 Likes

Yeah, C has a typed memory model where memory stores "objects". But in Rust memory just stores bytes (somewhat strange bytes but bytes nevertheless), and anything higher-level and typed, like the idea of a "value", only arises transiently during the execution of a single statement.

2 Likes

But I'm pretty sure I've never heard of C programmers being tripped up by the term, thinking it refers to OOP objects - there's lots of possible reasons for that, not just my silly joke answer, but at least it's some evidence that the "object" part of the term "object safety" is only somewhat bad.

1 Like

Perhaps "dyn-able"?

1 Like

I think there are couple of important differences: C has nothing OOP-like, so there's nothing to confuse it with, and the spec term is used mostly by language lawyers. In other contexts in C "object" be loosely used to refer to what a C pointer or struct is representing (like a network socket or an audio channel), rather than the span of memory itself.

OTOH Rust has associated functions that look very much like methods, and a CamelCase naming convention for types that resembles boxed types in Java/C#/Swift.

1 Like

I think there is no ambiguity with OOP: Rust objects, C objects and OOP objects are the same sort of thing. Object-oriented languages aren't the only ones that have objects, just like functional languages aren't the only ones that have functions. Objects in OOP are just at the center of attention and thus get more features packed into them.

Let me make my proposal a bit more nuanced:

  1. dyn T is a "dynamic type".
  2. Objects of type dyn T (trait objects) are "dynamically typed objects".
  3. Traits T that can be used in dyn T (object-safe traits) are "dynamically typeable traits".
4 Likes

That would mean that in let x = 1 the x is an object (as it is in C), and by that definition "object safe" is even more ambiguous.

2 Likes

Yes. The reference uses the word "object" in many places, for example:

An object with the boolean type has a size and alignment of 1 each. The value false has the bit pattern 0x00 and the value true has the bit pattern 0x01 . It is undefined behavior for an object with the boolean type to have any other bit pattern.

3 Likes

Allow me to counterpropose wording of "Trait object eligible"

Edit: This, basically...

1 Like

So I guess the note in rustdoc would be rephrased?

Object Dyn Safety

This trait is not object dyn safe.

1 Like
3 Likes