Skip to content

Make owners explicit in reflection API #10406

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

Merged
merged 1 commit into from
Nov 20, 2020
Merged
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
16 changes: 8 additions & 8 deletions compiler/src/scala/quoted/internal/impl/Matcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -199,19 +199,19 @@ object Matcher {
def bodyFn(lambdaArgs: List[Tree]): Tree = {
val argsMap = args.map(_.symbol).zip(lambdaArgs.asInstanceOf[List[Term]]).toMap
new TreeMap {
override def transformTerm(tree: Term)(using ctx: Context): Term =
override def transformTerm(tree: Term)(owner: Symbol): Term =
tree match
case tree: Ident => summon[Env].get(tree.symbol).flatMap(argsMap.get).getOrElse(tree)
case tree => super.transformTerm(tree)
}.transformTree(scrutinee)
case tree => super.transformTerm(tree)(owner)
}.transformTree(scrutinee)(Symbol.spliceOwner)
}
val names = args.map {
case Block(List(DefDef("$anonfun", _, _, _, Some(Apply(Ident(name), _)))), _) => name
case arg => arg.symbol.name
}
val argTypes = args.map(x => x.tpe.widenTermRefExpr)
val resType = pattern.tpe
val res = Lambda(Symbol.currentOwner, MethodType(names)(_ => argTypes, _ => resType), (meth, x) => bodyFn(x).changeOwner(meth))
val res = Lambda(Symbol.spliceOwner, MethodType(names)(_ => argTypes, _ => resType), (meth, x) => bodyFn(x).changeOwner(meth))
matched(res.asExpr)

//
Expand Down Expand Up @@ -354,12 +354,12 @@ object Matcher {
/** Return all free variables of the term defined in the pattern (i.e. defined in `Env`) */
def freePatternVars(term: Term)(using ctx: Context, env: Env): Set[Symbol] =
val accumulator = new TreeAccumulator[Set[Symbol]] {
def foldTree(x: Set[Symbol], tree: Tree)(using ctx: Context): Set[Symbol] =
def foldTree(x: Set[Symbol], tree: Tree)(owner: Symbol): Set[Symbol] =
tree match
case tree: Ident if env.contains(tree.symbol) => foldOverTree(x + tree.symbol, tree)
case _ => foldOverTree(x, tree)
case tree: Ident if env.contains(tree.symbol) => foldOverTree(x + tree.symbol, tree)(owner)
case _ => foldOverTree(x, tree)(owner)
}
accumulator.foldTree(Set.empty, term)
accumulator.foldTree(Set.empty, term)(Symbol.spliceOwner)
}

private object IdentArgs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2205,7 +2205,6 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl

object Symbol extends SymbolModule:
def spliceOwner: Symbol = ctx.owner
def currentOwner(using ctx: Context): Symbol = ctx.owner
def requiredPackage(path: String): Symbol = dotc.core.Symbols.requiredPackage(path)
def requiredClass(path: String): Symbol = dotc.core.Symbols.requiredClass(path)
def requiredModule(path: String): Symbol = dotc.core.Symbols.requiredModule(path)
Expand Down Expand Up @@ -2244,8 +2243,6 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
def fullName: String = self.denot.fullName.toString
def pos: Position = self.sourcePos

