Repository navigation
Fix mixin adaptation for Fabric mods on 26.1.2 - #13
Open
1499501762 wants to merge 16 commits into
Open
1499501762 wants to merge 16 commits into
1499501762 wants to merge 16 commits into
Conversation
1499501762
force-pushed
the
connector-26.1.2-mixin-fixes
branch
2 times, most recently
from
October 1, 2026 13:54
28749db to
fe6066e
Compare
Mixin refuses a non-static callback that targets a static method, and the error is fatal. The member can end up on a static method after being moved into a generated class, so sync the modifier - but only when the handler does not read the receiver. As an instance method the body reserved local 0 for the receiver, so its parameters sat at 1..n; once the receiver is gone every slot reference shifts down by one. Slot numbers are fixed at compile time and do not depend on branches, exception handlers or variable lifetimes, so the uniform shift is correct - the one shape it is not safe for is a body that reads local 0. A body that reads local 0 cannot become static at all: a @shadow member access compiles to exactly "aload 0 + getfield/invokevirtual", and Candidates#canMove deliberately lets that shape through. Those handlers are now reported as unadapted before anything is moved, so Patcher#stripFailedMixins drops them instead of emitting a class that no longer verifies. Dropping the receiver also invalidates the method's StackMapTable: an explicit full_frame still describes local 0 and every slot after it, while frame deltas relative to the descriptor happen to survive. The transform now returns COMPUTE_FRAMES so Connector re-derives them. Without the shift Mixin sees a body whose locals no longer line up and the game dies with "VerifyError: Bad local variable type" (locals[3] = top); without the frames the same happens for any handler whose encoding contains a full_frame ("Stack map does not match the one at exception handler N").
1499501762
force-pushed
the
connector-26.1.2-mixin-fixes
branch
from
October 8, 2026 10:25
fe6066e to
b21b373
Compare
Most of them restated the code or recorded how the change was found. Keep the reason where it is not visible in the code itself, and drop the rest. No code changes: the diff is comment lines only.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix mixin adaptation for Fabric mods on 26.1.2
I hit these while getting carpet and a few other mods running on NeoForge 26.1.2. Most are bugs in the adapter, two are just missing mixin types.
@Localsugar. Relocating the target re-points theinjection point, and
@Localis resolved against the local variable frame at that point (MixinExtras'LocalSugarApplicator#validate->makeLvtContext(target, node)), so the sugar ends up re-resolved againstthe lambda's frame and local variable table instead of the original method's. Whether that still matches
depends on the shape - a captured local becomes a lambda parameter - but when it does not, MixinExtras throws
SugarApplicationException, which is aMixinExceptionand not anInvalidInjectionException; Mixin thenescalates it to a fatal
Critical injection failure ... (0/1) succeededthat can no longer be stripped.Only
@Localis gated:@Share'svalidateis a type check that never looks at the injection point.Testing:
Not fixed here:
Update: one more fix, "Sync the callback modifier when a member moves onto a static target".
When the adapter moves a mixin method into a generated class, the member can move onto a static method (a
Fabric instance method mapped onto a NeoForge static hook). Mixin rejects a non-static callback that targets a
static method, fatally. The extract path now syncs the modifier - but only when the handler does not read the
receiver.
Removing the receiver shifts every slot reference down by one. Slot numbers are fixed at compile time and do
not depend on branches, exception handlers or variable lifetimes, so a uniform shift is correct. A body that
reads local 0 (a
@Shadowmember access compiles to exactlyaload 0 + getfield/invokevirtual) cannot becomestatic at all, so those handlers are reported as unadapted before anything is moved and get stripped instead
of emitting a class that no longer verifies.
Dropping the receiver also invalidates the method's StackMapTable - an explicit
full_framestill describeslocal 0 and every slot after it - so the transform now returns
COMPUTE_FRAMESand Connector re-derives theframes.
With both parts, Create Fly has no injection failures left. It still does not start - it fails later, on its
own registry timing (Registry is already frozen: it registers from an @Inject at the TAIL of
BuiltInRegistries.freeze), which is not something the adapter can fix. The same jar runs fine on Fabric.