Skip to content

cmd/compile: unexpected crash when using -G=3 with external symbols. #45597

@Gh0u1L5

Description

@Gh0u1L5

What version of Go are you using (go version)?

$ go version
go version devel go1.17-48b7432e3f Thu Apr 15 01:54:41 2021 +0000 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What did you do?

Firstly, create the following two files.

  1. item/item.go
package item

type Int struct {
	value int
}

func NewInt() *Int {
	return &Int{0}
}

func (i *Int) Add(delta int) {
	i.value += delta
}
  1. main.go
package main

import (
	"fmt"
	"test/item"
)

type wrapper[T any] struct {
	value T
}

func (w wrapper[T]) Get() T {
	return w.value
}

func main() {
	w := wrapper[item.Int]{}
	fmt.Println(w)
}

Then, execute the following commands to compile the codes.

$ go mod init test
$ go build -gcflags=-G=3 main.go

The compiler will first crash with the following logs:

# command-line-arguments
<autogenerated>:1: internal compiler error: method mismatch: wrapper[item.Int] for *wrapper[Int]

goroutine 1 [running]:
runtime/debug.Stack(0x1ba6480, 0xc00000e018, 0x0)
        /home/Gh0u1L5/Projects/go/src/runtime/debug/stack.go:24 +0x9f
cmd/compile/internal/base.FatalfAt(0x100000000001, 0x1a665bf, 0x1a, 0xc000389fd8, 0x2, 0x2)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/base/print.go:227 +0x1ea
cmd/compile/internal/base.Fatalf(...)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/base/print.go:196
cmd/compile/internal/typecheck.Lookdot(0xc000406300, 0xc00037f8f0, 0x0, 0x1bbaf00)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:1244 +0xccc
cmd/compile/internal/typecheck.tcDot(0xc000406300, 0xe, 0x1a15260, 0x1a49240)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/expr.go:499 +0x331
cmd/compile/internal/typecheck.typecheck1(0x1bbb628, 0xc000406300, 0xe, 0xc000406300, 0x120f92c)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:682 +0x1327
cmd/compile/internal/typecheck.typecheck(0x1bbb628, 0xc000406300, 0xe, 0x1, 0x1bb12e8)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:371 +0x63b
cmd/compile/internal/typecheck.tcCall(0xc0001799e0, 0x12, 0xc0004a39f0, 0xc0004a39f0)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/func.go:397 +0xac
cmd/compile/internal/typecheck.typecheck1(0x1bb9b98, 0xc0001799e0, 0x12, 0xc0001799e0, 0x20)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:715 +0xd9a
cmd/compile/internal/typecheck.typecheck(0x1bb9b98, 0xc0001799e0, 0x12, 0x3a98b01, 0x10000c00038abe0)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:371 +0x63b
cmd/compile/internal/typecheck.typecheckslice(0xc0000667c0, 0x1, 0x1, 0x12)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:177 +0x6c
cmd/compile/internal/typecheck.typecheckargs(0x1bbd288, 0xc0004a3b30)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:928 +0x1fe
cmd/compile/internal/typecheck.tcReturn(0xc0004a3b30, 0xc00049e97d, 0xc00040162f)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/stmt.go:343 +0x3b
cmd/compile/internal/typecheck.typecheck1(0x1bbb498, 0xc0004a3b30, 0x1, 0xc0004a3b30, 0xc00049e9a0)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:864 +0x2f1a
cmd/compile/internal/typecheck.typecheck(0x1bbb498, 0xc0004a3b30, 0x1, 0x1, 0x1bba368)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:371 +0x63b
cmd/compile/internal/typecheck.typecheckslice(0xc0000667d0, 0x1, 0x1, 0x1)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:177 +0x6c
cmd/compile/internal/typecheck.Stmts(...)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/typecheck/typecheck.go:36
cmd/compile/internal/reflectdata.methodWrapper(0xc0004a5960, 0xc000079e50, 0x1137201)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/reflectdata/reflect.go:1807 +0x14b5
cmd/compile/internal/reflectdata.methods(0xc0004a5960, 0x10, 0x34eea75a, 0x4)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/reflectdata/reflect.go:353 +0x485
cmd/compile/internal/reflectdata.uncommonSize(...)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/reflectdata/reflect.go:82
cmd/compile/internal/reflectdata.dcommontype(0xc0004df900, 0xc0004a5960, 0xc0004de300)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/reflectdata/reflect.go:719 +0x214
cmd/compile/internal/reflectdata.writeType(0xc0004a5960, 0xc0004a5960)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/reflectdata/reflect.go:1120 +0x450
cmd/compile/internal/reflectdata.dcommontype(0xc0004a1780, 0xc00037f8f0, 0x1014c00)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/reflectdata/reflect.go:693 +0xe6
cmd/compile/internal/reflectdata.writeType(0xc00037f8f0, 0xc0004e04f8)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/reflectdata/reflect.go:1145 +0x12b7
cmd/compile/internal/reflectdata.WriteRuntimeTypes()
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/reflectdata/reflect.go:1317 +0x34e
cmd/compile/internal/gc.dumpdata()
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/gc/obj.go:117 +0x91
cmd/compile/internal/gc.Main(0x1a83070)
        /home/Gh0u1L5/Projects/go/src/cmd/compile/internal/gc/main.go:304 +0x12ea
main.main()
        /home/Gh0u1L5/Projects/go/src/cmd/compile/main.go:54 +0x155

After a tough debugging, I managed to patch types.Identical to fix this crash.

diff --git a/src/cmd/compile/internal/types/identity.go b/src/cmd/compile/internal/types/identity.go
index dde9f51856..853e748f5d 100644
--- a/src/cmd/compile/internal/types/identity.go
+++ b/src/cmd/compile/internal/types/identity.go
@@ -28,7 +28,7 @@ func identical(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) b
        if t1 == nil || t2 == nil || t1.kind != t2.kind || t1.Broke() || t2.Broke() {
                return false
        }
-       if t1.sym != nil || t2.sym != nil {
+       if (t1.sym != nil || t2.sym != nil) && t1.kind != TSTRUCT {
                // Special case: we keep byte/uint8 and rune/int32
                // separate for error messages. Treat them as equal.
                switch t1.kind {

Basically, a struct with type param now also has a non-nil sym. So if we find a struct with sym, instead of returning false, we should allow it to continue to the compare logic for structs.

However, the codes immediately triggered another crash with the following logs:

# command-line-arguments
type.main.wrapper[Int]: relocation target main.wrapper[Int].Get not defined

Apparently, the target here should be main.wrapper[item.Int]. I added some codes that explicitly replace every main.wrapper[Int] to main.wrapper[item.Int]. The compiler just worked like a charm.

Then I spend some time walking around, but failed to find where the compiler introduced the improper symbols. So I decide to file an issue here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions