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

Introduce Go/Ada style subtyping aka C++ "opaque typedef" #13092

Closed
dsaf opened this issue Aug 11, 2016 · 8 comments
Closed

Introduce Go/Ada style subtyping aka C++ "opaque typedef" #13092

dsaf opened this issue Aug 11, 2016 · 8 comments

Comments

@dsaf
Copy link

dsaf commented Aug 11, 2016

It would be great if there was an overhead-free quick way of adding more compile-time verification when using "primitive" types.

For example:

bool CheckNameExists(string name);
bool CheckAddressKnown(string address);

Semantically name and address are different, yet they can (mistakenly) be used interchangeably without any compiler warnings or errors. Today the only option to work around this would be introducing two new types, which means runtime overhead having to deal with equality overloads etc.

Go and Ada have a way of dealing with this, which looks like type aliases but in addition gives a level of type checking:

https://golang.org/ref/spec#Type_identity
https://en.wikibooks.org/wiki/Ada_Programming/Type_System#Defining_new_types_and_subtypes

Similar feature "opaque typedef" is overdue in C++ as well apparently:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3515.pdf

Relevant SO answers:

http://stackoverflow.com/questions/17538955/overhead-of-type-alias-in-go
http://stackoverflow.com/questions/19334542/why-can-i-type-alias-functions-and-use-them-without-casting
http://programmers.stackexchange.com/questions/328055/why-do-mainstream-strong-static-oop-languages-prevent-inheriting-primitives

Some theory:

http://cstheory.stackexchange.com/questions/10620/how-does-inheritance-differ-from-subtyping
http://cstheory.stackexchange.com/questions/3991/implicit-vs-explicit-subtyping

@dsaf
Copy link
Author

dsaf commented Aug 11, 2016

Couldn't find anything very related except for this:

#6739 (comment)

It is proposed to use using to declare "strongly typed type aliases" so that it would support generics and all the goods that come with types.

public using class EmailAddress = String;
public using struct Identity = Int32;

@svick
Copy link
Contributor

svick commented Aug 11, 2016

So, such types would not really exist the IL level? They would be enforced only at the language level?

Also, I think a trivial struct containing one field of some type could be as efficient as a value of that type. As far as I know, the CLR does not currently treat them with the same efficiency, but that could be improved and then this language feature wouldn't be necessary (or it could be just syntax sugar for that trivial struct).

@dsaf
Copy link
Author

dsaf commented Aug 11, 2016

@svick

So, such types would not really exist the IL level? They would be enforced only at the language level?

It would be nice to emit some sort of metadata to preserve this information when consuming compiled libraries. Otherwise it will be like F# units of measure but applicable to any types (not just numbers).

Also, I think a trivial struct containing one field of some type could be as efficient as a value of that type. As far as I know, the CLR does not currently treat them with the same efficiency, but that could be improved and then this language feature wouldn't be necessary (or it could be just syntax sugar for that trivial struct).

Sounds hypothetical.

@ilmax
Copy link

ilmax commented Aug 11, 2016

@dsaf Thank you for posting this.
There are tons of case when this would be useful.

First use case I can think of is when you pass around the key of entities, so instead of

FindBlogByKey(int blogKey);
FindPostByKey(int postKey);

Ideally I would like to set a sort of global alias somewhere to allow me to write

using BlogKey = Int32; // this is not the proposed syntax, only for illustrative purpose
using PostKey = Int32;
....
FindBlogByKey(BlogKey blogKey);
FindPostByKey(PostKey postKey);

so that calling FindPostByKey with an int parameter should result in a compile time error.

There are of course a lot of open points

  • What's the alias syntax?
  • What's the alias scope?
  • What's the story of client code (defined in another project)
  • What's the story of casts? (e.g. FindByBlogKey((BlogKey)42);

Just to name a few, but I like to see this discussion started

@HaloFour
Copy link

This is very similar to #58.

To note the proposal #2044 to introduce project/global type aliases has already been closed as "Won't Fix".

@dsaf
Copy link
Author

dsaf commented Aug 11, 2016

@HaloFour

This is very similar to #58.

Maybe in spirit. Also it bears the dreadful "Discussion" label :(.

To note the proposal #2044 to introduce project/global type aliases has already been closed as "Won't Fix".

This suggestion is about subtyping rather than aliases as in synonyms.

@dsaf
Copy link
Author

dsaf commented Aug 11, 2016

@ilmax

What's the alias syntax?

Open to ideas. Historically existing keywords tend to be re-used, but I am afraid that using will make it confused with aliases.

What's the alias scope?

These are types not aliases. So same as other types.

What's the story of client code (defined in another project)

Either preserve as metadata or erase during compilation.

What's the story of casts? (e.g. FindByBlogKey((BlogKey)42);

#1203

@gafter
Copy link
Member

gafter commented Aug 17, 2016

Dup of #58

@gafter gafter closed this as completed Aug 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants