Is !Sized a thing, or just an attempt at communication?

In rust - Implementing Sized trait - Stack Overflow, a responder refers to "!Sized". I don't see any documentation on this, and I suspect he's either referring to ?Sized, or trying to talk about something explicitly not Sized in some kind of abstract. Sorry if this should have been obvious to me. I am wishing with this, as with a lot of things, that I had more hard Computer Science knowledge to back up my Rust learning.

It’s not stable Rust syntax.[1] For communication, it is useful, and different from ?Sized. Instead of “!Sized”, one could also use the terms “unsized” or “dynamically sized”. (Between these two wordings, yet again, the latter could be more accurate, because values of “unsized” types like [T] or str or dyn Trait have a size, but it’s only known for each individual value, at run-time.)

The syntax ?Sized in Rust does not mean “unsized” or “dynamically sized”. Instead it just means “not forced to be sized”, i.e. “potentially unsized”/“potentially dynamically sized”. It can appear in contexts where usually things would implicitly be restricted to implement the Sized trait, typically for generic parameters of functions, structs, or traits, in a form like T: ?Sized. Speaking in terms of the trait Sized, writing T: ?Sized does not mean “T doesn’t implement Sized” but instead “T is allowed here to be a type that implements Sized or a type that doesn’t implement Sized”.'

In some unstable Rust features, and colloqually, the notation Type: !Trait is used to say Type does not implement Trait, so that’s where this notation would be adapted from.

It also appears stably in Rust documentation, for auto-traits. For example you can find an impl<T: ?Sized> !Sync for RefCell<T> in the standard library docs. (Ahh… and even for Sized itself, as @mbrubeck just kindly pointed out below.)


  1. Except for notation appearing in generated Rust documentation, see my last paragraph and @mbrubeck's answer below. ↩︎

5 Likes

This notation also shows up in rustdoc, for example impl !Sized for str.

3 Likes

To summarize: you can't write T: !Sized in a Rust program, but if you could, there is general agreement that it would mean that T is definitely not Sized, and someday you may in fact be able to write that.

1 Like

It's being actively worked on, in fact: https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types/topic/Negative.20impls.20work/near/407068626

1 Like

Well, strictly speaking, this is not only a documentation, this is exactly how it's specified in source. Of course, that's standard library, and standard library is allowed some superpowers, including unstable syntax.

other examples includes:

It should be noted that Ty: !Trait for non-auto traits[1] doesn't mean "the type happens to not implement Trait", it means "the type has explicitly opted out of implementing Trait". That is, it requires an explicit

impl !Trait for Ty {}

And that "implementation" must obey the orphan rules, and it is a breaking change to remove the "implementation" similar to how it's a breaking change to remove a positive implementation.

The reasoning being, if coherence can some day rely on negative bounds, it would become a breaking change to implement a trait that wasn't implemented before; that is too restrictive to be something you don't opt into.


  1. in the current unstable model, but it's unlikely to change ↩︎

3 Likes

I did have cases when I wanted to do that.