diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index 280cc40e944e..153037dfaf8f 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -56,9 +56,9 @@ object Implicits { case mt: MethodType => mt.isImplicit || mt.paramTypes.length != 1 || - !(argType relaxed_<:< wildApprox(mt.paramTypes.head)(ctx.fresh.setExploreTyperState)) + !(argType relaxed_<:< wildApprox(mt.paramTypes.head, poly)(ctx.fresh.setExploreTyperState)) case rtp => - discardForView(wildApprox(rtp), argType) + discardForView(wildApprox(rtp, poly), argType) } case tpw: TermRef => false // can't discard overloaded refs diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala index db196f0c2fbe..ae89fe0e4752 100644 --- a/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -391,7 +391,10 @@ object ProtoTypes { case tp: TypeAlias => // default case, inlined for speed tp.derivedTypeAlias(wildApprox(tp.alias, theMap)) case tp @ PolyParam(poly, pnum) => - ctx.typerState.constraint.entry(tp) match { + val constrOrInst = + if (theMap != null && (poly eq theMap.disregarded)) NoType + else ctx.typerState.constraint.entry(tp) + constrOrInst match { case bounds: TypeBounds => wildApprox(WildcardType(bounds)) case NoType => WildcardType(wildApprox(poly.paramBounds(pnum)).bounds) case inst => wildApprox(inst) @@ -426,7 +429,20 @@ object ProtoTypes { (if (theMap != null) theMap else new WildApproxMap).mapOver(tp) } - private[ProtoTypes] class WildApproxMap(implicit ctx: Context) extends TypeMap { + /** Like unary wildApprox, but assume that all parameters of `disregarded` are not + * bound in current constraint. This is necessary because an instance of + * the type of a polymorphic function might already be part of the current + * constraint when we try to check another occurrence of the same polymorphic + * function for eligibility. An example is in i1044.scala where one expression + * requires two implicit calls of the same refArrayOps method. When approximating + * the parameter types of such a method we should always map the type parameters of + * the method itself to wildcards, even though some of these parameters might still be + * bound in the constraint. + */ + final def wildApprox(tp: Type, disregarded: PolyType)(implicit ctx: Context): Type = + wildApprox(tp, new WildApproxMap(disregarded)) + + private[ProtoTypes] class WildApproxMap(val disregarded: Type = NoType)(implicit ctx: Context) extends TypeMap { def apply(tp: Type) = wildApprox(tp, this) } diff --git a/tests/pos/i1044.scala b/tests/pos/i1044.scala new file mode 100644 index 000000000000..a984dbd67449 --- /dev/null +++ b/tests/pos/i1044.scala @@ -0,0 +1,3 @@ +object Test { + val x = ???.getClass.getMethods.head.getParameterTypes.mkString(",") +}