Commit 5bb29fb1 authored by Rob Pike's avatar Rob Pike

spec changes for panic and recover.

R=rsc, gri
CC=golang-dev
https://golang.org/cl/763041
parent 6358e1fa
......@@ -1108,7 +1108,7 @@ The comparison operators <code>==</code> and <code>!=</code>
key type; thus the key type must be a boolean, numeric, string, pointer, function, interface,
map, or channel type. If the key type is an interface type, these
comparison operators must be defined for the dynamic key values;
failure will cause a run-time error.
failure will cause a <a href="#Run_time_panics">run-time panic</a>.
</p>
......@@ -2397,7 +2397,8 @@ or for <code>a</code> of type <code>S</code> where <code>S</code> is a <a href="
<li><code>x</code> must be an integer value and <code>0 &lt;= x &lt; len(a)</code></li>
<li><code>a[x]</code> is the array element at index <code>x</code> and the type of
<code>a[x]</code> is the element type of <code>A</code></li>
<li>if the index <code>x</code> is out of range, a run-time exception occurs</li>
<li>if the index <code>x</code> is out of range,
a <a href="#Run_time_panics">run-time panic</a> occurs</li>
</ul>
<p>
......@@ -2409,7 +2410,8 @@ where <code>T</code> is a <a href="#String_types">string type</a>:
<li><code>a[x]</code> is the byte at index <code>x</code> and the type of
<code>a[x]</code> is <code>byte</code></li>
<li><code>a[x]</code> may not be assigned to
<li>if the index <code>x</code> is out of range, a run-time exception occurs</li>
<li>if the index <code>x</code> is out of range,
a <a href="#Run_time_panics">run-time panic</a> occurs</li>
</ul>
<p>
......@@ -2542,8 +2544,9 @@ of <code>x</code> implements the interface <code>T</code> (§<a href="#Interface
</p>
<p>
If the type assertion holds, the value of the expression is the value
stored in <code>x</code> and its type is <code>T</code>. If the type assertion is false, a run-time
exception occurs. In other words, even though the dynamic type of <code>x</code>
stored in <code>x</code> and its type is <code>T</code>. If the type assertion is false,
a <a href="#Run_time_panics">run-time panic</a> occurs.
In other words, even though the dynamic type of <code>x</code>
is known only at run-time, the type of <code>x.(T)</code> is
known to be <code>T</code> in a correct program.
</p>
......@@ -2562,7 +2565,7 @@ the result of the assertion is a pair of values with types <code>(T, bool)</code
If the assertion holds, the expression returns the pair <code>(x.(T), true)</code>;
otherwise, the expression returns <code>(Z, false)</code> where <code>Z</code>
is the <a href="#The_zero_value">zero value</a> for type <code>T</code>.
No run-time exception occurs in this case.
No run-time panic occurs in this case.
The type assertion in this construct thus acts like a function call
returning a value and a boolean indicating success. (§<a href="#Assignments">Assignments</a>)
</p>
......@@ -4281,7 +4284,7 @@ Deferred function calls are executed in LIFO order
immediately before the surrounding function returns,
after the return values, if any, have been evaluated, but before they
are returned to the caller. For instance, if the deferred function is
a <a href="#Function_literals">function literal<a/> and the surrounding
a <a href="#Function_literals">function literal</a> and the surrounding
function has <a href="#Function_types">named result parameters</a> that
are in scope within the literal, the deferred function may access and modify
the result parameters before they are returned.
......@@ -4510,6 +4513,150 @@ var im = imag(b) // has type float
var rl = real(c64) // type float32
</pre>
<h3 id="Handling_panics">Handling panics</h3>
<p> Two built-in functions, <code>panic</code> and <code>recover</code>,
assist in reporting and handling <a href="#Run_time_panics">run-time panics</a>
and program-defined error conditions.
</p>
<pre class="grammar">
func panic(interface{})
func recover() interface{}
</pre>
<p>
<font color=red>TODO: Most of this text could move to the respective
comments in <code>runtime.go</code> once the functions are implemented.
They are here, at least for now, for reference and discussion.
</font>
</p>
<p>
When a function <code>F</code> calls <code>panic</code>, normal
execution of <code>F</code> stops immediately. Any functions whose
execution was <a href="#Defer_statements">deferred</a> by the
invocation of <code>F</code> are run in the usual way, and then
<code>F</code> returns to its caller. To the caller, <code>F</code>
then behaves like a call to <code>panic</code>, terminating its own
execution and running deferred functions. This continues until all
functions in the goroutine have ceased execution, in reverse order.
At that point, the program is
terminated and the error condition is reported, including the value of
the argument to <code>panic</code>. This termination sequence is
called <i>panicking</i>.
</p>
<p>
The <code>recover</code> function allows a program to manage behavior
of a panicking goroutine. Executing a <code>recover</code> call
inside a deferred function (but not any function called by it) stops
the panicking sequence by restoring normal execution, and retrieves
the error value passed to the call of <code>panic</code>. If
<code>recover</code> is called outside the deferred function it will
not stop a panicking sequence. In this case, and when the goroutine
is not panicking, <code>recover</code> returns <code>nil</code>.
</p>
<p>
If the function defined here,
</p>
<pre>
func f(hideErrors bool) {
defer func() {
if x := recover(); x != nil {
println("panicking with value", v)
if !hideErrors {
panic(x) // go back to panicking
}
}
println("function returns normally") // executes only when hideErrors==true
}()
println("before")
p()
println("after") // never executes
}
func p() {
panic(3)
}
</pre>
<p>
is called with <code>hideErrors=true</code>, it prints
</p>
<pre>
before
panicking with value 3
function returns normally
</pre>
<p>
and resumes normal execution in the function that called <code>f</code>. Otherwise, it prints
</p>
<pre>
before
panicking with value 3
</pre>
<p>
and, absent further <code>recover</code> calls, terminates the program.
</p>
<p>
Since deferred functions run before assigning the return values to the caller
of the deferring function, a deferred invocation of a function literal may modify the
invoking function's return values in the event of a panic. This permits a function to protect its
caller from panics that occur in functions it calls.
</p>
<pre>
func IsPrintable(s string) (ok bool) {
ok = true
defer func() {
if recover() != nil {
println("input is not printable")
ok = false
}
// Panicking has stopped; execution will resume normally in caller.
// The return value will be true normally, false if a panic occurred.
}
panicIfNotPrintable(s) // will panic if validations fails.
}
</pre>
<!---
<p>
A deferred function that calls <code>recover</code> will see the
argument passed to <code>panic</code>. However, functions called
<i>from</i> the deferred function run normally, without behaving as
though they are panicking. This allows deferred code to run normally
in case recovery is necessary and guarantees that functions that manage
their own panics will not fail incorrectly. The function
</p>
<pre>
func g() {
s := ReadString()
defer func() {
if IsPrintable(s) {
println("finished processing", s)
} else {
println("finished processing unprintable string")
}
}()
Analyze(s)
}
</pre>
<p>
will not cause <code>IsPrintable</code> to print <code>"input is not printable"</code>
due to a <code>panic</code> triggered by the call to <code>Analyze</code>.
</p>
-->
<h3 id="Bootstrapping">Bootstrapping</h3>
......@@ -4524,7 +4671,6 @@ Function Behavior
print prints all arguments; formatting of arguments is implementation-specific
println like print but prints spaces between arguments and a newline at the end
panic like print, aborts execution after printing
</pre>
......@@ -4822,6 +4968,28 @@ Implementation restriction: The compiler assumes package <code>main</code>
is not imported by any other package.
</p>
<h2 id="Run_time_errors">Run-time panics</h2>
<p>
Execution errors such as attempting to index an array out
of bounds trigger a <i>run-time panic</i> equivalent to a call of
the built-in function <a href="#Handling_panics"><code>panic</code></a>
with a value of the implementation-defined interface type <code>runtime.Error</code>.
That type defines at least the method
<code>String() string</code>. The exact error values that
represent distinct run-time error conditions are unspecified,
at least for now.
</p>
<pre>
package runtime
type Error interface {
String() string
// and perhaps others
}
</pre>
<h2 id="System_considerations">System considerations</h2>
<h3 id="Package_unsafe">Package <code>unsafe</code></h3>
......@@ -4942,4 +5110,6 @@ The following minimal alignment properties are guaranteed:
<li><span class="alert">Gccgo allows only one init() function per source file.</span></li>
<li><span class="alert">Deferred functions cannot access the surrounding function's result parameters.</span></li>
<li><span class="alert">Function results are not addressable.</span></li>
<li><span class="alert">Recover is not implemented.</span></li>
<li><span class="alert">The implemented version of panic differs from its specification.</span></li>
</ul>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment