Silver Enums Issues

How is the thing with enums going in Silver?

Enums with tuple parameters seems to be still broken. (9.1.99.2141)

public enum UltimateEnum {
	case initRealm
	case initSomethingWithValue(String)
}

//...

if ultimate == UltimateEnum.initRealm {
	print("First thing is working")
}
	
let lessUltimate = UltimateEnum.initSomethingWithValue("wow wow")
if case .initSomethingWithValue(let string) = lessUltimate {
	print("Would be call if this would be working too")
}

This compiles, however instantiation of lessUltimate fails with

[NullPointerException]: Attempt to write to field 'long lakestonecore.eunit.UltimateEnum.fValue' on a null object reference

Is there any way I can make it working somehow, so that syntactically silver enums with tuple parameters will correspond to Swift?
I am writing Redux architecture in a shared framework and it is quite critical for enums like this to work.
Any suggestion guys?

Which platform is this?

Android. (sorry, forgot to mention)

Thanks, logged as bugs://77957

@mh - Any way I can hack it somehow with something like reflection?

Or any compiler magic that I can make my custom structs that will be interpreted as enums with == .something ?

i can’t say, i’ll have to check with Cerlo.

Thanks!

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

(More feedback)The decompiled java indicates the issue during the initialization:

public final class UltimateEnum {
    public static final int __initRealm = 0;
    public static final int __initSomethingWithValue = 1;
    public static final int __initSomethingWithSomethingElse = 2;
    private int fValue;
    private Object fAssocValue;

    public int get__Value() {
        return self.fValue;
    }

    public static UltimateEnum initRealm() {
        Object Result = null;
        Result = null;
        ((UltimateEnum)Result).fValue = 0;
        return (UltimateEnum)Result;
    }

    public static UltimateEnum initSomethingWithValue(String par0) {
        if(par0 == null) {
            throw new IllegalArgumentException("par0");
        } else {
            Object Result = null;
            Result = null;
            ((UltimateEnum)Result).fValue = 1;
            ((UltimateEnum)Result).fAssocValue = par0;
            return (UltimateEnum)Result;
        }
    }

    public static UltimateEnum initSomethingWithSomethingElse(String par0, String par1) {
        if(par0 == null) {
            throw new IllegalArgumentException("par0");
        } else if(par1 == null) {
            throw new IllegalArgumentException("par1");
        } else {
            Object Result = null;
            Result = null;
            ((UltimateEnum)Result).fValue = 2;
            ((UltimateEnum)Result).fAssocValue = new Tuple2(par0, par1);
            return (UltimateEnum)Result;
        }
    }

    public int hashCode() {
        return self.fValue ^ (self.fAssocValue != null?self.fAssocValue.hashCode():0);
    }

    public static boolean op_Equality(UltimateEnum aLeft, UltimateEnum aRight) {
        return aLeft.fValue != aRight.fValue?false:(aLeft.fAssocValue == null & aRight.fAssocValue == null?true:(aLeft.fAssocValue == null | aRight.fAssocValue == null?false:aLeft.fAssocValue.equals(aRight.fAssocValue)));
    }

    public static boolean op_Inequality(UltimateEnum aLeft, UltimateEnum aRight) {
        return !op_Equality(aLeft, aRight);
    }

    public boolean equals(Object aOther) {
        return !(aOther instanceof UltimateEnum)?false:op_Equality(self, (UltimateEnum)aOther);
    }
}

@mh: Ok, with some luck It actually can work with help of Objenesis and reflection.

The enum backing class has no constructors, so Objenesis can help instantiating such objects. Glad the if case pattern works…

Reference code:

let genesis = ObjenesisStd()
let inst = genesis.getInstantiatorOf(UltimateEnum.self)
let enumEntry = inst.newInstance() as! UltimateEnum
		
if let valueField = (try enumEntry.Class.getDeclaredFields().filter { (field) in return field.Name == "fValue" }).first,
   let associatedValueField = (try enumEntry.Class.getDeclaredFields().filter { (field) in return field.Name == "fAssocValue"}).first {
			   
	valueField.setAccessible(true)
	associatedValueField.setAccessible(true)
			
	valueField.`set`(enumEntry, 1)
	associatedValueField.`set`(enumEntry, "someString")
}
		
if case .initSomethingWithValue(let string) = enumEntry {
	print("I am here woohoo!!!")
	print(string)
}

But still it would be great if the actual issue can get fixed soon :slight_smile:

bugs://77957 got closed with status fixed.

This was indeed because of the lack of a default constructor (java only). Fixed for vnext, thanks!

1 Like