Description
Compiler version
Regressed in 3.6.4-RC1 (with 26ecda540b9), present until today (3.7.2-RC1).
Minimized code
A_1.scala:
package pkg
import scala.quoted.*
trait HasElem {
type Elem
type Alias = Elem
}
object Macro:
inline def foo: Unit = ${fooImpl}
def fooImpl(using Quotes): Expr[Unit] =
'{
val lll: (he: HasElem) => he.Alias =
(hx: HasElem) => ???
}
B_2.scala:
object Test:
def test: Unit = pkg.Macro.foo
Output
[error] ./try/qb/B_2.scala:2:20
[error] Found: (hx: pkg.HasElem) => hx.Elem
[error] Required: (he: pkg.HasElem) => he.Elem
[error] def test: Unit = pkg.Macro.foo
[error] ^^^^^^^^^^^^^
When compiling with -Ycheck:all
:
checking /home/smarter/opt/dotty/try/qb/A_1.scala after phase staging
*** error while checking /home/smarter/opt/dotty/try/qb/A_1.scala after phase staging ***
unhandled exception while running Ycheck on /home/smarter/opt/dotty/try/qb/A_1.scala
An unhandled exception was thrown in the compiler.
Please file a crash report here:
https://github.com/scala/scala3/issues/new/choose
For non-enriched exceptions, compile with -Xno-enrich-error-messages.
while compiling: /home/smarter/opt/dotty/try/qb/A_1.scala
during phase: Ycheck
mode: Mode(ImplicitsEnabled)
library version: version 2.13.16
compiler version: version 3.7.2-RC1
settings: -Ycheck List(all) -bootclasspath /home/smarter/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.7.2-RC1/scala3-library_3-3.7.2-RC1.jar:/home/smarter/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.16/scala-library-2.13.16.jar -classpath /home/smarter/opt/dotty/try/qb/.scala-build/.bloop/qb_602a3656b0-ef55e4b6ab/bloop-internal-classes/main-irbvWweBRRmK1j4mRX8ZSg==:/home/smarter/opt/dotty/try/qb/.scala-build/qb_602a3656b0-ef55e4b6ab/classes/classes-empty-qb_602a3656b0-ef55e4b6ab -d /home/smarter/opt/dotty/try/qb/.scala-build/.bloop/qb_602a3656b0-ef55e4b6ab/bloop-internal-classes/main-irbvWweBRRmK1j4mRX8ZSg== -sourceroot /home/smarter/opt/dotty/try/qb
Error compiling project (Scala 3.7.2-RC1, JVM (17))
Error: java.lang.AssertionError: assertion failed: Type Mismatch (while checking typedUnadapted):
Found: (hx: pkg.HasElem) => hx.Elem
Required: (hx: pkg.HasElem) => hx.Alias
I tried to show that
(hx: pkg.HasElem) => hx.Elem
conforms to
(hx: pkg.HasElem) => hx.Alias
but none of the attempts shown below succeeded:
==> (hx: pkg.HasElem) => hx.Elem <: (hx: pkg.HasElem) => hx.Alias
==> (hx: pkg.HasElem) => hx.Elem <: pkg.HasElem => pkg.HasElem#Alias
==> pkg.HasElem => pkg.HasElem#Elem <: pkg.HasElem => pkg.HasElem#Alias
==> pkg.HasElem#Elem <: pkg.HasElem#Alias
==> Any <: pkg.HasElem#Alias = false
The tests were made under the empty constraint
tree = closure($anonfun) Closure
Expectation
Code that typechecks should not break in a later phase. This regressed after 26ecda540b9 which made the following change impact when asSeenFrom decides to approximate a type:
diff --git compiler/src/dotty/tools/dotc/core/TypeOps.scala compiler/src/dotty/tools/dotc/core/TypeOps.scala
index 2403a6e22b..c27b3c3978 100644
--- compiler/src/dotty/tools/dotc/core/TypeOps.scala
+++ compiler/src/dotty/tools/dotc/core/TypeOps.scala
@@ -124,7 +124,7 @@ object TypeOps:
}
def isLegalPrefix(pre: Type)(using Context): Boolean =
- pre.isStable || !ctx.phase.isTyper
+ pre.isStable
/** Implementation of Types#simplified */
def simplify(tp: Type, theMap: SimplifyMap | Null)(using Context): Type = {
Reverting that change fixes this issue, but breaks the test cases from 26ecda540b9 like tests/pos/i17222.8.scala From the original PR I found #22653 which shows it was reverted in 3.6.4 final (and indeed my test case works in 3.6.4 final), but this was only done in the 3.6 branch and I haven't understood why, do you remember @WojciechMazur @dwijnand ?
I can also fix this issue by removing an unnecessary de-aliasing in the staging phase:
diff --git compiler/src/dotty/tools/dotc/staging/HealType.scala compiler/src/dotty/tools/dotc/staging/HealType.scala
index a73f884fba..fc7c56b7b5 100644
--- compiler/src/dotty/tools/dotc/staging/HealType.scala
+++ compiler/src/dotty/tools/dotc/staging/HealType.scala
@@ -32,7 +32,10 @@ class HealType(pos: SrcPos)(using Context) extends TypeMap {
*/
def apply(tp: Type): Type =
tp match
- case NonSpliceAlias(aliased) => this.apply(aliased)
+ case NonSpliceAlias(aliased) =>
+ val aliased1 = this.apply(aliased)
+ if aliased1 ne aliased then aliased1
+ else tp
case tp: TypeRef => healTypeRef(tp)
case tp: TermRef =>
val inconsistentRoot = levelInconsistentRootOfPath(tp)
Which is not a bad change by itself, but I'm afraid we'll find other problematic and hard-to-debug cases due to this recent behavior of isLegalPrefix.