-
Notifications
You must be signed in to change notification settings - Fork 1.1k
There is no way to create Selector
s in macros
#21225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
there is no utility to creating an import, it would be a no-op - why are you trying to do this? |
So following #21199 I was looking for a workaround and tried #21224. After failing on both I was like "ok, let's write the tree myself" which looks like: val givenSelector = '{ import DummyImplicit.given; val _ = summon[DummyImplicit] }.asTerm match
case Inlined(_, _, Block(List(Import(_, List(givenSelector)), _), _)) => givenSelector
findAllTypesInPackage(typesPackage).map: typeRepr =>
typeRepr.asType match
case '[t] =>
val companionObject = typeRepr.typeSymbol.owner.declaredFields.find(sym =>
sym.name == typeRepr.typeSymbol.name && sym.flags.is(Flags.Module)
)
val importCompanionGivens =
companionObject.map(companionObject => Import(Ident(companionObject.termRef), List(givenSelector)))
val summonParser = TypeApply(
Ident(Symbol.requiredMethod("scala.compiletime.summonInline").termRef),
List(Inferred(TypeRepr.of[Parser].appliedTo(typeRepr)))
)
val parser = Block(importCompanionGivens.toList, summonParser).asExprOf[Parser[t]]
'{$parser()} because the following does not resolve givens in companion objects: findAllTypesInPackage(typesPackage).map(_.asType).map:
case '[t] => '{summonInline[t]()} I'm not even sure how I could create an import of the companion object of a type (if it exists) in a quote blocks. |
I think I have a valid use case for creating Let's assume we have a typeclass with a trait Codec[T]
object Codec {
inline def derived[T]: Codec[T] = ???
} Now, I want to create an enhanced version of the So, instead of doing this: import CustomCodecs.given
case class Data(int: Int, str: String) derives Codec I would prefer this: case class Data(int: Int, str: String)
object Data {
given codec: Codec[T] = Codec.derivedWithDeps[T](CustomCodecs)
} or perhaps even something like this: case class Data(int: Int, str: String)
object Data extends HasCodecWithDeps[Data](CustomCodecs) Why do I think this is better?
Here's how I successfully managed to implement import scala.quoted.*
trait Codec[T]
object Codec {
inline def derived[T]: Codec[T] = ???
inline def derivedWithDeps[T](deps: Any): Codec[T] = ${derivedWithDepsImpl[T]}
private def derivedWithDepsImpl[T](deps: Expr[Any])(using q: Quotes)(using Type[T]): Expr[Codec[T]] = {
import q.reflect.*
val givenSelector: Selector = {
import dotty.tools.dotc.ast.untpd
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.StdNames
import scala.quoted.runtime.impl.QuotesImpl
given ctx: Context = q.asInstanceOf[QuotesImpl].ctx
untpd.ImportSelector(untpd.Ident(StdNames.nme.EMPTY)).asInstanceOf[Selector]
}
val theImport = Import(deps.asTerm, List(givenSelector))
Block(List(theImport), '{Codec.derived[T]}.asTerm).asExprOf[Codec[T]]
}
} It works as intended, but of course the missing piece is an API to create the Note: trying to do the same with plain quote doesn't work: '{
import ${deps}.given
Codec.derived[T]
} This syntax isn't even recognized as valid, so it looks like splicing an |
Compiler version
3.4.2
Minimized code
The
apply
function onGivenSelector
orSimpleSelector
orRenameSelector
orOmitSelector
does not exist.Workaround
Expectation
We should have a way to create
Selector
sThanks
The text was updated successfully, but these errors were encountered: