deadmut

command module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2026 License: MIT Imports: 4 Imported by: 0

README

deadmut

A Go linter that detects mutations to range loop value copies.

Name origin: "dead mutation" = mutation with no effect

Background

Go's range loop copies values, so modifications to the copy don't affect the original slice:

for _, user := range users {
    user.Name = "updated"  // Does NOT update the original slice!
}

This is:

  • A common pitfall for beginners
  • Not a compile error
  • Not a runtime panic
  • A silent bug

Comparison with Existing Linters

Linter Detects Range loop value mutation
staticcheck SA4005 Field assignment to value receiver No
copyloopvar i := i copy pattern Different issue
ineffassign Assignment to unused variable No
loopclosure Capture in goroutine/defer Different issue
deadmut Mutation to range loop value Yes

Installation

go install github.com/mickamy/deadmut@latest

Usage

deadmut ./...

What It Detects

1. Field Assignment
for _, user := range users {
    user.Name = "updated"  // deadmut: mutation to range value copy has no effect
}
2. Pointer Receiver Method Call
for _, user := range users {
    user.SetName("updated")  // deadmut: pointer receiver method on range value copy has no effect
}
3. Taking Pointer of Value
for _, user := range users {
    updateUser(&user)  // deadmut: pointer to range value copy may not have intended effect
}

What It Ignores

Index Access
for i := range users {
    users[i].Name = "updated"  // OK - direct modification
}
Slice of Pointers
for _, user := range users {  // users is []*User
    user.Name = "updated"  // OK - modifying via pointer
}
Value Used After Mutation
for _, user := range users {
    user.Name = "updated"
    process(user)  // OK - intentionally using the copy
}
Collecting Copies
for _, user := range users {
    user.Name = "updated"
    results = append(results, user)  // OK - collecting modified copies
}

How to Fix

// Before (bug)
for _, user := range users {
    user.Name = "updated"
}

// After (fix 1: use index)
for i := range users {
    users[i].Name = "updated"
}

// After (fix 2: use pointer slice)
for _, user := range users {  // users is []*User
    user.Name = "updated"
}

License

MIT

Documentation

Overview

deadmut detects mutations to range loop value copies that have no effect.

Directories

Path Synopsis
internal
analyzer
Package analyzer provides a linter that detects mutations to range loop value copies.
Package analyzer provides a linter that detects mutations to range loop value copies.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL