Implicit resolution conflict

145 views
Skip to first unread message

Eugene Yokota

unread,
Oct 21, 2012, 12:43:12 PM10/21/12
to scala-l...@googlegroups.com
Hi,

Tried using Scala 2.10.0-RC1 with scalaxb-generated code, and the usage code broke with "ambiguous implicit values".
This made me think about implicit conflicts in general, so I wrote this test: https://gist.github.com/3926159 

Let's compare the difference between the usage of Int and DataRecord[Address] with both import rt._ and import client._:

    // compiles
    def test1 {
      import rt._
      import client._
      println(something[Int])
    }

Both package objects' intFormat are visible in the scope. Shouldn't it not compile?

    /* doesn't compile
     * [error] demo.scala:47: error: ambiguous implicit values:
     * [error]  both method dataRecordFormat in trait StandardInstances of type [A](implicit evidence$1: rt.Format[A])rt.Format[rt.DataRecord[A]]{val str: String}
     * [error]  and method dataRecordFormat in trait StandardInstances of type [A](implicit evidence$1: rt.Format[A])rt.Format[rt.DataRecord[A]]{val str: String}
     * [error]  match expected type rt.Format[rt.DataRecord[client.Address]]
     * [error]     println(something[DataRecord[Address]])
     * [error]                      ^
     */
    def test2 {
      import rt._
      import client._
      println(something[DataRecord[Address]])
    }

This compiles on Scala 2.9.2, but I think 2.10.0-RC1 is the correct for not compiling.
dataRecordFormat is available twice. Both require context bound Format[Address], but it's available via implicit scope (client package object). How is this any different from intFormat?

I see that the conflicts can be avoided by only one of the package object extending StandardInstances.
I would likely make the change, but the current behavior seems non-uniform nonetheless.

-eugene

Jason Zaugg

unread,
Oct 21, 2012, 12:49:11 PM10/21/12
to scala-l...@googlegroups.com
The fix for SI-4270 [1] explains the change since 2.9.2

-jason

[1] https://issues.scala-lang.org/browse/SI-4270

eugene yokota

unread,
Oct 21, 2012, 2:24:53 PM10/21/12
to scala-l...@googlegroups.com
Does this mean that due to SI-4270 fix the two import statements
canceled each other out,
because neither intFormat is available as symbol in the scope, and
effectively became the same as test5 and test6
without the imports?:

// compiles
def test5 {
println(rt.something[Int])
}

/* doesn't compile
* [error] Foo.scala:76: error: ambiguous implicit values:
* [error] both method dataRecordFormat in trait StandardInstances
of type [A](implicit evidence$1:
rt.Format[A])rt.Format[rt.DataRecord[A]]{val str: String}
* [error] and method dataRecordFormat in trait StandardInstances
of type [A](implicit evidence$1:
rt.Format[A])rt.Format[rt.DataRecord[A]]{val str: String}
* [error] match expected type rt.Format[rt.DataRecord[client.Address]]
* [error] println(rt.something[rt.DataRecord[client.Address]])
* [error] ^
*/
def test6 {
println(rt.something[rt.DataRecord[client.Address]])
}

If so it all makes sense.

It'd be helpful in the error message where the conflicting implicits
are coming from though.
Even if it's just local scope vs implicit scope (companion/package object).

-eugene

Jason Zaugg

unread,
Oct 21, 2012, 2:32:13 PM10/21/12
to scala-l...@googlegroups.com
Give it a shot with -Xlog-implicits. (See [1])

The rules are now simple: local scope implicits only work if the
corresponding explicit call would type check.

-jason

[1] https://github.com/scala/scala/commit/445c2f

eugene yokota

unread,
Oct 21, 2012, 2:44:48 PM10/21/12
to scala-l...@googlegroups.com
This is helpful since it mentions the fact that the name is imported twice.

-eugene

default-c2c40c> compile
[info] Compiling 1 Scala source to
/Users/eed3si9n/work/quick-demo/bug1/target/scala-2.10/classes...
[info] /Users/eed3si9n/work/quick-demo/bug1/demo.scala:33: <intFormat:
error> is not a valid implicit value for rt.Format[Int] because:
[info] reference to intFormat is ambiguous;
[info] it is imported twice in the same scope by
[info] import client._
[info] and import rt._
[info] println(something[Int])
[info] ^
[info] /Users/eed3si9n/work/quick-demo/bug1/demo.scala:47:
<dataRecordFormat: error> is not a valid implicit value for
rt.Format[rt.DataRecord[client.Address]] because:
[info] reference to dataRecordFormat is ambiguous;
[info] it is imported twice in the same scope by
[info] import client._
[info] and import rt._
[info] println(something[DataRecord[Address]])
[info] ^
[info] /Users/eed3si9n/work/quick-demo/bug1/demo.scala:47:
<dataRecordFormat: error> is not a valid implicit value for
rt.Format[rt.DataRecord[client.Address]] because:
[info] reference to dataRecordFormat is ambiguous;
[info] it is imported twice in the same scope by
[info] import client._
[info] and import rt._
[info] println(something[DataRecord[Address]])
[info] ^
[info] /Users/eed3si9n/work/quick-demo/bug1/demo.scala:47:
<dataRecordFormat: error> is not a valid implicit value for
rt.Format[rt.DataRecord[client.Address]] because:
[info] reference to dataRecordFormat is ambiguous;
[info] it is imported twice in the same scope by
[info] import client._
[info] and import rt._
[info] println(something[DataRecord[Address]])
[info] ^
[error] /Users/eed3si9n/work/quick-demo/bug1/demo.scala:47: ambiguous
implicit values:
[error] both method dataRecordFormat in trait StandardInstances of
type [A](implicit evidence$1:
rt.Format[A])rt.Format[rt.DataRecord[A]]{val str: String}
[error] and method dataRecordFormat in trait StandardInstances of
type [A](implicit evidence$1:
rt.Format[A])rt.Format[rt.DataRecord[A]]{val str: String}
[error] match expected type rt.Format[rt.DataRecord[client.Address]]
[error] println(something[DataRecord[Address]])
[error] ^
[error] /Users/eed3si9n/work/quick-demo/bug1/demo.scala:76: ambiguous
implicit values:
[error] both method dataRecordFormat in trait StandardInstances of
type [A](implicit evidence$1:
rt.Format[A])rt.Format[rt.DataRecord[A]]{val str: String}
[error] and method dataRecordFormat in trait StandardInstances of
type [A](implicit evidence$1:
rt.Format[A])rt.Format[rt.DataRecord[A]]{val str: String}
[error] match expected type rt.Format[rt.DataRecord[client.Address]]
[error] println(rt.something[rt.DataRecord[client.Address]])
[error] ^
[error] two errors found
[error] (compile:compile) Compilation failed
[error] Total time: 1 s, completed Oct 21, 2012 2:37:44 PM
Reply all
Reply to author
Forward
0 new messages