Skip to content

SSA sanity check fails on nested shift with untyped constant: value << (1 << byteVar) #1530

@cpunion

Description

@cpunion

Description

When compiling code containing a nested shift expression where the inner shift has an untyped constant as the left operand and a byte variable as the right operand, the SSA sanity check fails with:

Error: function xxx, block 0: instruction has 'untyped' result: t2 = 1:untyped int << t1 : untyped int
Error: function xxx, block 0: operand #0 of convert uint <- untyped int (t2) is untyped: untyped int
panic: SanityCheck failed

Reproduction

The following code triggers the bug:

func nestedShift(bytes []byte) uint32 {
    value := uint32(1)
    return value << (1 << bytes[3])  // BUG: inner shift produces untyped int
}

This pattern is used in real-world code, e.g., github.com/marcinbor85/gohex:

adr = uint32(binary.BigEndian.Uint16(bytes[4:6])) << (1 << bytes[3])

SSA Output

The SSA for the nested shift shows the problem:

t1 = *t0                                           byte
t2 = 1:untyped int << t1                    untyped int  ← BUG
t3 = convert uint <- untyped int (t2)              uint
t4 = 1:uint32 << t3                              uint32

The expression 1 << t1 produces untyped int instead of being properly typed.

Key Observation

  • uint(1 << bytes[3]) - ✅ Works (simple shift with explicit conversion)
  • value << (1 << bytes[3]) - ❌ Fails (nested shift, inner expression untyped)

The bug is triggered when an untyped shift expression is used as the right operand of another shift expression.

Environment

  • Go version: 1.24.x
  • golang.org/x/tools: v0.36.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions