plan for return requirements

1,026 views
Skip to first unread message

Russ Cox

unread,
Feb 28, 2013, 11:48:01 PM2/28/13
to golang-dev
For Go 1.1 we propose to specify when a function requires a return statement. The 6g and gccgo compilers agree today, by design, but the details have never been part of the spec. At the same time, we propose to make the requirements a little less strict.

The details are at http://golang.org/s/go11return. Comments are welcome in this thread.

Thanks.
Russ

andrey mirtchovski

unread,
Mar 1, 2013, 12:16:12 AM3/1/13
to golang-dev
offtopic, sorry, but:

"In total, I downloaded 38,734 Go source files containing 8,330,489 lines."

unique? wow!

Russ Cox

unread,
Mar 1, 2013, 12:25:55 AM3/1/13
to andrey mirtchovski, golang-dev
Hard to say. There are definitely some dups. For example camlistore includes a bunch of other projects. I put a copy of the go source files only (not the .git and .hg directories and not any non-go files) at https://code.google.com/p/rsc/downloads/detail?name=pubgo.zip. 66 MB compressed, 225 MB uncompressed.

Russ

Andrew Wilkins

unread,
Mar 1, 2013, 2:30:31 AM3/1/13
to golan...@googlegroups.com
On Friday, 1 March 2013 12:48:01 UTC+8, rsc wrote:
For Go 1.1 we propose to specify when a function requires a return statement. The 6g and gccgo compilers agree today, by design, but the details have never been part of the spec. At the same time, we propose to make the requirements a little less strict.

The details are at http://golang.org/s/go11return. Comments are welcome in this thread.

I don't have much to say, other than SGTM. Will these rules be added to go/types?
I can't think of any good reason to implement alternative three, seems to be excessive for little gain.
Alternative four sounds like it'd cause more problems than it'd solve.

Cheers,
Andrew

Jan Mercl

unread,
Mar 1, 2013, 3:55:54 AM3/1/13
to Russ Cox, golang-dev
"The godoc.org web site listed 6,021 known open source Go packages,
and I downloaded all the ones I could using “go get.” In total, I
downloaded 38,734 Go source files containing 8,330,489 lines."

"In total, there are 2,112 function-ending panics in the source files."

2,112 such functions in 38,734 Go source files is about 1 such
function in 18 Go source files (and cca only one per three packages).
One Go source file typically consists of more than one function. Let
me estimate there are at least 5 funcs/package on average.

Whatever the resolution is going to be, it can improve the life of
perhaps not even 1% of function written out there. Which I'm not sure
is worth of the effort.

-j

PS: Local numbers:

(09:45) jnml@fsc-r550:~/src/github.com/cznic$ grep -nr
'panic("unreachable")' * | wc -l
59
(09:45) jnml@fsc-r550:~/src/github.com/cznic$ find -name \*.go | wc -l
166
(09:45) jnml@fsc-r550:~/src/github.com/cznic$

roger peppe

unread,
Mar 1, 2013, 5:32:59 AM3/1/13
to Russ Cox, golang-dev
looks great to me.

mg

unread,
Mar 1, 2013, 8:53:44 AM3/1/13
to golan...@googlegroups.com
On Friday, March 1, 2013 5:48:01 AM UTC+1, rsc wrote:
At the same time, we propose to make the requirements a little less strict.

In my opinion the current behaviour is acceptable, further complicating
the spec is not worth it.  At least I don't have to additionally
remember or teach the less strict rules ;-)

Ermm, my very naive feeling is, the Go tool chain could (as with the semicolon)
do the panic() legwork.

Martin

Michael Jones

unread,
Mar 1, 2013, 9:15:35 AM3/1/13
to roger peppe, Russ Cox, golang-dev
Russ, one comment on "...or return the current values of the named return parameters on reaching the end." This case, once that I was going to mention in your definition at the top of the proposal, makes sense to me even though your next sentence says you don't like it. Here's why I do:

