Skip to content

Commit 4bd9400

Browse files
Merge pull request #7009 from dotty-staging/fix-6988
Fix #6988: add test
2 parents cdf74b8 + 26c3215 commit 4bd9400

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

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

+14-4
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,22 @@ trait TreeOps extends Core {
241241

242242
object Ref {
243243

244-
/** Create a reference tree */
244+
/** Create a reference tree from a symbol
245+
*
246+
* If `sym` refers to a class member `foo` in class `C`,
247+
* returns a tree representing `C.this.foo`.
248+
*
249+
* If `sym` refers to a local definition `foo`, returns
250+
* a tree representing `foo`.
251+
*
252+
* @note In both cases, the constructed tree should only
253+
* be spliced into the places where such accesses make sense.
254+
* For example, it is incorrect to have `C.this.foo` outside
255+
* the class body of `C`, or have `foo` outside the lexical
256+
* scope for the definition of `foo`.
257+
*/
245258
def apply(sym: Symbol)(given ctx: Context): Ref =
246259
internal.Ref_apply(sym)
247-
248-
// TODO def copy(original: Tree)(name: String)(given ctx: Context): Ref
249-
250260
}
251261

252262
given (given Context): IsInstanceOf[Ident] = internal.isInstanceOfIdent
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package foo
2+
3+
case class FirstArg(value: Any, source: String)
4+
object FirstArg {
5+
inline given create: FirstArg = ${Macros.argsImpl}
6+
}
7+
8+
object Macros {
9+
import scala.quoted._
10+
11+
def argsImpl(given qctx: QuoteContext): Expr[FirstArg] = {
12+
import qctx.tasty.{_, given}
13+
14+
def enclosingClass(cur: Symbol = rootContext.owner): Symbol =
15+
if (cur.isClassDef) cur
16+
else enclosingClass(cur.owner)
17+
18+
def enclosingParamList(owner: Symbol): Seq[Seq[Symbol]] =
19+
if owner.isClassDef then
20+
owner.tree match
21+
case tdef: ClassDef =>
22+
tdef.constructor.paramss map { _ map {_.symbol }}
23+
else enclosingParamList(owner.owner)
24+
25+
def literal(value: String): Expr[String] =
26+
Literal(Constant(value)).seal.asInstanceOf[Expr[String]]
27+
val paramss = enclosingParamList(rootContext.owner)
28+
val firstArg = paramss.flatten.head
29+
val ref = Select.unique(This(enclosingClass()), firstArg.name)
30+
'{ FirstArg(${ref.seal}, ${Expr(firstArg.name)}) }
31+
}
32+
}

tests/run-macros/i6988/Test_2.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
object Test {
2+
var firstArgName = ""
3+
var firstArgValue: Any = ""
4+
def main(args: Array[String]): Unit = {
5+
val x = new Foo("something", 2L, false)
6+
assert("p1" == firstArgName)
7+
assert("something" == firstArgValue)
8+
}
9+
def debug(given foo.FirstArg): Unit = {
10+
firstArgName = summon[foo.FirstArg].source
11+
firstArgValue = summon[foo.FirstArg].value
12+
}
13+
class Foo(p1: String, p2: Long, p3: Boolean) {
14+
debug
15+
}
16+
}

0 commit comments

Comments
 (0)