aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-03-09 18:34:31 +0100
committerMartin Odersky <odersky@gmail.com>2016-03-09 18:35:03 +0100
commit7dfab5f427ad9600b8e54b61716461787d7fa4a1 (patch)
treebe29d0130d3c2d549993606d7e563b8c5621769e /src
parentf63110edc7ab8299ef1cd33b2b156e7987e35931 (diff)
downloaddotty-7dfab5f427ad9600b8e54b61716461787d7fa4a1.tar.gz
dotty-7dfab5f427ad9600b8e54b61716461787d7fa4a1.tar.bz2
dotty-7dfab5f427ad9600b8e54b61716461787d7fa4a1.zip
Refine pretypeArgs
It worked more or less by accident before. Now it's more complicated, but we also have tests.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala29
1 files changed, 25 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index b3a71408b..d655b25f6 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -1151,9 +1151,30 @@ trait Applications extends Compatibility { self: Typer =>
}
arg match {
case arg: untpd.Function if arg.args.exists(isUnknownParamType) =>
- val commonFormal = altFormals.map(_.head).reduceLeft(_ | _)
- overload.println(i"pretype arg $arg with expected type $commonFormal")
- pt.typedArg(arg, commonFormal)
+ def isUniform[T](xs: List[T])(p: (T, T) => Boolean) = xs.forall(p(_, xs.head))
+ val formalsForArg: List[Type] = altFormals.map(_.head)
+ // For alternatives alt_1, ..., alt_n, test whether formal types for current argument are of the form
+ // (p_1_1, ..., p_m_1) => r_1
+ // ...
+ // (p_1_n, ..., p_m_n) => r_n
+ val decomposedFormalsForArg: List[Option[(List[Type], Type)]] =
+ formalsForArg.map(defn.FunctionOf.unapply)
+ if (decomposedFormalsForArg.forall(_.isDefined)) {
+ val formalParamTypessForArg: List[List[Type]] =
+ decomposedFormalsForArg.map(_.get._1)
+ if (isUniform(formalParamTypessForArg)((x, y) => x.length == y.length)) {
+ val commonParamTypes = formalParamTypessForArg.transpose.map(ps =>
+ // Given definitions above, for i = 1,...,m,
+ // ps(i) = List(p_i_1, ..., p_i_n) -- i.e. a column
+ // If all p_i_k's are the same, assume the type as formal parameter
+ // type of the i'th parameter of the closure.
+ if (isUniform(ps)(ctx.typeComparer.isSameTypeWhenFrozen(_, _))) ps.head
+ else WildcardType)
+ val commonFormal = defn.FunctionOf(commonParamTypes, WildcardType)
+ overload.println(i"pretype arg $arg with expected type $commonFormal")
+ pt.typedArg(arg, commonFormal)
+ }
+ }
case _ =>
}
recur(altFormals.map(_.tail), args1)
@@ -1161,7 +1182,7 @@ trait Applications extends Compatibility { self: Typer =>
}
def paramTypes(alt: Type): List[Type] = alt match {
case mt: MethodType => mt.paramTypes
- case mt: PolyType => paramTypes(mt.resultType).map(wildApprox(_))
+ case mt: PolyType => paramTypes(mt.resultType)
case _ => Nil
}
recur(alts.map(alt => paramTypes(alt.widen)), pt.args)