Skip to content

Commit 2a58e50

Browse files
committed
Fix #7048: Heal phase inconsistent path dependent types
1 parent 9de9c4d commit 2a58e50

File tree

10 files changed

+120
-3
lines changed

10 files changed

+120
-3
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,9 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
116116
// Adapt direct references to the type of the type parameter T of a quoted.Type[T].
117117
// Replace it with a properly encoded type splice. This is the normal for expected for type splices.
118118
tp.prefix.select(tpnme.splice)
119-
case tp: NamedType =>
120-
checkSymLevel(tp.symbol, tp, pos) match {
119+
case tp: NamedType if !tp.symbol.isClass =>
120+
if (tp.prefix.isInstanceOf[TermRef] && tp.prefix.isStable) tp
121+
else checkSymLevel(tp.symbol, tp, pos) match {
121122
case Some(tpRef) => tpRef.tpe
122123
case _ =>
123124
if (tp.symbol.is(Param)) tp
@@ -169,7 +170,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
169170
sym.isClass // reference to this in inline methods
170171
)
171172
case None =>
172-
!sym.is(Param) || levelOK(sym.owner)
173+
sym.isRoot || sym.maybeOwner.isStaticOwner || levelOK(sym.owner)
173174
}
174175

175176
/** Try to heal phase-inconsistent reference to type `T` using a local type definition.

tests/neg/i5954b.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
abstract class MatcherFactory1[A] {
2+
class AndNotWord
3+
}
4+
5+
object MatcherFactory1 {
6+
import scala.quoted._
7+
8+
def impl[T](self: Expr[MatcherFactory1[T]#AndNotWord]) given QuoteContext =
9+
'{ val a: Any = $self } // error: access to type T from wrong staging level
10+
11+
}

tests/neg/i5954c.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
abstract class MatcherFactory1 {
2+
class AndNotWord[A]
3+
}
4+
5+
object MatcherFactory1 {
6+
import scala.quoted._
7+
8+
def impl[T](self: Expr[MatcherFactory1#AndNotWord[T]]) given QuoteContext =
9+
'{ val a: Any = $self } // error: access to type T from wrong staging level
10+
11+
}

tests/neg/i7048.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
3+
trait IsExpr {
4+
type Underlying
5+
}
6+
7+
def foo: IsExpr = ???
8+
9+
def g(e: IsExpr) given (tu: Type[e.Underlying]): Unit = ???
10+
11+
def mcrImpl: Unit = {
12+
g(foo) // error
13+
}

tests/neg/i7048b.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
3+
trait IsExpr {
4+
type Underlying
5+
}
6+
7+
def foo: IsExpr = ???
8+
9+
def g(e: IsExpr) given (tu: Type[e.Underlying]): Unit = ???
10+
11+
def mcrImpl: Unit = {
12+
g(foo) given '[foo.Underlying] // error: => IsExpr(foo) is not stable
13+
}

tests/pos/i5954b.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
abstract class MatcherFactory1 {
2+
class AndNotWord[A]
3+
}
4+
5+
object MatcherFactory1 {
6+
import scala.quoted._
7+
8+
def impl(self: Expr[MatcherFactory1#AndNotWord[Int]]) given QuoteContext =
9+
'{ val a: Any = $self }
10+
11+
12+
def impl[T: Type](self: Expr[MatcherFactory1#AndNotWord[T]]) given QuoteContext =
13+
'{ val a: Any = $self }
14+
15+
}

tests/pos/i5954c.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
abstract class MatcherFactory1[A] {
2+
class AndNotWord
3+
}
4+
5+
object MatcherFactory1 {
6+
import scala.quoted._
7+
8+
def impl(self: Expr[MatcherFactory1[Int]#AndNotWord]) given QuoteContext =
9+
'{ val a: Any = $self }
10+
11+
12+
def impl[T: Type](self: Expr[MatcherFactory1[T]#AndNotWord]) given QuoteContext =
13+
'{ val a: Any = $self }
14+
15+
}

tests/pos/i7048.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
3+
trait IsExpr[T] {
4+
type Underlying
5+
def expr: Expr[Underlying]
6+
}
7+
8+
def f(x: Any): String = x.toString
9+
10+
def g[T] given (e: IsExpr[T], tu: Type[e.Underlying]): given QuoteContext => Expr[String] = {
11+
val underlying: Expr[e.Underlying] = e.expr
12+
'{f($underlying)}
13+
}

tests/pos/i7048b.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.quoted._
2+
3+
trait IsExpr {
4+
type Underlying
5+
}
6+
7+
val foo: IsExpr = ???
8+
9+
def g() given QuoteContext: Unit = {
10+
val a = '[foo.Underlying]
11+
()
12+
}

tests/pos/i7048c.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import scala.quoted._
2+
3+
trait IsExpr {
4+
type Underlying
5+
}
6+
7+
val foo: IsExpr = ???
8+
9+
def g(e: IsExpr) given (tu: Type[e.Underlying]): Unit = ???
10+
11+
def mcrImpl given QuoteContext: Unit = {
12+
g(foo)
13+
}

0 commit comments

Comments
 (0)