You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
+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.
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 }.
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.
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) = ...
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.
Activity
brson commentedon Sep 19, 2012
+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.
nikomatsakis commentedon Sep 19, 2012
Another advantage to using fields: it closes the "* violates privacy"
loophole.
catamorphism commentedon Sep 20, 2012
I agree. It's just another special case that is likely to result in bugs.
bblum commentedon Sep 21, 2012
There should be syntax sugar for declaring structs this way (newtyping is an important feature), but I agree with using structs for it.
nikomatsakis commentedon Sep 21, 2012
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.bblum commentedon Sep 21, 2012
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 tostruct foo { foo: innertype }.catamorphism commentedon Dec 28, 2012
Can we go ahead with this? Objections from @graydon or @pcwalton ?
nikomatsakis commentedon Dec 28, 2012
I believe that
struct Foo(T)currently is intended to act more-or-less exactly likeenum Foo = T(e.g.,*xis 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 writestruct Foo { repr: T }and then usereprlike 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 removeenum Foo = Tbut otherwise leave things as they are.brson commentedon Jan 22, 2013
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) = ...brson commentedon Apr 27, 2013
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.
nikomatsakis commentedon May 10, 2013
Closing in favor of #6246, which is more tailored to the last remaining point of discussion.
Merge rust-lang#3534