Skip to content

main: add tinygo fix - #5992

Open
davecheney wants to merge 1 commit into
tinygo-org:devfrom
davecheney:davecheney-overlay-fix-driver
Open

davecheney wants to merge 1 commit into
tinygo-org:devfrom
davecheney:davecheney-overlay-fix-driver

Conversation

@davecheney

Copy link
Copy Markdown
Contributor

go fix cannot load TinyGo's src packages or target-specific code because it does not know TinyGo's overlays and build tags.

Instead, tinygo fix runs the go fix analyzers through TinyGo's loader, so the same modernizations can be applied to TinyGo itself and to programs built for a TinyGo target.

/ht to @dgryski for the suggestion

@davecheney davecheney added this to the 0.44 milestone Oct 22, 2026
@davecheney

davecheney commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

This is mostly working now. It has some usability issues compared to regular go fix because the intersectional nature of tinygo's use of build tags. However, if applied surgically, it does work, examples follow.

More than modernising existing tinygo code, it unlocks the //go:fix inline pragma which lets us deprecate older methods and have code automatically rewriting from the forwarding stubs to newer forms. I'll include an example as well

@davecheney

davecheney commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

example one

./build/tinygo fix -target pico -diff -rangeint ./src/internal/reflectlite
-for i := uintptr(0); i < size; i++ {
+for range size {

example two

./build/tinygo fix -target pico -diff -rangeint ./src/machine/usb/msc
-for i := 0; i < length; i++ {
+for i := range length {

example three

./build/tinygo fix -C ~/devel/drivers -target pico -diff -rangeint ./ssd1289
-for i := uint8(0); i < 16; i++ {
+for i := range uint8(16) {
     pin := machine.Pin(i + uint8(firstPin))
     pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
 }

example four; interface{} -> any

./build/tinygo fix -C ~/devel/drivers -target pico -diff -any ./tester
- Fatalf(f string, a ...interface{})
+ Fatalf(f string, a ...any)

#5966 adds RandomUint32 and marks the old GetRNG wrapper with //go:fix inline.

TINYGOROOT=<rename-branch-sources> ./build/tinygo fix \
  -C <caller-module> -target pico -inline -diff .
-value, err := machine.GetRNG()
+value, err := machine.RandomUint32()

@davecheney
davecheney force-pushed the davecheney-overlay-fix-driver branch from b0b5d18 to 0f4e85c Compare October 22, 2026 13:34
@davecheney

Copy link
Copy Markdown
Contributor Author

The test failure is karma for fixing the tests so they actually run on windows :)

@davecheney
davecheney force-pushed the davecheney-overlay-fix-driver branch from 0f4e85c to fb7ea26 Compare October 22, 2026 14:02
@davecheney
davecheney marked this pull request as ready for review October 24, 2026 22:04
go fix cannot load TinyGo's src packages or target-specific code because
it does not know TinyGo's overlays and build tags. tinygo fix runs the
go fix analyzers through TinyGo's loader, so the same modernizations can
be applied to TinyGo itself and to programs built for a TinyGo target.
@davecheney
davecheney force-pushed the davecheney-overlay-fix-driver branch from fb7ea26 to 5b0b244 Compare October 24, 2026 22:04
@deadprogram

Copy link
Copy Markdown
Member

@davecheney thanks for working on fixing fix. I checked out this PR and ran the tests locally. Here are some notes edited from an automated review:

  1. /... patterns under TinyGo's src find no packages. ./src/machine/..., ./src/machine/usb/..., ./src/internal/... and ./src/runtime/... all end with no packages matched. The cached GOROOT has those directories as symlinks, and go list does not follow symlinks for .... ./src/... turns into std, which fails with package net (test) imports internal/poll: build constraints exclude all Go files. The error for plain ./src also suggests ./src/.... Perhaps expand these patterns by walking $TINYGOROOT/src instead of passing them to go list, or at least change that hint?

  2. The -diff output is always one hunk from the first change to the last, so unchanged lines in between show up as removed and added. For example tinygo fix -target pico -diff ./src/machine shows 83 lines of -/+ in machine_rp2_i2c.go and the whole roscRandByte function in machine_rp2_rng.go for two rangeint changes. The patch still applies, but it is hard to read. Separate hunks with 3 lines of context, like go fix -diff, might help.

  3. Test files are always loaded, so one test file that does not build for the target blocks the whole package. tinygo fix -target pico -diff ./src/os/... fails type checking in os_test.go and stat_test.go (chtmpdir, os.SameFile). Maybe add a way to leave tests out, or skip test packages that fail to type check with a warning?

  4. go1.25 is hardcoded in loader/analysis.go and must match minorMin in builder/config.go. Sharing one constant would keep them from drifting when the minimum Go version goes up.

What do you think? Thanks!

@davecheney

Copy link
Copy Markdown
Contributor Author

@davecheney thanks for working on fixing fix. I checked out this PR and ran the tests locally. Here are some notes edited from an automated review:

  1. /... patterns under TinyGo's src find no packages. ./src/machine/..., ./src/machine/usb/..., ./src/internal/... and ./src/runtime/... all end with no packages matched. The cached GOROOT has those directories as symlinks, and go list does not follow symlinks for .... ./src/... turns into std, which fails with package net (test) imports internal/poll: build constraints exclude all Go files. The error for plain ./src also suggests ./src/.... Perhaps expand these patterns by walking $TINYGOROOT/src instead of passing them to go list, or at least change that hint?
  2. The -diff output is always one hunk from the first change to the last, so unchanged lines in between show up as removed and added. For example tinygo fix -target pico -diff ./src/machine shows 83 lines of -/+ in machine_rp2_i2c.go and the whole roscRandByte function in machine_rp2_rng.go for two rangeint changes. The patch still applies, but it is hard to read. Separate hunks with 3 lines of context, like go fix -diff, might help.
  3. Test files are always loaded, so one test file that does not build for the target blocks the whole package. tinygo fix -target pico -diff ./src/os/... fails type checking in os_test.go and stat_test.go (chtmpdir, os.SameFile). Maybe add a way to leave tests out, or skip test packages that fail to type check with a warning?
  4. go1.25 is hardcoded in loader/analysis.go and must match minorMin in builder/config.go. Sharing one constant would keep them from drifting when the minimum Go version goes up.

What do you think? Thanks!

Thanks for the feedback. I'll take another pass at this in the morning. buenas noches

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants