Skip to content

Commit e38bdbc

Browse files
committed
Dealias less in OrderingConstraint.replace and AvoidMap
Basically if the transformation doesn't apply to the dealias type, then return the original type instead of the dealiased one. In general it's reduce dealiasing to a minimum when typing, because it can affect type unification as shown in the tests. Unfortunately this doesn't handle the case of a singleton type alias, because `widenSingletons` also dealiases and the same fix doesn't work.
1 parent b1b1dfd commit e38bdbc

File tree

5 files changed

+38
-6
lines changed

5 files changed

+38
-6
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
454454
* of the parameter elsewhere in the constraint by type `tp`.
455455
*/
456456
def replace(param: TypeParamRef, tp: Type)(using Context): OrderingConstraint =
457-
val replacement = tp.dealiasKeepAnnots.stripTypeVar
457+
val replacement = tp.withDealiased(_.stripTypeVar)
458458
if param == replacement then this.checkNonCyclic()
459459
else
460460
assert(replacement.isValueTypeOrLambda)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,8 @@ object TypeOps:
451451
try
452452
tp match
453453
case tp: TermRef if toAvoid(tp) =>
454-
tp.info.widenExpr.dealias match {
455-
case info: SingletonType => apply(info)
454+
tp.info.widenExpr.withDealiased {
455+
case singleton: SingletonType => apply(singleton)
456456
case info => range(defn.NothingType, apply(info))
457457
}
458458
case tp: TypeRef if toAvoid(tp) =>

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,14 @@ object Types {
14301430
*/
14311431
final def dealiasKeepOpaques(using Context): Type = dealias1(keepNever, keepOpaques = true)
14321432

1433+
/** Apply `f` to this type dealiased. If the type changes, keep the change,
1434+
* otherwise return the original (not dealiased) type.
1435+
*/
1436+
final def withDealiased(f: Type => Type)(using Context): Type =
1437+
val tpd = dealias
1438+
val result = f(tpd)
1439+
if result eq tpd then this else result
1440+
14331441
/** Approximate this type with a type that does not contain skolem types. */
14341442
final def deskolemized(using Context): Type =
14351443
val deskolemizer = new ApproximatingTypeMap {
@@ -1478,10 +1486,9 @@ object Types {
14781486
}
14791487

14801488
/** Dealias, and if result is a dependent function type, drop the `apply` refinement. */
1481-
final def dropDependentRefinement(using Context): Type = dealias match {
1489+
final def dropDependentRefinement(using Context): Type = dealias match
14821490
case RefinedType(parent, nme.apply, _) => parent
1483-
case tp => tp
1484-
}
1491+
case _ => this
14851492

14861493
/** The type constructor of an applied type, otherwise the type itself */
14871494
final def typeConstructor(using Context): Type = this match {

tests/neg/i14171.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object Test:
2+
trait MyTypeclass[F[_]]
3+
def f[F[_]: MyTypeclass, U](t: F[U]) = ()
4+
5+
// using a non-singleton type makes it compile because `widenSingletons` dealiases
6+
type MyType[T] = Nil.type
7+
given MyTypeclass[MyType] = null
8+
9+
val stream: Option[MyType[Int]] = null
10+
for
11+
keyStream <- stream
12+
x = 17 // commenting this line makes it compile
13+
yield f(keyStream) // error

tests/pos/i14171.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
object Test:
2+
trait MyTypeclass[F[_]]
3+
def f[F[_]: MyTypeclass, U](t: F[U]) = ()
4+
5+
type MyType[T] = String
6+
given MyTypeclass[MyType] = null
7+
8+
val stream: Option[MyType[Int]] = null
9+
for
10+
keyStream <- stream
11+
x = 17
12+
yield f(keyStream)

0 commit comments

Comments
 (0)