Fabric: Tweak the screen registy's generics

Created on 26 Jun 2020  路  4Comments  路  Source: FabricMC/fabric

The screen registry's generics currently has a few ? extends T where T extends .... These double extends is unnecessary and breaks java's type inference.

I.e. basically change
https://github.com/FabricMC/fabric/blob/dfd0b839f4ea14da86c0ac92db3f60a6128d1a30/fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/api/client/screenhandler/v1/ScreenRegistry.java#L64-L67
to

public static <H extends ScreenHandler, S extends Screen & ScreenHandlerProvider<H>> void register(ScreenHandlerType<H> type, Factory<? super H, S> screenFactory) {
    // Convert our factory to the vanilla provider here as the vanilla interface won't be available to modders.
    HandledScreens.<H, S>register(type, screenFactory::create);
}
bug enhancement in progress

Most helpful comment

In that example the double extends is unnecessary, but you can't remove them all. For example:

<T extends Something> List<T> something(List<? extends T> a, List<? extends T> b) can be called with different types for each (something(List<Something1>, List<Something2>)) which wouldn't work if the ? extends were removed.

In those cases, it should be changed to something like this: <T extends Something, T1 extends T, T2 extends T> List<T> something(List<T1> a, List<T2> b)

All 4 comments

So this is what causes the type inference issues... 馃う

I figured it was something with the wildcards, but didn't realise that there were redundant ones. I'll make a PR to fix this in a few days.

In that example the double extends is unnecessary, but you can't remove them all. For example:

<T extends Something> List<T> something(List<? extends T> a, List<? extends T> b) can be called with different types for each (something(List<Something1>, List<Something2>)) which wouldn't work if the ? extends were removed.

In those cases, it should be changed to something like this: <T extends Something, T1 extends T, T2 extends T> List<T> something(List<T1> a, List<T2> b)

This may have to be a 2.0.0 bump as removing the wildcards from the parameters breaks some code in the test mod:

Using a HandledScreen<T> for a ScreenHandlerType<U> where U extends T doesn't work anymore as that screen doesn't implement ScreenHandlerProvider<U>. In the test mod's case, T is Generic3x3ContainerScreenHandler and U is BagScreenHandler which extends the vanilla class.

Actually, it seems that just removing the wildcards from the factory parameter (so that Factory<? super H, ? extends S> becomes Factory<H, S>) is enough and retains source compatibility.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

neolightning picture neolightning  路  6Comments

ignirtoq picture ignirtoq  路  3Comments

MatthewOverall picture MatthewOverall  路  6Comments

8bit-coder picture 8bit-coder  路  6Comments

Juuxel picture Juuxel  路  3Comments