Skip to content

x/tools/go/ssa: SanityCheckFunctions fails on non-constant shift with untyped constant left operand #77067

Description

@cpunion

Summary

When SanityCheckFunctions mode is enabled in golang.org/x/tools/go/ssa, it panics on code containing a nested shift expression where the inner shift has an untyped constant as the left operand and a runtime value as the right operand.

Reproduction

package main

func nestedShift(bytes []byte) uint32 {
    value := uint32(1)
    return value << (1 << bytes[3])  // SSA sanity check fails here
}

Error Output

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

Analysis

The issue arises because:

  1. go/types returns untyped int as the type for the expression 1 << bytes[3] in its TypeAndValue
  2. go/ssa builder uses this type directly when constructing the BinOp instruction (via emitArith)
  3. The sanity checker explicitly disallows untyped types in instruction results (sanity.go:202)

According to the Go spec:

"If the left operand of a non-constant shift expression is an untyped constant, it is first implicitly converted to the type it would assume if the shift expression were replaced by its left operand alone."

This means 1 << bytes[3] should have type int (the default type for untyped int), not untyped int.

Verification

Using go/types to inspect the types:

BinaryExpr: value << (1 << bytes[3]) => Type: uint32        # Correct
BinaryExpr: 1 << bytes[3]            => Type: untyped int   # Should be int per spec

Expected Behavior

Either:

  1. go/ssa should handle this case in emitArith by converting untyped left operands to their default type before creating the BinOp, OR
  2. The sanity check should not consider this an error

Environment

  • Go version: 1.24.11
  • golang.org/x/tools: v0.40.0

Workaround

We are currently working around this in our project (llgo) by fixing the TypesInfo before calling prog.CreatePackage.

Metadata

Metadata

Assignees

Labels

BugReportIssues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.ToolsThis label describes issues relating to any tools in the x/tools repository.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions