From 534e4ad9f6ef1dfb767adc89c9544484cab4f48a Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 6 Feb 2016 00:51:20 +0100 Subject: [PATCH] Fix #1044: handle TypevarsMissContext mode in wildApprox When `wildApprox` encounters a PolyParam it approximates it by its bounds in the current constraint set, but this is incorrect if `TypevarsMissContext` is set, we might get the bounds of another use of this `PolyType`. This is exactly what happened in i1044.scala where the implicit view `refArrayOps` needs to be used twice with two different type parameters. The fix is to approximate a PolyParam by its original bounds in its PolyType if `TypevarsMissContext` is set. This fix was inspired by the approach of #1054. --- src/dotty/tools/dotc/typer/Implicits.scala | 2 ++ src/dotty/tools/dotc/typer/ProtoTypes.scala | 14 +++++++++----- tests/pos/i1044.scala | 3 +++ 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 tests/pos/i1044.scala diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index 280cc40e944e..6cb1f1271fce 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -52,6 +52,8 @@ object Implicits { mt.paramTypes.length != 1 || !(argType relaxed_<:< mt.paramTypes.head)(ctx.fresh.setExploreTyperState) case poly: PolyType => + // We do not need to call ProtoTypes#constrained on `poly` because + // `refMatches` is always called with mode TypevarsMissContext enabled. poly.resultType match { case mt: MethodType => mt.isImplicit || diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala index db196f0c2fbe..8a758bcc82e2 100644 --- a/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -391,11 +391,15 @@ 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 { - case bounds: TypeBounds => wildApprox(WildcardType(bounds)) - case NoType => WildcardType(wildApprox(poly.paramBounds(pnum)).bounds) - case inst => wildApprox(inst) - } + def unconstrainedApprox = WildcardType(wildApprox(poly.paramBounds(pnum)).bounds) + if (ctx.mode.is(Mode.TypevarsMissContext)) + unconstrainedApprox + else + ctx.typerState.constraint.entry(tp) match { + case bounds: TypeBounds => wildApprox(WildcardType(bounds)) + case NoType => unconstrainedApprox + case inst => wildApprox(inst) + } case MethodParam(mt, pnum) => WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum)))) case tp: TypeVar => 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(",") +}