Skip to content

Commit a4db0c1

Browse files
committed
Check flags for method, val and bind symbols
1 parent c221229 commit a4db0c1

File tree

2 files changed

+33
-15
lines changed

2 files changed

+33
-15
lines changed

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import dotty.tools.dotc.ast.untpd
99
import dotty.tools.dotc.core.Annotations
1010
import dotty.tools.dotc.core.Contexts._
1111
import dotty.tools.dotc.core.Decorators._
12-
import dotty.tools.dotc.core.Flags._
1312
import dotty.tools.dotc.core.NameKinds
1413
import dotty.tools.dotc.core.NameOps._
1514
import dotty.tools.dotc.core.StdNames._
@@ -276,12 +275,13 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
276275

277276
object DefDef extends DefDefModule:
278277
def apply(symbol: Symbol, rhsFn: List[List[Tree]] => Option[Term]): DefDef =
279-
assert(symbol.isTerm, s"expected a term symbol but received $symbol")
278+
xCheckMacroAssert(symbol.isTerm, s"expected a term symbol but received $symbol")
279+
xCheckMacroAssert(symbol.flags.is(Flags.Method), "expected a symbol with `Method` flag set")
280280
withDefaultPos(tpd.DefDef(symbol.asTerm, prefss =>
281-
xCheckMacroedOwners(xCheckMacroValidExpr(rhsFn(prefss)), symbol).getOrElse(tpd.EmptyTree)
281+
xCheckedMacroOwners(xCheckMacroValidExpr(rhsFn(prefss)), symbol).getOrElse(tpd.EmptyTree)
282282
))
283283
def copy(original: Tree)(name: String, paramss: List[ParamClause], tpt: TypeTree, rhs: Option[Term]): DefDef =
284-
tpd.cpy.DefDef(original)(name.toTermName, paramss, tpt, xCheckMacroedOwners(rhs, original.symbol).getOrElse(tpd.EmptyTree))
284+
tpd.cpy.DefDef(original)(name.toTermName, paramss, tpt, xCheckedMacroOwners(rhs, original.symbol).getOrElse(tpd.EmptyTree))
285285
def unapply(ddef: DefDef): (String, List[ParamClause], TypeTree, Option[Term]) =
286286
(ddef.name.toString, ddef.paramss, ddef.tpt, optional(ddef.rhs))
287287
end DefDef
@@ -307,9 +307,10 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
307307

308308
object ValDef extends ValDefModule:
309309
def apply(symbol: Symbol, rhs: Option[Term]): ValDef =
310-
withDefaultPos(tpd.ValDef(symbol.asTerm, xCheckMacroedOwners(xCheckMacroValidExpr(rhs), symbol).getOrElse(tpd.EmptyTree)))
310+
xCheckMacroAssert(!symbol.flags.is(Flags.Method), "expected a symbol without `Method` flag set")
311+
withDefaultPos(tpd.ValDef(symbol.asTerm, xCheckedMacroOwners(xCheckMacroValidExpr(rhs), symbol).getOrElse(tpd.EmptyTree)))
311312
def copy(original: Tree)(name: String, tpt: TypeTree, rhs: Option[Term]): ValDef =
312-
tpd.cpy.ValDef(original)(name.toTermName, tpt, xCheckMacroedOwners(xCheckMacroValidExpr(rhs), original.symbol).getOrElse(tpd.EmptyTree))
313+
tpd.cpy.ValDef(original)(name.toTermName, tpt, xCheckedMacroOwners(xCheckMacroValidExpr(rhs), original.symbol).getOrElse(tpd.EmptyTree))
313314
def unapply(vdef: ValDef): (String, TypeTree, Option[Term]) =
314315
(vdef.name.toString, vdef.tpt, optional(vdef.rhs))
315316

