pholser/junit-quickcheck

Generic variables cause TypeValidationException: Variable substitution established for variable

vlsi opened this issue · 10 comments

vlsi commented

Test code:

    @Property
    public <X extends HashMap<Integer, Character>> void genericVars(Callable<X> callable) {
        println(callable.call())
    }

Exception:

org.javaruntype.exceptions.TypeValidationException: Variable substitution established for variable "X" in type "java.util.concurrent.Callable<X>" is "java.util.HashMap<?,?>", which does not conform to upper bound "extends java.util.HashMap<java.lang.Integer,java.lang.Character>"

	at org.javaruntype.type.TypeUtil.createFromJavaLangReflectTypeParameter(TypeUtil.java:1006)
	at org.javaruntype.type.TypeUtil.createFromJavaLangReflectType(TypeUtil.java:1094)
	at org.javaruntype.type.TypeUtil.createFromJavaLangReflectType(TypeUtil.java:1057)
	at org.javaruntype.type.TypeRegistry.forJavaLangReflectType(TypeRegistry.java:179)
	at org.javaruntype.type.Types.forJavaLangReflectType(Types.java:1030)
	at com.pholser.junit.quickcheck.internal.ParameterTypeContext.<init>(ParameterTypeContext.java:97)
	at com.pholser.junit.quickcheck.runner.PropertyStatement.parameterContextFor(PropertyStatement.java:185)
	at com.pholser.junit.quickcheck.runner.PropertyStatement.lambda$evaluate$0(PropertyStatement.java:99)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
	at com.pholser.junit.quickcheck.runner.PropertyStatement.evaluate(PropertyStatement.java:107)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

@visi Thanks for this. I've got a question in to the creator of generics-resolver to see whether perhaps I'm misusing the library, or whether there's a bug.

@vlsi Almost there -- generics-resolver 3.0.1 allows X to resolve to HashMap<Integer, Character>, but there is still a problem in that the lambda generator doesn't propagate that resolution onto the Callable method parameter. Will keep digging.

jlink commented

Just an aside: Does X extends HashMap<...> make sense in a property? I'd understand X extends Map<...>, though.

The reason I'm asking: I'd expect junit-quickcheck to have a default generator for Map but not necessarily for HashMap.

@jlink In practice Map is an exception for me since might generate an IdentityHashMap (since there is an IdentityHashMapGenerator), and that's often confusing.

jlink commented

@csamak Makes sense.

@vlsi Sorry for the delay -- I've finally had some time to take a serious look at addressing this one. Take the above PR for a spin, if you would; let me know how it works for you. Thanks!

@vlsi Let me know if you have any feedback on the above PR. If all looks well, this'll go into a patch release for 0.9.

vlsi commented

@pholser , sorry for the delay. The PR that added junit-quickcheck to Gradle was declined (a part of the story was the fix was too invasive, and a part of the story was the tests were too complex :( ), so the use case vanished a bit.

However, issues/240/carry-generics-further branch looks good to me.
It is strange you add two ReproIssue240Test classes that are almost identical. Does it really make sense to add duplicate tests?

@visi Thanks for this. I wanted to confirm your case in -generators, which involved its generators for Character, HashMap, etc., and in -core, which didn't.

@vlsi I'll plan on cutting a 0.9.1 release within the next 24 hr; will include this change. Thanks for getting back to me!