Skip to content

Commit c126902

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 0b4c6e7 commit c126902

File tree

5 files changed

+39
-8
lines changed

5 files changed

+39
-8
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
436436
* of the parameter elsewhere in the constraint by type `tp`.
437437
*/
438438
def replace(param: TypeParamRef, tp: Type)(using Context): OrderingConstraint =
439-
val replacement = tp.dealiasKeepAnnots.stripTypeVar
439+
val replacement = tp.withDealiased(_.stripTypeVar)
440440
if param == replacement then this.checkNonCyclic()
441441
else
442442
assert(replacement.isValueTypeOrLambda)

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -424,10 +424,9 @@ object TypeOps:
424424
case _ => true
425425

426426
override def apply(tp: Type): Type = tp match
427-
case tp: TermRef
428-
if toAvoid(tp) =>
429-
tp.info.widenExpr.dealias match {
430-
case info: SingletonType => apply(info)
427+
case tp: TermRef if toAvoid(tp) =>
428+
tp.info.widenExpr.withDealiased {
429+
case singleton: SingletonType => apply(singleton)
431430
case info => range(defn.NothingType, apply(info))
432431
}
433432
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
@@ -1407,6 +1407,14 @@ object Types {
14071407
*/
14081408
final def dealiasKeepOpaques(using Context): Type = dealias1(keepNever, keepOpaques = true)
14091409

1410+
/** Apply `f` to this type dealiased. If the type changes, keep the change,
1411+
* otherwise return the original (not dealiased) type.
1412+
*/
1413+
final def withDealiased(f: Type => Type)(using Context): Type =
1414+
val tpd = dealias
1415+
val result = f(tpd)
1416+
if result eq tpd then this else result
1417+
14101418
/** Approximate this type with a type that does not contain skolem types. */
14111419
final def deskolemized(using Context): Type =
14121420
val deskolemizer = new ApproximatingTypeMap {
@@ -1455,10 +1463,9 @@ object Types {
14551463
}
14561464

14571465
/** Dealias, and if result is a dependent function type, drop the `apply` refinement. */
1458-
final def dropDependentRefinement(using Context): Type = dealias match {
1466+
final def dropDependentRefinement(using Context): Type = dealias match
14591467
case RefinedType(parent, nme.apply, _) => parent
1460-
case tp => tp
1461-
}
1468+
case _ => this
14621469

14631470
/** The type constructor of an applied type, otherwise the type itself */
14641471
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)