Skip to content

Error in -Ycheck:typer when refining String on StringOps defs #17465

@timotheeandres

Description

@timotheeandres

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())

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions