Scala 3 - when calling method with implicit value within quotes, implicit in scope is not found

Main:

import scala.quoted.{Expr, Quotes, Type}

trait CustomTag[A]

class MyClass[A] {

  def add[B](mc2: MyClass[B])(using CustomTag[B]) = ???

}


object Macros {

  inline def myMacro(inline lhs: MyClass[_], inline rhs: MyClass[_]): Unit =
    ${ myMacroImpl('lhs, 'rhs) }

  def myMacroImpl(lhs: Expr[MyClass[_]], rhs: Expr[MyClass[_]])(using Quotes): Expr[Unit] = {

    val l3 = lhs match {
      case '{ $lhs: MyClass[i] } =>
        rhs match {
          case '{ $rhs: MyClass[i2] } =>
            '{ $lhs.add($rhs) }
//            Expr.summon[CustomTag[i2]] match {
//              case Some(t) => '{ $lhs.add($rhs)(using $t) }
//              case None => ???
//            }
        }
    }

    '{$l3; ()}
  }


  implicit transparent inline def materialize[A]: CustomTag[A] =
    ${ materializeImpl[A] }

  def materializeImpl[A: Type](using Quotes): Expr[CustomTag[A]] = {
    ???
  }
}

Test:

import Macros._

def test[MyC: CustomTag]() = {

  val m1 = MyClass[String]()
  val m2 = MyClass[MyC]()

  val o = Macros.myMacro(m1, m2)
}

@main
def main() = {

}

When calling $lhs.add($rhs) implicit that is actually found is not one from MyC: CustomTag, but is from implicit def. I would expect macro to find implicit that is in it’s closest scope, not the global one. To use implicit that is in macro’s scope I have to use Expr.summon[CustomTag] and explicitly pass it to method invocation, is it by design?

Note that '{ $lhs.add($rhs) } generates an Expr. This then becomes the code that is execute at run-time. However, Expr.summon[CustomTag[i2]] is executed during macro execution, that is during compile-time. So, yes it is by design. See:

https://docs.scala-lang.org/scala3/guides/macros/quotes.html#summon-values

EDIT: by the way, you also have compile time support for summoning when using inline definitions. See:

https://docs.scala-lang.org/scala3/reference/metaprogramming/compiletime-ops.html

My goal is to get local implicit, but also nice error message from implicitNotFound annotation. I’ll see if explicit summoning in quote will work.

I may be misunderstanding, but this should not be a problem within a macro:

Expr.summon[AType[T]].getOrElse {
  report.throwError("Required instance of a AType[ ${Type.show[T]}] but did not find one.")
}

The issue is that this implicit has custom implicitNotFound message and I don’t want to copy it…
Maybe I can extract it within macro.