Skip to content

Remove reflect context #9634

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5cc649a
Remove Context from Reflection.Source
nicolasstucki Aug 25, 2020
c18888a
Remove Context from Reflect.{error, warning}
nicolasstucki Aug 25, 2020
82562a3
Remove Context from Reflection.Symbol
nicolasstucki Aug 25, 2020
d96b60d
Remove Context from Reflection.Signature
nicolasstucki Aug 25, 2020
b2cc434
Remove Context from Reflection.let
nicolasstucki Aug 25, 2020
8b75a19
Remove Context from Reflection TypeTests
nicolasstucki Aug 25, 2020
a336c64
Remove Context from Reflection patterns
nicolasstucki Aug 25, 2020
bc37222
Remove Context from Reflection.Tree
nicolasstucki Aug 25, 2020
c9ddce0
Remove Context from Reflection.implicitSearch
nicolasstucki Aug 25, 2020
49209f6
Remove Context from CompilerInterface.betaReduce
nicolasstucki Aug 25, 2020
2c2a4c7
Remove Context from CompilerInteface.lambdaExtractor
nicolasstucki Aug 25, 2020
943b57f
Remove Context from Reflection imports
nicolasstucki Aug 25, 2020
45d63be
Remove Context form withDefaultPos
nicolasstucki Aug 25, 2020
340e8e9
Make localContext a no-op
nicolasstucki Aug 26, 2020
ffb0dcc
Remove Context from Reflection show
nicolasstucki Aug 26, 2020
56a4ffe
Remove Context form Reflect Type
nicolasstucki Aug 26, 2020
a925e1b
Initialize constraints on the QuoteContext
nicolasstucki Aug 26, 2020
c74f8a9
Disable localContext
nicolasstucki Aug 26, 2020
1d17309
Do not expose rootContext to the users
nicolasstucki Aug 26, 2020
dcd806e
Remove Context from CompilerInterface
nicolasstucki Aug 26, 2020
2883c78
Remove Context form Constraints
nicolasstucki Aug 26, 2020
e023fde
Remove rootContext from CompilerInterface
nicolasstucki Aug 26, 2020
18b8595
Remove Context from Printers
nicolasstucki Aug 26, 2020
9c9a7da
Remove Context from Matcher
nicolasstucki Aug 26, 2020
8d8154c
Remove Context from TreeMap and TreeAccumulator
nicolasstucki Aug 26, 2020
5153d30
Remove Context from ExprMap
nicolasstucki Aug 27, 2020
fcc70f7
Remove Context from Reflection
nicolasstucki Aug 27, 2020
aacc6ee
Remove Context type from Reflection
nicolasstucki Aug 27, 2020
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
10 changes: 5 additions & 5 deletions compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ object QuoteContextImpl {
type ScopeId = Int

def apply()(using Context): QuoteContext =
new QuoteContextImpl(ctx)
new QuoteContextImpl

def showTree(tree: tpd.Tree)(using Context): String = {
val qctx = QuoteContextImpl()(using MacroExpansion.context(tree))
val syntaxHighlight =
if (ctx.settings.color.value == "always") SyntaxHighlight.ANSI
else SyntaxHighlight.plain
show(using qctx)(tree.asInstanceOf[qctx.tasty.Tree], syntaxHighlight)(using ctx.asInstanceOf[qctx.tasty.Context])
show(using qctx)(tree.asInstanceOf[qctx.tasty.Tree], syntaxHighlight)
}

private def show(using qctx: QuoteContext)(tree: qctx.tasty.Tree, syntaxHighlight: SyntaxHighlight)(using qctx.tasty.Context) =
private def show(using qctx: QuoteContext)(tree: qctx.tasty.Tree, syntaxHighlight: SyntaxHighlight) =
tree.showWith(syntaxHighlight)

private[dotty] def checkScopeId(id: ScopeId)(using Context): Unit =
Expand All @@ -36,8 +36,8 @@ object QuoteContextImpl {

}

class QuoteContextImpl private (ctx: Context) extends QuoteContext {
class QuoteContextImpl private (using ctx: Context) extends QuoteContext {
// NOTE: The tasty class should only mixin the compiler interface and the reflection interface.
// We should not implement methods here, all should be implemented by `ReflectionCompilerInterface`
val tasty = new ReflectionCompilerInterface(ctx) with scala.tasty.Reflection
val tasty = new ReflectionCompilerInterface with scala.tasty.Reflection
}

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion library/src-bootstrapped/scala/internal/quoted/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ object Expr {
*/
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: scala.quoted.Expr[Any])(using patternExpr: scala.quoted.Expr[Any],
hasTypeSplices: Boolean, qctx: QuoteContext): Option[Tup] = {
new Matcher.QuoteMatcher[qctx.type](qctx).termMatch(scrutineeExpr.unseal, patternExpr.unseal, hasTypeSplices).asInstanceOf[Option[Tup]]
val qctx1 = quoteContextWithCompilerInterface(qctx)
val qctx2 = if hasTypeSplices then qctx1.tasty.Constraints_context else qctx1
given qctx2.type = qctx2
new Matcher.QuoteMatcher[qctx2.type](qctx2).termMatch(scrutineeExpr.unseal, patternExpr.unseal, hasTypeSplices).asInstanceOf[Option[Tup]]
}

/** Returns a null expresssion equivalent to `'{null}` */
Expand Down
48 changes: 20 additions & 28 deletions library/src-bootstrapped/scala/internal/quoted/Matcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ object Matcher {

// TODO improve performance

// TODO use flag from qctx.tasty.rootContext. Maybe -debug or add -debug-macros
// TODO use flag from qctx.tasty. Maybe -debug or add -debug-macros
private final val debug = false

import qctx.tasty._
Expand All @@ -149,43 +149,35 @@ object Matcher {

def termMatch(scrutineeTerm: Term, patternTerm: Term, hasTypeSplices: Boolean): Option[Tuple] = {
given Env = Map.empty
if (hasTypeSplices) {
val ctx: Context = qctx.tasty.Constraints_init(rootContext)
given Context = ctx
val matchings = scrutineeTerm =?= patternTerm
val matchings = scrutineeTerm =?= patternTerm
if !hasTypeSplices then matchings
else {
// After matching and doing all subtype checks, we have to approximate all the type bindings
// that we have found and seal them in a quoted.Type
matchings.asOptionOfTuple.map { tup =>
Tuple.fromArray(tup.toArray.map { // TODO improve performance
case x: SymBinding => qctx.tasty.Constraints_approximation(summon[Context])(x.sym, !x.fromAbove).seal
case x: SymBinding => qctx.tasty.Constraints_approximation(x.sym, !x.fromAbove).seal
case x => x
})
}
}
else {
scrutineeTerm =?= patternTerm
}
}

// TODO factor out common logic with `termMatch`
def typeTreeMatch(scrutineeTypeTree: TypeTree, patternTypeTree: TypeTree, hasTypeSplices: Boolean): Option[Tuple] = {
given Env = Map.empty
if (hasTypeSplices) {
val ctx: Context = qctx.tasty.Constraints_init(rootContext)
given Context = ctx
val matchings = scrutineeTypeTree =?= patternTypeTree
val matchings = scrutineeTypeTree =?= patternTypeTree
if !hasTypeSplices then matchings
else {
// After matching and doing all subtype checks, we have to approximate all the type bindings
// that we have found and seal them in a quoted.Type
matchings.asOptionOfTuple.map { tup =>
Tuple.fromArray(tup.toArray.map { // TODO improve performance
case x: SymBinding => qctx.tasty.Constraints_approximation(summon[Context])(x.sym, !x.fromAbove).seal
case x: SymBinding => qctx.tasty.Constraints_approximation(x.sym, !x.fromAbove).seal
case x => x
})
}
}
else {
scrutineeTypeTree =?= patternTypeTree
}
}

private def hasPatternTypeAnnotation(sym: Symbol) = sym.annots.exists(isPatternTypeAnnotation)
Expand All @@ -211,7 +203,7 @@ object Matcher {

extension (scrutinees: List[Tree]):
/** Check that all trees match with =?= and concatenate the results with &&& */
private def =?= (patterns: List[Tree])(using Context, Env): Matching =
private def =?= (patterns: List[Tree])(using Env): Matching =
matchLists(scrutinees, patterns)(_ =?= _)

extension (scrutinee0: Tree):
Expand All @@ -223,7 +215,7 @@ object Matcher {
* @param `summon[Env]` Set of tuples containing pairs of symbols (s, p) where s defines a symbol in `scrutinee` which corresponds to symbol p in `pattern`.
* @return `None` if it did not match or `Some(tup: Tuple)` if it matched where `tup` contains the contents of the holes.
*/
private def =?= (pattern0: Tree)(using Context, Env): Matching = {
private def =?= (pattern0: Tree)(using Env): Matching = {

/* Match block flattening */ // TODO move to cases
/** Normalize the tree */
Expand Down Expand Up @@ -273,7 +265,7 @@ 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): Term =
tree match
case tree: Ident => summon[Env].get(tree.symbol).flatMap(argsMap.get).getOrElse(tree)
case tree => super.transformTerm(tree)
Expand Down Expand Up @@ -326,7 +318,7 @@ object Matcher {
fn1 =?= fn2 &&& args1 =?= args2

case (Block(stats1, expr1), Block(binding :: stats2, expr2)) if isTypeBinding(binding) =>
qctx.tasty.Constraints_add(summon[Context])(binding.symbol :: Nil)
qctx.tasty.Constraints_add(binding.symbol :: Nil)
matched(new SymBinding(binding.symbol, hasFromAboveAnnotation(binding.symbol))) &&& Block(stats1, expr1) =?= Block(stats2, expr2)

/* Match block */
Expand All @@ -343,7 +335,7 @@ object Matcher {

case (scrutinee, Block(typeBindings, expr2)) if typeBindings.forall(isTypeBinding) =>
val bindingSymbols = typeBindings.map(_.symbol)
qctx.tasty.Constraints_add(summon[Context])(bindingSymbols)
qctx.tasty.Constraints_add(bindingSymbols)
bindingSymbols.foldRight(scrutinee =?= expr2)((x, acc) => matched(new SymBinding(x, hasFromAboveAnnotation(x))) &&& acc)

/* Match if */
Expand Down Expand Up @@ -382,7 +374,7 @@ object Matcher {
/* Match val */
case (ValDef(_, tpt1, rhs1), ValDef(_, tpt2, rhs2)) if checkValFlags() =>
def rhsEnv = summon[Env] + (scrutinee.symbol -> pattern.symbol)
tpt1 =?= tpt2 &&& treeOptMatches(rhs1, rhs2)(using summon[Context], rhsEnv)
tpt1 =?= tpt2 &&& treeOptMatches(rhs1, rhs2)(using rhsEnv)

/* Match def */
case (DefDef(_, typeParams1, paramss1, tpt1, Some(rhs1)), DefDef(_, typeParams2, paramss2, tpt2, Some(rhs2))) =>
Expand Down Expand Up @@ -431,13 +423,13 @@ object Matcher {

private object ClosedPatternTerm {
/** Matches a term that does not contain free variables defined in the pattern (i.e. not defined in `Env`) */
def unapply(term: Term)(using Context, Env): Option[term.type] =
def unapply(term: Term)(using Env): Option[term.type] =
if freePatternVars(term).isEmpty then Some(term) else None

/** 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] =
def freePatternVars(term: Term)(using 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): Set[Symbol] =
tree match
case tree: Ident if env.contains(tree.symbol) => foldOverTree(x + tree.symbol, tree)
case _ => foldOverTree(x, tree)
Expand All @@ -446,7 +438,7 @@ object Matcher {
}

private object IdentArgs {
def unapply(args: List[Term])(using Context): Option[List[Ident]] =
def unapply(args: List[Term]): Option[List[Ident]] =
args.foldRight(Option(List.empty[Ident])) {
case (id: Ident, Some(acc)) => Some(id :: acc)
case (Block(List(DefDef("$anonfun", Nil, List(params), Inferred(), Some(Apply(id: Ident, args)))), Closure(Ident("$anonfun"), None)), Some(acc))
Expand All @@ -456,7 +448,7 @@ object Matcher {
}
}

private def treeOptMatches(scrutinee: Option[Tree], pattern: Option[Tree])(using Context, Env): Matching = {
private def treeOptMatches(scrutinee: Option[Tree], pattern: Option[Tree])(using Env): Matching = {
(scrutinee, pattern) match {
case (Some(x), Some(y)) => x =?= y
case (None, None) => matched
Expand Down
5 changes: 4 additions & 1 deletion library/src-bootstrapped/scala/internal/quoted/Type.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ object Type {
*/
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeType: scala.quoted.Type[_])(using patternType: scala.quoted.Type[_],
hasTypeSplices: Boolean, qctx: QuoteContext): Option[Tup] = {
new Matcher.QuoteMatcher[qctx.type](qctx).typeTreeMatch(scrutineeType.unseal, patternType.unseal, hasTypeSplices).asInstanceOf[Option[Tup]]
val qctx1 = quoteContextWithCompilerInterface(qctx)
val qctx2 = if hasTypeSplices then qctx1.tasty.Constraints_context else qctx1
given qctx2.type = qctx2
new Matcher.QuoteMatcher[qctx2.type](qctx2).typeTreeMatch(scrutineeType.unseal, patternType.unseal, hasTypeSplices).asInstanceOf[Option[Tup]]
}

def Unit: QuoteContext ?=> quoted.Type[Unit] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ object UnsafeExpr {
import qctx.tasty._
val map = params.map(_.symbol).zip(args).toMap
new TreeMap {
override def transformTerm(tree: Term)(using ctx: Context): Term =
override def transformTerm(tree: Term): Term =
super.transformTerm(tree) match
case tree: Ident => map.getOrElse(tree.symbol, tree)
case tree => tree
Expand Down
36 changes: 18 additions & 18 deletions library/src-bootstrapped/scala/quoted/util/ExprMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ trait ExprMap {
import qctx.tasty._
final class MapChildren() {

def transformStatement(tree: Statement)(using ctx: Context): Statement = {
def localCtx(definition: Definition): Context = definition.symbol.localContext
def transformStatement(tree: Statement): Statement = {
// def localCtx(definition: Definition): Context = ctx // definition.symbol.localContext
tree match {
case tree: Term =>
transformTerm(tree, defn.AnyType)
Expand All @@ -24,15 +24,15 @@ trait ExprMap {
}
}

def transformDefinition(tree: Definition)(using ctx: Context): Definition = {
def localCtx(definition: Definition): Context = definition.symbol.localContext
def transformDefinition(tree: Definition): Definition = {
// def localCtx(definition: Definition): Context = ctx // definition.symbol.localContext
tree match {
case tree: ValDef =>
given Context = localCtx(tree)
// given Context = localCtx(tree)
val rhs1 = tree.rhs.map(x => transformTerm(x, tree.tpt.tpe))
ValDef.copy(tree)(tree.name, tree.tpt, rhs1)
case tree: DefDef =>
given Context = localCtx(tree)
// given Context = localCtx(tree)
DefDef.copy(tree)(tree.name, tree.typeParams, tree.paramss, tree.returnTpt, tree.rhs.map(x => transformTerm(x, tree.returnTpt.tpe)))
case tree: TypeDef =>
tree
Expand All @@ -42,7 +42,7 @@ trait ExprMap {
}
}

def transformTermChildren(tree: Term, tpe: Type)(using ctx: Context): Term = tree match {
def transformTermChildren(tree: Term, tpe: Type): Term = tree match {
case Ident(name) =>
tree
case Select(qualifier, name) =>
Expand Down Expand Up @@ -101,7 +101,7 @@ trait ExprMap {
Inlined.copy(tree)(call, transformDefinitions(bindings), transformTerm(expansion, tpe)/*()call.symbol.localContext)*/)
}

def transformTerm(tree: Term, tpe: Type)(using ctx: Context): Term =
def transformTerm(tree: Term, tpe: Type): Term =
tree match
case _: Closure =>
tree
Expand All @@ -115,39 +115,39 @@ trait ExprMap {
case _ =>
transformTermChildren(tree, tpe)

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

def transformCaseDef(tree: CaseDef, tpe: Type)(using ctx: Context): CaseDef =
def transformCaseDef(tree: CaseDef, tpe: Type): CaseDef =
CaseDef.copy(tree)(tree.pattern, tree.guard.map(x => transformTerm(x, defn.BooleanType)), transformTerm(tree.rhs, tpe))

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

def transformStats(trees: List[Statement])(using ctx: Context): List[Statement] =
def transformStats(trees: List[Statement]): List[Statement] =
trees mapConserve (transformStatement(_))

def transformDefinitions(trees: List[Definition])(using ctx: Context): List[Definition] =
def transformDefinitions(trees: List[Definition]): List[Definition] =
trees mapConserve (transformDefinition(_))

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

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

def transformTypeTrees(trees: List[TypeTree])(using ctx: Context): List[TypeTree] =
def transformTypeTrees(trees: List[TypeTree]): List[TypeTree] =
trees mapConserve (transformTypeTree(_))

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

def transformTypeCaseDefs(trees: List[TypeCaseDef])(using ctx: Context): List[TypeCaseDef] =
def transformTypeCaseDefs(trees: List[TypeCaseDef]): List[TypeCaseDef] =
trees mapConserve (transformTypeCaseDef(_))

}
Expand Down
Loading