Term for "exact type turned into a dyn"?

If you lose the original type of something when it is turned into a dyn trait object .. is there an established term for this besides "cast" -- something that emphasizes that the cast is unidirectional?

struct Ctx {
  w: Box<dyn std::io::Write>
}
fn main() {
  let mut f = MySpecialWriter::new("hello.dat").unwrap();
  let ctx = Ctx {
    w: Box::new(f);   // <- What would you call this?
  }
}

"type-erased cast"?

This is a coercion, more specifically a unsized coercion.

3 Likes

I also like the term “unsizing coercion” (I don’t know… makes grammatically more sense to me), or short “unsizing”.

1 Like

I also initially wrote "unsizing" because it felt more natural, but then changed to "unsized" when I saw the reference was using it.

Then maybe we should just change the reference :crazy_face:

2 Likes

On second thought & second look at the two traits Unsize and CoerceUnsized maybe they want to draw a distinction between “unsizing” the target type into the actual unsized type, and unsized coercing the pointer type pointing to it. (When used as a verb “unsized coercing” perhaps sounds better than “unsizing coercing”.) Gotta check RFC and other discussions for context on whether or not that actually is a relevant terminological distinction here.

On the other hand, it’s not like these are two separate processes. The only form of unsizing is through an unsized coercion ~ unsizing coercion.

Is "unsized coercision" and "type erasure" identical? If not, where do they differ ?

As @quinedot pointed out in your other thread

So the differences are:

Some kinds of unsizing coercions may not be considered type erasure. Coercing to a slice from an array like Box<[T; N]> to Box<[T]> might not be called “type erasure”. Sure, it erases the array length, but dynamic length information is so common that it doesn’t necessarily count as an erased type. (After all, Box<[T]> can also be very well thought of as just an alternative to Vec<T> without the option for spare capacity.)

Some kinds of type erasure are not related to unsizing coercions. (The mentioned example of “passing around *mut () with some other way of tracking the type at runtime”.)

The terminologies differ in their grade of formality.

I, too, understand “type erasure” as an informal term for some programming concept; the concept that the implementation of type objects is based on, the concept to bundle up some somewhat untyped data, often with some pointer type (often something like *const () or *mut ()), sometimes also with data (like some [MaybeUninit<u8>; N] array… or even a union[1]) that could be pointing to values of different types, together with additional information that makes it stillusable. By the way, check out the first part of this video for a great exposure to the ideas how trait objects are / could be implemented manually:

On the other hand, “unsizing coercions” are clearly defined. They are those (implicit) type coercions in Rust that are powered by the CoerceUnsized trait internally.


  1. combing a union with a tag ==>> maybe enums are an instance of “type erasure”, too… right? ↩︎

4 Likes

I think I get it now. "Unsized Coercion" refers to precisely those 3 transforms in Type coercions - The Rust Reference

"type erasure" is slightly less formal and includes T -> dyn and T -> *mut ().

Thus, [T; n] -> [T] is unsized coercision but not "type erasure", while `T -> *mut ()" is type erasure, but not unsized coercision.

^-- This is your "argument" right ?

What is the relationship between a "deref'able type" and a "unsizing coercion" if any?

unsiz(ed|ing) coercision refers to precisely the 3 things in Type coercions - The Rust Reference and nothing else

I do not know what "deferable type" means in this context.

I'm wondering about the unsizing conversion from &'a mut (dyn T + 'static) to &'a mut (dyn T + 'a). Which I think is both a deref and an unsizing conversion. It may just be overlap in the example and not shared context between a deref coercion and a unsizing coercion. Is it that the dyn T + 'a is not related to the reference, or in other words, does a derefence always attach a 'static lifetime and nothing more?

No actually it's the other way around 'static doesn't have references, and 'a is adding a reference and not dereferencing.

That particular case is just an unsizing coercion.

1 Like