Skip to content

Commit fa62051

Browse files
Merge pull request #6599 from dotty-staging/fix-#6588
Fix #6588: Dealias inferred quoted types
2 parents 8144f98 + 2b36c21 commit fa62051

File tree

8 files changed

+64
-31
lines changed

8 files changed

+64
-31
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
388388
case New(_) | Closure(_, _, _) =>
389389
Pure
390390
case TypeApply(fn, _) =>
391-
if (fn.symbol.is(Erased)) Pure else exprPurity(fn)
391+
if (fn.symbol.is(Erased) || fn.symbol == defn.InternalQuoted_typeQuote) Pure else exprPurity(fn)
392392
case Apply(fn, args) =>
393393
def isKnownPureOp(sym: Symbol) =
394394
sym.owner.isPrimitiveValueClass || sym.owner == defn.StringClass

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,17 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
202202
val reqType = defn.QuotedTypeType.appliedTo(tp)
203203
val tag = ctx.typer.inferImplicitArg(reqType, pos.span)
204204
tag.tpe match {
205-
case fail: SearchFailureType =>
205+
case _: TermRef =>
206+
Some(tag.select(tpnme.splice))
207+
case _: SearchFailureType =>
206208
levelError(i"""
207209
|
208210
| The access would be accepted with the right type tag, but
209211
| ${ctx.typer.missingArgMsg(tag, reqType, "")}""")
210212
case _ =>
211-
Some(tag.select(tpnme.splice))
213+
levelError(i"""
214+
|
215+
| The access would be accepted with an implict $reqType""")
212216
}
213217
}
214218
case _ =>

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ class Staging extends MacroTransform {
6161
checker.transform(tree)
6262
case _ =>
6363
}
64+
65+
tree.tpe match {
66+
case tpe @ TypeRef(prefix, _) if tpe.typeSymbol eq defn.QuotedType_splice =>
67+
// Type splices must have a know term ref, usually to an implicit argument
68+
// This is mostly intended to catch `quoted.Type[T]#splice` types which should just be `T`
69+
assert(prefix.isInstanceOf[TermRef] || prefix.isInstanceOf[ThisType], prefix)
70+
case _ =>
71+
// OK
72+
}
6473
}
6574
}
6675

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

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,9 @@ trait Implicits { self: Typer =>
674674
EmptyTree
675675
}
676676

677+
/** Synthesize the tree for `'[T]` for an implicit `scala.quoted.Type[T]`.
678+
* `T` is deeply dealiassed to avoid references to local type aliases.
679+
*/
677680
lazy val synthesizedTypeTag: SpecialHandler =
678681
(formal: Type, span: Span) => implicit (ctx: Context) => {
679682
def quotedType(t: Type) = {
@@ -682,26 +685,11 @@ trait Implicits { self: Typer =>
682685
ref(defn.InternalQuoted_typeQuote).appliedToType(t)
683686
}
684687
formal.argInfos match {
685-
case arg :: Nil if !arg.typeSymbol.is(Param) =>
686-
object bindFreeVars extends TypeMap {
687-
var ok = true
688-
def apply(t: Type) = t match {
689-
case t @ TypeRef(NoPrefix, _) =>
690-
inferImplicit(defn.QuotedTypeType.appliedTo(t), EmptyTree, span) match {
691-
case SearchSuccess(tag, _, _) if tag.tpe.isStable =>
692-
tag.tpe.select(defn.QuotedType_splice)
693-
case _ =>
694-
ok = false
695-
t
696-
}
697-
case _ => t
698-
}
688+
case arg :: Nil =>
689+
val deepDealias = new TypeMap {
690+
def apply(tp: Type): Type = mapOver(tp.dealias)
699691
}
700-
val tag = bindFreeVars(arg)
701-
if (bindFreeVars.ok) quotedType(tag)
702-
else EmptyTree
703-
case arg :: Nil if ctx.inInlineMethod =>
704-
quotedType(arg)
692+
quotedType(deepDealias(arg))
705693
case _ =>
706694
EmptyTree
707695
}

tests/neg/quote-0.scala

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,4 @@ class Test {
1414

1515
'{(y: Expr[Int]) => $y } // error: wrong staging level
1616

17-
def f[T](t: Type[T], x: Expr[T]) = '{
18-
val z2 = $x // error // error: wrong staging level
19-
}
20-
21-
def g[T](implicit t: Type[T], x: Expr[T]) = '{
22-
val z2 = $x // ok
23-
}
24-
2517
}

tests/neg/quote-1.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+
class Test {
4+
5+
def f[T](t: Type[T], x: Expr[T]) = '{
6+
val z2 = $x // error // error: wrong staging level
7+
}
8+
9+
def g[T](implicit t: Type[T], x: Expr[T]) = '{
10+
val z2 = $x // ok
11+
}
12+
13+
}

tests/pos/i6588.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import scala.quoted._
2+
3+
inline def foo[T:Type]: Int = 10
4+
5+
def main = {
6+
type S = Int
7+
foo[S]
8+
foo[Int]
9+
10+
type T = Int => Int
11+
foo[T]
12+
foo[Int => Int]
13+
14+
type U = List[Int]
15+
foo[U]
16+
foo[List[Int]]
17+
18+
type N = List
19+
foo[N]
20+
foo[List]
21+
22+
type V = List[S]
23+
foo[V]
24+
25+
type B = V => T
26+
foo[B]
27+
}

tests/run-with-compiler/i4350.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
(null: scala.Any).asInstanceOf[java.lang.Object]
2-
(null: scala.Any).asInstanceOf[scala.Predef.String]
2+
(null: scala.Any).asInstanceOf[java.lang.String]

0 commit comments

Comments
 (0)