Repository: go
Issue: proposal: spec: require return values to be explicitly used or ignored (Go 2)
Labels: LanguageChange,Proposal,error-handling,LanguageChangeReview

Today, if a Go function returns both a value and an error, the user must either assign the error to a variable
```go
v, err := computeTheThing()
```
or explicitly ignore it
```go
v, _ := computeTheThing()
```
However, errors that are the only return value (as from `io.Closer.Close` or  [`proto.Unmarshal`](https://godoc.org/github.com/golang/protobuf/proto#Unmarshal)) or paired with an often-unneeded return value (as from `io.Writer.Write`) are easy to accidentally forget, and not obvious in the code when forgotten.

```go
tx.Commit()  // Store the transaction in the database!
```

The same problem can occur even when errors are not involved, as in functional-style APIs:
```go
t := time.Now()
t.Add(10 * time.Second)  // Should be t = t.Add(…)
```
```go
strconv.AppendQuote(dst, "suffix")  // Should be dst = strconv.AppendQuote(…)
```

For the few cases where the user really does intend to ignore the return-values, it's easy to make that explicit in the code:
```go
_, _ = fmt.Fprintln(&buf, v)  // Writes to a bytes.Buffer cannot fail.

go func() { _, _ = fmt.Fprintln(os.Stderr, findTheBug()) }()
```
And that transformation should be straightforward to apply to an existing code base (e.g. in a Go 1-to-2 conversion).

On the other hand, the consequences of a forgotten error-check or a dropped assignment can be quite severe (e.g., corrupted entries stored to a production database, silent failure to commit user data to long-term storage, crashes due to unvalidated user inputs).

----

Other modern languages with explicit error propagation avoid this problem by requiring (or allowing API authors to require) return-values to be used.

* Swift warns about unused return values, but allows the warning to be suppressed if the [`@discardableResult`](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Attributes.html#//apple_ref/doc/uid/TP40014097-CH35-ID347) attribute is set.
  * Prior to a [change in Swift 3](https://github.com/apple/swift-evolution/blob/master/proposals/0047-nonvoid-warn.md), return-values could be ignored by default (but a warning could be added with `@warn_unused_result`)
* Rust has the [`#[must_use]`](https://doc.rust-lang.org/std/result/#results-must-be-used) attribute.
* C++17 has the [`[[nodiscard]]`](http://en.cppreference.com/w/cpp/language/attributes) attribute, which standardizes the longstanding `__attribute__((warn_unused_result))` GNU extension.
* The `ghc` Haskell compiler provides warning flags for unused results ([`-fwarn-unused-do-bind` and `-fwarn-wrong-do-bind`](https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/options-sanity.html)).
* OCaml warns about unused return values by default. It provides an [`ignore`](https://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html) function in the standard library.

I believe that the OCaml approach in particular would mesh well with the existing design of the Go language. 

I propose that Go should reject unused return-values by default.

If we do so, we may also want to consider an `ignore` built-in or keyword to ignore any number of values:
```go
go func() { ignore(fmt.Fprintln(os.Stderr, findTheBug())) }()
```
or
```go
go func() { ignore fmt.Fprintln(os.Stderr, findTheBug()) }()
```
or 
```go
go func() { _ fmt.Fprintln(os.Stderr, findTheBug()) }()
```
If we use a built-in function, we would probably want a corresponding `vet` check to avoid subtle eager-evaluation bugs:
```go
go ignore(fmt.Fprintln(os.Stderr, findTheBug()))  // BUG: evaluated immediately
```

----

**Related proposals**
Extending `vet` checks for dropped errors: #19727, #20148
Making the language more strict about unused variables in general: #20802 
Changing error-propagation: #19991