Skip to content

Confusing behavior around unsized return values in traits #51784

Open
@RalfJung

Description

@RalfJung

The following traits are accepted, but not object safe:

pub trait MyTrait {
    fn deserialize(input: u32) -> Self;
}
pub trait YourTrait {
    type Output: ?Sized;
    fn deserialize(&self, input: u32) -> Self::Output;
}

On the other hand, the following traits are rejected saying the trait bound Self: std::marker::Sized is not satisfied:

pub trait MyTrait {
    fn deserialize(input: u32) -> Option<Self>;
}
pub trait YourTrait {
    type Output: ?Sized;
    fn deserialize(&self, input: u32) -> Option<Self::Output>;
}

The error makes sense in principle, but

  • (a) it is really confusing that it is okay to have unsized return types (where usually the same check would apply!), but not return enums with unsized types inside them. What seems to happen here is that there is a special rule if the return type is unsized to drop object safety (if the type is Self) or do nothing (otherwise) instead of complaining.
  • (b) The fix is far from obvious: One has to add Sized as a supertrait to MyTrait. Given that Sized is usually added implicitly, people will run into this without ever having dealt with Sized before (and in fact, that's what just happened when a friend asked me about this). The error will certainly not help with finding this.

Both of these points would be fixed if that exception for unsized argument/return types would be extended to also cover the above cases.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-DSTsArea: Dynamically-sized types (DSTs)A-trait-systemArea: Trait systemC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions