Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,8 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
end TypeProjectionTypeTest

object TypeProjection extends TypeProjectionModule:
def apply(qualifier: TypeTree, name: String): TypeProjection =
withDefaultPos(tpd.Select(qualifier, name.toTypeName))
def copy(original: Tree)(qualifier: TypeTree, name: String): TypeProjection =
tpd.cpy.Select(original)(qualifier, name.toTypeName)
def unapply(x: TypeProjection): (TypeTree, String) =
Expand Down Expand Up @@ -1289,6 +1291,9 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
end RefinedTypeTest

object Refined extends RefinedModule:
def apply(tpt: TypeTree, refinements: List[Definition], refineCls: Symbol): Refined = // Symbol of the class being refined, according to which the refinements are typed
assert(refineCls.isClass, "refineCls must be a class/trait/object")
withDefaultPos(tpd.RefinedTypeTree(tpt, refinements, refineCls.asClass).asInstanceOf[tpd.RefinedTypeTree])
def copy(original: Tree)(tpt: TypeTree, refinements: List[Definition]): Refined =
tpd.cpy.RefinedTypeTree(original)(tpt, refinements)
def unapply(x: Refined): (TypeTree, List[Definition]) =
Expand Down
8 changes: 8 additions & 0 deletions library/src/scala/quoted/Quotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>

/** Methods of the module object `val TypeProjection` */
trait TypeProjectionModule { this: TypeProjection.type =>
def apply(qualifier: TypeTree, name: String): TypeProjection
def copy(original: Tree)(qualifier: TypeTree, name: String): TypeProjection
def unapply(x: TypeProjection): (TypeTree, String)
}
Expand Down Expand Up @@ -2021,6 +2022,13 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>

/** Methods of the module object `val Refined` */
trait RefinedModule { this: Refined.type =>
/** Creates and types a Refined AST node.
* @param tpt - parent type being refined
* @param refinements - List of definitions represesenting refinements
* @param refineCls - symbol of the class of which the refinement definitions originally come from
* @return
*/
def apply(tpt: TypeTree, refinements: List[Definition], refineCls: Symbol): Refined
def copy(original: Tree)(tpt: TypeTree, refinements: List[Definition]): Refined
def unapply(x: Refined): (TypeTree, List[Definition])
}
Expand Down
4 changes: 3 additions & 1 deletion project/MiMaFilters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object MiMaFilters {

ProblemFilters.exclude[DirectMissingMethodProblem]("scala.Conversion.underlying"),
ProblemFilters.exclude[MissingClassProblem]("scala.Conversion$"),
ProblemFilters.exclude[MissingClassProblem]("scala.annotation.internal.RuntimeChecked"),
ProblemFilters.exclude[MissingClassProblem]("scala.annotation.internal.RuntimeChecked"),
ProblemFilters.exclude[MissingClassProblem]("scala.annotation.stableNull"),

ProblemFilters.exclude[DirectMissingMethodProblem]("scala.NamedTuple.namedTupleOrdering"),
Expand Down Expand Up @@ -138,6 +138,8 @@ object MiMaFilters {
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeMethods.isContextual"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#ImplicitsModule.searchIgnoring"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#ValDefModule.let"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#RefinedModule.apply"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#TypeProjectionModule.apply"),
// Change `experimental` annotation to a final class
ProblemFilters.exclude[FinalClassProblem]("scala.annotation.experimental"),
),
Expand Down
4 changes: 2 additions & 2 deletions tests/neg-macros/i23008.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
| Exception occurred while executing macro expansion.
| java.lang.IllegalArgumentException: requirement failed: value of StringConstant cannot be `null`
| at scala.Predef$.require(Predef.scala:337)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$StringConstant$.apply(QuotesImpl.scala:2540)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$StringConstant$.apply(QuotesImpl.scala:2539)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$StringConstant$.apply(QuotesImpl.scala:2545)
| at scala.quoted.runtime.impl.QuotesImpl$reflect$StringConstant$.apply(QuotesImpl.scala:2544)
| at scala.quoted.ToExpr$StringToExpr.apply(ToExpr.scala:82)
| at scala.quoted.ToExpr$StringToExpr.apply(ToExpr.scala:80)
| at scala.quoted.Expr$.apply(Expr.scala:72)
Expand Down
19 changes: 19 additions & 0 deletions tests/pos-macros/typedProjectionApply/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import scala.quoted._
class Test {type test = Int }
object Macro:
inline def inlineCall(): Any = ${impl}
transparent inline def transparentInlineCall(): Any = ${impl}

/* Returns:
* val value: Test#test = 0 : Test#test
* value: Test#test
*/
def impl(using Quotes): Expr[Any] =
import quotes.reflect._
val typeTree = TypeProjection(TypeTree.of[Test], "test")
val typeRepr = TypeRepr.of[Test#test]
val sym = Symbol.newVal(Symbol.spliceOwner, "value", typeRepr, Flags.EmptyFlags, Symbol.noSymbol)
Block(
List(ValDef(sym, Some(Typed(Literal(IntConstant(0)), typeTree)))),
Typed(Ref(sym), typeTree)
).asExpr
4 changes: 4 additions & 0 deletions tests/pos-macros/typedProjectionApply/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import scala.quoted._
def test() =
Macro.transparentInlineCall()
Macro.inlineCall()
30 changes: 30 additions & 0 deletions tests/run-macros/refined-apply/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//> using options -experimental
import scala.quoted._
class Foo { type test1; val test2: List[Any] = List() }
object Macro:
inline def inlineCall(): Any = ${impl}
transparent inline def transparentInlineCall(): Any = ${impl}

def impl(using Quotes): Expr[Any] =
import quotes.reflect._
val tpt = TypeTree.of[Foo]

val typeDefSym = Symbol.newTypeAlias(Symbol.spliceOwner, "test1", Flags.EmptyFlags, TypeRepr.of[Int], Symbol.noSymbol)
val valDefSym = Symbol.newVal(Symbol.spliceOwner, "test2", TypeRepr.of[List[Int]], Flags.EmptyFlags, Symbol.noSymbol)

val defs = List(
TypeDef(typeDefSym),
ValDef(valDefSym, None)
)
val typeTree = Refined(tpt, defs, TypeRepr.of[Foo].typeSymbol)

// A little redundant, but we only want to see if Refined.apply() works,
// so we only replace the type with one we just constructed
val body = '{
new Foo { type test1 = Int; override val test2: List[Int] = List(0) }
}
val blockWithNewTypeTree = body.asTerm match
case Inlined(_, _, Block(cDef : ClassDef, Typed(invocation, _))) =>
Block(cDef, Typed(invocation, typeTree))

blockWithNewTypeTree.asExpr
9 changes: 9 additions & 0 deletions tests/run-macros/refined-apply/Main_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//> using options -experimental

import scala.quoted._
def testInt(i: Int) = ()
@main def Test(): Unit =
val withType = Macro.transparentInlineCall()
summon[withType.test1 <:< Int]
withType.test2.map(testInt)
Macro.inlineCall()
Loading