- Notifications
You must be signed in to change notification settings - Fork 1.1k
Behaviour of implicit search #22171
Replies: 1 comment · 6 replies
-
summon[Show2[B.type]]is ambiguous, which becomes evident when compiling valt1:Show2[B.type] =Show2.given_Show2_T[B.type] valt2:Show2[B.type] =Show2.given_Show2_T[A] |
BetaWas this translation helpful?Give feedback.
All reactions
-
To my understanding the compiler simply doesn't know what type to substitute for |
BetaWas this translation helpful?Give feedback.
All reactions
-
Thinking out loud now. traitShow[T]{defshow(v: T):String } traitShow2[-T]{defshow2(a: T):String } objectShow2{implicitdefgiven_Show2_T[T](implicitshow: Show[T]):Show2[T] =newShow2[T]{overridedefshow2(a: T):String= show.show(a) } } sealedtraitAcaseobjectBextendsAobjectTest{implicitlazyvalgiven_Show_A:Show[A] =newShow[A]{defshow(v: A):String="A" } implicitlazyvalgiven_Show_B_type:Show[B.type] =newShow[B.type]{defshow(v: B.type):String="B" } valt= implicitly[Show2[B.type]] }Compiling this with package<empty>{abstracttraitShow[T] extends scala.AnyRef{defshow(v: T):String }; abstracttraitShow2[-T] extends scala.AnyRef{defshow2(a: T):String }; objectShow2extends scala.AnyRef{def<init>():Show2.type={Show2.super.<init>(); () }; implicitdefgiven_Show2_T[T](implicitshow: Show[T]):Show2[T] ={finalclass$anonextendsAnyRefwithShow2[T]{def<init>():<$anon: Show2[T]>={$anon.super.<init>(); () }; overridedefshow2(a: T):String= show.show(a) }; new $anon() } }; sealedabstracttraitAextends scala.AnyRef; caseobjectBextendsAnyRefwithAwithProductwithSerializable{def<init>():B.type={B.super.<init>(); () }; override <synthetic> defproductPrefix:String="B"; <synthetic> defproductArity:Int=0; <synthetic> defproductElement(x$1: Int):Any= x$1match{case _ => scala.runtime.Statics.ioobe[Any](x$1) }; override <synthetic> defproductIterator:Iterator[Any] = scala.runtime.ScalaRunTime.typedProductIterator[Any](B.this); <synthetic> defcanEqual(x$1: Any):Boolean= x$1.$isInstanceOf[B.type](); override <synthetic> defhashCode():Int=66; override <synthetic> deftoString():String="B"; <synthetic> privatedefwriteReplace():Object=new scala.runtime.ModuleSerializationProxy(classOf[B$]) }; objectTestextends scala.AnyRef{def<init>():Test.type={Test.super.<init>(); () }; implicit <stable> <accessor> lazyvalgiven_Show_A:Show[A] ={finalclass$anonextendsAnyRefwithShow[A]{def<init>():<$anon: Show[A]>={$anon.super.<init>(); () }; defshow(v: A):String="A" }; new $anon() }; implicit <stable> <accessor> lazyvalgiven_Show_B_type:Show[B.type] ={finalclass$anonextendsAnyRefwithShow[B.type]{def<init>():<$anon: Show[B.type]>={$anon.super.<init>(); () }; defshow(v: B.type):String="B" }; new $anon() }; private[this] valt:Show2[B.type] = scala.Predef.implicitly[Show2[B.type]](Show2.given_Show2_T[B.type](Test.this.given_Show_B_type)); <stable> <accessor> deft:Show2[B.type] =Test.this.t } }So maybe now the question is actually why scala 2 doesn't report an ambiguity here? |
BetaWas this translation helpful?Give feedback.
All reactions
-
@prolativ sorry for late response, that's good point about scala2. But getting back to my question: I do understand what does ambiguity in implicit search mean, that it cannot choose between those two. But what I would like to understand is: some sort of reasoning about how does the implicit search implementation reaches the state where it cannot decide in this particular example, taking into account the variance of typeclasses, |
BetaWas this translation helpful?Give feedback.
All reactions
-
Not sure if I get how exactly you modified the example to make it work. Could you paste the entire compile-ready snippet here? |
BetaWas this translation helpful?Give feedback.
All reactions
-
here it is: objectTest{traitShow[-T]{defshow(v: T):String } traitShow2[T]{defshow2(a: T):String } objectShow2{given [T](usingshow: Show[T]):Show2[T] withoverridedefshow2(a: T):String= show.show(a) } sealedtraitAcaseobjectBextendsAgivenShow[A] withdefshow(v: A):String="A"givenShow[B.type] withdefshow(v: B.type):String="B"valt= summon[Show2[B.type]] } Also I think it's not such a rare case, I bumped into it while migrating from scala2 to scala3. and such hierarchy represents the integration layer between not such a rare two libraries, which is |
BetaWas this translation helpful?Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello folks, I was researching different cases of variance quirks in scala and I bumped into this one for which I so far wasn't able to produce any sensible explanation whatsoever, maybe somebody could help me here with explanation or perhaps it's a bug...
Here we have invariant
Show[T]typeclass, which has been implicitly converted into contrvariantShow2[-T]typeclass. This variance difference causing an ambiguous implicit search error.Interestingly this example(when givens are replaced with implicits) is compiling in scala2, therefore I thought that there are some changes in implicit resolution, but going through this multiple times didn't really help.
Another note is that results is the same for all stable major versions of scala3, I tested with: 3.3.3, 3.4.2, 3.5.2, 3.6.2-RC1
Since original
Show[T]is invariant, I expect search to be able to narrow it down to one of the presented givensand I get this error:
BetaWas this translation helpful?Give feedback.
All reactions