Skip to content

Commit fe749ea

Browse files
Merge pull request #6615 from dotty-staging/select-symbol
Add reflect API: Select.apply with a symbol
2 parents 33ad06b + 609f01d commit fe749ea

File tree

5 files changed

+83
-0
lines changed

5 files changed

+83
-0
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala

+3
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
282282
if (self.symbol.signature == core.Signature.NotAMethod) None
283283
else Some(self.symbol.signature)
284284

285+
def Select_apply(qualifier: Term, symbol: Symbol)(implicit ctx: Context): Select =
286+
withDefaultPos(implicit ctx => tpd.Select(qualifier, Types.TermRef(qualifier.tpe, symbol)))
287+
285288
def Select_unique(qualifier: Term, name: String)(implicit ctx: Context): Select = {
286289
val denot = qualifier.tpe.member(name.toTermName)
287290
assert(!denot.isOverloaded, s"The symbol `$name` is overloaded. The method Select.unique can only be used for non-overloaded symbols.")

library/src/scala/tasty/reflect/Kernel.scala

+1
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ trait Kernel {
329329
def Select_name(self: Select)(implicit ctx: Context): String
330330
def Select_signature(self: Select)(implicit ctx: Context): Option[Signature]
331331

332+
def Select_apply(qualifier: Term, symbol: Symbol)(implicit ctx: Context): Select
332333
def Select_unique(qualifier: Term, name: String)(implicit ctx: Context): Select
333334
// TODO rename, this returns an Apply and not a Select
334335
def Select_overloaded(qualifier: Term, name: String, targs: List[Type], args: List[Term])(implicit ctx: Context): Apply

library/src/scala/tasty/reflect/TreeOps.scala

+4
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ trait TreeOps extends Core {
231231

232232
/** Scala term selection */
233233
object Select {
234+
/** Select a term member by symbol */
235+
def apply(qualifier: Term, symbol: Symbol)(implicit ctx: Context): Select =
236+
kernel.Select_apply(qualifier, symbol)
237+
234238
/** Select a field or a non-overloaded method by name
235239
*
236240
* @note The method will produce an assertion error if the selected
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import scala.quoted._
2+
import scala.tasty._
3+
4+
object scalatest {
5+
6+
inline def assert(condition: => Boolean): Unit = ${ assertImpl('condition, '{""}) }
7+
8+
def assertImpl(cond: Expr[Boolean], clue: Expr[Any])(implicit refl: Reflection): Expr[Unit] = {
9+
import refl._
10+
import util._
11+
12+
def isImplicitMethodType(tp: Type): Boolean =
13+
Type.IsMethodType.unapply(tp).flatMap(tp => if tp.isImplicit then Some(true) else None).nonEmpty
14+
15+
cond.unseal.underlyingArgument match {
16+
case t @ Apply(sel @ Select(lhs, op), rhs :: Nil) =>
17+
let(lhs) { left =>
18+
let(rhs) { right =>
19+
val app = Apply(Select(left, sel.symbol), right :: Nil)
20+
let(app) { result =>
21+
val l = left.seal
22+
val r = right.seal
23+
val b = result.seal.cast[Boolean]
24+
val code = '{ scala.Predef.assert($b) }
25+
code.unseal
26+
}
27+
}
28+
}.seal.cast[Unit]
29+
case Apply(f @ Apply(sel @ Select(Apply(qual, lhs :: Nil), op), rhs :: Nil), implicits)
30+
if isImplicitMethodType(f.tpe) =>
31+
let(lhs) { left =>
32+
let(rhs) { right =>
33+
val app = Apply(Select(Apply(qual, left :: Nil), sel.symbol), right :: Nil)
34+
let(Apply(app, implicits)) { result =>
35+
val l = left.seal
36+
val r = right.seal
37+
val b = result.seal.cast[Boolean]
38+
val code = '{ scala.Predef.assert($b) }
39+
code.unseal
40+
}
41+
}
42+
}.seal.cast[Unit]
43+
}
44+
}
45+
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
object Test {
2+
import scalatest._
3+
4+
case class Box[T](v: T) {
5+
def >(that: Box[T]): Boolean = this == that
6+
}
7+
8+
trait EqInt
9+
implicit val eq: EqInt = new EqInt {}
10+
11+
implicit class AnyOps[T](x: T) {
12+
def === (y: T)(implicit c: EqInt) = x == y
13+
}
14+
15+
def main(args: Array[String]): Unit = {
16+
val a = Box(Some(10))
17+
val five: Float = 5.0f
18+
val six: Double = 6.0
19+
val ten: Int = 10
20+
assert(a.v === Some(10))
21+
assert(five < six)
22+
assert(five > 4)
23+
assert(ten > 5)
24+
assert(six < 7)
25+
assert(six > 5L)
26+
assert(Box(6) > Box(6))
27+
assert(Box("h") > Box("h"))
28+
}
29+
}

0 commit comments

Comments
 (0)