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

[Proposal] Add Never type and support for methods that cannot return. #1226

Closed
gafter opened this Issue Mar 12, 2015 · 19 comments

Comments

Projects
None yet
@gafter
Member

gafter commented Mar 12, 2015

Please add a compiler-recognized special type that means "you cannot get here". I suggest it be called System.Never.

The compiler would treat a value of the type specially for definite assignment purposes - whenever a value of this type appears on the stack, everything is definitely assigned and the code is unreachable. This type can be used as the return type of a method that cannot return, though for compatibility it cannot be retrofitted onto existing methods that are declared to return void. The type is not instantiable (that is, it has no instances), like System.Void.

This language change enables us to change the specification of throw-statement to change it from a statement to an expression. That would allow you to use it in ??, ?:, &&, and other contexts to simplify some kinds of invariant and argument validation.

Implementation note: The code generator would throw an exception at any point where the type appears on the stack to cover the loopholes that the compiler cannot catch. I implemented Never for java (called Nothing there) in the closures project and it was straightforward.

Note: This is proposed as an alternative to #59, and is inspired by Scala's Nothing type.

@thomaslevesque

This comment has been minimized.

Show comment
Hide comment
@thomaslevesque

thomaslevesque Mar 12, 2015

Contributor

Would it allow us to use () => throw new Exception() as a Func<T> or Action?

Contributor

thomaslevesque commented Mar 12, 2015

Would it allow us to use () => throw new Exception() as a Func<T> or Action?

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter Mar 12, 2015

Member

@thomaslevesque Yes, it would.

@amcasey @MadsTorgersen You both pointed out to me that in order for this type to be useful in VB, it cannot be named Nothing. Perhaps Never.

Member

gafter commented Mar 12, 2015

@thomaslevesque Yes, it would.

@amcasey @MadsTorgersen You both pointed out to me that in order for this type to be useful in VB, it cannot be named Nothing. Perhaps Never.

@gafter gafter changed the title from [Proposal] Add Nothing type and support for methods that cannot return. to [Proposal] Add Never type and support for methods that cannot return. Mar 12, 2015

@ashmind

This comment has been minimized.

Show comment
Hide comment
@ashmind

ashmind Mar 13, 2015

That would allow you to use it in ??, ?:, &&, and other contexts to simplify some kinds of invariant and argument validation.

It would be very interesting to see some examples.

ashmind commented Mar 13, 2015

That would allow you to use it in ??, ?:, &&, and other contexts to simplify some kinds of invariant and argument validation.

It would be very interesting to see some examples.

@BillWagner

This comment has been minimized.

Show comment
Hide comment
@BillWagner

BillWagner Mar 15, 2015

Member

I really like this suggestion.

@ashmind Here are a couple examples of where it could be used:

  1. Tools that auto generate methods (think TDD) could write:
public void Foo() => throw new NotImplementedException();

If your type implements IDisposable, properties might be written as follows:

public string Connection => (!alreadyDisposed) ? this.connection : throw new AlreadyDisposedException();
Member

BillWagner commented Mar 15, 2015

I really like this suggestion.

@ashmind Here are a couple examples of where it could be used:

  1. Tools that auto generate methods (think TDD) could write:
public void Foo() => throw new NotImplementedException();

If your type implements IDisposable, properties might be written as follows:

public string Connection => (!alreadyDisposed) ? this.connection : throw new AlreadyDisposedException();
@paulomorgado

This comment has been minimized.

Show comment
Hide comment
@paulomorgado

paulomorgado Mar 15, 2015

This mean that this Never type would have to be implicitly convertible to any type, right?

paulomorgado commented Mar 15, 2015

This mean that this Never type would have to be implicitly convertible to any type, right?

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter Mar 16, 2015

Member

@paulomorgado Right. But the conversion does not generate any code.

Member

gafter commented Mar 16, 2015

@paulomorgado Right. But the conversion does not generate any code.

@matlus

This comment has been minimized.

Show comment
Hide comment
@matlus

matlus Mar 16, 2015

I think there are two different requirements here.

  1. A method that that never returns
  2. The ability to use the following syntax
return orders ?? throw new Exception("No orders found for Customer with Id:" + customerId.ToString());

currently we need to write code like so:

if (orders == null)
    throw new Exception("No orders found for Customer with Id:" + customerId.ToString());
return orders;

For the "never" case. Could we have a method decorated with [Throws] instead of "Never".
Marking a method as one that throws Exceptions

