#611 Covariance, value types, and nullability

tompalmer Tue 26 May 2009

I've got some requests for enhancements to the handling of covariance. Here's a method header in a supertype:

Obj? get(Obj coords)

In a subtype, if I say this:

override Float? get(Obj coords)

I get this error:

Cannot use covariance with value types 'math::Mat.get' - 'sys::Obj?' != 'sys::Float?'

If I say this:

override Obj get(Obj coords)

I get this error:

Return type mismatch in override of 'math::Mat.get' - 'sys::Obj?' != 'sys::Obj'

Side note, what I really want to see here is this:

override Float get(Obj coords)

That presumably hits both of my problems indicated above.

At some level, I think keep the abstract view consistent is more important than filtering up the implementation details, and I think that's what's happening here with the value types issue. Obviously, unless you secretly generate two methods, one performing boxing and the other not, you will obviously have to box the Float as an Obj, but I think that's okay. In the nullable case (first example above), you would need to box anyway, so I'm not sure what the issue is. But whether nullable or not, I think Float should be an acceptable subtype of Obj for covariance purposes. Keeps the type system consistent, I think. Everything still (almost) is just an object, even if it gets optimized in some cases.

Concerning Obj as a subtype of Obj?, I very much recommend supporting that. Basically, Obj is the same set of possible values except for null. This would also mean (for example) that Str is a subtype of Obj?, but Str? is not a subtype of Obj (since null is not a member of Obj).

brian Wed 27 May 2009

Promoted to ticket #611 and assigned to brian

I think this makes sense. Covariance came before value-types and nullable types, and I wasn't sure exactly what to do with those, so I just punted.

But I agree the method covariance rules should be:

  1. Value types can override Obj or Obj?
  2. Int/Float types can override Num or Num?
  3. Non-nullable can override a nullable type

In all cases the override is returning a more restricted type than the super-class.

tompalmer Wed 27 May 2009

Sounds great.

geo Sat 30 Jun 2012

Are there any plans to support covariance with value types?

i.e. Int overriding a return type of Obj

SlimerDude Tue 19 Mar 2013

Just to say I just bumped into this myself:

class A {
  virtual Obj cow() { return 6 }
}

class B : A {
  override Int cow() { return 9 }
}

gives

Cannot use covariance with value types 'wotever::A.cow' - 'sys::Obj' != 'sys::Int'

As we don't have generics, overriding a return type with a more restricted type would be really useful.

brian Wed 20 Mar 2013

As we don't have generics, overriding a return type with a more restricted type would be really useful.

Just to be clear Fantom does support covariance. However it does not handle the special value types Bool, Int, Float since those aren't returned as objects in the JVM.

SlimerDude Wed 20 Mar 2013

So it does, cool!

The trap I fell into was with using inconsistent nullable types:

class Val { }

class A {
  virtual Obj? cow() { return Val() }
}

class B : A {
  override Val cow() { return Val() }
}

gives

Return type mismatch in override of 'wotever::A.cow' - 'sys::Obj?' != 'wotever::Val'

which I took to mean covariance wasn't supported.

But having cow() return Val? works just fine:

class B : A {
  override Val? cow() { return Val() }
}

Would it be possible to make the error message more explicit?

Login or Signup to reply.