tokiwa-software / fuzion

The Fuzion Language Implementation
https://fuzion-lang.dev
GNU General Public License v3.0
46 stars 11 forks source link

confusion of types when using inheritance #578

Open michaellilltokiwa opened 1 year ago

michaellilltokiwa commented 1 year ago
test =>
  nom is
    parser ref is
      parse(i i32) i32 is abstract

    c(arg parser) : parser is
      parse(i i32) i32 is
        arg.parse i

  ex : nom =>

    my_parser : parser is
      parse(n i32) i32 is
        1
    c my_parser

  ex
sam@debian /home/not_synced/fuzion (main)1$ fz ~/playground/test\ copy\ 4.fz 

/home/sam/playground/test copy 4.fz:20:7: error 1: Incompatible types when passing argument in a call
    c my_parser
------^
Actual type for argument #1 'arg' does not match expected type.
In call to          : 'test.nom.c'
expected formal type: 'test.nom.parser'
actual type found   : 'test.ex.my_parser'
assignable to       : 'Object',
                      'test.ex.my_parser',
                      'test.ex.parser'
for value assigned  : 'box(ex.this.my_parser)'
To solve this, you could change the type of the target 'arg' to 'test.ex.my_parser' or convert the type of the assigned value to 'test.nom.parser'.

one error.
michaellilltokiwa commented 1 year ago

It would be good to get more details in the error message than "just" incompatible types.

michaellilltokiwa commented 1 year ago

Another example, illustrating the issues with the inheritance semantics. I think it might be quite surprising for most that this does not work:

sam@debian ~ 130$ cat ~/playground/test.fz
ex is

  a is
    distance(m u64) is
      infix + (other distance) distance is
        distance m+other.m
      redef asString => "{m}m"

  b : a is
    d := (distance 10) + (distance 11)

sam@debian ~ $ fz ~/playground/test.fz 

/home/sam/playground/test.fz:10:27: error 1: Incompatible types when passing argument in a call
    d := (distance 10) + (distance 11)
--------------------------^
Actual type for argument #1 'other' does not match expected type.
In call to          : 'ex.a.distance.infix +'
expected formal type: 'ex.a.distance'
actual type found   : 'ex.b.distance'
assignable to       : 'ex.b.distance'
for value assigned  : 'b.this.distance(11)'
To solve this, you could change the type of the target 'other' to 'ex.b.distance' or convert the type of the assigned value to 'ex.a.distance'.

one error.
fridis commented 1 year ago

Here is a solution to the second problem:

ex is

  a is
    distance(m u64) is
      infix + (other distance) distance is
        distance m+other.m
      redef as_string => "{m}m"

  b : a is
    fixed me => b.this
    d := (distance 10) + (me.distance 11)

I could not find a suggestion for the first problem yet, but I recommend just not to inherit like that since the different outer feature makes types incompatible.