diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index 45effed04a84..23002f2c1719 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -2009,6 +2009,7 @@ class Typer extends Namer
             fun = ref(defn.InternalQuotedMatcher_unapplyR).appliedToTypeTrees(typeBindingsTuple :: TypeTree(patType) :: Nil),
             implicits =
               ref(defn.InternalQuoted_exprQuoteR).appliedToType(shape.tpe).appliedTo(shape) ::
+              Literal(Constant(typeBindings.nonEmpty)) ::
               implicitArgTree(defn.TastyReflectionType, tree.span) :: Nil,
             patterns = splicePat :: Nil,
             proto = pt)
diff --git a/library/src-3.x/scala/internal/quoted/Matcher.scala b/library/src-3.x/scala/internal/quoted/Matcher.scala
index 71feae8b5e66..60d55f2eed3f 100644
--- a/library/src-3.x/scala/internal/quoted/Matcher.scala
+++ b/library/src-3.x/scala/internal/quoted/Matcher.scala
@@ -27,17 +27,18 @@ object Matcher {
    *
    *  @param scrutineeExpr `Expr[_]` on which we are pattern matching
    *  @param patternExpr `Expr[_]` containing the pattern tree
+   *  @param hasTypeSplices `Boolean` notify if the pattern has type splices (if so we use a GADT context)
    *  @param reflection instance of the reflection API (implicitly provided by the macro)
    *  @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Expr[Ti]``
    */
-  def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], reflection: Reflection): Option[Tup] = {
+  def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], hasTypeSplices: Boolean, reflection: Reflection): Option[Tup] = {
     // TODO improve performance
     import reflection.{Bind => BindPattern, _}
     import Matching._
 
     type Env = Set[(Symbol, Symbol)]
 
-    class SymBinding(val sym: Symbol)
+    class SymBinding(val sym: Symbol, val fromBellow: Boolean)
 
     inline def withEnv[T](env: Env)(body: => given Env => T): T = body given env
 
@@ -140,7 +141,8 @@ object Matcher {
 
         case (Block(stats1, expr1), Block(binding :: stats2, expr2)) if isTypeBinding(binding) =>
           reflection.kernel.Context_GADT_addToConstraint(the[Context])(binding.symbol :: Nil)
-          matched(new SymBinding(binding.symbol)) && Block(stats1, expr1) =#= Block(stats2, expr2)
+          val fromBellow = true // TODO
+          matched(new SymBinding(binding.symbol, fromBellow)) && Block(stats1, expr1) =#= Block(stats2, expr2)
 
         case (Block(stat1 :: stats1, expr1), Block(stat2 :: stats2, expr2)) =>
           withEnv(the[Env] + (stat1.symbol -> stat2.symbol)) {
@@ -150,7 +152,8 @@ object Matcher {
         case (scrutinee, Block(typeBindings, expr2)) if typeBindings.forall(isTypeBinding) =>
           val bindingSymbols = typeBindings.map(_.symbol)
           reflection.kernel.Context_GADT_addToConstraint(the[Context])(bindingSymbols)
-          bindingSymbols.foldRight(scrutinee =#= expr2)((x, acc) => matched(new SymBinding(x)) && acc)
+          val fromBellow = true // TODO
+          bindingSymbols.foldRight(scrutinee =#= expr2)((x, acc) => matched(new SymBinding(x, fromBellow)) && acc)
 
         case (If(cond1, thenp1, elsep1), If(cond2, thenp2, elsep2)) =>
           cond1 =#= cond2 && thenp1 =#= thenp2 && elsep1 =#= elsep2
@@ -335,18 +338,24 @@ object Matcher {
 
     implied for Env = Set.empty
 
-    {
-      // TODO only set GADT context when needed
-      implicit val ctx2 = reflection.kernel.Context_GADT_setFreshGADTBounds(rootContext)
-      val matchings = scrutineeExpr.unseal.underlyingArgument =#= patternExpr.unseal.underlyingArgument
-      val res = matchings.asOptionOfTuple.map { tup =>
-        Tuple.fromArray(tup.toArray.map { // TODO improve code
-          case x: SymBinding => reflection.kernel.Context_GADT_approximation(ctx2)(x.sym, true).seal
-          case x => x
-        })
+    val res = {
+      if (hasTypeSplices) {
+        implied for Context = reflection.kernel.Context_GADT_setFreshGADTBounds(rootContext)
+        val matchings = scrutineeExpr.unseal.underlyingArgument =#= patternExpr.unseal.underlyingArgument
+        // After matching and doing all subtype check, we have to aproximate 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 performace
+            case x: SymBinding => kernel.Context_GADT_approximation(the[Context])(x.sym, x.fromBellow).seal
+            case x => x
+          })
+        }
+      }
+      else {
+        scrutineeExpr.unseal.underlyingArgument =#= patternExpr.unseal.underlyingArgument
       }
-      res.asInstanceOf[Option[Tup]]
     }
+    res.asInstanceOf[Option[Tup]]
   }
 
   /** Result of matching a part of an expression */
diff --git a/tests/run-macros/quote-matcher-runtime/quoted_1.scala b/tests/run-macros/quote-matcher-runtime/quoted_1.scala
index 75b9e87bceca..97677157725c 100644
--- a/tests/run-macros/quote-matcher-runtime/quoted_1.scala
+++ b/tests/run-macros/quote-matcher-runtime/quoted_1.scala
@@ -10,7 +10,7 @@ object Macros {
   private def impl[A, B](a: Expr[A], b: Expr[B])(implicit reflect: Reflection): Expr[Unit] = {
     import reflect.{Bind => _, _}
 
-    val res = scala.internal.quoted.Matcher.unapply[Tuple, Tuple](a)(b, reflect).map { tup =>
+    val res = scala.internal.quoted.Matcher.unapply[Tuple, Tuple](a)(b, true, reflect).map { tup =>
       tup.toArray.toList.map {
         case r: Expr[_] =>
           s"Expr(${r.unseal.show})"