matlus commented Mar 16, 2015

I think there are two different requirements here.

  1. A method that that never returns
  2. The ability to use the following syntax
return orders ?? throw new Exception("No orders found for Customer with Id:" + customerId.ToString());

currently we need to write code like so:

if (orders == null)
    throw new Exception("No orders found for Customer with Id:" + customerId.ToString());
return orders;

For the "never" case. Could we have a method decorated with [Throws] instead of "Never".
Marking a method as one that throws Exceptions

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter Mar 16, 2015

Member

@matlus No, we do not use attributes to change the way the language type system works. Also, "Throws" would be a misnomer as throwing an exception is only one of the ways that a piece of code can fail to return to its caller.

Member

gafter commented Mar 16, 2015

@matlus No, we do not use attributes to change the way the language type system works. Also, "Throws" would be a misnomer as throwing an exception is only one of the ways that a piece of code can fail to return to its caller.

@diab0l

This comment has been minimized.

Show comment
Hide comment
@diab0l

diab0l Apr 24, 2015

@gafter So, this Never type..

  • has no values (is an uninhabited type)
  • has an implicit conversion to any other type
  • is supposed to be a return type of functions which do not return

Well, that's Bottom with equivalent semantics as in Haskell.

So let's call it Bottom :)

diab0l commented Apr 24, 2015

@gafter So, this Never type..

  • has no values (is an uninhabited type)
  • has an implicit conversion to any other type
  • is supposed to be a return type of functions which do not return

Well, that's Bottom with equivalent semantics as in Haskell.

So let's call it Bottom :)

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter Apr 24, 2015

Member

@diab0l That would make me blush every time I type it!

Member

gafter commented Apr 24, 2015

@diab0l That would make me blush every time I type it!

@diab0l

This comment has been minimized.

Show comment
Hide comment
@diab0l

diab0l Apr 26, 2015

@gafter Now that you mention it, I think thy type theory guys have a lot of fun with Bottom and the lift operation

diab0l commented Apr 26, 2015

@gafter Now that you mention it, I think thy type theory guys have a lot of fun with Bottom and the lift operation

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter Aug 27, 2015

Member

Wonderful discussion in #4843 but we need to have one issue per issue.

Member

gafter commented Aug 27, 2015

Wonderful discussion in #4843 but we need to have one issue per issue.

@HaloFour

This comment has been minimized.

Show comment
Hide comment
@HaloFour

HaloFour Aug 28, 2015

@gafter It sounds like #4843 took it a little bit further by pushing for variance on this bottom/never/whatever type, allowing you to assign a Func<Never> to a Func<int> or Func<string> since the return type wouldn't matter. Is your proposal more syntax-candy or actually a change to the underlying type system and generic/variance?

HaloFour commented Aug 28, 2015

@gafter It sounds like #4843 took it a little bit further by pushing for variance on this bottom/never/whatever type, allowing you to assign a Func<Never> to a Func<int> or Func<string> since the return type wouldn't matter. Is your proposal more syntax-candy or actually a change to the underlying type system and generic/variance?

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter Aug 28, 2015

Member

@HaloFour Yes, this proposal was intended to be for a new type at the bottom of the type hierarchy. #4843 is like a spec of what this is asking for.

Member

gafter commented Aug 28, 2015

@HaloFour Yes, this proposal was intended to be for a new type at the bottom of the type hierarchy. #4843 is like a spec of what this is asking for.

@Eyas

This comment has been minimized.

Show comment
Hide comment
@Eyas

Eyas Aug 28, 2015

Contributor

Great. I'm happy to see that an issue is being tracked. When creating #4843 I looked for a few keywords like 'bottom type' and 'nothing type' and didn't manage to find this. Generally a type for a throwing statement sounds great. never is a great name.

I'm always down to call things Bottom.. but yes, Never is good!

How close are we to get a proposal/spec for this? Could we explicitly call out that Never is a bottom type in the proposal?

Contributor

Eyas commented Aug 28, 2015

Great. I'm happy to see that an issue is being tracked. When creating #4843 I looked for a few keywords like 'bottom type' and 'nothing type' and didn't manage to find this. Generally a type for a throwing statement sounds great. never is a great name.

I'm always down to call things Bottom.. but yes, Never is good!

How close are we to get a proposal/spec for this? Could we explicitly call out that Never is a bottom type in the proposal?

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter Aug 28, 2015

Member

It requires CLR support for variance to work. That probably can't happen until C# 9 or so, so this is on the back burner.

