Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polymorphic types are incorrectly propagated into aggregated objects implementing traits using the same type variable names #297

Closed
Bearmarshal opened this issue Dec 3, 2015 · 10 comments
Assignees

Comments

@Bearmarshal
Copy link

When an aggregated polymorphic class is parameterised with a type name the trait it implements uses internally for a different type variable, the typechecker will propagate the types incorrectly. Consider the following:

trait AB<a, b> {
  require aa : a
  require bb : b

  def fun(aa : a) : b {
    this.aa = aa;
    this.bb
  }
}

passive class Foo<a, b> : AB<a, b> {
  aa : a
  bb : b

  def init(aa : a, bb : b) : void {
    this.aa = aa;
    this.bb = bb;
  }
}

passive class Bar<b, c> {
  foo : AB<b, c>

  def init(bb : b, cc : c) : void {
    this.foo = new Foo<b, c>(bb, cc);
  }

  def fun(bb : b) : c {
    this.foo.fun(bb)
  }
}

class Main {
  def main() : void {
    let bar = new Bar<real, int>(3.14, 42) in {
      print("assert(bar.fun(4.13) == 42): {}\n", bar.fun(4.13))
    }
  }
}

Now you would expect foo to be a AB<real, int>, but the typechecker will turn it into a AB<int, int> while still keeping Bar<real, int>, promptly causing errors with Bar.fun() as the type of bb (real) doesn't match the type incorrectly expected by foo.fun() (int).

EDIT:
Hopefully made my example runnable.

EDIT:
Changed the example to an example which actually contains the bug, and updated the description accordingly. Note that it's the names in Bar and AB which are clashing. The names in Foo are irrelevant.

@Bearmarshal
Copy link
Author

For the record, the error does not appear if Bar was parameterised internally as <c, b> instead, as the type names either match the same positions outside and inside of Foo, or aren't shared at all.

@albertnetymk
Copy link
Contributor

Could you provide a complete example? My attempt seems to working. Maybe I missed your original idea.

passive class Foo<a, b> {
  x : b
  def init() : void { () }

  def fun(aa : a) : b {
    this.x
  }
}

passive class Bar<b, c> {
  foo : Foo<b, c>

  def init() : void {
    this.foo = new Foo<b, c>()
  }

  def fun(bb : b) : c {
    this.foo.fun(bb)
  }
}

class Main {
  def main() : void {()}
}

@Bearmarshal
Copy link
Author

You aren't actally creating a Bar object, so the typechecker isn't trying to set its type parameters to anything. Try calling (new Bar<real, int>()).fun(3.14) inside main

@Bearmarshal
Copy link
Author

I updated my initial example to make something which at least looks runnable. I've been on Windows all day, so I forgot some of the crucial syntax at first... X3

@albertnetymk
Copy link
Contributor

I just need to use this to reference foo in Bar.fun, and it works; sth like:

Assert 42 == 42

@Bearmarshal
Copy link
Author

Weird. I'll try it out to see where the line is drawn...

(And that was a typo in the example, my original code doesn't have any such errors.)

@Bearmarshal
Copy link
Author

Okay, I've isolated it. Foo needs to implement a trait, like this:

trait AB<a, b> {
  require aa : a
  require bb : b

  def fun(aa : a) : b {
    this.aa = aa;
    this.bb
  }
}

passive class Foo<a, b> : AB<a, b> {
  aa : a
  bb : b

  def init(aa : a, bb : b) : void {
    this.aa = aa;
    this.bb = bb;
  }
}

passive class Bar<b, c> {
  foo : AB<b, c>

  def init(bb : b, cc : c) : void {
    this.foo = new Foo<b, c>(bb, cc);
  }

  def fun(bb : b) : c {
    this.foo.fun(bb)
  }
}

class Main {
  def main() : void {
    let bar = new Bar<real, int>(3.14, 42) in {
      print("assert(bar.fun(4.13) == 42): {}\n", bar.fun(4.13))
    }
  }
}

@Bearmarshal Bearmarshal changed the title Polymorphic types are incorrectly propagated into aggregated objects using the same type variable names Polymorphic types are incorrectly propagated into aggregated objects implementing traits using the same type variable names Dec 4, 2015
@Bearmarshal
Copy link
Author

I tried changing the names around in Foo, and it seems to be AB and Bar which are clashing. The parameter names in Foo are irrelevant.

@albertnetymk
Copy link
Contributor

Confirmed. Fix on the way.

@albertnetymk albertnetymk self-assigned this Dec 8, 2015
@albertnetymk
Copy link
Contributor

Can't reproduce it on development, closing now. Reopen, if not so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants