Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Remove newtypes #3534

Closed
nikomatsakis opened this issue Sep 19, 2012 · 11 comments
Closed

RFC: Remove newtypes #3534

nikomatsakis opened this issue Sep 19, 2012 · 11 comments
Labels
A-typesystem Area: The type system

Comments

@nikomatsakis
Copy link
Contributor

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.

@brson
Copy link
Contributor

brson commented 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
Copy link
Contributor Author

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

@catamorphism
Copy link
Contributor

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

@bblum
Copy link
Contributor

bblum commented 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
Copy link
Contributor Author

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
Copy link
Contributor

bblum commented 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 to struct foo { foo: innertype }.

@catamorphism
Copy link
Contributor

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

@nikomatsakis
Copy link
Contributor Author

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.

@brson
Copy link
Contributor

brson commented 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
Copy link
Contributor

brson commented 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
Copy link
Contributor Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system
Projects
None yet
Development

No branches or pull requests

4 participants