Skip to content

RFC: Remove newtypes #3534

Closed
Closed

Description

@nikomatsakis

We currently have special syntax and semantics for "newtypes", which are defined as enums with one variant and one argument. For such enums, we overload the * operator and support autoderef. They can be declared with the rather non-obvious notation of enum Foo = T.

With the advent of structs, I think this special treatment has little purpose. We could as easily write:

struct Foo { repr: T }

and then create instances of such new types as Foo { repr: v }. Accessing the representation of a newtype would simply be foo.repr. It would not be possible to "autoderef" through a newtype'd value, but I am not sure if this is a problem---I have had problems where I introduced a newtype only to find that it was "leaking" out of its newtype wrapper due to implicit derefs I wasn't aware of.

Another advantage is that currently our method lookup rules must have a special case just to accommodate newtype'd enums. Currently we auto-deref as long as we can and then attempt auto-ref---except if one of the intermediate states is an enum, in which case we attempt auto-ref for that enum as well.

Activity

  1. brson commented on Sep 19, 2012

    @brson
    Contributor

    +1. Using enums for newtypes makes less sense now that they aren't the only nominal types and the implementation has always been wonkey, with any single-variant enum being surprisingly dereffable.

    I do think that newtyping will become more important with impl coherence (e.g. if the creator of the type forgot to implement Hash), but we can probably do it better.

  2. nikomatsakis commented on Sep 19, 2012

    @nikomatsakis
    ContributorAuthor

    Another advantage to using fields: it closes the "* violates privacy"
    loophole.

  3. catamorphism commented on Sep 20, 2012

    @catamorphism
    Contributor

    I agree. It's just another special case that is likely to result in bugs.

  4. bblum commented on Sep 21, 2012

    @bblum
    Contributor

    There should be syntax sugar for declaring structs this way (newtyping is an important feature), but I agree with using structs for it.

  5. nikomatsakis commented on Sep 21, 2012

    @nikomatsakis
    ContributorAuthor

    I'd like to separate out the syntax from the overloading of *.

    FWIW, I am not sure that syntactic sugar is necessary, but I am not necessarily opposed to having it.

    I would however prefer to remove the special treatment of * and integration with auto-deref. * should be for pointer dereferences.

  6. bblum commented on Sep 21, 2012

    @bblum
    Contributor

    Ambivalent about * as the operator for it; I never thought it made sense to auto-deref them though.

    I do think it's important to have sugar for these that doesn't require the user to come up with a field name for the interior, though. Newtypes are an important idiom for code hygiene and so should be lightweight.

    It's too bad we have camel case types now or I'd suggest just using the type name as the field name (i.e., struct foo(innertype) expands to struct foo { foo: innertype }.

  7. catamorphism commented on Dec 28, 2012

    @catamorphism
    Contributor

    Can we go ahead with this? Objections from @graydon or @pcwalton ?

  8. nikomatsakis commented on Dec 28, 2012

    @nikomatsakis
    ContributorAuthor

    I believe that struct Foo(T) currently is intended to act more-or-less exactly like enum Foo = T (e.g., *x is used to extract the T, and this is auto-derefd). My proposal here was a bit more ambitious. I basically wanted to remove all special newtype behavior, so you'd have to write struct Foo { repr: T } and then use repr like any other field. Although I wouldn't mind this, I have a feeling it is not going to be popular, so perhaps it's best to just remove enum Foo = T but otherwise leave things as they are.

  9. brson commented on Jan 22, 2013

    @brson
    Contributor

    I agree with removing the special dereference behavior, or at least trying to. There are plenty of ways to get at a newtype struct, like let NewType(value) = ...

  10. brson commented on Apr 27, 2013

    @brson
    Contributor

    I think this issue is just about resolved. What niko said last still seems to be true.

    I would like to mention though that newtype auto-dereferencing has confused me several times. At this point I think I know that if I see an unexpected error about mismatched arguments that I should check if the type is a newtype.

  11. nikomatsakis commented on May 10, 2013

    @nikomatsakis
    ContributorAuthor

    Closing in favor of #6246, which is more tailored to the last remaining point of discussion.

  12. added a commit that references this issue on Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions