title: How does the Scala compiler perform implicit conversion?
body: <p>I have a custom class, <code>A</code>, and I have defined some operations within the class as follows:</p>
  
  <pre class="lang-scala prettyprint-override"><code>def +(that: A) = ...
  def -(that: A) = ...
  def *(that: A) = ...
  
  def +(that: Double) = ...
  def -(that: Double) = ...
  def *(that: Double) = ...
  </code></pre>
  
  <p>In order to have something like <code>2.0 + x</code> make sense when <code>x</code> is of type <code>A</code>, I have defined the following implicit class:</p>
  
  <pre class="lang-scala prettyprint-override"><code>object A {
    implicit class Ops (lhs: Double) {
      def +(rhs: A) = ...
      def -(rhs: A) = ...
      def *(rhs: A) = ...
    }
  }
  </code></pre>
  
  <p>This all works fine normally. Now I introduce a compiler plugin with a <code>TypingTransformer</code> that performs some optimizations. Specifically, let's say I have a <code>ValDef</code>:</p>
  
  <pre class="lang-scala prettyprint-override"><code>val x = y + a * z
  </code></pre>
  
  <p>where <code>x</code>, <code>y</code>, and <code>z</code> are of type <code>A</code>, and <code>a</code> is a <code>Double</code>. Normally, this compiles fine. I put it through the optimizer, which uses quasiquotes to change <code>y + a * z</code> into something else. <strong>BUT</strong> in this particular example, the expression is unchanged (there are no optimizations to perform). Suddenly, the compiler no longer does an implicit conversion for <code>a * z</code>.</p>
  
  <p>To summarize, I have a compiler plugin that takes an expression that would normally have implicit conversions applied to it. It creates a new expression via quasiquotes, which syntactically appears the same as the old expression. But for this new expression, the compiler fails to perform implicit conversion.</p>
  
  <p>So my question — how does the compiler determine that an implicit conversion must take place? Is there a specific flag or something that needs to be set in the AST that quasiquotes are failing to set?</p>
  
  <hr>
  
  <p><strong>UPDATE</strong></p>
  
  <p>The plugin phase looks something like this:</p>
  
  <pre class="lang-scala prettyprint-override"><code>override def transform(tree: Tree) = tree match {
    case ClassDef(classmods, classname, classtparams, impl) if classname.toString == "Module" =&gt; {
      var implStatements: List[Tree] = List()
      for (node &lt;- impl.body) node match {
        case DefDef(mods, name, tparams, vparamss, tpt, body) if name.toString == "loop" =&gt; {
          var statements: List[Tree] = List()
          for (statement &lt;- body.children.dropRight(1)) statement match {
            case Assign(opd, rhs) =&gt; {
              val optimizedRHS = optimizeStatement(rhs)
              statements = statements ++ List(Assign(opd, optimizedRHS))
            }
            case ValDef(mods, opd, tpt, rhs) =&gt; {
              val optimizedRHS = optimizeStatement(rhs)
              statements = statements ++
                List(ValDef(mods, opd, tpt, optimizedRHS))
            }
            case Apply(Select(src1, op), List(src2)) if op.toString == "push" =&gt; {
              val optimizedSrc2 = optimizeStatement(src2)
              statements = statements ++
                List(Apply(Select(src1, op), List(optimizedSrc2)))
            }
            case _ =&gt; statements = statements ++ List(statement)
          }
  
          val newBody = Block(statements, body.children.last)
          implStatements = implStatements ++
            List(DefDef(mods, name, tparams, vparamss, tpt, newBody))
        }
        case _ =&gt; implStatements = implStatements ++ List(node)
      }
      val newImpl = Template(impl.parents, impl.self, implStatements)
      ClassDef(classmods, classname, classtparams, newImpl)
    }
    case _ =&gt; super.transform(tree)
  }
  
  def optimizeStatement(tree: Tree): Tree = {
    // some logic that transforms
    // 1.0 * x + 2.0 * (x + y)
    // into
    // 3.0 * x + 2.0 * y
    // (i.e. distribute multiplication &amp; collect like terms)
    //
    // returned trees are always newly created
    // returned trees are create w/ quasiquotes
    // something like
    // 1.0 * x + 2.0 * y
    // will return
    // 1.0 * x + 2.0 * y
    // (i.e. syntactically unchanged)
  }
  </code></pre>
  
  <hr>
  
  <p><strong>UPDATE 2</strong></p>
  
  <p>Please refer to this GitHub repo for a minimum working example: <a href="https://github.com/darsnack/compiler-plugin-demo" rel="noreferrer">https://github.com/darsnack/compiler-plugin-demo</a></p>
  
  <p>The issue is that <code>a * z</code> turns into <code>a.&lt;$times: error&gt;(z)</code> after I optimize the statement.</p>