Skip to content

Commit 8320d3b

Browse files
oderskymichelou
authored andcommitted
Don't flag match type aliases as unreducible
If `M[_]` is a match type alias, it was rejected for being an unreducible application of wildcard types. It is now accepted. I believe that is sound - this is siply an unreducible match type. The situation is not the same as `F[_]` where `F` is an abstract type that can be refined in several ways in subclasses. Fixes scala#9999
1 parent d486eb9 commit 8320d3b

File tree

4 files changed

+68
-4
lines changed

4 files changed

+68
-4
lines changed

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

+19-3
Original file line numberDiff line numberDiff line change
@@ -4004,7 +4004,7 @@ object Types {
40044004
case nil => x
40054005
foldArgs(op(x, tycon), args)
40064006

4007-
override def tryNormalize(using Context): Type = tycon match {
4007+
override def tryNormalize(using Context): Type = tycon.stripTypeVar match {
40084008
case tycon: TypeRef =>
40094009
def tryMatchAlias = tycon.info match {
40104010
case MatchAlias(alias) =>
@@ -4014,13 +4014,29 @@ object Types {
40144014
case _ =>
40154015
NoType
40164016
}
4017-
40184017
tryCompiletimeConstantFold.orElse(tryMatchAlias)
4019-
40204018
case _ =>
40214019
NoType
40224020
}
40234021

4022+
/** Does this application expand to a match type? */
4023+
def isMatchAlias(using Context): Boolean = tycon.stripTypeVar match
4024+
case tycon: TypeRef =>
4025+
tycon.info match
4026+
case _: MatchAlias => true
4027+
case _ => false
4028+
case _ => false
4029+
4030+
/** Is this an unreducible application to wildcard arguments?
4031+
* This is the case if tycon is higher-kinded. This means
4032+
* it is a subtype of a hk-lambda, but not a match alias.
4033+
* (normal parameterized aliases are removed in `appliedTo`).
4034+
* Applications of hgher-kinded type constructors to wildcard arguments
4035+
* are equivalent to existential types, which are not supported.
4036+
*/
4037+
def isUnreducibleWild(using Context): Boolean =
4038+
tycon.isLambdaSub && hasWildcardArg && !isMatchAlias
4039+
40244040
def tryCompiletimeConstantFold(using Context): Type = tycon match {
40254041
case tycon: TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) =>
40264042
def constValue(tp: Type): Option[Any] = tp.dealias match {

compiler/src/dotty/tools/dotc/typer/Checking.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ object Checking {
113113

114114
def checkWildcardApply(tp: Type): Unit = tp match {
115115
case tp @ AppliedType(tycon, _) =>
116-
if (tycon.isLambdaSub && tp.hasWildcardArg)
116+
if tp.isUnreducibleWild then
117117
report.errorOrMigrationWarning(
118118
showInferred(UnreducibleApplication(tycon), tp, tpt),
119119
tree.srcPos)

compiler/test/dotc/pos-test-pickling.blacklist

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ i7872.scala
3535
i11236.scala
3636
i11247.scala
3737
i11250
38+
i9999.scala
3839

3940
# Opaque type
4041
i5720.scala

tests/pos/i9999.scala

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
case class A();
2+
case class B();
3+
4+
type M2[X <: A|B] = X match {
5+
case A => A
6+
case B => B
7+
}
8+
9+
def f2(x: A|B): M2[x.type] = x match {
10+
case _: A => A()
11+
case _: B => B()
12+
}
13+
14+
type M1[X <: A|B] = X match {
15+
case A => A
16+
case B => (x: A|B) => M2[x.type]
17+
}
18+
19+
def f1(x: A|B): M1[x.type] = x match {
20+
case _: A => A()
21+
case _: B => (x: A|B) => f2(x)
22+
}
23+
24+
case class More(); case class Stop();
25+
26+
sealed abstract class DSL
27+
case class Fun[F <: More|Stop => DSL](cont: F) extends DSL
28+
case class Nop() extends DSL
29+
30+
type Match2[X <: More|Stop] <: DSL = X match {
31+
case More => Fun[(y: More|Stop) => Match1[y.type]]
32+
case Stop => Nop
33+
}
34+
type Match1[X] <: DSL = X match {
35+
case More => Nop
36+
case Stop => Nop
37+
}
38+
39+
def fun2(x: More|Stop): Match2[x.type] = x match {
40+
case _: More => Fun(fun1) // error
41+
case _: Stop => Nop()
42+
}
43+
44+
def fun1(y: More|Stop): Match1[y.type] = y match {
45+
case _: More => Nop()
46+
case _: Stop => Nop()
47+
}

0 commit comments

Comments
 (0)