rf
rf copied to clipboard
rf: GoCompiledFiles is empty when running rf on the runtime package
When trying to run rf
on the runtime package I got a bunch of failures. I dug down and noticed that GoCompiledFiles
(a field that appears in the JSON output of go list
when -compiled
is passed) is empty when trying to use rf
in std.
I worked around this with the following patch:
diff --git a/refactor/snap.go b/refactor/snap.go
index fe543ed..ae0ffbe 100644
--- a/refactor/snap.go
+++ b/refactor/snap.go
@@ -307,7 +307,22 @@ func (r *Refactor) Load() (*Snapshot, error) {
// Set up for loading from source code.
p.Export = "" // Remember NOT to load from export data.
- for _, name := range jp.CompiledGoFiles {
+ files := jp.CompiledGoFiles
+ lowLevelPkgs := map[string]struct{}{
+ "runtime/internal/math": struct{}{},
+ "internal/bytealg": struct{}{},
+ "runtime": struct{}{},
+ }
+ if _, ok := lowLevelPkgs[p.PkgPath]; ok {
+ // For any number of reasons, `go list` doesn't
+ // actually return a populated CompiledGoFiles
+ // for any of these packages, preventing anything
+ // useful from being done. Use GoFiles because
+ // it's already filtered out all the right arch-specific
+ // files and that's good enough for the runtime.
+ files = jp.GoFiles
+ }
+ for _, name := range files {
if strings.HasSuffix(name, ".s") { // surprise!
continue
}
AFAICT GoFiles does already filter by GOOS
and GOARCH
, so I'm not totally sure what the benefit of using GoCompiledFiles
over GoFiles
is in general.
@prattmic noted that this problem disappears if the -export
flag is removed, but then he encountered
../crypto/ecdsa/ecdsa.go:123:19: cannot use r (variable of type *big.Int) as *big.Int value in argument to b.AddASN1BigInt
../crypto/ecdsa/ecdsa.go:124:19: cannot use s (variable of type *big.Int) as *big.Int value in argument to b.AddASN1BigInt
rf: errors found after script
when trying to run rf
on the runtime. Not sure yet what's going wrong there. I'll dig deeper a little deeper later, but first I wanted to just get this down in writing.
Some observations I've made:
CompiledGoFiles
works fine for my system-install GOROOT:
$ go list -export -compiled -f '{{.CompiledGoFiles}}' runtime
[alg.go arena.go atomic_pointer.go cgo.go cgo_mmap.go cgo_sigaction.go cgocall.go cgocallback.go cgocheck.go chan.go checkptr.go compiler.go complex.go corehelper_linux.go cpuflags.go cpuflags_amd64.go cpuprof.go cputicks.go debug.go debugcall.go debuglog.go debuglog_off.go defs_linux_amd64.go env_posix.go error.go extern.go fastlog2.go fastlog2table.go float.go googleexit.go hash64.go heapdump.go histogram.go iface.go lfstack.go lfstack_64bit.go lock_futex.go lockrank.go lockrank_off.go malloc.go map.go map_fast32.go map_fast64.go map_faststr.go mbarrier.go mbitmap.go mcache.go mcentral.go mcheckmark.go mem_linux.go metrics.go mfinal.go mfixalloc.go mgc.go mgcmark.go mgcscavenge.go mgcstack.go mgcsweep.go mgcwork.go mheap.go mpagealloc.go mpagealloc_64bit.go mpagecache.go mpallocbits.go mprof.go mranges.go msan0.go msize.go mspanset.go mstats.go mwbbuf.go nbpipe_pipe2.go netpoll.go netpoll_epoll.go os_linux.go os_linux_generic.go os_linux_noauxv.go os_linux_x86.go os_nonopenbsd.go panic.go plugin.go preempt.go preempt_nonwindows.go print.go proc.go profbg.go profbuf.go proflabel.go pstats.go race0.go rdebug.go relax_stub.go runtime.go runtime1.go runtime2.go runtime_boring.go rwmutex.go select.go sema.go signal_amd64.go signal_linux_amd64.go signal_unix.go sigqueue.go sigqueue_note.go sigtab_linux_generic.go sizeclasses.go slice.go softfloat64.go stack.go string.go stubs.go stubs2.go stubs3.go stubs_amd64.go stubs_linux.go symtab.go sys_nonppc64x.go sys_x86.go time.go time_nofake.go timestub.go timestub2.go trace.go traceback.go type.go typekind.go utf8.go vdso_elf64.go vdso_linux.go vdso_linux_amd64.go write_err.go asm.s asm_amd64.s duff_amd64.s memclr_amd64.s memmove_amd64.s preempt_amd64.s rt0_linux_amd64.s sys_linux_amd64.s]
But does not work when set to my dev repo (the one I want to refactor):
$ GOROOT=~/src/go go list -export -compiled -f '{{.CompiledGoFiles}}' runtime
# internal/abi
compile: version "devel +87c6fa4f47 Wed Mar 31 20:28:39 2021 +0000" does not match go tool version "go1.16.2"
# runtime/internal/sys
compile: version "devel +87c6fa4f47 Wed Mar 31 20:28:39 2021 +0000" does not match go tool version "go1.16.2"
# internal/cpu
compile: version "devel +87c6fa4f47 Wed Mar 31 20:28:39 2021 +0000" does not match go tool version "go1.16.2"
# runtime/internal/atomic
compile: version "devel +87c6fa4f47 Wed Mar 31 20:28:39 2021 +0000" does not match go tool version "go1.16.2"
[]
But does work again if I also use the go
tool from that dev GOROOT
:
$ GOROOT=~/src/go ~/src/go/bin/go list -export -compiled -f '{{.CompiledGoFiles}}' runtime
[alg.go atomic_pointer.go cgo.go cgo_mmap.go cgo_sigaction.go cgocall.go cgocallback.go cgocheck.go chan.go checkptr.go compiler.go complex.go cpuflags.go cpuflags_amd64.go cpuprof.go cputicks.go debug.go debugcall.go debuglog.go debuglog_off.go defs_linux_amd64.go env_posix.go error.go extern.go fastlog2.go fastlog2table.go float.go hash64.go heapdump.go histogram.go iface.go lfstack.go lfstack_64bit.go lock_futex.go lockrank.go lockrank_off.go malloc.go map.go map_fast32.go map_fast64.go map_faststr.go mbarrier.go mbitmap.go mcache.go mcentral.go mcheckmark.go mem_linux.go metrics.go mfinal.go mfixalloc.go mgc.go mgcmark.go mgcscavenge.go mgcstack.go mgcsweep.go mgcwork.go mheap.go mpagealloc.go mpagealloc_64bit.go mpagecache.go mpallocbits.go mprof.go mranges.go msan0.go msize.go mspanset.go mstats.go mwbbuf.go nbpipe_pipe2.go netpoll.go netpoll_epoll.go os_linux.go os_linux_generic.go os_linux_noauxv.go os_linux_x86.go os_nonopenbsd.go panic.go plugin.go preempt.go preempt_nonwindows.go print.go proc.go profbuf.go proflabel.go race0.go rdebug.go regabidefer_off.go relax_stub.go runtime.go runtime1.go runtime2.go rwmutex.go select.go sema.go signal_amd64.go signal_linux_amd64.go signal_unix.go sigqueue.go sigqueue_note.go sigtab_linux_generic.go sizeclasses.go slice.go softfloat64.go stack.go string.go stubs.go stubs2.go stubs3.go stubs_amd64.go stubs_linux.go symtab.go sys_nonppc64x.go sys_x86.go time.go time_nofake.go timestub.go timestub2.go tls_stub.go trace.go traceback.go type.go typekind.go utf8.go vdso_elf64.go vdso_linux.go vdso_linux_amd64.go write_err.go asm.s asm_amd64.s duff_amd64.s memclr_amd64.s memmove_amd64.s preempt_amd64.s rt0_linux_amd64.s sys_linux_amd64.s]
So maybe the answer here is that we need to temporarily add the dev go
tool to PATH when running rf
, or have an option to specify which go
tool to use?
That does more-or-less work:
PATH=~/src/go/bin:$PATH ~/src/rf/rf -diff 'mv findrunnable findRunnable'
diff old/runtime/proc.go new/runtime/proc.go
--- old/runtime/proc.go
+++ new/runtime/proc.go
@@ -2590,7 +2590,7 @@
// Finds a runnable goroutine to execute.
// Tries to steal from other P's, get g from local or global queue, poll network.
-func findrunnable() (gp *g, inheritTime bool) {
+func findRunnable() (gp *g, inheritTime bool) {
_g_ := getg()
// The conditions here and in handoffp must agree: if
@@ -3161,7 +3161,7 @@
// if checkTimers added a local goroutine via goready.
}
if gp == nil {
- gp, inheritTime = findrunnable() // blocks until work is available
+ gp, inheritTime = findRunnable() // blocks until work is available
}
// This thread is going to run a goroutine and is not spinning anymore,
../crypto/ecdsa/ecdsa.go:123:19: cannot use r (variable of type *big.Int) as *big.Int value in argument to b.AddASN1BigInt
../crypto/ecdsa/ecdsa.go:124:19: cannot use s (variable of type *big.Int) as *big.Int value in argument to b.AddASN1BigInt
rf: errors found after script
There are two caveats:
- Michael didn't mention this above, but it is also necessary to drop
-test
fromrf
'sgo list
, otherwise it chokes onLOST runtime [internal/cpu.test]
and fails type-checking. - I am still getting the strange "cannot use *big.Int as *big.Int error".
I am still getting the strange "cannot use *big.Int as *big.Int error".
I would guess what's happening is package A imports package B and they both import "math/big", but the go/types.Importer is giving them separate *types.Package instances. I'd suspect one of them is getting the version with in-package _test.go files, and the other is getting it without.
I'd suspect one of them is getting the version with in-package _test.go files, and the other is getting it without.
That's https://github.com/rsc/rf/issues/9 :)
have an option to specify which
go
tool to use?
In general, the way for tools to use a specific Go version/install is to set up $PATH when invoking them. See https://github.com/golang/go/issues/44329, for example.