@@ -398,7 +399,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
398399
def etaExpand(owner: Symbol): Term = self.tpe.widen match {
399400
case mtpe: Types.MethodType if !mtpe.isParamDependent =>
400401
val closureResType = mtpe.resType match {
401-
case t: Types.MethodType => t.toFunctionType(isJava = self.symbol.is(JavaDefined))
402+
case t: Types.MethodType => t.toFunctionType(isJava = self.symbol.is(dotc.core.Flags.JavaDefined))
402403
case t => t
403404
}
404405
val closureTpe = Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType)
@@ -811,7 +812,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
811812
object Lambda extends LambdaModule:
812813
def apply(owner: Symbol, tpe: MethodType, rhsFn: (Symbol, List[Tree]) => Tree): Block =
813814
val meth = dotc.core.Symbols.newAnonFun(owner, tpe)
814-
withDefaultPos(tpd.Closure(meth, tss => xCheckMacroedOwners(xCheckMacroValidExpr(rhsFn(meth, tss.head.map(withDefaultPos))), meth)))
815+
withDefaultPos(tpd.Closure(meth, tss => xCheckedMacroOwners(xCheckMacroValidExpr(rhsFn(meth, tss.head.map(withDefaultPos))), meth)))
815816

816817
def unapply(tree: Block): Option[(List[ValDef], Term)] = tree match {
817818
case Block((ddef @ DefDef(_, tpd.ValDefs(params) :: Nil, _, Some(body))) :: Nil, Closure(meth, _))
@@ -1482,6 +1483,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
14821483

14831484
object Bind extends BindModule:
14841485
def apply(sym: Symbol, pattern: Tree): Bind =
1486+
xCheckMacroAssert(sym.flags.is(Flags.Case), "expected a symbol with `Case` flag set")
14851487
withDefaultPos(tpd.Bind(sym, pattern))
14861488
def copy(original: Tree)(name: String, pattern: Tree): Bind =
14871489
withDefaultPos(tpd.cpy.Bind(original)(name.toTermName, pattern))
@@ -2520,13 +2522,22 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
25202522
def newMethod(owner: Symbol, name: String, tpe: TypeRepr): Symbol =
25212523
newMethod(owner, name, tpe, Flags.EmptyFlags, noSymbol)
25222524
def newMethod(owner: Symbol, name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol): Symbol =
2525+
checkValidFlags(flags.toTermFlags, Flags.validMethodFlags)
25232526
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags | dotc.core.Flags.Method, tpe, privateWithin)
25242527
def newVal(owner: Symbol, name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol): Symbol =
2528+
checkValidFlags(flags.toTermFlags, Flags.validValFlags)
25252529
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags, tpe, privateWithin)
25262530
def newBind(owner: Symbol, name: String, flags: Flags, tpe: TypeRepr): Symbol =
2527-
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags | Case, tpe)
2531+
checkValidFlags(flags.toTermFlags, Flags.validBindFlags)
2532+
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags | dotc.core.Flags.Case, tpe)
25282533
def noSymbol: Symbol = dotc.core.Symbols.NoSymbol
25292534

2535+
private inline def checkValidFlags(inline flags: Flags, inline valid: Flags): Unit =
2536+
xCheckMacroAssert(
2537+
flags <= valid,
2538+
s"Received invalid flags. Expected flags ${flags.show} to only contain a subset of ${valid.show}."
2539+
)
2540+
25302541
def freshName(prefix: String): String =
25312542
NameKinds.MacroNames.fresh(prefix.toTermName).toString
25322543
end Symbol
@@ -2599,7 +2610,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
25992610
self.isTerm && !self.is(dotc.core.Flags.Method) && !self.is(dotc.core.Flags.Case/*, FIXME add this check and fix sourcecode butNot = Enum | Module*/)
26002611
def isDefDef: Boolean = self.is(dotc.core.Flags.Method)
26012612
def isBind: Boolean =
2602-
self.is(dotc.core.Flags.Case, butNot = Enum | Module) && !self.isClass
2613+
self.is(dotc.core.Flags.Case, butNot = dotc.core.Flags.Enum | dotc.core.Flags.Module) && !self.isClass
26032614
def isNoSymbol: Boolean = self == Symbol.noSymbol
26042615
def exists: Boolean = self != Symbol.noSymbol
26052616

