Description
Go Programming Experience
Experienced
Other Languages Experience
Go, Ruby, JavaScript, C, Python, Elixir, Kotlin, Dart
Related Idea
- Has this idea, or one like it, been proposed before?
- Does this affect error handling?
- Is this about generics?
- Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit
Has this idea, or one like it, been proposed before?
As far as I know, no.
Does this affect error handling?
Not directly, but it can help with certain existing error handling patterns.
Is this about generics?
No.
Proposal
I propose adding a new builtin nothing
type, nothing
would only be valid to use as a return type of a function and would indicate that the function never returns because every code path in the function either stays in an infinite loop forever, panics, or calls a function that returns nothing
.
This would primarily be helpful for writing helper functions for code that passes data around via panic and recover. For example, in a recent project of mine I used this mechanism in a recursive descent parser to get unrecoverable errors back up to the top of the recursion without needing to return and check them at every step of the recursion. To help with this, I wrote a number of methods along the lines of func (p *parser) raiseUnexpectedToken(tok scanner.Token)
that simply construct the correct error type and then panic it, and that panic is then recovered at the top of the parser's recursion. However when I use those methods instead of panicking directly, which is more error prone as passing the wrong thing will prevent the recover from catching It, Go can't tell that the code won't continue after the call site. This leads to me having to put dummy return
statements after every call to any of those helper functions. Not a huge deal, but certainly an annoyance, and it makes reading the code more confusing as it looks like the code returns there.
A nothing
builtin would also have the benefit of being able to enforce that the function actually doesn't return, thus making the implementation of functions for that purpose safer.
Example
func raiseNegative() nothing {
panic(errors.New("negative"))
}
func example(v int) int {
switch {
case v < 0:
raiseNegative()
// Without nothing, this line would have to return something.
default:
return v
}
}
Reflect
reflect
is the biggest complication that I can think of with this. For example, code like
reflect.New(reflect.TypeOf(func() nothing { panic(nil) }).Out(0))
would have to do something, despite it not being legal to do new(nothing)
in regular Go code. Simply panicking is probably the simplest approach.
nothing
might also need its own reflect.Kind
.
Bikeshedding
I'm very much not stuck on nothing
as the name. Some alternatives that I also kind of like are noreturn
and panics
.
Language Spec Changes
No response
Informal Change
The nothing
predeclared identifier can be used as the sole return type of a function to indicate that it never returns. If a function is marked with this, every code path in the function must either loop forever, panic, or call a function that also returns nothing
.
Is this change backward compatible?
Yes.
Orthogonality: How does this change interact or overlap with existing features?
It fits well with panic()
.
Would this change make Go easier or harder to learn, and why?
Mildly harder, perhaps. It's not a very complicated feature.
Cost Description
- A new predeclared identifier.
- A new
reflect.Kind
, potentially. - Slight increase in complexity to type-checking to handle the various cases that
nothing
is for.
Changes to Go ToolChain
Anything that parsed Go code would be affected.
Performance Costs
Very minor increase to compile-time cost. No increase at all to runtime.
Prototype
No response