Skip to content

Commit 11af161

Browse files
committed
missing cases for less eager dealiasing after following type alias
1 parent a4b11d1 commit 11af161

File tree

6 files changed

+66
-26
lines changed

6 files changed

+66
-26
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,31 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
171171
else if GADTused then CompareResult.OKwithGADTUsed
172172
else CompareResult.OK
173173

174+
/** original aliases of types used to instantiate type parameters
175+
* collected in `recur` and to be restored after sub type check */
176+
private var realiases: List[(TypeParamRef, NamedType, Type)] = List.empty
177+
178+
private def realiasConstraints() =
179+
this.realiases foreach { (param, alias, dealiased) =>
180+
constraint.entry(param) match
181+
case TypeBounds(lo, hi) =>
182+
val aliasLo = (alias ne lo) && (dealiased eq lo)
183+
val aliasHi = (alias ne hi) && (dealiased eq hi)
184+
if aliasLo || aliasHi then
185+
constraint = constraint.updateEntry(param, TypeBounds(
186+
if aliasLo then alias else lo,
187+
if aliasHi then alias else hi))
188+
case tp =>
189+
if (alias ne tp) && (dealiased eq tp) then
190+
constraint = constraint.updateEntry(param, alias)
191+
}
192+
193+
private inline def aliasedConstraint(param: Type, alias: NamedType, dealiased: Type) =
194+
if alias.symbol.isStatic then
195+
param.stripTypeVar match
196+
case param: TypeParamRef => this.realiases ::= (param, alias, dealiased)
197+
case _ =>
198+
174199
/** The current approximation state. See `ApproxState`. */
175200
private var approx: ApproxState = ApproxState.Fresh
176201
protected def approxState: ApproxState = approx
@@ -210,18 +235,24 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
210235
try op finally comparedTypeLambdas = saved
211236

