Skip to content

ClassCastException in OrderingConstraint.nonParamBounds #4720

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
panacekcz opened this issue Jun 26, 2018 · 3 comments
Closed

ClassCastException in OrderingConstraint.nonParamBounds #4720

panacekcz opened this issue Jun 26, 2018 · 3 comments

Comments

@panacekcz
Copy link
Contributor

Seems to work in release 0.8.0, crash in master:

cce.scala:

object Test {
  def main(args: Array[String]):Unit = m(1)
  def m[Y<:Int, Z>:Int, W>:Z<:Y](d:Y):Unit={}
}

dotc cce.scala:

exception occurred while typechecking cce.scala
exception occurred while compiling cce.scala
Exception in thread "main" java.lang.ClassCastException: dotty.tools.dotc.core.Types$CachedTypeRef cannot be cast to dotty.tools.dotc.core.Types$TypeBounds
        at dotty.tools.dotc.core.OrderingConstraint.nonParamBounds(OrderingConstraint.scala:195)
        at dotty.tools.dotc.core.ConstraintHandling.$anonfun$addToConstraint$2(ConstraintHandling.scala:350)
        at scala.runtime.java8.JFunction1$mcZI$sp.apply(JFunction1$mcZI$sp.java:12)
        at scala.collection.Iterator.forall(Iterator.scala:956)
        at scala.collection.Iterator.forall$(Iterator.scala:954)
        at scala.collection.AbstractIterator.forall(Iterator.scala:1432)
        at scala.collection.IterableLike.forall(IterableLike.scala:74)
        at scala.collection.IterableLike.forall$(IterableLike.scala:73)
        at scala.collection.AbstractIterable.forall(Iterable.scala:54)
        at dotty.tools.dotc.core.ConstraintHandling.addToConstraint(ConstraintHandling.scala:348)
        at dotty.tools.dotc.core.ConstraintHandling.addToConstraint$(ConstraintHandling.scala:344)
        at dotty.tools.dotc.core.TypeComparer.addToConstraint(TypeComparer.scala:19)
        at dotty.tools.dotc.typer.ProtoTypes$.constrained(ProtoTypes.scala:459)
        at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:2534)
        at dotty.tools.dotc.typer.Typer.$anonfun$adapt$1(Typer.scala:2091)
        at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
        at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:2086)
        at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1873)
        at dotty.tools.dotc.reporting.trace$.apply(trace.scala:40)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1869)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1885)
        at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:1944)
        at dotty.tools.dotc.typer.Applications.$anonfun$typedApply$1(Applications.scala:694)
        at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
        at dotty.tools.dotc.typer.Applications.realApply$1(Applications.scala:692)
        at dotty.tools.dotc.typer.Applications.typedApply(Applications.scala:792)
        at dotty.tools.dotc.typer.Applications.typedApply$(Applications.scala:690)
        at dotty.tools.dotc.typer.Typer.typedApply(Typer.scala:82)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:1791)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1842)
        at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1873)
        at dotty.tools.dotc.reporting.trace$.apply(trace.scala:40)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1869)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1885)
        at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:1944)
        at dotty.tools.dotc.typer.Typer.$anonfun$typedDefDef$1(Typer.scala:1431)
        at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
        at dotty.tools.dotc.typer.Typer.typedDefDef(Typer.scala:1410)
        at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:1779)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1841)
        at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1873)
        at dotty.tools.dotc.reporting.trace$.apply(trace.scala:40)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1869)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1885)
        at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:1904)
        at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:1933)
        at dotty.tools.dotc.typer.Typer.$anonfun$typedClassDef$1(Typer.scala:1536)
        at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
        at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:1458)
        at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:1782)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1841)
        at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1873)
        at dotty.tools.dotc.reporting.trace$.apply(trace.scala:40)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1869)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1885)
        at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:1904)
        at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:1933)
        at dotty.tools.dotc.typer.Typer.$anonfun$typedPackageDef$1(Typer.scala:1648)
        at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
        at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:1641)
        at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:1821)
        at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1842)
        at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1873)
        at dotty.tools.dotc.reporting.trace$.apply(trace.scala:40)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1869)
        at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1885)
        at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:1944)
        at dotty.tools.dotc.typer.FrontEnd.$anonfun$typeCheck$1(FrontEnd.scala:66)
        at dotty.tools.dotc.typer.FrontEnd.monitor(FrontEnd.scala:34)
        at dotty.tools.dotc.typer.FrontEnd.typeCheck(FrontEnd.scala:64)
        at dotty.tools.dotc.typer.FrontEnd.$anonfun$runOn$7(FrontEnd.scala:95)
        at dotty.tools.dotc.typer.FrontEnd.$anonfun$runOn$7$adapted(FrontEnd.scala:95)
        at scala.collection.immutable.List.foreach(List.scala:389)
        at dotty.tools.dotc.typer.FrontEnd.runOn(FrontEnd.scala:95)
        at dotty.tools.dotc.Run.$anonfun$compileUnits$3(Run.scala:174)
        at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
        at dotty.tools.dotc.util.Stats$.trackTime(Stats.scala:47)
        at dotty.tools.dotc.Run.$anonfun$compileUnits$2(Run.scala:171)
        at dotty.tools.dotc.Run.$anonfun$compileUnits$2$adapted(Run.scala:169)
        at scala.collection.IndexedSeqOptimized.foreach(IndexedSeqOptimized.scala:32)
        at scala.collection.IndexedSeqOptimized.foreach$(IndexedSeqOptimized.scala:29)
        at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:194)
        at dotty.tools.dotc.Run.runPhases$1(Run.scala:169)
        at dotty.tools.dotc.Run.$anonfun$compileUnits$1(Run.scala:194)
        at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
        at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:88)
        at dotty.tools.dotc.Run.compileUnits(Run.scala:149)
        at dotty.tools.dotc.Run.compileSources(Run.scala:136)
        at dotty.tools.dotc.Run.compile(Run.scala:120)
        at dotty.tools.dotc.Driver.doCompile(Driver.scala:29)
        at dotty.tools.dotc.Driver.process(Driver.scala:127)
        at dotty.tools.dotc.Driver.process(Driver.scala:96)
        at dotty.tools.dotc.Driver.process(Driver.scala:108)
        at dotty.tools.dotc.Driver.main(Driver.scala:135)
        at dotty.tools.dotc.Main.main(Main.scala)
