@@ -396,12 +396,13 @@ object Implicits:
396396 }
397397
398398 /** A successful search
399- * @param tree The typed tree that needs to be inserted
400- * @param ref The implicit reference that succeeded
401- * @param level The level where the reference was found
399+ * @param tree The typed tree that needs to be inserted
400+ * @param ref The implicit reference that succeeded
401+ * @param level The level where the reference was found
402+ * @param isExtension Whether the result is an extension method application
402403 * @param tstate The typer state to be committed if this alternative is chosen
403404 */
404- case class SearchSuccess (tree : Tree , ref : TermRef , level : Int )(val tstate : TyperState , val gstate : GadtConstraint )
405+ case class SearchSuccess (tree : Tree , ref : TermRef , level : Int , isExtension : Boolean = false )(val tstate : TyperState , val gstate : GadtConstraint )
405406 extends SearchResult with RefAndLevel with Showable
406407
407408 /** A failed search */
@@ -491,12 +492,14 @@ object Implicits:
491492 class AmbiguousImplicits (val alt1 : SearchSuccess , val alt2 : SearchSuccess , val expectedType : Type , val argument : Tree ) extends SearchFailureType {
492493 def explanation (using Context ): String =
493494 em " both ${err.refStr(alt1.ref)} and ${err.refStr(alt2.ref)} $qualify"
494- override def whyNoConversion (using Context ): String = {
495- val what = if (expectedType.isInstanceOf [SelectionProto ]) " extension methods" else " conversions"
496- i """
497- |Note that implicit $what cannot be applied because they are ambiguous;
498- | $explanation"""
499- }
495+ override def whyNoConversion (using Context ): String =
496+ if ! argument.isEmpty && argument.tpe.widen.isRef(defn.NothingClass ) then
497+ " "
498+ else
499+ val what = if (expectedType.isInstanceOf [SelectionProto ]) " extension methods" else " conversions"
500+ i """
501+ |Note that implicit $what cannot be applied because they are ambiguous;
502+ | $explanation"""
500503 }
501504
502505 class MismatchedImplicit (ref : TermRef ,
@@ -802,12 +805,11 @@ trait Implicits:
802805 val inferred = inferImplicit(adjust(to), from, from.span)
803806
804807 inferred match {
805- case SearchSuccess (tree, ref, _)
806- if isOldStyleFunctionConversion(ref.underlying) && ! tree.isInstanceOf [Applications .ExtMethodApply ] =>
807- report.migrationWarning(
808- i " The conversion ${ref} will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views. " ,
809- from
810- )
808+ case SearchSuccess (_, ref, _, false ) if isOldStyleFunctionConversion(ref.underlying) =>
809+ report.migrationWarning(
810+ i " The conversion ${ref} will not be applied implicitly here in Scala 3 because only implicit methods and instances of Conversion class will continue to work as implicit views. " ,
811+ from
812+ )
811813 case _ =>
812814 }
813815
@@ -829,7 +831,7 @@ trait Implicits:
829831 */
830832 def inferImplicitArg (formal : Type , span : Span )(using Context ): Tree =
831833 inferImplicit(formal, EmptyTree , span) match
832- case SearchSuccess (arg, _, _) => arg
834+ case SearchSuccess (arg, _, _, _ ) => arg
833835 case fail @ SearchFailure (failed) =>
834836 if fail.isAmbiguous then failed
835837 else
@@ -937,7 +939,6 @@ trait Implicits:
937939 case Select (qual, _) => apply(x, qual)
938940 case Apply (fn, _) => apply(x, fn)
939941 case TypeApply (fn, _) => apply(x, fn)
940- case tree : Applications .AppProxy => apply(x, tree.app)
941942 case _ : This => false
942943 case _ => foldOver(x, tree)
943944 }
@@ -1026,13 +1027,23 @@ trait Implicits:
10261027 pt, locked)
10271028 }
10281029 pt match
1029- case selProto @ SelectionProto (selName : TermName , mbrType, _, _) if cand.isExtension =>
1030+ case selProto @ SelectionProto (selName : TermName , mbrType, _, _) =>
1031+
10301032 def tryExtension (using Context ) =
10311033 extMethodApply(untpd.Select (untpdGenerated, selName), argument, mbrType)
1032- if cand.isConversion then
1034+
1035+ def tryConversionForSelection (using Context ) =
1036+ val converted = tryConversion
1037+ if ! ctx.reporter.hasErrors && ! selProto.isMatchedBy(converted.tpe) then
1038+ // this check is needed since adapting relative to a `SelectionProto` can succeed
1039+ // even if the term is not a subtype of the `SelectionProto`
1040+ err.typeMismatch(converted, selProto)
1041+ converted
1042+
1043+ if cand.isExtension && cand.isConversion then
10331044 val extensionCtx, conversionCtx = ctx.fresh.setNewTyperState()
10341045 val extensionResult = tryExtension(using extensionCtx)
1035- val conversionResult = tryConversion (using conversionCtx)
1046+ val conversionResult = tryConversionForSelection (using conversionCtx)
10361047 if ! extensionCtx.reporter.hasErrors then
10371048 extensionCtx.typerState.commit()
10381049 if ! conversionCtx.reporter.hasErrors then
@@ -1041,7 +1052,8 @@ trait Implicits:
10411052 else
10421053 conversionCtx.typerState.commit()
10431054 conversionResult
1044- else tryExtension
1055+ else if cand.isExtension then tryExtension
1056+ else tryConversionForSelection
10451057 case _ =>
10461058 tryConversion
10471059 }
@@ -1060,10 +1072,7 @@ trait Implicits:
10601072 SearchFailure (adapted.withType(new MismatchedImplicit (ref, pt, argument)))
10611073 }
10621074 else
1063- val returned =
1064- if (cand.isExtension) Applications .ExtMethodApply (adapted)
1065- else adapted
1066- SearchSuccess (returned, ref, cand.level)(ctx.typerState, ctx.gadt)
1075+ SearchSuccess (adapted, ref, cand.level, cand.isExtension)(ctx.typerState, ctx.gadt)
10671076 }
10681077
10691078 /** An implicit search; parameters as in `inferImplicit` */
@@ -1126,20 +1135,13 @@ trait Implicits:
11261135 case alt1 : SearchSuccess =>
11271136 var diff = compareAlternatives(alt1, alt2)
11281137 assert(diff <= 0 ) // diff > 0 candidates should already have been eliminated in `rank`
1129- if diff == 0 then
1138+ if diff == 0 && alt1.isExtension && alt2.isExtension then
11301139 // Fall back: if both results are extension method applications,
11311140 // compare the extension methods instead of their wrappers.
1132- object extMethodApply :
1133- def unapply (t : Tree ): Option [Type ] = t match
1134- case t : Applications .ExtMethodApply => Some (methPart(stripApply(t.app)).tpe)
1135- case _ => None
1136- end extMethodApply
1137-
1138- (alt1.tree, alt2.tree) match
1139- case (extMethodApply(ref1 : TermRef ), extMethodApply(ref2 : TermRef )) =>
1140- diff = compare(ref1, ref2)
1141+ def stripExtension (alt : SearchSuccess ) = methPart(stripApply(alt.tree)).tpe
1142+ (stripExtension(alt1), stripExtension(alt2)) match
1143+ case (ref1 : TermRef , ref2 : TermRef ) => diff = compare(ref1, ref2)
11411144 case _ =>
1142-
11431145 if diff < 0 then alt2
11441146 else if diff > 0 then alt1
11451147 else SearchFailure (new AmbiguousImplicits (alt1, alt2, pt, argument), span)
@@ -1565,7 +1567,7 @@ final class SearchRoot extends SearchHistory:
15651567 else
15661568 result match {
15671569 case failure : SearchFailure => failure
1568- case success @ SearchSuccess (tree, _, _) =>
1570+ case success : SearchSuccess =>
15691571 import tpd ._
15701572
15711573 // We might have accumulated dictionary entries for by name implicit arguments
@@ -1588,7 +1590,7 @@ final class SearchRoot extends SearchHistory:
15881590 else prune(in.map(_._2) ++ trees, out, in ++ acc)
15891591 }
15901592
1591- val pruned = prune(List (tree), implicitDictionary.map(_._2).toList, Nil )
1593+ val pruned = prune(List (success. tree), implicitDictionary.map(_._2).toList, Nil )
15921594 myImplicitDictionary = null
15931595 if (pruned.isEmpty) result
15941596 else if (pruned.exists(_._2 == EmptyTree )) NoMatchingImplicitsFailure
@@ -1645,7 +1647,7 @@ final class SearchRoot extends SearchHistory:
16451647 case tree => tree
16461648 })
16471649
1648- val res = resMap(tree)
1650+ val res = resMap(success. tree)
16491651
16501652 val blk = Block (classDef :: inst :: Nil , res).withSpan(span)
16511653
0 commit comments