Member

gafter commented Aug 28, 2015

It requires CLR support for variance to work. That probably can't happen until C# 9 or so, so this is on the back burner.

@eyalsk

This comment has been minimized.

Show comment
Hide comment
@eyalsk

eyalsk Jun 10, 2016

C# 9.. that's a long time! :D

eyalsk commented Jun 10, 2016

C# 9.. that's a long time! :D

@omariom

This comment has been minimized.

Show comment
Hide comment
@omariom

omariom Jun 24, 2016

CLR could take advantage of that and optimize generated code around callsites of never returning methods as it does now with throws .

omariom commented Jun 24, 2016

CLR could take advantage of that and optimize generated code around callsites of never returning methods as it does now with throws .

@gafter

This comment has been minimized.

Show comment
Hide comment
@gafter

gafter May 15, 2017

Member

We are now taking language feature discussion in other repositories:

Features that are under active design or development, or which are "championed" by someone on the language design team, have already been moved either as issues or as checked-in design documents. For example, the proposal in this repo "Proposal: Partial interface implementation a.k.a. Traits" (issue 16139 and a few other issues that request the same thing) are now tracked by the language team at issue 52 in https://github.com/dotnet/csharplang/issues, and there is a draft spec at https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md and further discussion at issue 288 in https://github.com/dotnet/csharplang/issues. Prototyping of the compiler portion of language features is still tracked here; see, for example, https://github.com/dotnet/roslyn/tree/features/DefaultInterfaceImplementation and issue 17952.

In order to facilitate that transition, we have started closing language design discussions from the roslyn repo with a note briefly explaining why. When we are aware of an existing discussion for the feature already in the new repo, we are adding a link to that. But we're not adding new issues to the new repos for existing discussions in this repo that the language design team does not currently envision taking on. Our intent is to eventually close the language design issues in the Roslyn repo and encourage discussion in one of the new repos instead.

Our intent is not to shut down discussion on language design - you can still continue discussion on the closed issues if you want - but rather we would like to encourage people to move discussion to where we are more likely to be paying attention (the new repo), or to abandon discussions that are no longer of interest to you.

If you happen to notice that one of the closed issues has a relevant issue in the new repo, and we have not added a link to the new issue, we would appreciate you providing a link from the old to the new discussion. That way people who are still interested in the discussion can start paying attention to the new issue.

Also, we'd welcome any ideas you might have on how we could better manage the transition. Comments and discussion about closing and/or moving issues should be directed to #18002. Comments and discussion about this issue can take place here or on an issue in the relevant repo.


Discussion on this issue has moved to dotnet/csharplang#538

Member

gafter commented May 15, 2017

We are now taking language feature discussion in other repositories:

Features that are under active design or development, or which are "championed" by someone on the language design team, have already been moved either as issues or as checked-in design documents. For example, the proposal in this repo "Proposal: Partial interface implementation a.k.a. Traits" (issue 16139 and a few other issues that request the same thing) are now tracked by the language team at issue 52 in https://github.com/dotnet/csharplang/issues, and there is a draft spec at https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md and further discussion at issue 288 in https://github.com/dotnet/csharplang/issues. Prototyping of the compiler portion of language features is still tracked here; see, for example, https://github.com/dotnet/roslyn/tree/features/DefaultInterfaceImplementation and issue 17952.

In order to facilitate that transition, we have started closing language design discussions from the roslyn repo with a note briefly explaining why. When we are aware of an existing discussion for the feature already in the new repo, we are adding a link to that. But we're not adding new issues to the new repos for existing discussions in this repo that the language design team does not currently envision taking on. Our intent is to eventually close the language design issues in the Roslyn repo and encourage discussion in one of the new repos instead.

Our intent is not to shut down discussion on language design - you can still continue discussion on the closed issues if you want - but rather we would like to encourage people to move discussion to where we are more likely to be paying attention (the new repo), or to abandon discussions that are no longer of interest to you.

If you happen to notice that one of the closed issues has a relevant issue in the new repo, and we have not added a link to the new issue, we would appreciate you providing a link from the old to the new discussion. That way people who are still interested in the discussion can start paying attention to the new issue.

Also, we'd welcome any ideas you might have on how we could better manage the transition. Comments and discussion about closing and/or moving issues should be directed to #18002. Comments and discussion about this issue can take place here or on an issue in the relevant repo.


Discussion on this issue has moved to dotnet/csharplang#538

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment