func castIfOverflow(ident *ast.Ident) ast.Expr { c, ok := defs[ident].(*types.Const) if !ok || c == nil { return ident } v := c.Val() switch { case v.Kind() != exact.Int: return ident case exact.Compare(v, token.LSS, minInt32): return &ast.CallExpr{Fun: ast.NewIdent("int64"), Args: []ast.Expr{ident}} case exact.Compare(v, token.GTR, maxInt32): return &ast.CallExpr{Fun: ast.NewIdent("uint64"), Args: []ast.Expr{ident}} default: return ident } }
func (check *Checker) comparison(x, y *operand, op token.Token) { // spec: "In any comparison, the first operand must be assignable // to the type of the second operand, or vice versa." err := "" if x.assignableTo(check.conf, y.typ) || y.assignableTo(check.conf, x.typ) { defined := false switch op { case token.EQL, token.NEQ: // spec: "The equality operators == and != apply to operands that are comparable." defined = Comparable(x.typ) || x.isNil() && hasNil(y.typ) || y.isNil() && hasNil(x.typ) case token.LSS, token.LEQ, token.GTR, token.GEQ: // spec: The ordering operators <, <=, >, and >= apply to operands that are ordered." defined = isOrdered(x.typ) default: unreachable() } if !defined { typ := x.typ if x.isNil() { typ = y.typ } err = check.sprintf("operator %s not defined for %s", op, typ) } } else { err = check.sprintf("mismatched types %s and %s", x.typ, y.typ) } if err != "" { check.errorf(x.pos(), "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err) x.mode = invalid return } if x.mode == constant && y.mode == constant { x.val = exact.MakeBool(exact.Compare(x.val, op, y.val)) // The operands are never materialized; no need to update // their types. } else { x.mode = value // The operands have now their final types, which at run- // time will be materialized. Update the expression trees. // If the current types are untyped, the materialized type // is the respective default type. check.updateExprType(x.expr, defaultType(x.typ), true) check.updateExprType(y.expr, defaultType(y.typ), true) } // spec: "Comparison operators compare two operands and yield // an untyped boolean value." x.typ = Typ[UntypedBool] }