From 8106cc9ee369aa94d805f1a7a1e4c1805be8b8ab Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 2 Sep 2020 17:33:11 +0200 Subject: [PATCH] Remove constraints abstraction from Context The constraints API is available durring the execution of the Matcher and initialized before the matching strats independently of the local contexts in the Matcher. --- .../reflect/ReflectionCompilerInterface.scala | 13 ++++---- .../scala/internal/quoted/Expr.scala | 5 +++- .../scala/internal/quoted/Matcher.scala | 30 +++++++------------ .../scala/internal/quoted/Type.scala | 5 +++- .../internal/tasty/CompilerInterface.scala | 6 ++-- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/quoted/reflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/quoted/reflect/ReflectionCompilerInterface.scala index ebb34f2fb892..77339b933ebe 100644 --- a/compiler/src/dotty/tools/dotc/quoted/reflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/quoted/reflect/ReflectionCompilerInterface.scala @@ -55,14 +55,15 @@ class ReflectionCompilerInterface(val rootContext: Context) extends CompilerInte // Constraints // ///////////////// - def Constraints_init(self: Context): Context = - self.fresh.setFreshGADTBounds.addMode(Mode.GadtConstraintInference) + def Constraints_context[T]: scala.quoted.QuoteContext = + val ctx1 = ctx.fresh.setFreshGADTBounds.addMode(Mode.GadtConstraintInference) + dotty.tools.dotc.quoted.QuoteContextImpl()(using ctx1) - def Constraints_add(self: Context)(syms: List[Symbol]): Boolean = - self.gadt.addToConstraint(syms) + def Constraints_add(syms: List[Symbol]): Boolean = + ctx.gadt.addToConstraint(syms) - def Constraints_approximation(self: Context)(sym: Symbol, fromBelow: Boolean): Type = - self.gadt.approximation(sym, fromBelow) + def Constraints_approximation(sym: Symbol, fromBelow: Boolean): Type = + ctx.gadt.approximation(sym, fromBelow) //////////// // Source // diff --git a/library/src-bootstrapped/scala/internal/quoted/Expr.scala b/library/src-bootstrapped/scala/internal/quoted/Expr.scala index 0cfcacfe2814..e34d6c95ba38 100644 --- a/library/src-bootstrapped/scala/internal/quoted/Expr.scala +++ b/library/src-bootstrapped/scala/internal/quoted/Expr.scala @@ -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}` */ diff --git a/library/src-bootstrapped/scala/internal/quoted/Matcher.scala b/library/src-bootstrapped/scala/internal/quoted/Matcher.scala index 68d57e1dbc50..fccf8f96ae3f 100644 --- a/library/src-bootstrapped/scala/internal/quoted/Matcher.scala +++ b/library/src-bootstrapped/scala/internal/quoted/Matcher.scala @@ -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._ @@ -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) @@ -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 */ @@ -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 */ diff --git a/library/src-bootstrapped/scala/internal/quoted/Type.scala b/library/src-bootstrapped/scala/internal/quoted/Type.scala index 646359c6a7d1..74477105cfa9 100644 --- a/library/src-bootstrapped/scala/internal/quoted/Type.scala +++ b/library/src-bootstrapped/scala/internal/quoted/Type.scala @@ -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] = diff --git a/library/src/scala/internal/tasty/CompilerInterface.scala b/library/src/scala/internal/tasty/CompilerInterface.scala index b3146276b0b2..24bd84a6204f 100644 --- a/library/src/scala/internal/tasty/CompilerInterface.scala +++ b/library/src/scala/internal/tasty/CompilerInterface.scala @@ -33,9 +33,9 @@ trait CompilerInterface extends scala.tasty.reflect.Types { // Constraints // ///////////////// - def Constraints_init(self: Context): Context - def Constraints_add(self: Context)(syms: List[Symbol]): Boolean - def Constraints_approximation(self: Context)(sym: Symbol, fromBelow: Boolean): Type + def Constraints_context[T]: scala.quoted.QuoteContext + def Constraints_add(syms: List[Symbol]): Boolean + def Constraints_approximation(sym: Symbol, fromBelow: Boolean): Type //////////// // Source //