Closed
Description
Compiler version
3.3.0-RC4
Minimized code
Compile this code with the -Ycheck:typer
flag.
import reflect.Selectable.reflectiveSelectable
trait A[T](x: T{ def *(y: Int): T }):
def f: T = x * 2
class B extends A("Hello")
Edit: further minimization (thanks to @nicolasstucki):
import reflect.Selectable.reflectiveSelectable
def f[T](x: T{ def *(y: Int): T }): T = x * 2
def test = f[scala.collection.StringOps | String]("Hello")
Output
checking a.scala after phase typer
exception while retyping new A[scala.collection.StringOps | String](augmentString("Hello")) of class Apply # -1
An unhandled exception was thrown in the compiler.
Please file a crash report here:
https://github.com/lampepfl/dotty/issues/new/choose
while compiling: a.scala
during phase: typer
mode: Mode(ImplicitsEnabled)
library version: version 2.13.10
compiler version: version 3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped-git-b3643ee
settings: -Ycheck List(typer) -classpath C:\Users\Tim\AppData\Local\Coursier\Cache\v1\https\repo1.maven.org\maven2\org\scala-lang\scala-library\2.13.10\scala-library-2.13.10.jar;D:\Bureau\dotty\library\..\out\bootstrap\scala3-library-bootstrapped\scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped\scala3-library_3-3.3.1-RC1-bin-SNAPSHOT.jar
tree: PackageDef(object <empty>)
tree position: a.scala:1:0
tree type: <empty>.type
symbol: package <empty>
symbol definition: final lazy module object <empty>: <empty> (a Symbol)
symbol package: <root>
symbol owners:
call site: constructor B in class B in module class <empty>
== Source file context for tree position ==
-- Error: a.scala:1:0 --------------------------------------------------------------------------------------------------
1 |import reflect.Selectable.reflectiveSelectable
|^
2 |trait A[T](x: T{ def *(y: Int): T }):
3 | def f: T = x * 2
4 |class B extends A("Hello")
*** error while checking a.scala after phase typer ***
Exception in thread "main" java.lang.AssertionError: assertion failed: Types differ
Original type : (x: (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String}):
A[scala.collection.StringOps | String]
After checking: (x: (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String}):
A[scala.collection.StringOps | String]
Original tree : new A[scala.collection.StringOps | String]
After checking: new A[scala.collection.StringOps | String]
Why different :
Subtype trace:
A[scala.collection.StringOps | String] <: (x: (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String}):
==> (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} in frozen constraint
==> (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: scala.collection.StringOps | String in frozen constraint
==> (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: scala.collection.StringOps | String in frozen constraint
==> (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: scala.collection.StringOps in frozen constraint
==> lub(scala.collection.StringOps, <notype>, canConstrain=false, isSoft=true)
<== lub(scala.collection.StringOps, <notype>, canConstrain=false, isSoft=true) = <notype>
<== (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: scala.collection.StringOps in frozen constraint = false
==> (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: String in frozen constraint
==> lub(<notype>, String, canConstrain=false, isSoft=true)
<== lub(<notype>, String, canConstrain=false, isSoft=true) = <notype>
<== (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: String in frozen constraint = false
<== (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: scala.collection.StringOps | String in frozen constraint = false
<== (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: scala.collection.StringOps | String in frozen constraint = false
<== (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} <: (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String} in frozen constraint = false
A[scala.collection.StringOps | String] = false: (scala.collection.StringOps | String){def *(y: Int): scala.collection.StringOps | String}):
at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
at dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:408)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3175)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3179)
at dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:378)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3291)
at dotty.tools.dotc.typer.Applications.realApply$1(Applications.scala:941)
at dotty.tools.dotc.typer.Applications.typedApply(Applications.scala:1101)
at dotty.tools.dotc.typer.Applications.typedApply$(Applications.scala:352)
at dotty.tools.dotc.transform.TreeChecker$Checker.typedApply(TreeChecker.scala:501)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3040)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3103)
at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:126)
at dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:395)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3175)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3179)
at dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:378)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3291)
at dotty.tools.dotc.typer.Typer.typedParent$1(Typer.scala:2560)
at dotty.tools.dotc.typer.Typer.$anonfun$58(Typer.scala:2644)
at dotty.tools.dotc.core.Decorators$.loop$1(Decorators.scala:94)
at dotty.tools.dotc.core.Decorators$.mapconserve(Decorators.scala:110)
at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:2644)
at dotty.tools.dotc.transform.TreeChecker$Checker.typedClassDef(TreeChecker.scala:567)
at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$1(Typer.scala:3028)
at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:3032)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3102)
at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:126)
at dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:395)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3175)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3179)
at dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:378)
at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3201)
at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3247)
at dotty.tools.dotc.transform.TreeChecker$Checker.typedStats(TreeChecker.scala:632)
at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:2804)
at dotty.tools.dotc.transform.TreeChecker$Checker.typedPackageDef(TreeChecker.scala:658)
at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:3073)
at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:3103)
at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:126)
at dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:395)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3175)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3179)
at dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:378)
at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3291)
at dotty.tools.dotc.transform.TreeChecker.check(TreeChecker.scala:126)
at dotty.tools.dotc.transform.TreeChecker.run(TreeChecker.scala:106)
at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:324)
at scala.collection.immutable.List.map(List.scala:246)
at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:328)
at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:246)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1321)
at dotty.tools.dotc.Run.runPhases$1(Run.scala:262)
at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:270)
at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:279)
at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:67)
at dotty.tools.dotc.Run.compileUnits(Run.scala:279)
at dotty.tools.dotc.Run.compileSources(Run.scala:194)
at dotty.tools.dotc.Run.compile(Run.scala:179)
at dotty.tools.dotc.Driver.doCompile(Driver.scala:37)
at dotty.tools.dotc.Driver.process(Driver.scala:197)
at dotty.tools.dotc.Driver.process(Driver.scala:165)
at dotty.tools.dotc.Driver.process(Driver.scala:177)
at dotty.tools.dotc.Driver.main(Driver.scala:207)
at dotty.tools.dotc.Main.main(Main.scala)
Expectation
The code compiles both with and without the -Ycheck:typer
flag.
More information
This seems to be related to the widening of String
to scala.collection.StringOps | String
, as this issue does not arise with a homemade class: the following code passes the check.
import reflect.Selectable.reflectiveSelectable
class C:
def *(y: Int): C = this
trait A[T](x: T{ def *(y: Int): T }):
def f: T = x * 2
class B extends A(new C())