@@ -545,29 +545,49 @@ trait Implicits { self: Typer =>
545545 /** If `formal` is of the form ClassTag[T], where `T` is a class type,
546546 * synthesize a class tag for `T`.
547547 */
548- def synthesizedClassTag (formal : Type , pos : Position )(implicit ctx : Context ): Tree = {
549- if (formal.isRef(defn.ClassTagClass ))
550- formal.argTypes match {
551- case arg :: Nil =>
552- fullyDefinedType(arg, " ClassTag argument" , pos) match {
553- case defn.ArrayOf (elemTp) =>
554- val etag = inferImplicitArg(defn.ClassTagType .appliedTo(elemTp), error, pos)
555- if (etag.isEmpty) etag else etag.select(nme.wrap)
556- case tp if hasStableErasure(tp) =>
557- if (defn.isBottomClass(tp.typeSymbol))
558- error(where => i " attempt to take ClassTag of undetermined type for $where" )
559- ref(defn.ClassTagModule )
560- .select(nme.apply)
561- .appliedToType(tp)
562- .appliedTo(clsOf(erasure(tp)))
563- .withPos(pos)
564- case tp =>
565- EmptyTree
566- }
567- case _ =>
568- EmptyTree
569- }
570- else EmptyTree
548+ def synthesizedClassTag (formal : Type )(implicit ctx : Context ): Tree =
549+ formal.argTypes match {
550+ case arg :: Nil =>
551+ fullyDefinedType(arg, " ClassTag argument" , pos) match {
552+ case defn.ArrayOf (elemTp) =>
553+ val etag = inferImplicitArg(defn.ClassTagType .appliedTo(elemTp), error, pos)
554+ if (etag.isEmpty) etag else etag.select(nme.wrap)
555+ case tp if hasStableErasure(tp) =>
556+ if (defn.isBottomClass(tp.typeSymbol))
557+ error(where => i " attempt to take ClassTag of undetermined type for $where" )
558+ ref(defn.ClassTagModule )
559+ .select(nme.apply)
560+ .appliedToType(tp)
561+ .appliedTo(clsOf(erasure(tp)))
562+ .withPos(pos)
563+ case tp =>
564+ EmptyTree
565+ }
566+ case _ =>
567+ EmptyTree
568+ }
569+
570+ /** If `formal` is of the form Eq[T, U], where no `Eq` instance exists for
571+ * either `T` or `U`, synthesize `Eq.eqAny[T, U]` as solution.
572+ */
573+ def synthesizedEq (formal : Type )(implicit ctx : Context ): Tree = {
574+ // println(i"synth eq $formal / ${formal.argTypes}%, %")
575+ formal.argTypes match {
576+ case args @ (arg1 :: arg2 :: Nil )
577+ if ! ctx.featureEnabled(defn.LanguageModuleClass , nme.strictEquality) &&
578+ validEqAnyArgs(arg1, arg2)(ctx.fresh.setExploreTyperState) =>
579+ ref(defn.Eq_eqAny ).appliedToTypes(args).withPos(pos)
580+ case _ =>
581+ EmptyTree
582+ }
583+ }
584+
585+ def hasEq (tp : Type ): Boolean =
586+ inferImplicit(defn.EqType .appliedTo(tp, tp), EmptyTree , pos).isInstanceOf [SearchSuccess ]
587+
588+ def validEqAnyArgs (tp1 : Type , tp2 : Type )(implicit ctx : Context ) = {
589+ List (tp1, tp2).foreach(fullyDefinedType(_, " eqAny argument" , pos))
590+ assumedCanEqual(tp1, tp2) || ! hasEq(tp1) && ! hasEq(tp2)
571591 }
572592
573593 /** The context to be used when resolving a by-name implicit argument.
@@ -606,7 +626,13 @@ trait Implicits { self: Typer =>
606626 error(where => s " ambiguous implicits: ${ambi.explanation} of $where" )
607627 EmptyTree
608628 case failure : SearchFailure =>
609- val arg = synthesizedClassTag(formalValue, pos)
629+ val arg =
630+ if (formalValue.isRef(defn.ClassTagClass ))
631+ synthesizedClassTag(formalValue)
632+ else if (formalValue.isRef(defn.EqClass ))
633+ synthesizedEq(formalValue)
634+ else
635+ EmptyTree
610636 if (! arg.isEmpty) arg
611637 else {
612638 var msgFn = (where : String ) =>
@@ -638,10 +664,10 @@ trait Implicits { self: Typer =>
638664 }
639665
640666 val lift = new TypeMap {
641- def apply (t : Type ) = t match {
667+ def apply (t : Type ): Type = t match {
642668 case t : TypeRef =>
643669 t.info match {
644- case TypeBounds (lo, hi) if lo ne hi => hi
670+ case TypeBounds (lo, hi) if lo ne hi => apply(hi)
645671 case _ => t
646672 }
647673 case _ =>
@@ -714,6 +740,8 @@ trait Implicits { self: Typer =>
714740 if (argument.isEmpty) f(resultType) else ViewProto (f(argument.tpe.widen), f(resultType))
715741 // Not clear whether we need to drop the `.widen` here. All tests pass with it in place, though.
716742
743+ private def isCoherent = pt.isRef(defn.EqClass )
744+
717745 assert(argument.isEmpty || argument.tpe.isValueType || argument.tpe.isInstanceOf [ExprType ],
718746 em " found: $argument: ${argument.tpe}, expected: $pt" )
719747
@@ -761,40 +789,16 @@ trait Implicits { self: Typer =>
761789 case _ => false
762790 }
763791 }
764- // Does there exist an implicit value of type `Eq[tp, tp]`
765- // which is different from `eqAny`?
766- def hasEq (tp : Type ): Boolean = {
767- def search (contextual : Boolean ): Boolean =
768- new ImplicitSearch (defn.EqType .appliedTo(tp, tp), EmptyTree , pos)
769- .bestImplicit(contextual) match {
770- case result : SearchSuccess =>
771- result.ref.symbol != defn.Predef_eqAny ||
772- contextual && search(contextual = false )
773- case result : AmbiguousImplicits => true
774- case _ => false
775- }
776- search(contextual = true )
777- }
778792
779- def validEqAnyArgs (tp1 : Type , tp2 : Type ) = {
780- List (tp1, tp2).foreach(fullyDefinedType(_, " eqAny argument" , pos))
781- assumedCanEqual(tp1, tp2) || ! hasEq(tp1) && ! hasEq(tp2) ||
782- { implicits.println(i " invalid eqAny[ $tp1, $tp2] " ); false }
783- }
784793 if (ctx.reporter.hasErrors)
785794 nonMatchingImplicit(ref, ctx.reporter.removeBufferedMessages)
786795 else if (contextual && ! ctx.mode.is(Mode .ImplicitShadowing ) &&
787796 ! shadowing.tpe.isError && ! refSameAs(shadowing)) {
788797 implicits.println(i " SHADOWING $ref in ${ref.termSymbol.owner} is shadowed by $shadowing in ${shadowing.symbol.owner}" )
789798 shadowedImplicit(ref, methPart(shadowing).tpe)
790799 }
791- else generated1 match {
792- case TypeApply (fn, targs @ (arg1 :: arg2 :: Nil ))
793- if fn.symbol == defn.Predef_eqAny && ! validEqAnyArgs(arg1.tpe, arg2.tpe) =>
794- nonMatchingImplicit(ref, Nil )
795- case _ =>
796- SearchSuccess (generated1, ref, cand.level, ctx.typerState)
797- }
800+ else
801+ SearchSuccess (generated1, ref, cand.level, ctx.typerState)
798802 }}
799803
800804 /** Given a list of implicit references, produce a list of all implicit search successes,
@@ -812,7 +816,7 @@ trait Implicits { self: Typer =>
812816 case fail : SearchFailure =>
813817 rankImplicits(pending1, acc)
814818 case best : SearchSuccess =>
815- if (ctx.mode.is(Mode .ImplicitExploration )) best :: Nil
819+ if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent ) best :: Nil
816820 else {
817821 val newPending = pending1.filter(cand1 =>
818822 isAsGood(cand1.ref, best.ref, cand1.level, best.level)(nestedContext.setExploreTyperState))
0 commit comments