212237
protected def isSubType(tp1: Type, tp2: Type, a: ApproxState): Boolean = {
238+
val outermostCall = leftRoot eq null
213239
val savedApprox = approx
214240
val savedLeftRoot = leftRoot
215241
if (a == ApproxState.Fresh) {
216242
this.approx = ApproxState.None
217243
this.leftRoot = tp1
218244
}
219245
else this.approx = a
220-
try recur(tp1, tp2)
246+
if outermostCall then this.realiases = List.empty
247+
try
248+
val res = recur(tp1, tp2)
249+
if outermostCall then realiasConstraints()
250+
res
221251
catch {
222252
case ex: Throwable => handleRecursive("subtype", i"$tp1 <:< $tp2", ex, weight = 2)
223253
}
224254
finally {
255+
if outermostCall then this.realiases = List.empty
225256
this.approx = savedApprox
226257
this.leftRoot = savedLeftRoot
227258
}
@@ -297,13 +328,15 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
297328
val info2 = tp2.info
298329
info2 match
299330
case info2: TypeAlias =>
331+
aliasedConstraint(tp1, tp2, info2.alias)
300332
if recur(tp1, info2.alias) then return true
301333
if tp2.asInstanceOf[TypeRef].canDropAlias then return false
302334
case _ =>
303335
tp1 match
304336
case tp1: NamedType =>
305337
tp1.info match {
306338
case info1: TypeAlias =>
339+
aliasedConstraint(tp2, tp1, info1.alias)
307340
if recur(info1.alias, tp2) then return true
308341
if tp1.asInstanceOf[TypeRef].canDropAlias then return false
309342
case _ =>
@@ -413,26 +446,9 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
413446
case tp1: NamedType =>
414447
tp1.info match {
415448
case info1: TypeAlias =>
416-
def realiasConstraint() = tp2 match {
417-
case tp2: TypeParamRef =>
418-
constraint.entry(tp2) match {
419-
case TypeBounds(lo, hi) =>
420-
val aliasLo = (tp1 ne lo) && (info1.alias eq lo)
421-
val aliasHi = (tp1 ne hi) && (info1.alias eq hi)
422-
if aliasLo || aliasHi then
423-
constraint = constraint.updateEntry(tp2, TypeBounds(
424-
if aliasLo then tp1 else lo,
425-
if aliasHi then tp1 else hi))
426-
case tp =>
427-
if (tp1 ne tp) && (info1.alias eq tp) then
428-
constraint = constraint.updateEntry(tp2, tp1)
429-
}
430-
case _ =>
431-
}
432-
val res = recur(info1.alias, tp2)
433-
if (tp1.symbol.isStatic) realiasConstraint()
434-
if (res) return true
435-
if (tp1.prefix.isStable) return tryLiftedToThis1
449+
aliasedConstraint(tp2, tp1, info1.alias)
450+
if recur(info1.alias, tp2) then return true
451+
if tp1.prefix.isStable then return tryLiftedToThis1
436452
case _ =>
437453
if (tp1 eq NothingType) || isBottom(tp1) then return true
438454
}

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -666,19 +666,20 @@ class SpaceEngine(using Context) extends SpaceLogic {
666666

667667
/** Abstract sealed types, or-types, Boolean and Java enums can be decomposed */
668668
def canDecompose(tp: Type): Boolean =
669-
val res = tp.dealias match
669+
val underlying = tp.dealias
670+
val res = underlying match
670671
case _: SingletonType => false
671672
case _: OrType => true
672673
case and: AndType => canDecompose(and.tp1) || canDecompose(and.tp2)
673674
case _ =>
674-
val cls = tp.classSymbol
675+
val cls = underlying.classSymbol
675676
cls.is(Sealed)
676677
&& cls.isOneOf(AbstractOrTrait)
677678
&& !cls.hasAnonymousChild
678679
&& cls.children.nonEmpty
679680
|| cls.isAllOf(JavaEnumTrait)
680-
|| tp.isRef(defn.BooleanClass)
681-
|| tp.isRef(defn.UnitClass)
681+
|| underlying.isRef(defn.BooleanClass)
682+
|| underlying.isRef(defn.UnitClass)
682683
//debug.println(s"decomposable: ${tp.show} = $res")
683684
res
684685

tests/run-macros/i15304.check

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Test.MyString
2+
Test.MyString
3+
Test.MyString
4+
scala.Seq[Test.MyString]
5+
scala.Tuple2[Test.MyString, scala.Int]

tests/run-macros/i15304/Macro_1.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.quoted._
2+
3+
def typeNameOf[A: Type](using Quotes): Expr[String] =
4+
val name = Type.show[A]
5+
Expr(name)
6+
7+
inline def typeNameOf[A]: String = ${ typeNameOf[A] }
8+
9+
inline def typeNameOfF1[A](f: A => Unit): String = ${ typeNameOf[A] }

tests/run-macros/i15304/Test_2.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Test:
2+
type MyString = String
3+
4+
def main(args: Array[String]): Unit =
5+
println(typeNameOf[MyString])
6+
println(typeNameOfF1 { (x: MyString) => })
7+
println(typeNameOfF1[MyString] { (x: MyString) => })
8+
println(typeNameOfF1 { (x: Seq[MyString]) => })
9+
println(typeNameOfF1 { (x: (MyString, Int)) => })

tests/run-macros/quote-matcher-runtime.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ Pattern: scala.StringContext.apply("abc", "xyz")
245245
Result: Some(List())
246246

247247
Scrutinee: scala.StringContext.apply("abc", "xyz")
248-
Pattern: scala.StringContext.apply(scala.quoted.runtime.Patterns.patternHole[java.lang.String], scala.quoted.runtime.Patterns.patternHole[java.lang.String])
248+
Pattern: scala.StringContext.apply(scala.quoted.runtime.Patterns.patternHole[scala.Predef.String], scala.quoted.runtime.Patterns.patternHole[scala.Predef.String])
249249
Result: Some(List(Expr("abc"), Expr("xyz")))
250250

251251
Scrutinee: scala.StringContext.apply("abc", "xyz")

0 commit comments

Comments
 (0)