Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: "relocation target not defined" for constant of instantiated type #51245

Closed
findleyr opened this issue Feb 17, 2022 · 11 comments
Closed
Labels
NeedsInvestigation
Milestone

Comments

@findleyr
Copy link
Contributor

@findleyr findleyr commented Feb 17, 2022

Compiling the following code:

package main

type T[P any] int

const C T[int] = 3

func main() {
}

Yields the following linker error:

go.constinfo.main: relocation target go.info.main.T[int] not defined

https://go.dev/play/p/sR5foIWLFEg?v=gotip

This looks like a valid program to me, so I think this is a bug (at the very least, the error message could be improved).

CC @danscales @randall77 @mdempsky @griesemer

@findleyr findleyr added the NeedsInvestigation label Feb 17, 2022
@findleyr findleyr added this to the Go1.18 milestone Feb 17, 2022
@randall77
Copy link
Contributor

@randall77 randall77 commented Feb 17, 2022

Hm, works fine on my desktop. Maybe something with the playground?

@findleyr
Copy link
Contributor Author

@findleyr findleyr commented Feb 17, 2022

I can reproduce on my laptop:

[roam:generics_repros]> cat issue51245.go
package main

type T[P any] int

const C T[int] = 3

func main() {
}
[roam:generics_repros]> go build issue51245.go
# command-line-arguments
go.constinfo.main: relocation target go.info.main.T[int] not defined

@randall77
Copy link
Contributor

@randall77 randall77 commented Feb 17, 2022

Ah, go build fails but go run works fine. Odd.

@randall77
Copy link
Contributor

@randall77 randall77 commented Feb 17, 2022

I think this is DWARF, which is turned off by go run.
When I compile with -p main, I see these symbols:

% ../bin/go tool compile -S -p main ~/gowork/issue51245.go
"".main STEXT nosplit size=1 args=0x0 locals=0x0 funcid=0x0 align=0x0
	0x0000 00000 (/Users/khr/gowork/issue51245.go:7)	TEXT	"".main(SB), NOSPLIT|ABIInternal, $0-0
	0x0000 00000 (/Users/khr/gowork/issue51245.go:7)	FUNCDATA	$0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
	0x0000 00000 (/Users/khr/gowork/issue51245.go:7)	FUNCDATA	$1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
	0x0000 00000 (/Users/khr/gowork/issue51245.go:8)	RET
	0x0000 c3                                               .
go.cuinfo.producer.main SDWARFCUINFO dupok size=0
	0x0000 72 65 67 61 62 69                                regabi
go.cuinfo.packagename.main SDWARFCUINFO dupok size=0
	0x0000 6d 61 69 6e                                      main
""..inittask SNOPTRDATA size=24
	0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
	0x0010 00 00 00 00 00 00 00 00                          ........
go.constinfo.main SDWARFCONST size=13
	0x0000 0b 6d 61 69 6e 2e 43 00 00 00 00 00 03           .main.C......
	rel 8+4 t=31 go.info."".T[int]+0
gclocals·33cdeccccebe80329f1fdbee7f5874cb SRODATA dupok size=8
	0x0000 01 00 00 00 00 00 00 00                          ........

Indeed there is no go.info."".T[int].

@thanm

@randall77
Copy link
Contributor

@randall77 randall77 commented Feb 17, 2022

Strangely, if I change the constant to const D int = 3, the bug goes away. But that undefined symbol is still there in the assembly output:

% ../bin/go tool compile -S -p main ~/gowork/issue51245.go
"".main STEXT nosplit size=1 args=0x0 locals=0x0 funcid=0x0 align=0x0
	0x0000 00000 (/Users/khr/gowork/issue51245.go:9)	TEXT	"".main(SB), NOSPLIT|ABIInternal, $0-0
	0x0000 00000 (/Users/khr/gowork/issue51245.go:9)	FUNCDATA	$0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
	0x0000 00000 (/Users/khr/gowork/issue51245.go:9)	FUNCDATA	$1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
	0x0000 00000 (/Users/khr/gowork/issue51245.go:10)	RET
	0x0000 c3                                               .
go.cuinfo.producer.main SDWARFCUINFO dupok size=0
	0x0000 72 65 67 61 62 69                                regabi
go.cuinfo.packagename.main SDWARFCUINFO dupok size=0
	0x0000 6d 61 69 6e                                      main
""..inittask SNOPTRDATA size=24
	0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
	0x0010 00 00 00 00 00 00 00 00                          ........
go.constinfo.main SDWARFCONST size=13
	0x0000 0b 6d 61 69 6e 2e 44 00 00 00 00 00 04           .main.D......
	rel 8+4 t=31 go.info.int+0
gclocals·33cdeccccebe80329f1fdbee7f5874cb SRODATA dupok size=8
	0x0000 01 00 00 00 00 00 00 00                          ........

Is the linker making up the go.info.int symbol somehow? Or does a standard package (runtime?) provide ones for all the types that could be the types of constants?

@cherrymui
Copy link
Member

@cherrymui cherrymui commented Feb 17, 2022

I think the linker creates DWARF type symbols, from Go type descriptor symbols (e.g. type.int). For basic types the type descriptor symbol is from the runtime package.

@thanm
Copy link
Contributor

@thanm thanm commented Feb 17, 2022

I'll take a look.

Is the linker making up the go.info.int symbol somehow? Or does a standard package (runtime?) provide ones for all the types that could be the types of constants?

In our current design the linker manufactures all go.info.<type> symbols.

@cherrymui
Copy link
Member

@cherrymui cherrymui commented Feb 17, 2022

When T is not a generic type, when compiling the main package it emits the type descriptor symbol (type."".T), which turns into the DWARF symbol by the linker. When T is a generic type, the type descriptor symbol is not emitted.

@thanm
Copy link
Contributor

@thanm thanm commented Feb 17, 2022

Why is the compiler not emitting any "type.*" symbols in this example? If I change the code to

package main

type T[P any] int
const C T[int] = 3

type T2 int
const C2 T2 = 9

func main() {
}

then as part of the assembly output I see

type..namedata.*main.T2. SRODATA dupok size=10
	0x0000 01 08 2a 6d 61 69 6e 2e 54 32                    ..*main.T2
type.*"".T2 SRODATA dupok size=56
	0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00  ................
	0x0010 82 b1 e3 f3 08 08 08 36 00 00 00 00 00 00 00 00  .......6........
	0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
	0x0030 00 00 00 00 00 00 00 00                          ........
	rel 24+8 t=1 runtime.memequal64·f+0
	rel 32+8 t=1 runtime.gcbits.01+0
	rel 40+4 t=5 type..namedata.*main.T2.+0
	rel 48+8 t=1 type."".T2+0

Shouldn't these be there for the generic type as well?

@randall77
Copy link
Contributor

@randall77 randall77 commented Feb 17, 2022

I can imagine it not getting generated. We might use the type declaration to decide when to output, but for generics it is the instantiations that actually generate the concrete types.
If that type isn't used anywhere (e.g. in an interface{} conversion), it might not be referenced / might not get generated.

@gopherbot
Copy link

@gopherbot gopherbot commented Feb 26, 2022

Change https://go.dev/cl/388117 mentions this issue: cmd/compile: emit types of constants which are instantiated generic types

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation
Projects
None yet
Development

No branches or pull requests

5 participants