import scala.quoted.*
def refined(using Quotes) =
import quotes.reflect.*
val cl = '{
class Cl extends Object:
val field: String = "value"
new Cl
}
val tree = cl.asTerm
val typ = Refined.copy(tree)(
TypeTree.of[Object],
List(ValDef.copy(tree)("field", TypeIdent.copy(tree)("String"), None))
)
Typed(tree, typ).asExpr
transparent inline def m = ${refined}
If you want the compiler to infer a structural type without explicitly annotating it, I believe it needs to be a subtype of scala.Selectable. And for reflective access to the structural members you need scala.reflect.Selectable.
scala> import scala.quoted.*
| def refined(using Quotes) =
| '{
| new scala.reflect.Selectable:
| val field: String = "value"
| }
|
| transparent inline def m = ${refined}
def refined
(using x$1: quoted.Quotes): quoted.Expr[reflect.Selectable{val field: String}]
def m: reflect.Selectable{val field: String}
scala> m.field
val res0: String = value
And also m might be Any or AnyRef if the return type of refined cannot be more specific than Expr[Any] or Expr[AnyRef] (e.g. if your implementation gets more complex than it currently is), but the result of invoking m will have a more specific type because m is transparent.
scala> import scala.quoted.*
| def refined(using Quotes): Expr[Any] =
| '{
| new scala.reflect.Selectable:
| val field: String = "value"
| }
|
| transparent inline def m = ${refined}
def refined(using x$1: quoted.Quotes): quoted.Expr[Any]
def m: Any
scala> val a = m
val a: reflect.Selectable{val field: String} = anon$1@df0ae74