From 35b05c54ec26552f4f333dfb65edb6220c2fcac6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Oct 2019 13:00:51 +0200 Subject: [PATCH 1/3] Fix #7392: Interpolate all wildcards in the result prototype of a closure Make sure we interpolate all wildcards in the prototype before making it the result type of an anonymous function. This was done previously only for toplevel wildcards, but not for wildcards nested in some type. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 9 +++++++-- tests/pos/i7392.scala | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i7392.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 66845e343f7f..3685560df417 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -833,12 +833,18 @@ class Typer extends Namer case _: WildcardType => untpd.TypeTree() case _ => untpd.TypeTree(tp) } + def interpolateWildcards = new ApproximatingTypeMap { + def apply(t: Type) = t match + case WildcardType => emptyRange + case WildcardType(bounds: TypeBounds) => range(bounds.lo, bounds.hi) + case _ => mapOver(t) + } pt.stripTypeVar.dealias match { case pt1 if defn.isNonRefinedFunction(pt1) => // if expected parameter type(s) are wildcards, approximate from below. // if expected result type is a wildcard, approximate from above. // this can type the greatest set of admissible closures. - (pt1.argTypesLo.init, typeTree(pt1.argTypesHi.last)) + (pt1.argTypesLo.init, typeTree(interpolateWildcards(pt1.argTypesHi.last))) case SAMType(sam @ MethodTpe(_, formals, restpe)) => (formals, if (sam.isResultDependent) @@ -1900,7 +1906,6 @@ class Typer extends Namer else tree1 } - def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(implicit ctx: Context): Tree = { val untpd.PostfixOp(qual, Ident(nme.WILDCARD)) = tree val pt1 = if (defn.isFunctionType(pt)) pt else AnyFunctionProto diff --git a/tests/pos/i7392.scala b/tests/pos/i7392.scala new file mode 100644 index 000000000000..579e4422d2f7 --- /dev/null +++ b/tests/pos/i7392.scala @@ -0,0 +1,16 @@ +object Test { + + trait ZStream[-R, +E, +A] + + object ZStream { + def empty: ZStream[Any, Nothing, Nothing] = + ??? + } + + trait Gen[-R, +A](sample: ZStream[R, Nothing, A]) + + def fromIterable[R, A]( + as: Iterable[A], + shrinker: (A => ZStream[R, Nothing, A]) = (_: A) => ZStream.empty + ): Gen[R, A] = ??? +} \ No newline at end of file From 4cf3a1a5a161dd665eda161f1879ff2eb67f106d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Oct 2019 14:46:08 +0200 Subject: [PATCH 2/3] Replace wildcard types by TypeVars in decomposeProto Approximating wildcard types loses too much information. it's better to replace them by fresh typevars instead. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 3685560df417..39357aa87029 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -833,10 +833,10 @@ class Typer extends Namer case _: WildcardType => untpd.TypeTree() case _ => untpd.TypeTree(tp) } - def interpolateWildcards = new ApproximatingTypeMap { + def interpolateWildcards = new TypeMap { def apply(t: Type) = t match - case WildcardType => emptyRange - case WildcardType(bounds: TypeBounds) => range(bounds.lo, bounds.hi) + case WildcardType => newTypeVar(TypeBounds.empty) + case WildcardType(bounds: TypeBounds) => newTypeVar(bounds) case _ => mapOver(t) } pt.stripTypeVar.dealias match { From 4800aec152cc86deaac48a339f7b639d24e6eb2f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 9 Oct 2019 16:37:57 +0200 Subject: [PATCH 3/3] Recursively interpolate bounds in interpolateWildcards --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 39357aa87029..b49418661261 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -834,9 +834,9 @@ class Typer extends Namer case _ => untpd.TypeTree(tp) } def interpolateWildcards = new TypeMap { - def apply(t: Type) = t match - case WildcardType => newTypeVar(TypeBounds.empty) - case WildcardType(bounds: TypeBounds) => newTypeVar(bounds) + def apply(t: Type): Type = t match + case WildcardType(bounds: TypeBounds) => + newTypeVar(apply(bounds.orElse(TypeBounds.empty)).bounds) case _ => mapOver(t) } pt.stripTypeVar.dealias match {