@@ -80,15 +80,17 @@ object Implicits {
8080 case mt : MethodType =>
8181 mt.isImplicitMethod ||
8282 mt.paramInfos.lengthCompare(1 ) != 0 ||
83- ! ctx.test(implicit ctx => argType relaxed_<:< mt.paramInfos.head)
83+ ! ctx.test(implicit ctx =>
84+ argType relaxed_<:< mt.paramInfos.head.widenSingleton)
8485 case poly : PolyType =>
8586 // We do not need to call ProtoTypes#constrained on `poly` because
8687 // `refMatches` is always called with mode TypevarsMissContext enabled.
8788 poly.resultType match {
8889 case mt : MethodType =>
8990 mt.isImplicitMethod ||
9091 mt.paramInfos.length != 1 ||
91- ! ctx.test(implicit ctx => argType relaxed_<:< wildApprox(mt.paramInfos.head, null , Set .empty))
92+ ! ctx.test(implicit ctx =>
93+ argType relaxed_<:< wildApprox(mt.paramInfos.head.widenSingleton, null , Set .empty))
9294 case rtp =>
9395 discardForView(wildApprox(rtp, null , Set .empty), argType)
9496 }
@@ -132,14 +134,37 @@ object Implicits {
132134 case _ => false
133135 }
134136
137+ /** Widen singleton arguments of implicit conversions to their underlying type.
138+ * This is necessary so that they can be found eligible for the argument type.
139+ * Note that we always take the underlying type of a singleton type as the argument
140+ * type, so that we get a reasonable implicit cache hit ratio.
141+ */
142+ def adjustSingletonArg (tp : Type ): Type = tp match {
143+ case tp : PolyType =>
144+ val res = adjustSingletonArg(tp.resType)
145+ if (res `eq` tp.resType) tp else tp.derivedLambdaType(resType = res)
146+ case tp : MethodType =>
147+ tp.paramInfos match {
148+ case (single : SingletonType ) :: Nil =>
149+ tp.derivedLambdaType(paramInfos = single.widenSingleton :: Nil )
150+ case _ =>
151+ tp
152+ }
153+ case _ => tp
154+ }
155+
135156 (ref.symbol isAccessibleFrom ref.prefix) && {
136157 if (discard) {
137158 record(" discarded eligible" )
138159 false
139160 }
140161 else {
141162 val ptNorm = normalize(pt, pt) // `pt` could be implicit function types, check i2749
142- NoViewsAllowed .isCompatible(normalize(ref, pt), ptNorm)
163+ val refAdjusted =
164+ if (pt.isInstanceOf [ViewProto ]) adjustSingletonArg(ref.widenSingleton)
165+ else ref
166+ val refNorm = normalize(refAdjusted, pt)
167+ NoViewsAllowed .isCompatible(refNorm, ptNorm)
143168 }
144169 }
145170 }
0 commit comments