Skip to content

Problematic type inference in supercall when type parameter appears only in contravariant position #2218

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

Closed
liufengyun opened this issue Apr 10, 2017 · 4 comments

Comments

@liufengyun
Copy link
Contributor

Following code compiles fine in Scalac, but fails to compile in Dotty, because the type parameter inferred is new DefaultRule[Nothing, Out, A, X](f) with Name.

trait Rule[In, Out, A, X]
trait Result[Out, A, X]
trait Name

class C {
  def ruleWithName[In, Out, A, X](_name: String, f: In => Result[Out, A, X]): Rule[In, Out, A, X] with Name =
    new DefaultRule(f) with Name

  class DefaultRule[In, Out, A, X](f: In => Result[Out, A, X]) extends Rule[In, Out, A, X]
}

If we remove the intersection type, the following version compiles fine in Dotty:

trait Rule[In, Out, A, X]
trait Result[Out, A, X]

class C {
  def ruleWithName[In, Out, A, X](_name: String, f: In => Result[Out, A, X]): Rule[In, Out, A, X] =
    new DefaultRule(f)

  class DefaultRule[In, Out, A, X](f: In => Result[Out, A, X]) extends Rule[In, Out, A, X]
}

Note that adding variance doesn't help, following version also fails:

trait Rule[-In, +Out, +A, +X]
trait Result[+Out, +A, +X]
trait Name

class C {
  def ruleWithName[In, Out, A, X](_name: String, f: In => Result[Out, A, X]): Rule[In, Out, A, X] with Name =
    new DefaultRule(f) with Name

  class DefaultRule[In, Out, A, X](f: In => Result[Out, A, X]) extends Rule[In, Out, A, X]
}
@smarter
Copy link
Member

smarter commented Apr 10, 2017

Minimization:

trait Rule[In]

class C {
  def ruleWithName[In](f: In => Int): Rule[In] =
    new DefaultRule(f) {}

  class DefaultRule[In](f: In => Int) extends Rule[In]
}

An intersection type is not necessary, any new expression that creates an anonymous class seems to work.

@smarter smarter changed the title Incorrectly inferred Nothing in And-types Type inference bug with anonymous class Apr 10, 2017
@smarter
Copy link
Member

smarter commented Apr 10, 2017

Minimized further to not use a function type, the important part is that the type parameter has to appear in contravariant positions only:

trait Rule[In]

trait Contra[-T]

class C {
  def ruleWithName[In](f: Contra[In]): Rule[In] =
    new DefaultRule(f) {} // Inference works if the "{}" is removed.

  class DefaultRule[In](f: Contra[In]) extends Rule[In]
}

@smarter smarter changed the title Type inference bug with anonymous class Type inference bug with anonymous class and type parameter appearing in contravariant position only Apr 10, 2017
@smarter
Copy link
Member

smarter commented Apr 10, 2017

We can desugar the anonymous class to see that the problem is with the type inference of the superclass constructor of the anonymous class:

trait Rule[In]
trait Name

trait Contra[-T]

class C {
  def ruleWithName[In](f: Contra[In]): Rule[In] = {
    class Hi extends DefaultRule(f) // T=Nothing instead of T=In
    new Hi
  }

  class DefaultRule[T](f: Contra[T]) extends Rule[T]
}

@smarter smarter changed the title Type inference bug with anonymous class and type parameter appearing in contravariant position only Problematic type inference in supercall when type parameter appears only in contravariant position Apr 10, 2017
@smarter
Copy link
Member

smarter commented Apr 10, 2017

Note that Nothing and In are both valid instantiation of the type parameter in the supercall, but dotty should prefer In because that's the constraint given by the user, as opposed to Nothing which is the lower bound of the type parameter: https://github.com/lampepfl/dotty/blob/318700fdaacd7e6707519e03f15a5ede99ca558a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala#L52-L64 I don't know why this isn't working here.

@odersky odersky self-assigned this Apr 11, 2017
odersky added a commit that referenced this issue Apr 11, 2017
Fix #2218: Add fullyDefinedType for class parent types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants