#2706·xgo

Title: class-file name resolution can bind lowercase function calls to synthesized work fields

Author: joeykchenCreated Apr 9, 2026Updated Jun 18, 2026
Labelsbug

Related report

Downstream report: goplus/spx#1455

Summary

This looks like an xgo class-file name-resolution issue.

In a class-file project, if there is a project-level function like reset() and also a work file whose synthesized field name is Reset, the lowercase call may be resolved to the synthesized work field instead of the project-level function/method.

Environment

  • xgo version: xgo 1.6.2 darwin/amd64

Minimal reproduction

gop.mod:

txt
module github.com/goplus/demo

classfile = true

project .spx Game github.com/goplus/spx/v2,math
workfile .spx SpriteImpl

go.mod:

go
module github.com/goplus/demo

go 1.25.0

require github.com/goplus/spx/v2 v2.0.0-pre.28 //xgo:class

main.spx:

go
func reset() {
}

Reset.spx:

go
func test() {
	reset()
}

Steps

Run:

bash
xgo go .

Actual result

The generated code contains both:

go
type Game struct {
	spx.Game
	Reset *Reset
}

func (this *Game) reset() {
}

but the call in Reset.spx is compiled as:

go
func (this *Reset) test() {
	this.Reset()
}

So the lowercase reset() call is being bound to the synthesized work field Reset, not to the project-level reset function/method.

In downstream spx usage, the same underlying issue is reported as ambiguous selector this.Reset in goplus/spx#1455.

Expected result

reset() should resolve to the project-level function/method, or the compiler should report a direct naming-conflict error.

It should not be lowered to this.Reset().

Notes

My guess is that this comes from the interaction between:

  • class-file unqualified identifier lookup against this
  • member alias behavior that allows lowercase names to match capitalized members
  • synthesized work fields added to the project class