package main
func f(s1 uint, s2 uint) bool {
return ((1 << 32) << s1) > ((1 << 32) << s2)
}
If I understand correctly, (1<<32) is an untyped integer constant.
((1<<32)<<s1) is an untyped shift expression. Likewise for the right
operand.
After that, it gets complicated by the context type rule ("the type of
constant is what it would be if the shift operation were replaced by
the left operand alone"). If either operand is used in an assignment,
call, conversion, etc., then the context type is known and overflow
can be checked. If both operands are instead used in an arithmetic
operation, then determination of the context type can be deferred
until the outer context is known.
However, if both operands are used in a comparison expression, it's
not clear to me what the context type is. The old 8g I have on this
system seems to use "int" and gives the following for the example
above:
shift.go:3: constant 4294967296 overflows int
shift.go:3: constant 4294967296 overflows int
This is consistent with typeless variable declarations and makes sense
to me, but I can't find justification for it in the spec. Am I
missing an important rule, or is this just an oversight in the spec?
> However, if both operands are used in a comparison expression, it's
> not clear to me what the context type is. The old 8g I have on this
> system seems to use "int" and gives the following for the example
> above:
>
> shift.go:3: constant 4294967296 overflows int
> shift.go:3: constant 4294967296 overflows int
>
> This is consistent with typeless variable declarations and makes sense
> to me, but I can't find justification for it in the spec. Am I
> missing an important rule, or is this just an oversight in the spec?
I can't find it in the spec either. I suspect it's an oversight.
It's an interesting little hole.
I'm actually not at all fond of the rule that the type of a shift
operation is the type it would have if the left operand appeared
alone. It means that, e.g., float(1<<s) is erroneous. The context
type here is float, so the type of 1 becomes float, and you are not
permitted to shift a float. But I'm not sure how to fix it cleanly
without breaking int64(1<<s).
Ian
> I can't find it in the spec either. I suspect it's an oversight.
> It's an interesting little hole.
I opened an issue:
http://code.google.com/p/go/issues/detail?id=658
> I'm actually not at all fond of the rule that the type of a shift
> operation is the type it would have if the left operand appeared
> alone. It means that, e.g., float(1<<s) is erroneous. The context
> type here is float, so the type of 1 becomes float, and you are not
> permitted to shift a float. But I'm not sure how to fix it cleanly
> without breaking int64(1<<s).
I agree that the context type rule for shifting is onerous. A clearer
rule would be that the type of a shift expression is the type of the
left operand. That would mean your example would be spelled
int64(1)<<s.
Given the design of the language, I would guess there is some common C
programming error that the current rule prevents, but I'm not seeing
it. Do you know what it is?