@@ -545,29 +545,49 @@ trait Implicits { self: Typer =>
545
545
/** If `formal` is of the form ClassTag[T], where `T` is a class type,
546
546
* synthesize a class tag for `T`.
547
547
*/
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)
571
591
}
572
592
573
593
/** The context to be used when resolving a by-name implicit argument.
@@ -606,7 +626,13 @@ trait Implicits { self: Typer =>
606
626
error(where => s " ambiguous implicits: ${ambi.explanation} of $where" )
607
627
EmptyTree
608
628
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
610
636
if (! arg.isEmpty) arg
611
637
else {
612
638
var msgFn = (where : String ) =>
@@ -638,10 +664,10 @@ trait Implicits { self: Typer =>
638
664
}
639
665
640
666
val lift = new TypeMap {
641
- def apply (t : Type ) = t match {
667
+ def apply (t : Type ): Type = t match {
642
668
case t : TypeRef =>
643
669
t.info match {
644
- case TypeBounds (lo, hi) if lo ne hi => hi
670
+ case TypeBounds (lo, hi) if lo ne hi => apply(hi)
645
671
case _ => t
646
672
}
647
673
case _ =>
@@ -714,6 +740,8 @@ trait Implicits { self: Typer =>
714
740
if (argument.isEmpty) f(resultType) else ViewProto (f(argument.tpe.widen), f(resultType))
715
741
// Not clear whether we need to drop the `.widen` here. All tests pass with it in place, though.
716
742
743
+ private def isCoherent = pt.isRef(defn.EqClass )
744
+
717
745
assert(argument.isEmpty || argument.tpe.isValueType || argument.tpe.isInstanceOf [ExprType ],
718
746
em " found: $argument: ${argument.tpe}, expected: $pt" )
719
747
@@ -761,40 +789,16 @@ trait Implicits { self: Typer =>
761
789
case _ => false
762
790
}
763
791
}
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
- }
778
792
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
- }
784
793
if (ctx.reporter.hasErrors)
785
794
nonMatchingImplicit(ref, ctx.reporter.removeBufferedMessages)
786
795
else if (contextual && ! ctx.mode.is(Mode .ImplicitShadowing ) &&
787
796
! shadowing.tpe.isError && ! refSameAs(shadowing)) {
788
797
implicits.println(i " SHADOWING $ref in ${ref.termSymbol.owner} is shadowed by $shadowing in ${shadowing.symbol.owner}" )
789
798
shadowedImplicit(ref, methPart(shadowing).tpe)
790
799
}
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)
798
802
}}
799
803
800
804
/** Given a list of implicit references, produce a list of all implicit search successes,
@@ -812,7 +816,7 @@ trait Implicits { self: Typer =>
812
816
case fail : SearchFailure =>
813
817
rankImplicits(pending1, acc)
814
818
case best : SearchSuccess =>
815
- if (ctx.mode.is(Mode .ImplicitExploration )) best :: Nil
819
+ if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent ) best :: Nil
816
820
else {
817
821
val newPending = pending1.filter(cand1 =>
818
822
isAsGood(cand1.ref, best.ref, cand1.level, best.level)(nestedContext.setExploreTyperState))
0 commit comments