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

newtype / generalized newtype deriving #261

Open
rust-highfive opened this issue Sep 24, 2014 · 21 comments
Open

newtype / generalized newtype deriving #261

rust-highfive opened this issue Sep 24, 2014 · 21 comments
Labels
A-derive Deriving related proposals & ideas A-impls Implementations related proposals & ideas A-traits Trait system related proposals & ideas postponed RFCs that have been postponed and may be revisited at a later time. T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@rust-highfive
Copy link

Pretty

Tracking issue for postponed PR #186

@nrc nrc added the postponed RFCs that have been postponed and may be revisited at a later time. label Sep 24, 2014
@alexchandel
Copy link

An attribute like #[derive_newtype], applicable to "newtype" tuple structs like struct Wrapper(i32), would be fantastic.

@reem
Copy link

reem commented Jan 20, 2015

The interaction with TypeId and Any here is also of note, since an incorrect implementation of newtype deriving can cause serious problems when combined with downcasting - if get_type_id from Any is inherited such that it reports the same TypeId for the original type and the new type, bad things can be made to happen.

@aidancully
Copy link

If it's discovered that a keyword is required to support newtypes, if the language follows semver (and I seem to recall that it does), would that require that rust be bumped to 2.0 just to add the keyword? (since it's a breaking change when existing code that uses the token "newtype" stops working.) Wouldn't it be more conservative to reserve the keyword now, and release it if we can determine that the functionality can be implemented with a macro or some such?

@Kimundi
Copy link
Member

Kimundi commented Feb 23, 2015

Afaik the official stance is that keywords can be added without bumping the major version by adding an attribute for enabling them.

@nikomatsakis nikomatsakis changed the title Introduce a newtype keyword. newtype / generalized newtype deriving Mar 19, 2015
@nikomatsakis
Copy link
Contributor

Postponed RFC #949 contains a description of a possible newtype semantics.

@drewm1980
Copy link

Shouldn't something like this be a 1.0 blocker? It seems like you don't want people rolling their own solutions to get around a pain point in something as fundamental as newtype.

For example, it would be nice to be able to do checked addition, max_value(), etc... on a newtyped int without a bunch of boilerplane:

http://is.gd/7Cdzkd

Credit: this came from help I got during an IRC discussion with flan3002.

Thanks! And sorry if commenting on two related issues is considered a cross-post; not sure about ettiquet on this. This seems to be the higher priority / still open thread...

@Diggsey
Copy link
Contributor

Diggsey commented Mar 28, 2015

There seems to be a forwards compatibility problem with this RFC in combination with the coherence rules: even under the new rules proposed by @nikomatsakis in #1023 this would mean that a parent crate cannot add a new trait implementation to a type "Foo", without potentially breaking downstream crates, which may have newtyped "Foo" to "Bar", and then implemented that same trait for Bar.

@arienmalec
Copy link

@arienmalec
Copy link

Just to put more info into the thread: my proposal is more like the first alternative, supporting #[derive] -- is the newtype keyword even feasible post 1.0?

@munael
Copy link

munael commented Jul 6, 2015

One 👍 for #[derive] from me. Though I'm confused on what it mean to support such generalization for "all tuple types".

@nrc nrc added the T-lang Relevant to the language team, which will review and decide on the RFC. label Aug 17, 2016
@oli-obk
Copy link
Contributor

oli-obk commented Dec 11, 2017

I opened a new RFC for this: #2242

@Centril Centril added A-derive Deriving related proposals & ideas A-traits Trait system related proposals & ideas A-impls Implementations related proposals & ideas labels Nov 26, 2018
@corthon
Copy link

corthon commented Sep 22, 2020

I'm here because this would be useful for me. I want to be able to "enhance" the debug for a given type (by adding more functionality than the source crate provides), but would like all other behaviors to be transparent.

@TheLostLambda
Copy link

Also tossing in my voice here as my hands are tied without this feature. The newtype pattern is quite often needed to get around the orphan rule, but it's not much good if I lose all of the Traits of the type I'm wrapping.

