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

Open
gafter opened this Issue Mar 12, 2015 · 18 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
Contributor

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

@gafter
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
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

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 mean that this Never type would have to be implicitly convertible to any type, right?

@gafter
Member
gafter commented Mar 16, 2015

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

@matlus
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
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
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
Member
gafter commented Apr 24, 2015

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

@diab0l
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
Member
gafter commented Aug 27, 2015

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

@HaloFour

@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
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
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
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.

@gafter gafter added the 1 - Planning label Nov 20, 2015
@MadsTorgersen MadsTorgersen was unassigned by gafter Nov 20, 2015
@eyalsk
eyalsk commented Jun 10, 2016

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

@omariom
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 .

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