@@ -262,6 +262,7 @@ object Implicits {
262
262
case _ : SearchSuccess => this
263
263
case fail : SearchFailure => other(fail)
264
264
}
265
+ def isSuccess = isInstanceOf [SearchSuccess ]
265
266
}
266
267
267
268
/** A successful search
@@ -503,8 +504,7 @@ trait Implicits { self: Typer =>
503
504
&& from.isValueType
504
505
&& ( from.isValueSubType(to)
505
506
|| inferView(dummyTreeOfType(from), to)
506
- (ctx.fresh.addMode(Mode .ImplicitExploration ).setExploreTyperState())
507
- .isInstanceOf [SearchSuccess ]
507
+ (ctx.fresh.addMode(Mode .ImplicitExploration ).setExploreTyperState()).isSuccess
508
508
// TODO: investigate why we can't TyperState#test here
509
509
)
510
510
)
@@ -583,7 +583,7 @@ trait Implicits { self: Typer =>
583
583
}
584
584
585
585
def hasEq (tp : Type ): Boolean =
586
- inferImplicit(defn.EqType .appliedTo(tp, tp), EmptyTree , pos).isInstanceOf [ SearchSuccess ]
586
+ inferImplicit(defn.EqType .appliedTo(tp, tp), EmptyTree , pos).isSuccess
587
587
588
588
def validEqAnyArgs (tp1 : Type , tp2 : Type )(implicit ctx : Context ) = {
589
589
List (tp1, tp2).foreach(fullyDefinedType(_, " eqAny argument" , pos))
@@ -787,6 +787,8 @@ trait Implicits { self: Typer =>
787
787
/** The expected type where parameters and uninstantiated typevars are replaced by wildcard types */
788
788
val wildProto = implicitProto(pt, wildApprox(_, null , Set .empty))
789
789
790
+ val isNot = wildProto.classSymbol == defn.NotClass
791
+
790
792
/** Search a list of eligible implicit references */
791
793
def searchImplicits (eligible : List [Candidate ], contextual : Boolean ): SearchResult = {
792
794
val constr = ctx.typerState.constraint
@@ -896,10 +898,23 @@ trait Implicits { self: Typer =>
896
898
case cand :: pending1 =>
897
899
tryImplicit(cand) match {
898
900
case fail : SearchFailure =>
899
- if (fail.isAmbiguous) healAmbiguous(pending1, fail)
900
- else rank(pending1, found, fail :: rfailures)
901
+ if (isNot)
902
+ SearchSuccess (ref(defn.Not_value ), defn.Not_value .termRef, 0 )(ctx.typerState)
903
+ else if (fail.isAmbiguous)
904
+ if (ctx.scala2Mode) {
905
+ val result = rank(pending1, found, NoMatchingImplicitsFailure :: rfailures)
906
+ if (result.isSuccess)
907
+ warnAmbiguousNegation(fail.reason.asInstanceOf [AmbiguousImplicits ])
908
+ result
909
+ }
910
+ else
911
+ healAmbiguous(pending1, fail)
912
+ else
913
+ rank(pending1, found, fail :: rfailures)
901
914
case best : SearchSuccess =>
902
- if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent)
915
+ if (isNot)
916
+ NoMatchingImplicitsFailure
917
+ else if (ctx.mode.is(Mode .ImplicitExploration ) || isCoherent)
903
918
best
904
919
else disambiguate(found, best) match {
905
920
case retained : SearchSuccess =>
@@ -917,6 +932,15 @@ trait Implicits { self: Typer =>
917
932
else found.recoverWith(_ => rfailures.reverse.maxBy(_.tree.treeSize))
918
933
}
919
934
935
+ def warnAmbiguousNegation (ambi : AmbiguousImplicits ) =
936
+ ctx.migrationWarning(
937
+ i """ Ambiguous implicits ${ambi.alt1.ref.symbol.showLocated} and ${ambi.alt2.ref.symbol.showLocated}
938
+ |seem to be used to implement a local failure in order to negate an implicit search.
939
+ |According to the new implicit resolution rules this is no longer possible;
940
+ |the search will fail with a global ambiguity error instead.
941
+ |
942
+ |Consider using the scala.implicits.Not class to implement similar functionality. """ , pos)
943
+
920
944
/** A relation that imfluences the order in which implicits are tried.
921
945
* We prefer (in order of importance)
922
946
* 1. more deeply nested definitions
0 commit comments