a. A function with named result parameters by the spec has those values set to their zero vales before the body of the function is entered. Having those values returned to the caller upon function return is of course the rule of the spec as well. This means that a call-return with no changing of the value of these return parameters is completely defined by the spec and consistent, i.e., not a "fault" to be caught.

b. Such functions can the values of their return parameters directly with "paramName = value; ...; return" or indirectly with "return value" where the second feels a shorthand for the former. In neither case is there doubt about the meaning or unclarity in the code.

c. The end of any subroutine is the return to its caller. This is axiomatic. So too is returning the named parameter values to the caller. The "I'm returning now" of a bare "return" before the final "}" as at present feels redundant to me. Where else was the function going to go with the program counter other than back to the caller? What else was going to be returned other than the named parameters whose values were already established? It feels like stuttering to me.

That's why I'm a fan of implicit return for named result value functions. I would change the spec to say, "The return statement is optional in functions with named result parameters. Using it causes an assignment to all result parameters before returning to the caller." 


--

---
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.





--
Michael T. Jones | Chief Technology Advocate  | m...@google.com |  +1 650-335-5765

Robert Griesemer

unread,
Mar 1, 2013, 9:16:06 AM3/1/13
to Andrew Wilkins, golan...@googlegroups.com

Yes, I plan to add checking for the new return rules in go/types very soon.
- gri

--

Russ Cox

unread,
Mar 1, 2013, 9:23:54 AM3/1/13
to Robert Griesemer, Andrew Wilkins, golang-dev
There is an implementation of these rules over the go/ast in CL 7440047. The label handling should be done better; it's what I used for the analysis.

Russ


Rob Pike

unread,
Mar 1, 2013, 2:12:45 PM3/1/13
to benjami...@ai-solutions.com, golan...@googlegroups.com, roger peppe, Russ Cox
For the record I disagree with the proposal to assume a naked return
at the end of a function because I have often made the mistake of
forgetting the return outright and as often as not the current values
of the named return parameters are not the ones I mean to return.

-rob, channeling Gertrude Stein

Russ Cox

unread,
Mar 1, 2013, 2:26:58 PM3/1/13
to Rob Pike, benjami...@ai-solutions.com, golang-dev, roger peppe
Also many functions name parameters for documentation purposes only, with no intention of using the naked return.

Russ

Michael Jones

unread,
Mar 1, 2013, 3:07:16 PM3/1/13
to Russ Cox, Rob Pike, benjami...@ai-solutions.com, golang-dev, roger peppe
Rob and Russ make good arguments. Much of Go is about minimizing risks of error and confusion. If this is one of those areas then I have a counter proposal--not counter to yours but to mine. ;-) If the implicit return scares you then why not disallow the bare return for named arguments too -- force the programmer to say "I am returning now" and also "I am sending SQRT and ERROR to the caller." It could always be done by echoing the return value names in the return statement:

func x(...) (a int, b float64) {
    :
    a = 7
    :
    if ... { a = 9 }
    :
    b = ...
    :

    return a, b
}

This way there would be nothing to forget.


On Fri, Mar 1, 2013 at 11:26 AM, Russ Cox <r...@golang.org> wrote:
Also many functions name parameters for documentation purposes only, with no intention of using the naked return.

Russ

Russ Cox

unread,
Mar 1, 2013, 3:09:38 PM3/1/13
to Michael Jones, Rob Pike, benjami...@ai-solutions.com, golang-dev, roger peppe
There's probably a case to be made and a discussion that could be had. But having allowed the naked 'return' in Go 1, we are not in a position now to remove it.

Russ

Michael Jones

unread,
Mar 1, 2013, 3:13:02 PM3/1/13
to Russ Cox, Rob Pike, benjami...@ai-solutions.com, golang-dev, roger peppe
Of course. Sorry. Well, then I can only say that your proposal is very nice as originally written! ;-)


