milessabin / shapeless

Generic programming for Scala

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Generic in shapeless 2.3.5+ not working for classes with context bounds if some implicit value is present

lsrcz opened this issue · comments

Hi, I am using shapeless in my project and met some strange behavior. I am not sure if it is a bug.

The following code is a minimal example. It compiles with shapeless 2.3.5+ only if the instance is commented out. It works well with shapeless 2.3.3/2.3.4.

import shapeless._

trait ATypeClass[T]

case class AnUnrelatedCaseClass[T](v: T)

case class ACaseClassWithContextBound[T: ATypeClass]()

object Main extends App {
  implicit def instance[T: ATypeClass]: ATypeClass[AnUnrelatedCaseClass[T]] = new ATypeClass[AnUnrelatedCaseClass[T]] {}

  /*
   * With shapeless 2.3.5+, the following function compiles only if instance is commented out
   * With shapeless 2.3.3/2.3.4, the following function always compiles
   */
  def compilesOnlyIfInstanceIsCommented[T: ATypeClass]
  : Generic.Aux[ACaseClassWithContextBound[T], HNil] = Generic[ACaseClassWithContextBound[T]]
}

That sounds like a bug. But in general the interaction between shapeless and implicits might be confusing - because the implicit instance would be captured at Generic definition time, not when it is used.

I read something about debugging implicits and hope that I can provide you more information.

I turned on -Xlog-implicits, and the compiler reported that

instance is not a valid implicit value for ATypeClass[T] because:
hasMatchingSymbol reported error: diverging implicit expansion for type ATypeClass[T]
starting with value evidence$3
  : Generic.Aux[ACaseClassWithContextBound[T], HNil] = Generic[ACaseClassWithContextBound[T]]

shapeless.this.Generic.materialize is not a valid implicit value for shapeless.Generic[ACaseClassWithContextBound[T]] because:
hasMatchingSymbol reported error: ambiguous implicit values:
 both method instance in object Main of type [T](implicit evidence$2: ATypeClass[T])ATypeClass[AnUnrelatedCaseClass[T]]
 and value evidence$3 of type ATypeClass[T]
 match expected type ATypeClass[T]
  : Generic.Aux[ACaseClassWithContextBound[T], HNil] = Generic[ACaseClassWithContextBound[T]]

I am not so familiar with scala macros so I cannot fully understand the shapeless source. But if I understand it correctly, it failed to resolve the type class instance required by the constructor of ACaseClassWithContextBound.