Repository: go
Issue: spec: clarify assignability for non-constant untyped boolean values
Labels: Documentation,NeedsInvestigation

Consider the initialization of `c` in the following example:

http://play.golang.org/p/iwCeX6lwkg

``` Go
package main
var (
    a, b int
    c    bool = a > b
)
func main() {}
```

We have an untyped boolean value result of the comparison operator ("Comparison
operators compare two operands and yield an untyped boolean value.")

Regarding the declaration of `c` in the example, the specification says
(https://golang.org/ref/spec#Variable_declarations):

> (1) If a list of expressions is given, the variables are initialized with the
> expressions following the rule for assignments.
> (2) Otherwise, each variable is initialized to its zero value.
> 
> (3) If a type is present, each variable is given that type.
> (4) Otherwise, each variable is given the type of the corresponding
> initialization value in the assignment.  If that value is an untyped constant,
> it is first converted to its default type; if it is an untyped boolean value,
> it is first converted to type bool.

The example falls in the clauses (1) and (3). Clause (2) is not applicable,
because an initializer expression is given and (4) is not applicable, because a
type is present; in particular, the implicit conversion to `bool` in specified
by (4) does not take place.

Then, following (1) we consult the "rules for assignments"
(https://golang.org/ref/spec#Assignments)

> In assignments, each value must be assignable to the type of the operand to
> which it is assigned, with the following special cases:
> (1) Any typed value may be assigned to the blank identifier.
> (2) If an untyped constant is assigned to a variable of interface type or the
> blank identifier, the constant is first converted to its default type.
> (3) If an untyped boolean value is assigned to a variable of interface type or
> the blank identifier, it is first converted to type bool.

The special case (1) is not applicable, because neither the assignments is to
the blank identifier, nor the assigned value is untyped.

The special case (2) is not applicable, because neither the assigned value is an
untyped constant (it's not a constant), nor it is assigned to a variable of an
interface type (the type is `bool`), nor to the blank identifier

The special case (3) is not applicable, because the untyped boolean value is not
assigned to a variable of an interface type, or the blank identifier.

Therefore, the initialization of `c` must be checked according to the
assignability criteria (https://golang.org/ref/spec#Assignability) :

> A value x is assignable to a variable of type T ("x is assignable to T") in
> any of these cases:
> (1) x's type is identical to T.
> (2) x's type V and T have identical underlying types and at least one of V or T is
> not a named type.
> (3) T is an interface type and x implements T.
> (4) x is a bidirectional channel value, T is a channel type, x's type V and T have
> identical element types, and at least one of V or T is not a named type.
> (5) x is the predeclared identifier nil and T is a pointer, function, slice, map,
> channel, or interface type.
> (6) x is an untyped constant representable by a value of type T.

Clause (1) is not applicable because `T` is `bool` and the value is untyped
boolean.

Clause (2) is not applicable, because there is no way to derive an "underlying
type" (https://golang.org/ref/spec#Types) untyped boolean values.

Clause (3) is not applicable because `bool` is not an interface type.

Clause (4) is not applicable, because neither the expression's type, nor `T` is
a channel type.

Clause (5) it not applicable, because neither the expression if the `nil`, nor
`T` is one of the enumerated in the clause types.

Clause (6) is not applicable, because the expression is not an untyped constant.

In conclusion, I couldn't find a text the specification, which renders the above
example program as correct.  Similar issues arise with initializations and
assignments involving the additional untyped boolean values, yielded by type
assertions, receive operators, or map index operators.

The compilers (`go`, `gccgo` and `gotypes`) all accept the example program.

It seems there's an omission in the specification. One possible way to fix it is
to add to the assignability criteria a clause, which specifies that an untyped
boolean value is assignable to `T` if the underlying type of `T` is `bool`.