@@ -2843,6 +2854,10 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
28432854
def Synthetic: Flags = dotc.core.Flags.Synthetic
28442855
def Trait: Flags = dotc.core.Flags.Trait
28452856
def Transparent: Flags = dotc.core.Flags.Transparent
2857+
2858+
private[QuotesImpl] def validMethodFlags: Flags = Private | Protected | Override | Deferred | Final | Method | Implicit | Given | Local | JavaStatic | AbsOverride // Synthetic | ExtensionMethod | Exported | Erased | Infix | Invisible
2859+
private[QuotesImpl] def validValFlags: Flags = Private | Protected | Override | Deferred | Final | Param | Implicit | Lazy | Mutable | Local | ParamAccessor | Module | Package | Case | CaseAccessor | Given | Enum | JavaStatic | AbsOverride // Synthetic | Erased | Invisible
2860+
private[QuotesImpl] def validBindFlags: Flags = Case // | Implicit | Given | Erased
28462861
end Flags
28472862

28482863
given FlagsMethods: FlagsMethods with
@@ -2963,7 +2978,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
29632978
/** Checks that all definitions in this tree have the expected owner.
29642979
* Nested definitions are ignored and assumed to be correct by construction.
29652980
*/
2966-
private def xCheckMacroedOwners(tree: Option[Tree], owner: Symbol): tree.type =
2981+
private def xCheckedMacroOwners(tree: Option[Tree], owner: Symbol): tree.type =
29672982
if xCheckMacro then
29682983
tree match
29692984
case Some(tree) =>
@@ -2974,7 +2989,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
29742989
/** Checks that all definitions in this tree have the expected owner.
29752990
* Nested definitions are ignored and assumed to be correct by construction.
29762991
*/
2977-
private def xCheckMacroedOwners(tree: Tree, owner: Symbol): tree.type =
2992+
private def xCheckedMacroOwners(tree: Tree, owner: Symbol): tree.type =
29782993
if xCheckMacro then
29792994
xCheckMacroOwners(tree, owner)
29802995
tree
@@ -3045,6 +3060,9 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
30453060
"Reference to a method must be eta-expanded before it is used as an expression: " + term.show)
30463061
term
30473062

3063+
private inline def xCheckMacroAssert(inline cond: Boolean, inline msg: String): Unit =
3064+
assert(!xCheckMacro || cond, msg)
3065+
30483066
object Printer extends PrinterModule:
30493067

30503068
lazy val TreeCode: Printer[Tree] = new Printer[Tree]:

library/src/scala/quoted/Quotes.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3766,7 +3766,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
37663766
* @param parent The owner of the method
37673767
* @param name The name of the method
37683768
* @param tpe The type of the method (MethodType, PolyType, ByNameType)
3769-
* @param flags extra flags to with which the symbol should be constructed
3769+
* @param flags extra flags to with which the symbol should be constructed. `Method` flag will be added. Can be `Private | Protected | Override | Deferred | Final | Method | Implicit | Given | Local | JavaStatic`
37703770
* @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol.
37713771
*/
37723772
def newMethod(parent: Symbol, name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol): Symbol
@@ -3782,7 +3782,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
37823782
* @param parent The owner of the val/var/lazy val
37833783
* @param name The name of the val/var/lazy val
37843784
* @param tpe The type of the val/var/lazy val
3785-
* @param flags extra flags to with which the symbol should be constructed
3785+
* @param flags extra flags to with which the symbol should be constructed. Can be `Private | Protected | Override | Deferred | Final | Param | Implicit | Lazy | Mutable | Local | ParamAccessor | Module | Package | Case | CaseAccessor | Given | Enum | JavaStatic`
37863786
* @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol.
37873787
* @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
37883788
* direct or indirect children of the reflection context's owner.
@@ -3797,7 +3797,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
37973797
*
37983798
* @param parent The owner of the binding
37993799
* @param name The name of the binding
3800-
* @param flags extra flags to with which the symbol should be constructed
3800+
* @param flags extra flags to with which the symbol should be constructed. `Case` flag will be added. Can be `Case`
38013801
* @param tpe The type of the binding
38023802
* @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
38033803
* direct or indirect children of the reflection context's owner.

0 commit comments

Comments
 (0)