From 2aa9079256184b16d1b8593e8558795e83502a3e Mon Sep 17 00:00:00 2001 From: Kalin-Rudnicki Date: Tue, 17 Jun 2025 16:49:21 -0600 Subject: [PATCH] Add missing version of `ValDef.let` which accepts flags --- .../scala/quoted/runtime/impl/QuotesImpl.scala | 8 +++++++- library/src/scala/quoted/Quotes.scala | 16 ++++++++++++++++ project/MiMaFilters.scala | 3 +++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 852d7ee8b20f..e8ac90a37f69 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -369,6 +369,12 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def unapply(vdef: ValDef): (String, TypeTree, Option[Term]) = (vdef.name.toString, vdef.tpt, optional(vdef.rhs)) + def let(owner: Symbol, name: String, rhs: Term, flags: Flags)(body: Ref => Term): Term = + Symbol.checkValidFlags(flags.toTermFlags, Flags.validValFlags) + val vdef = tpd.SyntheticValDef(name.toTermName, rhs, flags)(using ctx.withOwner(owner)) + val ref = tpd.ref(vdef.symbol).asInstanceOf[Ref] + Block(List(vdef), body(ref)) + def let(owner: Symbol, name: String, rhs: Term)(body: Ref => Term): Term = val vdef = tpd.SyntheticValDef(name.toTermName, rhs)(using ctx.withOwner(owner)) val ref = tpd.ref(vdef.symbol).asInstanceOf[Ref] @@ -2863,7 +2869,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def noSymbol: Symbol = dotc.core.Symbols.NoSymbol - private inline def checkValidFlags(inline flags: Flags, inline valid: Flags): Unit = + private[QuotesImpl] inline def checkValidFlags(inline flags: Flags, inline valid: Flags): Unit = xCheckMacroAssert( flags <= valid, s"Received invalid flags. Expected flags ${flags.show} to only contain a subset of ${valid.show}." diff --git a/library/src/scala/quoted/Quotes.scala b/library/src/scala/quoted/Quotes.scala index 009f1c28fbd9..4336dea37681 100644 --- a/library/src/scala/quoted/Quotes.scala +++ b/library/src/scala/quoted/Quotes.scala @@ -682,6 +682,22 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => def copy(original: Tree)(name: String, tpt: TypeTree, rhs: Option[Term]): ValDef def unapply(vdef: ValDef): (String, TypeTree, Option[Term]) + /** Creates a block `{ val = ; }` + * + * Usage: + * ``` + * ValDef.let(owner, "x", rhs1, Flags.Lazy) { x => + * ValDef.let(x.symbol.owner, "y", rhs2, Flags.Mutable) { y => + * // use `x` and `y` + * } + * } + * ``` + * + * @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 | Synthetic | Artifact` + */ + // Keep: `flags` doc aligned with QuotesImpl's `validValFlags` + def let(owner: Symbol, name: String, rhs: Term, flags: Flags)(body: Ref => Term): Term + /** Creates a block `{ val = ; }` * * Usage: diff --git a/project/MiMaFilters.scala b/project/MiMaFilters.scala index c57136b262dd..fb9226997ee8 100644 --- a/project/MiMaFilters.scala +++ b/project/MiMaFilters.scala @@ -19,6 +19,9 @@ object MiMaFilters { ProblemFilters.exclude[DirectMissingMethodProblem]("scala.Conversion.underlying"), ProblemFilters.exclude[MissingClassProblem]("scala.Conversion$"), + + ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#ValDefModule.let"), + ProblemFilters.exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#ValDefModule.let"), ), // Additions since last LTS