aardappel / lobster

The Lobster Programming Language

Home Page:http://strlen.com/lobster

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Typing problem with subclasses in singleton lists

MortimerSnerd opened this issue · comments

Using the latest commit.

If I have a var or function parameter whose type is [SomeSuperClass] and I assign/pass [OneSubClass{}, TwoSubClass{}], it type checks fine. If I only assign/pass a single entry list like [OneSubClass{}], it complains that it requires a SomeSuperClass. Makes me wonder if there's something odd with the typing rule where the first entry in the list sets the inferred type of the list.

Example:

class HopMethod:

class M1: HopMethod
class M2: HopMethod

let good: [HopMethod] = [M1{}, M2{}]
let bad: [HopMethod] = [M1{}] // test.lobster(7): error: `definition` (initializer argument) requires type `[HopMethod]`, got `[M1]`

print("{good} {bad}")

That's not a bug I think.

The problem this is trying to prevent:

let subs = [ Sub{} ]
let supers = subs  // Not allowed, but if it were..
supers.push(Super {})
for(subs) s: s.subfield = 1  // UHOH, crash if Super?

In technical terms, it is enforcing contravariance of the vector type parameter.

In this case the initializer to good is ok, since there cannot be an alias to that list of the subtype.

The question is: should the compiler be better at finding the exceptions when it can be sure there is no alias, such as in the case of the bad initializer. Problem is the type-checker has no concept of "this value is un-aliased", so that would be a special purpose check, where when it checks for subtype compatibility, it would allow a covariant type if it knows the value is a constructor. Hmm...

That is more complicated. I can see it makes sense though, I can get around it by doing a let m: HopMethod = M1{}; bad = [m]; I think I was a little surprised when supplying the : [HopMethod] type specifier didn't change the behavior.

For some context, I'm using subtypes of a "base" class there only because I was doing a straight-ish translation of some Python code. I didn't want to try change the structure to something more idiomatic as I translated. So this isn't urgent, I'm just going to work around it in the test code. I suspect it's going to turn into a vector of function references.

The situation has been improved in a6b5d93

You should now be able to use vector/class constructors in any context that requires a supertype of it.
Hopefully that covers the majority of basic usecases.

I can verify this fixes the code I had that ran into this as well. Thanks.