@linclelinkpart5
Copy link

+1 from me, I'd love to have this functionality, it would let me reuse methods from the wrapped type and avoid having to use the "Deref as newtype" anti-pattern.

@DrSloth
Copy link

DrSloth commented Jan 13, 2021

I think this is one of the most important, missing features of Rust.
While this feature might seem simple it has some really great benefits like being able to circumvent orphan rules.
I often find myself having to write a lot of boilerplate in order to implement serde Serialize/Deserialize for types of crates which don't implement it. If a syntax like:

#[derive(Serialize, Deserialize)]
type ExternType as NewType;

would exist i could save a lot of boilerplate. Also it makes the whole ecosystem way more extensible and more easy to use.

@jplatte
Copy link
Contributor

jplatte commented Jan 13, 2021

@DrSloth I don't think what you describe will ever be possible. Newtype deriving generally means implementing a trait for a wrapper type in terms of the implementation of the same trait for the inner type. If the inner type doesn't implement said trait, you don't really have anything to go off for the derived trait implementation.

I guess you're imagining the Serialize / Deserialize derive macros being able to work with the original item definition, but that would break many abstraction boundaries. To even be safe and in line with semver, this would have to limited to types with no private fields, without #[non_exhaustive] and probably other attributes, and then it would still be incredibly hard or impossible to implement.

@DrSloth
Copy link

DrSloth commented Jan 13, 2021

@jplatte I get what you are saying, but i think new types should be exactly that. A way to simply create a type equivalent to another one with access to private fields, trait implementations, private methods and everything else.
I don't understand why it would be hard to implement though.
If i want to implement Serialize / Deserialize for an external struct i currently have to copy the complete struct with all needed fields and then implement From and Into for it. The most problems / the most wasted time is just exactly from things like this. I feel like this is a big hinderance for the ecosystem. The main problem of a shortened syntax is that you would not be able to use field attributes.
I feel like there should be at least one 'safe' way to opt out of the orphan rules.

@linclelinkpart5
Copy link

@jplatte I'e be curious to see an example of how the automatic new type derivation would break. I'm trying to come up with some mental examples to see how it would, but I'm unable to think of any!

@jplatte
Copy link
Contributor

jplatte commented Feb 8, 2021

@jplatte I'e be curious to see an example of how the automatic new type derivation would break. I'm trying to come up with some mental examples to see how it would, but I'm unable to think of any!

Imagine newtype-deriving Deserialize for

struct MyU32(NonZeroU32);

NonZeroU32 is itself a newtype around u32 but its u32 -> Self constructor is unsafe because that u32 must not be 0. If newtype-deriving was not limited to types with entirely public definition, Deserialize would (somehow) bypass that constructor function and you'd be able to create NonZeroU32(0u32) in safe code, which is unsound.

@DrSloth
Copy link

DrSloth commented Feb 8, 2021

This kind of new type deriving would pretty much just be an abbreviation for transmute and thus raises the same safety concernes as transmute does. Unsafe shouldn't be usable in such an implicit way and it would be better to keep it explicit.

@LoganDark
Copy link

i think new types should be exactly that. A way to simply create a type equivalent to another one with access to private fields, trait implementations, private methods and everything else.

This would completely break encapsulation and expose downstream crates to unstable, non-semver implementation details of not only third-party crates, but also the standard library itself. This sounds so extremely wrong that I'm not even sure how to describe the utter terror it gives me.

With that said, I feel like this issue has gathered enough "hey, we want this too" for the time being. Everyone knows this is a useful feature, but saying that is not going to help it arrive any sooner. What we need is concrete, usable information on how it should work, and an actual implementation. Till then, saying how useful it would be won't get it anywhere. :/

(I'm aware that this is somewhat of a necro-post; honestly I think this issue should be locked until actual news comes up.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-derive Deriving related proposals & ideas A-impls Implementations related proposals & ideas A-traits Trait system related proposals & ideas postponed RFCs that have been postponed and may be revisited at a later time. T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests