Skip to content

Implicit resolution fails with Predef in scope #10405

@YuvalItzchakov

Description

@YuvalItzchakov

Consider the following example:

case class A() case class B() implicit def aToB(a: A): B = B() implicit def convert[U, T](seq: Seq[U])( implicit converter: U => T): Seq[T] = { seq.map(converter) } val sa = Seq(A()) def example(): Seq[B] = sa

Given both aToB and convert, the compiler should be able to resolve the conversion in example, but fails:

Error:(16, 29) type mismatch; found : Seq[A] required: Seq[B] def example(): Seq[B] = sa 

Compiling this under -Xlog-implicits shows that the compiler seems to be searching for an implicit converter from A => A instead of A => B:

convert is not a valid implicit value for Seq[A] => Seq[B] because: incompatible: (seq: Seq[A])(implicit converter: A => A)Seq[A] does not match expected type Seq[A] => Seq[B] def example(): Seq[B] = sa 

Looking at Ytyper-debug proves that implicit search tries to apply Predef.conforms:

| | | | | [search #3] considering $conforms | | | | | solving for (A: ?A) | | | | | [adapt] $conforms adapted to [A]=> <:<[A,A] based on pt A => T | | | | | [search #3] solve tvars=?T, tvars.constr= >: A | | | | | solving for (T: ?T) | | | | | [search #3] success inferred value of type A => =?A is SearchResult(scala.Predef.$conforms[A], TreeTypeSubstituter(List(type T),List(A))) | | | | | [adapt] [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] adapted to [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] based on pt Seq[A] => Seq[B] | | | | | [search #4] start `Seq[A]`, searching for adaptation to pt=(=> Seq[A]) => Seq[B] (silent: method example in Test) implicits disabled SparkTests.scala:16: error: type mismatch; found : Seq[A] required: Seq[B] def example(): Seq[B] = sa 

If we rule out Predef.conforms, the implicit search succeeds (Yno-predef Ytyper-debug) and the code compiles:

| | | | | [adapt] [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] adapted to [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] based on pt Seq[A] => Seq[B] | | | | | [search #2] success inferred value of type Seq[A] => Seq[B] is SearchResult(convert[A, B], ) | | | | | |-- [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] : pt=Seq[B] EXPRmode (silent: method example in Test) implicits disabled | | | | | | [search #4] start `[U, T](seq: Seq[U])(implicit converter: U => T)Seq[T]`, searching for adaptation to pt=A => B (silent: method example in Test) implicits disabled | | | | | | [search #4] considering aToB | | | | | | |-- { ((a: A) => aToB(a)) } : pt=A => B EXPRmode (silent: method example in Test) implicits disabled | | | | | | | |-- ((a: A) => aToB(a)) : pt=A => B EXPRmode (silent: method example in Test) implicits disabled | | | | | | | | |-- (a: A)B : pt=B EXPRmode (silent: value $anonfun in Test) implicits disabled | | | | | | | | | |-- a : pt=A BYVALmode-EXPRmode (silent: value $anonfun in Test) implicits disabled | | | | | | | | | | \-> A | | | | | | | | | \-> B | | | | | | | | \-> A => B | | | | | | | \-> A => B | | | | | | [adapt] (a: A)B adapted to { ((a: A) => aToB(a)) } based on pt A => B | | | | | | [search #4] success inferred value of type A => B is SearchResult({ | | | | | | ((a: A) => aToB(a)) | | | | | | }, ) | | | | | | |-- [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] : pt=Seq[B] EXPRmode (silent: method example in Test) implicits disabled | | | | | | | \-> Seq[B] | | | | | | [adapt] [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] adapted to [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] based on pt Seq[B] | | | | | | \-> Seq[B] | | | | | [adapt] Seq[A] adapted to [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] based on pt Seq[B] | | | | | \-> Seq[B] | | | | \-> [def example] ()Seq[B] 

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions