package main;

import jdk.incubator.foreign.MemoryHandles;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;

public class VarHandleCombException {

    static final MethodHandle MH_m;
    static final MethodHandle MH_catchException;

    static {
        try {
            MH_m = MethodHandles.lookup().findStatic(VarHandleCombException.class, "m",
                    MethodType.methodType(Widget.class, Widget.class));
            MH_catchException = MethodHandles.lookup().findStatic(VarHandleCombException.class, "catchException",
                    MethodType.methodType(Widget.class, Widget.class, MethodHandle.class));
        } catch (NoSuchMethodException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws Throwable {
        MethodHandle mh = MH_m;
        mh = MethodHandles.insertArguments(MH_catchException, 1, mh);

        Widget w = (Widget) mh.invokeExact(new Widget()); // Exception caught: java.lang.Exception

        VarHandle vh_x = MethodHandles.lookup().findVarHandle(Widget.class, "x", int.class);
        // java.lang.IllegalArgumentException: Cannot adapt a var handle with a method handle which throws checked exceptions
        MemoryHandles.filterCoordinates(vh_x, 0, mh);
    }

    public static Widget catchException(Widget w, MethodHandle mh) {
        try {
            return (Widget) mh.invokeExact(w);
        } catch(Throwable t) {
            System.out.println("Exception caught: " + t);
            return null;
        }
    }

    public static Widget m(Widget w) throws Exception {
        throw new Exception();
    }

}

class Widget {
    public int x;
}