@Blaisorblade
Copy link
Contributor

We just got a new report on Gitter, so I took a look.
It's a cool bug, thanks! Basically, type inference is smarter than it expects to be.

IIUC from the code, when starting type inference for the call to [Y<:Int, Z>:Int, W>:Z<:Y], addToConstraint processes m's type arguments in turn, and expects the real inference to happen later.

But here type inference finishes earlier than expected: it processes Y and Z and propagates their bounds, then when it processes argument W and searches for its bounds, it doesn't find bounds, because W is already been inferred to be Int. If addToConstraint skips processing W, the code seems to compile correctly:

package <empty> {
  final lazy module val Test: Test$ = new Test$()
  final module class Test$() extends Object() { this: Test.type =>
    def main(args: Array[String]): Unit = Test.m[Int, Int, Int](1)
    def m[Y >: Nothing <: Int, Z >: Int <: Any, W >: Z <: Y](d: Y): Unit =
      {
        ()
      }
  }
}

It seems #4721 is similar, but there we find a problem because there's no solution for W.

@Blaisorblade
Copy link
Contributor

And the bug was apparently exposed (or introduced) by @smarter type inference in eeb5965 😉

Blaisorblade added a commit to dotty-staging/dotty that referenced this issue Aug 15, 2018
Fix regression in eeb5965. A type variable can
already be solved in addToConstraint, so don't assume it is unsolved (hence its
constraint entry is a TypeBounds) when first processing it.

Fix scala#4720.
Blaisorblade added a commit to dotty-staging/dotty that referenced this issue Aug 15, 2018
Fix regression in eeb5965. A type variable can
already be solved in addToConstraint, so don't assume it is unsolved (hence its
constraint entry is a TypeBounds) when first processing it.

Fix scala#4720.
@Blaisorblade
Copy link
Contributor

@pdbp on Gitter reports a variant of the same issue elsewhere, which suggests a more conservative fix strategy.

Blaisorblade added a commit to dotty-staging/dotty that referenced this issue Aug 15, 2018
Be more defensive to handle other issues such as
scala#4720 (comment).

Code that needs to access the actual entry can call `entry` or `contains`
instead.
Blaisorblade added a commit that referenced this issue Aug 21, 2018
…-smarter-type-inference

Fix #4720 and #4721: account for type inference being too smart
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

2 participants