def localContext: Context =
if self.exists then ctx.withOwner(self) else ctx
def documentation: Option[Documentation] =
import dotc.core.Comments.CommentsContext
val docCtx = ctx.docCtx.getOrElse {
Expand Down
103 changes: 50 additions & 53 deletions library/src-bootstrapped/scala/quoted/ExprMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,142 +10,139 @@ trait ExprMap:
import qctx.reflect._
final class MapChildren() {

def transformStatement(tree: Statement)(using ctx: Context): Statement = {
def localCtx(definition: Definition): Context = definition.symbol.localContext
def transformStatement(tree: Statement)(owner: Symbol): Statement = {
tree match {
case tree: Term =>
transformTerm(tree, TypeRepr.of[Any])
transformTerm(tree, TypeRepr.of[Any])(owner)
case tree: Definition =>
transformDefinition(tree)
transformDefinition(tree)(owner)
case tree: Import =>
tree
}
}

def transformDefinition(tree: Definition)(using ctx: Context): Definition = {
def localCtx(definition: Definition): Context = definition.symbol.localContext
def transformDefinition(tree: Definition)(owner: Symbol): Definition = {
tree match {
case tree: ValDef =>
given Context = localCtx(tree)
val rhs1 = tree.rhs.map(x => transformTerm(x, tree.tpt.tpe))
val owner = tree.symbol
val rhs1 = tree.rhs.map(x => transformTerm(x, tree.tpt.tpe)(owner))
ValDef.copy(tree)(tree.name, tree.tpt, rhs1)
case tree: DefDef =>
given Context = localCtx(tree)
DefDef.copy(tree)(tree.name, tree.typeParams, tree.paramss, tree.returnTpt, tree.rhs.map(x => transformTerm(x, tree.returnTpt.tpe)))
val owner = tree.symbol
DefDef.copy(tree)(tree.name, tree.typeParams, tree.paramss, tree.returnTpt, tree.rhs.map(x => transformTerm(x, tree.returnTpt.tpe)(owner)))
case tree: TypeDef =>
tree
case tree: ClassDef =>
val newBody = transformStats(tree.body)
val newBody = transformStats(tree.body)(owner)
ClassDef.copy(tree)(tree.name, tree.constructor, tree.parents, tree.derived, tree.self, newBody)
}
}

def transformTermChildren(tree: Term, tpe: TypeRepr)(using ctx: Context): Term = tree match {
def transformTermChildren(tree: Term, tpe: TypeRepr)(owner: Symbol): Term = tree match {
case Ident(name) =>
tree
case Select(qualifier, name) =>
Select.copy(tree)(transformTerm(qualifier, qualifier.tpe), name)
Select.copy(tree)(transformTerm(qualifier, qualifier.tpe)(owner), name)
case This(qual) =>
tree
case Super(qual, mix) =>
tree
case tree as Apply(fun, args) =>
val MethodType(_, tpes, _) = fun.tpe.widen
Apply.copy(tree)(transformTerm(fun, TypeRepr.of[Any]), transformTerms(args, tpes))
Apply.copy(tree)(transformTerm(fun, TypeRepr.of[Any])(owner), transformTerms(args, tpes)(owner))
case TypeApply(fun, args) =>
TypeApply.copy(tree)(transformTerm(fun, TypeRepr.of[Any]), args)
TypeApply.copy(tree)(transformTerm(fun, TypeRepr.of[Any])(owner), args)
case _: Literal =>
tree
case New(tpt) =>
New.copy(tree)(transformTypeTree(tpt))
New.copy(tree)(transformTypeTree(tpt)(owner))
case Typed(expr, tpt) =>
val tp = tpt.tpe match
case AppliedType(TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "<repeated>"), List(tp0: TypeRepr)) =>
TypeRepr.of[Seq].appliedTo(tp0)
case tp => tp
Typed.copy(tree)(transformTerm(expr, tp), transformTypeTree(tpt))
Typed.copy(tree)(transformTerm(expr, tp)(owner), transformTypeTree(tpt)(owner))
case tree: NamedArg =>
NamedArg.copy(tree)(tree.name, transformTerm(tree.value, tpe))
NamedArg.copy(tree)(tree.name, transformTerm(tree.value, tpe)(owner))
case Assign(lhs, rhs) =>
Assign.copy(tree)(lhs, transformTerm(rhs, lhs.tpe.widen))
Assign.copy(tree)(lhs, transformTerm(rhs, lhs.tpe.widen)(owner))
case Block(stats, expr) =>
Block.copy(tree)(transformStats(stats), transformTerm(expr, tpe))
Block.copy(tree)(transformStats(stats)(owner), transformTerm(expr, tpe)(owner))
case If(cond, thenp, elsep) =>
If.copy(tree)(
transformTerm(cond, TypeRepr.of[Boolean]),
transformTerm(thenp, tpe),
transformTerm(elsep, tpe))
transformTerm(cond, TypeRepr.of[Boolean])(owner),
transformTerm(thenp, tpe)(owner),
transformTerm(elsep, tpe)(owner))
case _: Closure =>
tree
case Match(selector, cases) =>
Match.copy(tree)(transformTerm(selector, selector.tpe), transformCaseDefs(cases, tpe))
Match.copy(tree)(transformTerm(selector, selector.tpe)(owner), transformCaseDefs(cases, tpe)(owner))
case Return(expr) =>
// FIXME
// ctx.owner seems to be set to the wrong symbol
// Return.copy(tree)(transformTerm(expr, expr.tpe))
tree
case While(cond, body) =>
While.copy(tree)(transformTerm(cond, TypeRepr.of[Boolean]), transformTerm(body, TypeRepr.of[Any]))
While.copy(tree)(transformTerm(cond, TypeRepr.of[Boolean])(owner), transformTerm(body, TypeRepr.of[Any])(owner))
case Try(block, cases, finalizer) =>
Try.copy(tree)(transformTerm(block, tpe), transformCaseDefs(cases, TypeRepr.of[Any]), finalizer.map(x => transformTerm(x, TypeRepr.of[Any])))
Try.copy(tree)(transformTerm(block, tpe)(owner), transformCaseDefs(cases, TypeRepr.of[Any])(owner), finalizer.map(x => transformTerm(x, TypeRepr.of[Any])(owner)))
case Repeated(elems, elemtpt) =>
Repeated.copy(tree)(transformTerms(elems, elemtpt.tpe), elemtpt)
Repeated.copy(tree)(transformTerms(elems, elemtpt.tpe)(owner), elemtpt)
case Inlined(call, bindings, expansion) =>
Inlined.copy(tree)(call, transformDefinitions(bindings), transformTerm(expansion, tpe)/*()call.symbol.localContext)*/)
Inlined.copy(tree)(call, transformDefinitions(bindings)(owner), transformTerm(expansion, tpe)(owner))
}

def transformTerm(tree: Term, tpe: TypeRepr)(using ctx: Context): Term =
def transformTerm(tree: Term, tpe: TypeRepr)(owner: Symbol): Term =
tree match
case _: Closure =>
tree
case _: Inlined =>
transformTermChildren(tree, tpe)
transformTermChildren(tree, tpe)(owner)
case _ if tree.isExpr =>
type X
val expr = tree.asExpr.asInstanceOf[Expr[X]]
val t = tpe.asType.asInstanceOf[Type[X]]
val transformedExpr = transform(expr)(using qctx, t)
Term.of(transformedExpr)
case _ =>
transformTermChildren(tree, tpe)
transformTermChildren(tree, tpe)(owner)

def transformTypeTree(tree: TypeTree)(using ctx: Context): TypeTree = tree
def transformTypeTree(tree: TypeTree)(owner: Symbol): TypeTree = tree

def transformCaseDef(tree: CaseDef, tpe: TypeRepr)(using ctx: Context): CaseDef =
CaseDef.copy(tree)(tree.pattern, tree.guard.map(x => transformTerm(x, TypeRepr.of[Boolean])), transformTerm(tree.rhs, tpe))
def transformCaseDef(tree: CaseDef, tpe: TypeRepr)(owner: Symbol): CaseDef =
CaseDef.copy(tree)(tree.pattern, tree.guard.map(x => transformTerm(x, TypeRepr.of[Boolean])(owner)), transformTerm(tree.rhs, tpe)(owner))

def transformTypeCaseDef(tree: TypeCaseDef)(using ctx: Context): TypeCaseDef = {
TypeCaseDef.copy(tree)(transformTypeTree(tree.pattern), transformTypeTree(tree.rhs))
}
def transformTypeCaseDef(tree: TypeCaseDef)(owner: Symbol): TypeCaseDef =
TypeCaseDef.copy(tree)(transformTypeTree(tree.pattern)(owner), transformTypeTree(tree.rhs)(owner))

def transformStats(trees: List[Statement])(using ctx: Context): List[Statement] =
trees mapConserve (transformStatement(_))
def transformStats(trees: List[Statement])(owner: Symbol): List[Statement] =
trees.mapConserve(x => transformStatement(x)(owner))

def transformDefinitions(trees: List[Definition])(using ctx: Context): List[Definition] =
trees mapConserve (transformDefinition(_))
def transformDefinitions(trees: List[Definition])(owner: Symbol): List[Definition] =
trees.mapConserve(x => transformDefinition(x)(owner))

def transformTerms(trees: List[Term], tpes: List[TypeRepr])(using ctx: Context): List[Term] =
def transformTerms(trees: List[Term], tpes: List[TypeRepr])(owner: Symbol): List[Term] =
var tpes2 = tpes // TODO use proper zipConserve
trees mapConserve { x =>
trees.mapConserve{ x =>
val tpe :: tail = tpes2
tpes2 = tail
transformTerm(x, tpe)
transformTerm(x, tpe)(owner)
}

def transformTerms(trees: List[Term], tpe: TypeRepr)(using ctx: Context): List[Term] =
trees.mapConserve(x => transformTerm(x, tpe))
def transformTerms(trees: List[Term], tpe: TypeRepr)(owner: Symbol): List[Term] =
trees.mapConserve(x => transformTerm(x, tpe)(owner))

def transformTypeTrees(trees: List[TypeTree])(using ctx: Context): List[TypeTree] =
trees mapConserve (transformTypeTree(_))
def transformTypeTrees(trees: List[TypeTree])(owner: Symbol): List[TypeTree] =
trees.mapConserve(x => transformTypeTree(x)(owner))

def transformCaseDefs(trees: List[CaseDef], tpe: TypeRepr)(using ctx: Context): List[CaseDef] =
trees mapConserve (x => transformCaseDef(x, tpe))
def transformCaseDefs(trees: List[CaseDef], tpe: TypeRepr)(owner: Symbol): List[CaseDef] =
trees.mapConserve(x => transformCaseDef(x, tpe)(owner))

def transformTypeCaseDefs(trees: List[TypeCaseDef])(using ctx: Context): List[TypeCaseDef] =
trees mapConserve (transformTypeCaseDef(_))
def transformTypeCaseDefs(trees: List[TypeCaseDef])(owner: Symbol): List[TypeCaseDef] =
trees.mapConserve(x => transformTypeCaseDef(x)(owner))

}
new MapChildren().transformTermChildren(Term.of(e), TypeRepr.of[T]).asExprOf[T]
new MapChildren().transformTermChildren(Term.of(e), TypeRepr.of[T])(Symbol.spliceOwner).asExprOf[T]
}

end ExprMap
Loading