Hello, Today I found the problem with mismatching actual object field type with field definition from class.
Here is an example:
class Foo {
new make(Foo[] foos := [,]) {this.foos = foos}
Foo[] foos
Int i := 1
public static Void main()
{
echo(Foo().foos.type) //prints sys::Obj?[]
echo(Foo([Foo()]).foos.type) //prints sys::Obj[]
}
}
After changing constructor parameter to Foo[] foos := Foo[,] everything works as expected. I think there should be either a compile error (like default parameter value does not match to parameter type), or implicit cast to Foo[], but this does not happen.
As a result, there is a problem with object equality.
In this particular case, casting a list doesn't actually change the type of the original list. So your can use Obj[,] where a Foo[] is expected. But the original list never changes its type. So you fix to change the default parameter to Foo[] is the right solution.
IvanI Fri 11 Sep 2009
Hello, Today I found the problem with mismatching actual object field type with field definition from class.
Here is an example:
class Foo {
new make(Foo[] foos := [,]) {this.foos = foos} Foo[] foos Int i := 1 public static Void main() { echo(Foo().foos.type) //prints sys::Obj?[] echo(Foo([Foo()]).foos.type) //prints sys::Obj[] }}
After changing constructor parameter to
Foo[] foos := Foo[,]everything works as expected. I think there should be either a compile error (like default parameter value does not match to parameter type), or implicit cast to Foo[], but this does not happen.As a result, there is a problem with object equality.
For example, we override
sys::Obj.equalsmethod like this:override Bool equals(Obj? that) {
}
And then have code like this:
public static Void main() {
foos := [Foo(), Foo()] a := Foo(foos) b := Foo() b.foos.addAll(a.foos) echo("(a == b) = ${a == b}") //false!}
brian Fri 11 Sep 2009
Promoted to ticket #739 and assigned to brian
Yeap, that is a definitely a bug - the compiler should catch that and perform an implicit cast.
brian Thu 5 Nov 2009
Ticket cancelled
Ok, I dug into this and I don't think there is a problem.
The compiler is correctly inserting a coerce opcode. For example:
static Void foo(Obj x := 3) { echo(x) }Will compile into:
foo (sys::Obj x) -> sys::Void [const public static] [Param 0] x -> sys::Obj 0: LoadInt 3 3: Coerce sys::Int => sys::Obj [Code] 0: LoadVar 0 3: CallStatic sys::Obj.echo(sys::Obj?) -> sys::Void 6: ReturnIn this particular case, casting a list doesn't actually change the type of the original list. So your can use Obj[,] where a Foo[] is expected. But the original list never changes its type. So you fix to change the default parameter to Foo[] is the right solution.