On Fri, Mar 1, 2013 at 12:09 PM, Russ Cox <r...@golang.org> wrote:
There's probably a case to be made and a discussion that could be had. But having allowed the naked 'return' in Go 1, we are not in a position now to remove it.

Russ


Michael Jones

unread,
Mar 1, 2013, 5:00:02 PM3/1/13
to Russ Cox, Rob Pike, benjami...@ai-solutions.com, golang-dev, roger peppe
Delayed realization ... go vet or fmt could "clothe" naked returns with the formal parameter names, then Rob's concerns would be assuaged and any code--sans such polishing--would still be Go 1 compliant. There can be no doubt about this since the names have been parsed at the top and are there to be appended at the bottom...
--

Russ Cox

unread,
Mar 1, 2013, 5:21:15 PM3/1/13
to Michael Jones, Rob Pike, benjami...@ai-solutions.com, golang-dev, roger peppe
On Fri, Mar 1, 2013 at 2:00 PM, Michael Jones <m...@google.com> wrote:
Delayed realization ... go vet or fmt could "clothe" naked returns with the formal parameter names, then Rob's concerns would be assuaged and any code--sans such polishing--would still be Go 1 compliant. There can be no doubt about this since the names have been parsed at the top and are there to be appended at the bottom...

FWIW, due to shadowed variables, one cannot always do this. The return variable may not be visible in the scope of the return statement.

Russ

Russ Cox

unread,
Mar 2, 2013, 11:35:28 AM3/2/13
to Steven Blenkinsop, golang-dev, Michael Jones, Rob Pike, benjami...@ai-solutions.com, roger peppe
On Fri, Mar 1, 2013 at 6:12 PM, Steven Blenkinsop <stev...@gmail.com> wrote:
The implementation (Go 1.0) already disallows naked return statements with shadowed return variables, unless this is changing in Go 1.1.

Indeed. That's not changing (and naked returns aren't going away either).

Russ

Dan Kortschak

unread,
Mar 2, 2013, 4:13:55 PM3/2/13
to golan...@googlegroups.com
I'd like to put forward support for the second alternative, excluding items 5 and 8. I believe that 5 and 8 are orthogonal to the problem noted in Issue 65. As Russ notes, it is easy to avoid the requirement for an artificial panic with the current implementation, and I don't believe that the items' exclusion does result in an irregularity.

Dan

Dave Cheney

unread,
Mar 2, 2013, 4:31:14 PM3/2/13
to Dan Kortschak, golan...@googlegroups.com
Despite being possibly being labeled a stick in the mud, I throw my
hat in the ring for the first alternative, documenting rules 1 through
4, the current behavior.

On consideration, I believe that most cases where panic("unreachable")
is used could be rewritten to avoid the panic under rules 1 through 4,
and those that cannot must be so complex that the presence of a panic
is a signal to the reader to exercise caution.

Dave

Kyle Lemons

unread,
Mar 2, 2013, 9:44:03 PM3/2/13
to Dan Kortschak, golan...@googlegroups.com
On Sat, Mar 2, 2013 at 1:13 PM, Dan Kortschak <dan.ko...@adelaide.edu.au> wrote:
I'd like to put forward support for the second alternative, excluding items 5 and 8. I believe that 5 and 8 are orthogonal to the problem noted in Issue 65. As Russ notes, it is easy to avoid the requirement for an artificial panic with the current implementation, and I don't believe that the items' exclusion does result in an irregularity.

For what it's worth, I share a mild preference for requiring unnecessary else and default clauses to be removed, but I understand that it would be a non-orthogonality, and I don't mind leaving it as a stylistic point that I enforce when doing code reviews.

Robert Griesemer

unread,
Mar 2, 2013, 9:55:03 PM3/2/13
to Dan Kortschak, golan...@googlegroups.com
Here's another way of looking at this proposal. In essence it says:

