Mixin icon indicating copy to clipboard operation
Mixin copied to clipboard

Initializers of fields added by mixins are added to all constructors, potentially reinitializing fields

Open Barteks2x opened this issue 6 years ago • 6 comments

I'm honestly not sure if it should be considered a bug. I've been unknowingly relying on this "feature" for my mod to work for quite a long time now But at least it should be documented somewhere because it's very surprising, unexpected behavior.

Take the Chunk class as an example. It has 2 constructors - one that takes World and 2 ints, and one that on top of that takes a ChunkPrimer. The second one obviously calls the first one, and then processes the ChunkPrimer.

For a long time, I've injected at RETURN of the first constructor and "really" initialized my own boolean field there, and had it explictly initialized to "false" at declaration. Now since the early initializer is also copied into the second constructor, AFTER the call to the first one, this completely overwrites the value I set in my injection. And I relied on it working that way, without realizing this until I figured out that my code can't work and tried to debug it.

As I said, I'm really not sure what should be done with it, and if it should even be considered a bug. But I'm reporting it anyway because it certainly doesn't look like an intended feature.

Barteks2x avatar Jun 13 '18 18:06 Barteks2x

I'll consider this a documentation issue since this is absolutely the intended behaviour, field initialisers in mixins are a powerful feature that can actually be used to do some cool things, and like all initialisers they appear in all constructors.

Mumfrey avatar Jun 14 '18 10:06 Mumfrey

@Mumfrey How is this not a bug? Java field initializers are not added to a constructor calling this(), while Mixin adds them after the this() call, making fields be initialized many times (possibly even final fields).

Runemoro avatar Jul 13 '18 22:07 Runemoro

If you think of mixin classes as data-driven ASM, it makes more sense to do some things different than what would normally happen in java. In this case, it's likely more useful in general to have this behavior than to stick with what java would do normally.

Barteks2x avatar Jul 13 '18 22:07 Barteks2x

@Barteks2x @Mumfrey I'm going to question this too. What's going to happen if you add a final field through mixins and it gets initialized twice? Will the game crash?

Sollace avatar Mar 07 '19 20:03 Sollace

JVM doesn't really verify that a final field isn't initialized second time (at least in the same class, and at least in java 8). It's only verified by java compiler. For a long time @Final @Mutable wouldn't even remove the final modifier (until I reported this https://github.com/SpongePowered/Mixin/issues/124)

Barteks2x avatar Mar 07 '19 22:03 Barteks2x

I also got "bitten" by this quirk. I can't figure out exactly in what situations Mixin fuses my mixin class's init with the target's init, for example initializer blocks do not work. I would very greatly appreciate documentation on what the heck is going on here

LoganDark avatar Mar 30 '22 20:03 LoganDark