Skip to content

Commit 2ecdf91

Browse files
committed
Disallow phase inconsitent inline parameters
1 parent 7282a9b commit 2ecdf91

File tree

63 files changed

+561
-169
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+561
-169
lines changed

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,6 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
8888
tree match {
8989
case Quoted(_) | Spliced(_) =>
9090
tree
91-
case tree: RefTree if tree.symbol.isAllOf(InlineParam) =>
92-
tree
9391
case _: This =>
9492
assert(checkSymLevel(tree.symbol, tree.tpe, tree.sourcePos).isEmpty)
9593
tree
@@ -197,10 +195,8 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
197195
case Some(l) =>
198196
l == level ||
199197
level == -1 && (
200-
// here we assume that Splicer.canBeSpliced was true before going to level -1,
201-
// this implies that all non-inline arguments are quoted and that the following two cases are checked
202-
// on inline parameters or type parameters.
203-
sym.is(Param) ||
198+
// here we assume that Splicer.checkValidMacroBody was true before going to level -1,
199+
// this implies that all arguments are quoted.
204200
sym.isClass // reference to this in inline methods
205201
)
206202
case None =>

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ object Splicer {
4949
catch {
5050
case ex: CompilationUnit.SuspendException =>
5151
throw ex
52+
case ex: scala.quoted.StopQuotedContext if ctx.reporter.hasErrors =>
53+
// errors have been emitted
54+
EmptyTree
5255
case ex: StopInterpretation =>
5356
ctx.error(ex.msg, ex.pos)
5457
EmptyTree
@@ -349,6 +352,8 @@ object Splicer {
349352
throw new StopInterpretation(sw.toString, pos)
350353
case ex: InvocationTargetException =>
351354
ex.getTargetException match {
355+
case ex: scala.quoted.StopQuotedContext =>
356+
throw ex
352357
case MissingClassDefinedInCurrentRun(sym) =>
353358
if (ctx.settings.XprintSuspension.value)
354359
ctx.echo(i"suspension triggered by a dependency on $sym", pos)

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import dotty.tools.dotc.util.Spans._
1919
import dotty.tools.dotc.util.{Property, SourcePosition}
2020
import dotty.tools.dotc.transform.SymUtils._
2121
import dotty.tools.dotc.typer.Implicits.SearchFailureType
22-
import dotty.tools.dotc.typer.Inliner
2322

2423
import scala.collection.mutable
2524
import scala.annotation.constructorOnly

library/src/scala/internal/quoted/Matcher.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ private[quoted] object Matcher {
229229
case (While(cond1, body1), While(cond2, body2)) =>
230230
cond1 =?= cond2 && body1 =?= body2
231231

232-
case (New(tpt1), New(tpt2)) =>
233-
tpt1 =?= tpt2
232+
case (New(tpt1), New(tpt2)) if tpt1.tpe.typeSymbol == tpt2.tpe.typeSymbol =>
233+
matched
234234

235235
case (This(_), This(_)) if scrutinee.symbol == pattern.symbol =>
236236
matched

library/src/scala/quoted/Expr.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ class Expr[+T] private[scala] {
1818
*/
1919
final def getValue[U >: T](given qctx: QuoteContext, valueOf: ValueOfExpr[U]): Option[U] = valueOf(this)
2020

21+
/** Return the value of this expression.
22+
*
23+
* Emits an error error and throws if the expression does not contain a value or contains side effects.
24+
* Otherwise returns the value.
25+
*/
26+
final def value[U >: T](given qctx: QuoteContext, valueOf: ValueOfExpr[U]): U =
27+
valueOf(this).getOrElse(qctx.throwError(s"Expected a known value. \n\nThe value of: $show\ncould not be recovered using $valueOf", this))
28+
2129
/** Pattern matches `this` against `that`. Effectively performing a deep equality check.
2230
* It does the equivalent of
2331
* ```

library/src/scala/quoted/QuoteContext.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class QuoteContext(val tasty: scala.tasty.Reflection) {
2222
tpe.unseal.show(syntaxHighlight)
2323
}
2424

25-
/** Report an error */
25+
/** Report an error at the position of the macro expansion */
2626
def error(msg: => String): Unit = {
2727
import tasty.{_, given}
2828
tasty.error(msg, rootPosition)(given rootContext)
@@ -34,6 +34,17 @@ class QuoteContext(val tasty: scala.tasty.Reflection) {
3434
tasty.error(msg, expr.unseal.pos)(given rootContext)
3535
}
3636

37+
/** Report an error at the position of the macro expansion and throws a StopQuotedContext */
38+
def throwError(msg: => String): Nothing = {
39+
error(msg)
40+
throw new StopQuotedContext
41+
}
42+
/** Report an error at the on the position of `expr` and throws a StopQuotedContext */
43+
def throwError(msg: => String, expr: Expr[_]): Nothing = {
44+
error(msg, expr)
45+
throw new StopQuotedContext
46+
}
47+
3748
/** Report a warning */
3849
def warning(msg: => String): Unit = {
3950
import tasty.{_, given}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package scala.quoted
2+
3+
/** Stop code generation after an error has been reported */
4+
class StopQuotedContext extends Throwable

library/src/scala/quoted/ValueOfExpr.scala

Lines changed: 252 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package scala.quoted
2+
package matching
3+
4+
/** Literal sequence of literal constant value expressions */
5+
object ValueSeq {
6+
7+
/** Matches literal sequence of literal constant value expressions and return a sequence of values.
8+
*
9+
* Usage:
10+
* ```scala
11+
* inline def sum(args: Int*): Int = ${ sumExpr('args) }
12+
* def sumExpr(argsExpr: Expr[Seq[Int]])(given QuoteContext): Expr[Int] = argsExpr match
13+
* case ValueSeq(args) =>
14+
* // args: Seq[Int]
15+
* ...
16+
* }
17+
* ```
18+
*/
19+
def unapply[T](expr: Expr[Seq[T]])(given valueOf: ValueOfExpr[T], qctx: QuoteContext): Option[Seq[T]] = expr match {
20+
case ExprSeq(elems) =>
21+
elems.foldRight(Option(List.empty[T])) { (elem, acc) =>
22+
(elem, acc) match {
23+
case (ValueOfExpr(value), Some(lst)) => Some(value :: lst)
24+
case (_, _) => None
25+
}
26+
}
27+
case _ => None
28+
}
29+
30+
}

0 commit comments

Comments
 (0)