a) return, goto, and panic are terminating
b) a single branch of control flow is terminating if the last statement in the branch is terminating.
c) a composite statement is terminating if all its branches of control flow are terminating.

The status quo is a) and b). The proposal adds c).

Rather simple and straight-forward.

Rule 5 and 8 are different sides of the same coin: An if is a switch is an if. So we can just talk about item 5 (if's.)

Without rule 5 (and thus 8), rule 6 seems out of place: Loops w/o conditions are relatively rare; and theoretically, a loop can be written recursively with a conditional, hence rule 6 can be seen as a variant of rule 5. That leaves rule 7, but select statements are even more rare relative to other statements, so why bother?

So the question really is: are we happy with the status quo, or do we want all statements be treated equally and add rule c). I think that is a valid question. If we believe the proposal is solving a real issue, we should consider it as a whole.

Personally, I believe the proposal solves a real issue, and I don't want the language to tell me how to write my if's or switches, as long as they are correct (even though I may favor the non-else style myself). There are reasons on occasion where a symmetric if may be better, for pedagogic, documentation, or other reasons.

- gri



On Sat, Mar 2, 2013 at 1:13 PM, Dan Kortschak <dan.ko...@adelaide.edu.au> wrote:
I'd like to put forward support for the second alternative, excluding items 5 and 8. I believe that 5 and 8 are orthogonal to the problem noted in Issue 65. As Russ notes, it is easy to avoid the requirement for an artificial panic with the current implementation, and I don't believe that the items' exclusion does result in an irregularity.

Dan

Dan Kortschak

unread,
Mar 2, 2013, 10:14:20 PM3/2/13
to Robert Griesemer, golan...@googlegroups.com
Thank you for that perspective on it, it makes it clearer in my mind why Russ sees it as an irregularity.

Robert Griesemer

unread,
Mar 3, 2013, 1:25:20 AM3/3/13
to Dan Kortschak, golan...@googlegroups.com
Thanks - though just to be clear, I am not presuming to know what Russ thinks :-) This is just how I see it.
- gri

Dan Kortschak

unread,
Mar 3, 2013, 2:00:16 AM3/3/13
to Robert Griesemer, golan...@googlegroups.com
No, of course. Thinking on it further, the three points you made would be a good preface to the spec rules, as a explanation for why the rules are what they are.

Alan Donovan

unread,
Mar 3, 2013, 10:15:43 PM3/3/13
to Russ Cox, golang-dev
Nice doc---sorry it took me a while to read it.

I have no quibbles with your proposed course of action, but two minor
comments on the doc:

(1) You might want to mention a sixth kind of call, even if only to
explain it away as sugar around the fifth:

type I interface { f(...) }
f := I.f // "standalone" interface method; equivalent to f :=
func(i I, ...) { return i.f(...) }
var i I
f(i, ...)

(2) The doc makes reference to the classic "two word" formulation of
closures, building the expectation that that's what you're going to
propose--but it isn't. The New Implementation section could
explicitly dismiss it briefly.

Feel free to ignore both of these comments if you don't intend the doc
to stick around after you've finished the work, but I hope that's not
the case, as it's a lucid explanation of and motivation for the new
(and soon to be current) implementation.

cheers
alan

Alan Donovan

unread,
Mar 3, 2013, 10:32:46 PM3/3/13
to Russ Cox, golang-dev
Brad points out that this belongs in Russ's other thread about
functions---sorry for the noise.

Russ Cox

unread,
Mar 4, 2013, 9:52:42 AM3/4/13
to golan...@googlegroups.com
On Fri, Mar 1, 2013 at 12:55 AM, Jan Mercl <0xj...@gmail.com> wrote:
2,112 such functions in 38,734 Go source files is about 1 such
function in 18 Go source files (and cca only one per three packages).
One Go source file typically consists of more than one function. Let
me estimate there are at least 5 funcs/package on average. 

