Skip to content

llgo: check hasImethod#89

Merged
visualfc merged 1 commit into
goplus:mainfrom
visualfc:llgo_imethod
Jul 16, 2026
Merged

llgo: check hasImethod#89
visualfc merged 1 commit into
goplus:mainfrom
visualfc:llgo_imethod

Conversation

@visualfc

Copy link
Copy Markdown
Member

No description provided.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors method creation and method set initialization in rtype_llgo.go and methodof.go by returning unsafe.Pointer directly from createMethod and avoiding repeated calls to UnsafePointer(). It also introduces conditional logic based on whether a method is an interface method (hasIfn). However, in methodof.go, replacing unsafe.Pointer(reflect.ValueOf(...).Pointer()) with reflect.ValueOf(...).UnsafePointer() directly will cause a compilation error because UnsafePointer() returns a uintptr instead of an unsafe.Pointer. This needs to be wrapped in an explicit cast.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread methodof.go

var (
zeroIfn = unsafe.Pointer(reflect.ValueOf(func() {}).Pointer())
zeroIfn = reflect.ValueOf(func() {}).UnsafePointer()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

In standard Go (which is used for the !llgo build in methodof.go), reflect.Value.UnsafePointer() returns a uintptr, not an unsafe.Pointer. Assigning it directly to zeroIfn without an explicit cast will cause a compilation error when zeroIfn is later used as an unsafe.Pointer (e.g., at line 272: var pifn unsafe.Pointer = zeroIfn).

To fix this while still using the non-deprecated UnsafePointer() method, wrap the call in unsafe.Pointer(...).

Suggested change
zeroIfn = reflect.ValueOf(func() {}).UnsafePointer()
zeroIfn = unsafe.Pointer(reflect.ValueOf(func() {}).UnsafePointer())

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

The change is a clean, sound refactor of the llgo method-set path plus a small cleanup in the !llgo path. createMethod now returns unsafe.Pointer directly and gates interface-function trampoline creation on ctx.hasImethod(...), substituting a shared zeroIfn when a method has no interface function — a genuine allocation saving for non-interface methods. The zeroIfn switch from unsafe.Pointer(reflect.ValueOf(...).Pointer()) to .UnsafePointer() is the correct, go vet-safe idiom. go build ./... (default !llgo tag) passes and both files are gofmt-clean.

No blocking issues. A few lower-confidence notes for your consideration:

  • onePtr gating divergence (confirm intent). In the !llgo reference (methodof.go:286), the value-method ifn is gated on hasIfn && onePtr, whereas the new llgo path gates only on hasIfn (rtype_llgo.go:372-380). This is very likely correct because the two backends use different interface ABIs — the !llgo path uses the Go runtime's direct-interface machinery (registerMethod/OnePtr), while llgo uses textOff/Ifn_ slots and the DirectIfaceData linkname. Flagging only so you can confirm the onePtr concept is intentionally absent here.

  • Test coverage. This is the first change routing hasImethod into the llgo createMethod path and emitting zeroIfn for the !hasIfn case, but there is no test exercising the hasIfn == false branch. llgo-tagged code generally can't run under the standard go test toolchain, which likely explains the gap — noting it as a coverage caveat, not a blocker.

  • Docs. SetHasImethod (context.go:33) — now load-bearing for this behavior — has no doc comment; a one-line note on what returning false implies (interface Ifn set to zeroIfn) would help callers.

See the inline comment for a robustness suggestion on the zeroIfn sentinel.

Comment thread rtype_llgo.go
}

var (
zeroIfn = reflect.ValueOf(func() {}).UnsafePointer()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The empty-func sentinel zeroIfn is safe only under the invariant that methods with hasImethod == false are never dispatched through an itab. If a caller-supplied SetHasImethod callback ever wrongly returns false for a method that is used via an interface, the runtime would jump into an empty func(){} with a mismatched calling convention — producing silent wrong return values / potential frame corruption rather than a fail-fast crash.

Consider a panicking sentinel to make invariant violations diagnosable:

zeroIfn = reflect.ValueOf(func() { panic("reflectx: ifn called for method without imethod") }).UnsafePointer()

Hardening suggestion, not a bug in the diff (default hasImethod returns true, preserving prior behavior when no callback is installed).

@visualfc
visualfc merged commit ee570c0 into goplus:main Jul 16, 2026
18 checks passed
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.

1 participant