Skip to content

fix: Call hooks from unexported embedded fields#620

Open
abhinav wants to merge 1 commit into
alecthomas:masterfrom
abhinav:fix-unexported-embedded-hooks
Open

fix: Call hooks from unexported embedded fields#620
abhinav wants to merge 1 commit into
alecthomas:masterfrom
abhinav:fix-unexported-embedded-hooks

Conversation

@abhinav

@abhinav abhinav commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Bug:
In #616, Kong stopped calling compiler-generated promoted methods.
It traversed exported embedded fields instead so each hook runs at its
declaring receiver.

That traversal cannot enter an unexported anonymous field. The promoted
method was ignored and the declaring receiver was skipped, so the hook
did not run. For example:

type options struct{}

func (*options) AfterApply() error { return nil }

type CLI struct {
    options
}

CLI.AfterApply is callable through Go's promoted method wrapper,
but the callback search introduced by #616 rejected that wrapper
and could not visit options through reflection.

Fix:
Fall back to the promoted method when traversal finds no explicit hook.
Exported embedded hooks still run at their declaring receiver once.
An unexported embedded hook runs through the callable parent wrapper.

Validation:
Includes a regression test that fails without this fix.

Bug:
In alecthomas#616, Kong stopped calling compiler-generated promoted methods.
It traversed exported embedded fields instead so each hook runs at its
declaring receiver.

That traversal cannot enter an unexported anonymous field. The promoted
method was ignored and the declaring receiver was skipped, so the hook
did not run. For example:

    type options struct{}

    func (*options) AfterApply() error { return nil }

    type CLI struct {
        options
    }

`CLI.AfterApply` is callable through Go's promoted method wrapper,
but the callback search introduced by alecthomas#616 rejected that wrapper
and could not visit `options` through reflection.

Fix:
Fall back to the promoted method when traversal finds no explicit hook.
Exported embedded hooks still run at their declaring receiver once.
An unexported embedded hook runs through the callable parent wrapper.

Validation:
Includes a regression test that fails without this fix.
@abhinav

abhinav commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

This change is part of the following stack:

Change managed by git-spice.

abhinav added a commit to abhinav/kong that referenced this pull request Jul 11, 2026
abhinav added a commit to abhinav/git-spice that referenced this pull request Jul 11, 2026
Commands that restack automatically can now skip restacking
with `--no-restack` or `--restack=none`.
The default remains to restack (`--restack=upstack` or `--restack`),
configurable with the `spice.<command>.restack` configuration option.

It's not strictly boolean to leave room for other options where relevant
in the future (similarly to --restack flags on `repo sync`, etc.).

Resolves #1352
Depends on alecthomas/kong#618, alecthomas/kong#620
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