Whatever the resolution is going to be, it can improve the life of
perhaps not even 1% of function written out there. Which I'm not sure
is worth of the effort.

On Fri, Mar 1, 2013 at 5:53 AM, mg <extraterrestr...@gmail.com> wrote:
In my opinion the current behaviour is acceptable, further complicating
the spec is not worth it.  At least I don't have to additionally
remember or teach the less strict rules ;-)
 
On Sat, Mar 2, 2013 at 1:31 PM, Dave Cheney <da...@cheney.net> wrote:
On consideration, I believe that most cases where panic("unreachable")
is used could be rewritten to avoid the panic under rules 1 through 4,
and those that cannot must be so complex that the presence of a panic
is a signal to the reader to exercise caution.

(and others not quoted)

Thanks for all the feedback.

I understand this general point of view, and to some extent I sympathize with it, but I believe the data is on the side of fixing things. 

It is true that there the 2,112 panics are a small fraction of the tree I examined, but even low-frequency constructs can have a significant impact on the feel of the language. That same tree has fewer than 3,000 select statements. A more compelling stat is that of the panics mentioning words like "reachable" or "never", this proposal eliminates the need for 75%. And of the ones that are actually unreachable, even in the presence of unexpected inputs, the proposal eliminates very nearly 100%.

The bulk of the effort is in gathering data and deciding what to do, both of which are fixed costs and almost fully paid. The ongoing costs of implementing and remembering the rule are more important, and the design is intended to minimize these. I actually believe the new rule is easier to teach and remember than the current ones. It can be stated as follows: if you can tell just from the shape of last statement (that is, ignoring the types and values involved) that it always redirects control away from the closing }, then the function is terminated properly; otherwise the function is missing a return. Today we have the very same rule, with special cases excluding the examination of if, for, switch, and select statements. I think that's harder to learn and to remember. In fact with the new rule I think it might be reasonable to leave it unmentioned: in far more cases it behaves exactly how people expect, much the same way you don't have to teach what x = y + z means. Considering only the final statement - and not everything that follows - was another conscious decision intended to reduce the evaluation cost both for compilers and people.

Most cases where panic("unreachable") is used and eliminated by this proposal are following non-terminating for loops (622 out of 1,007), and that case cannot be rewritten to avoid the panic. I gave an example of such a loop in the doc:

func readNonEmpty(c chan []byte) []byte {
        for {
                if p := <-c; len(p) > 0 {
                        return p
                }
        }
}

and in fact I think the code is clearer without the panic: from now on, when you see that loop without a panic you will be able to reason "well that for loop really must never terminate - no matter how complex it is - because otherwise the function would not compile".

Stepping into the qualitative realm for a minute, the effect of this change is to reduce the number of false positives for this compiler error, so that when the compiler says a function is missing a return, it is far more likely that it really is. This increases the signal-to-noise ratio of the interaction with the compiler, moving Go programs one more step in the right direction along the axis in the Dick Gabriel quote.*

Russ

* Part of his and Guy Steele's 50 in 50 talk: "At HOPL in 1978, Nygaard called himself a research worker. I'm always delighted by the light touch and stillness of early programming languages. Not much text; a lot gets done. Old programs read like quiet conversations between a well-spoken research worker and a well-studied mechanical colleague, not as a debate with a compiler. Who'd have guessed sophistication bought such noise?" http://www.youtube.com/watch?v=Nii1n8PYLrc

Michael Jones

unread,
Mar 4, 2013, 10:58:22 AM3/4/13
to Russ Cox, golan...@googlegroups.com
Absolutely a great plan. Also, on an emotional level, warnings/refusals about non-events are irritating.

--
 
---
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Russ Cox

unread,
Mar 5, 2013, 1:54:48 PM3/5/13
to Michael Jones, golan...@googlegroups.com
Done at tip.

Reply all
Reply to author
Forward
0 new messages