1
votes

Scala version: 2.12.4.

Let's say, there's one empty trait and one class with function, which accepts trait instance as implicit parameter:

trait I

class A {
  def fa()(implicit i: I): Unit = {}
}

Let's define another class, which invokes this fa() function. We'll try to import I instance from its companion object:

class B(a: A) {
  import B._

  def fb(): Unit = { a.fa() }
}

object B {
  private implicit object II extends I
}

But we face an error then!

error: could not find implicit value for parameter i: I
         def fb(): Unit = { a.fa() }
                                ^

Let's make implicit val then in class B:

class B(a: A) {
  import B._

  private implicit val ii = II

  def fb(): Unit = { a.fa() }
}

Suddenly, we still face an error anyway:

error: ambiguous implicit values:
 both value ii in class B of type => B.II.type
 and object II in object B of type B.II.type
 match expected type I
         def fb(): Unit = { a.fa() }
                                ^
  1. Compiler doesn't see implicit in the first case, but sees the same implicit in the second case. Why?
  2. How to import this implicit object from companion object?
1

1 Answers

2
votes

This is an ordering issue with type inference. There are other similar questions, I don't know if there is an exact duplicate.

The issue is that when class B is type-checked, type inference hasn't yet run on object B. Using II in the body of class B in the second example triggers this type inference and makes it visible as an implicit I.

It can be solved by either placing the companion object before the class, or by giving explicit type to II, e.g.

object B {
  private implicit val II: I = new I {}
}

See e.g. Why does this explicit call of a Scala method allow it to be implicitly resolved?