type opPredicates map[syntax.Operator]func(Type) bool
-var unaryOpPredicates = opPredicates{
- syntax.Add: isNumeric,
- syntax.Sub: isNumeric,
- syntax.Xor: isInteger,
- syntax.Not: isBoolean,
+var unaryOpPredicates opPredicates
+
+func init() {
+ // Setting unaryOpPredicates in init avoids declaration cycles.
+ unaryOpPredicates = opPredicates{
+ syntax.Add: isNumeric,
+ syntax.Sub: isNumeric,
+ syntax.Xor: isInteger,
+ syntax.Not: isBoolean,
+ }
}
func (check *Checker) op(m opPredicates, x *operand, op syntax.Operator) bool {
x.mode = value
}
-var binaryOpPredicates = opPredicates{
- syntax.Add: isNumericOrString,
- syntax.Sub: isNumeric,
- syntax.Mul: isNumeric,
- syntax.Div: isNumeric,
- syntax.Rem: isInteger,
+var binaryOpPredicates opPredicates
- syntax.And: isInteger,
- syntax.Or: isInteger,
- syntax.Xor: isInteger,
- syntax.AndNot: isInteger,
+func init() {
+ // Setting binaryOpPredicates in init avoids declaration cycles.
+ binaryOpPredicates = opPredicates{
+ syntax.Add: isNumericOrString,
+ syntax.Sub: isNumeric,
+ syntax.Mul: isNumeric,
+ syntax.Div: isNumeric,
+ syntax.Rem: isInteger,
- syntax.AndAnd: isBoolean,
- syntax.OrOr: isBoolean,
+ syntax.And: isInteger,
+ syntax.Or: isInteger,
+ syntax.Xor: isInteger,
+ syntax.AndNot: isInteger,
+
+ syntax.AndAnd: isBoolean,
+ syntax.OrOr: isBoolean,
+ }
}
// If e != nil, it must be the binary expression; it may be nil for non-constant expressions
// If it doesn't exist, the result is Typ[Invalid].
// under must only be called when a type is known
// to be fully set up.
-//
-// under is set to underf to avoid an initialization cycle.
-// TODO(gri) this doesn't happen in go/types - investigate
-var under func(Type) Type
-
-func init() {
- under = underf
-}
-
-func underf(t Type) Type {
+func under(t Type) Type {
// TODO(gri) is this correct for *Sum?
if n := asNamed(t); n != nil {
return n.under()