#2822 Cannot use covariance, sys::Obj? != sys::Bool?

Carlos Mon 15 Mar 2021

I have a mixin declaring an abstract method with this signature

abstract Obj? convert(Str str);

A subclass, let's name it BoolConverter, overrides that method with following signature

override Bool? convert(Str str) 

I have another subclass, NumberConverter, that overrides abstract method with following signature

override Number? convert(Str str) 

At build time I get this error at method BoolConverter.convert

Cannot use covariance with value types 'whybDataLoaderExt::ValConverter.convert' - 'sys::Obj?' != 'sys::Bool?'

I've seen that Bool inherits from Obj. What's wrong?

SlimerDude Tue 16 Mar 2021

Hi Carlos,

That's the leaky abstraction of Java oozing through.

Java doesn't allow primitive (or their wrapper counterparts) to be used as covariance return types (see StackOverflow) so Fantom doesn't (or rather, can't) either.

In your specific case, assuming Number is actually a haystack::Number, then the issue is with Bool:

override Bool? convert(Str str)

Changing the return type of this line should allow compilation.

Carlos Tue 16 Mar 2021

Hi SlimerDude,

thanks for your answer. You're right Number is actually haystack::Number.

So covariance doesn't work with any primitive type, does it?

I don't have a deep knowledge about Fantom API and libs, is there any wrapping type for sys::Bool that I can use in a similar way that I can use haystack::Number for sys::Int or sys::Float?

SlimerDude Tue 16 Mar 2021

Hi Carlos, I'm afraid not. You'd have to create your own Bool wrapper class.

But, assuming only the supertype is referenced / used in your codebase - do you really need covariance? Can you not change:

override Bool? convert(Str str) { ... }

to

override Obj? convert(Str str) { ... }

? The method can still only return a Bool, it's just the declaration that says it may return anything.

Just a thought.

Login or Signup to reply.