Skip to content

Commit 17777db

Browse files
Normalize and dealias more when testing if TypeTests are unchecked
Tests #13433 with a classpath dependency
1 parent 54d67e0 commit 17777db

File tree

6 files changed

+73
-6
lines changed

6 files changed

+73
-6
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,12 @@ object Types extends TypeUtils {
15341534
if (normed.exists) normed else this
15351535
}
15361536

1537+
final def dealiasNormalized(using Context): Type =
1538+
val dealiased = dealias
1539+
dealiased.tryNormalize match
1540+
case NoType => dealiased
1541+
case normed => normed.dealiasNormalized
1542+
15371543
/** If this type can be normalized at the top-level by rewriting match types
15381544
* of S[n] types, the result after applying all toplevel normalizations,
15391545
* otherwise NoType

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ object TypeTestsCasts {
6161
extension (inline b: Boolean) inline def |||(inline s: String): String = if b then "" else s
6262

6363
// Run just before ElimOpaque transform (which follows RefChecks)
64-
def isAbstract(P: Type) = !P.dealias.typeSymbol.isClass
64+
def isAbstract(P: Type) = !P.typeSymbol.isClass
6565

6666
def replaceP(tp: Type)(using Context) = new TypeMap {
6767
def apply(tp: Type) = tp match {
@@ -133,10 +133,10 @@ object TypeTestsCasts {
133133
}
134134

135135
def recur(X: Type, P: Type): String = trace(s"recur(${X.show}, ${P.show})") {
136-
(X <:< P) ||| P.dealias.match
136+
(X <:< P) ||| P.dealiasNormalized.match
137137
case _: SingletonType => ""
138-
case _: TypeProxy
139-
if isAbstract(P) => i"it refers to an abstract type member or type parameter"
138+
case tp: TypeProxy
139+
if isAbstract(tp) => i"it refers to an abstract type member or type parameter"
140140
case defn.ArrayOf(tpT) =>
141141
X match {
142142
case defn.ArrayOf(tpE) => recur(tpE, tpT)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ i16997.scala
2424
i7414.scala
2525
i17588.scala
2626
i9804.scala
27-
i13433.scala
27+
i13433a.scala
2828
i16649-irrefutable.scala
2929
strict-pattern-bindings-3.0-migration.scala
3030
i17186b.scala

tests/pos/i13433.scala renamed to tests/pos/i13433a.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import scala.reflect.TypeTest
44

5-
type Matcher[A] = A match { case String => String }
5+
type Matcher[A] = A match { case String => A }
66

77
def patternMatch[A](a: Any)(using tt: TypeTest[Any, Matcher[A]]): Option[Matcher[A]] = {
88
// type T = RDF.Triple[Rdf]
@@ -20,6 +20,11 @@ def patternMatchWithAlias[A](a: Any)(using tt: TypeTest[Any, Matcher[A]]): Optio
2020
}
2121
}
2222

23+
type S = String
24+
type MS = Matcher[S]
25+
26+
type S2 = MS
27+
type MS2 = Matcher[S2]
2328

2429
@main def main = {
2530
println(patternMatch[String]("abc"))
@@ -31,4 +36,13 @@ def patternMatchWithAlias[A](a: Any)(using tt: TypeTest[Any, Matcher[A]]): Optio
3136

3237
println(patternMatch[String](1))
3338
println(patternMatchWithAlias[String](1))
39+
40+
println(patternMatch[String]("abc")(using (s: Any) => {
41+
if s.isInstanceOf[S] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None}))
42+
println(patternMatch[String]("abc")(using (s: Any) => {
43+
if s.isInstanceOf[MS] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None}))
44+
println(patternMatch[String]("abc")(using (s: Any) => {
45+
if s.isInstanceOf[S2] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None}))
46+
println(patternMatch[String]("abc")(using (s: Any) => {
47+
if s.isInstanceOf[MS2] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None}))
3448
}

tests/pos/i13433c/A_1.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import scala.reflect.TypeTest
2+
3+
type Matcher[A] = A match { case String => A }
4+
5+
def patternMatch[A](a: Any)(using tt: TypeTest[Any, Matcher[A]]): Option[Matcher[A]] = {
6+
// type T = RDF.Triple[Rdf]
7+
a match {
8+
case res: Matcher[A] => Some(res)
9+
case _ => None
10+
}
11+
}
12+
13+
def patternMatchWithAlias[A](a: Any)(using tt: TypeTest[Any, Matcher[A]]): Option[Matcher[A]] = {
14+
type T = Matcher[A]
15+
a match {
16+
case res: T => Some(res)
17+
case _ => None
18+
}
19+
}
20+
21+
type S = String
22+
type MS = Matcher[S]
23+
24+
type S2 = MS
25+
type MS2 = Matcher[S2]

tests/pos/i13433c/B_2.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//> using options -Xfatal-warnings -deprecation -feature
2+
3+
@main def main = {
4+
println(patternMatch[String]("abc"))
5+
println(patternMatchWithAlias[String]("abc"))
6+
println(patternMatch[String]("abc")(using (s: Any) => {
7+
if s.isInstanceOf[Matcher[String]] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None }))
8+
println(patternMatchWithAlias[String]("abc")(using (s: Any) => {
9+
if s.isInstanceOf[Matcher[String]] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None }))
10+
11+
println(patternMatch[String](1))
12+
println(patternMatchWithAlias[String](1))
13+
14+
println(patternMatch[String]("abc")(using (s: Any) => {
15+
if s.isInstanceOf[S] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None}))
16+
println(patternMatch[String]("abc")(using (s: Any) => {
17+
if s.isInstanceOf[MS] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None}))
18+
println(patternMatch[String]("abc")(using (s: Any) => {
19+
if s.isInstanceOf[S2] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None}))
20+
println(patternMatch[String]("abc")(using (s: Any) => {
21+
if s.isInstanceOf[MS2] then Some[s.type & Matcher[String]](s.asInstanceOf[s.type & Matcher[String]]) else None}))
22+
}

0 commit comments

Comments
 (0)