aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Applications.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/typer/Applications.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala47
1 files changed, 35 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index e1d3d243d..dadd2afdc 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -127,6 +127,9 @@ trait Applications extends Compatibility { self: Typer =>
*/
protected def makeVarArg(n: Int, elemFormal: Type): Unit
+ /** If all `args` have primitive numeric types, make sure it's the same one */
+ protected def harmonizeArgs(args: List[TypedArg]): List[TypedArg]
+
/** Signal failure with given message at position of given argument */
protected def fail(msg: => String, arg: Arg): Unit
@@ -334,7 +337,14 @@ trait Applications extends Compatibility { self: Typer =>
addTyped(arg, formal)
case _ =>
val elemFormal = formal.widenExpr.argTypesLo.head
- args foreach (addTyped(_, elemFormal))
+ val origConstraint = ctx.typerState.constraint
+ var typedArgs = args.map(typedArg(_, elemFormal))
+ val harmonizedArgs = harmonizeArgs(typedArgs)
+ if (harmonizedArgs ne typedArgs) {
+ ctx.typerState.constraint = origConstraint
+ typedArgs = harmonizedArgs
+ }
+ typedArgs.foreach(addArg(_, elemFormal))
makeVarArg(args.length, elemFormal)
}
else args match {
@@ -389,6 +399,7 @@ trait Applications extends Compatibility { self: Typer =>
def argType(arg: Tree, formal: Type): Type = normalize(arg.tpe, formal)
def treeToArg(arg: Tree): Tree = arg
def isVarArg(arg: Tree): Boolean = tpd.isWildcardStarArg(arg)
+ def harmonizeArgs(args: List[Tree]) = harmonize(args)
}
/** Subclass of Application for applicability tests with type arguments and value
@@ -405,6 +416,7 @@ trait Applications extends Compatibility { self: Typer =>
def argType(arg: Type, formal: Type): Type = arg
def treeToArg(arg: Tree): Type = arg.tpe
def isVarArg(arg: Type): Boolean = arg.isRepeatedParam
+ def harmonizeArgs(args: List[Type]) = harmonizeTypes(args)
}
/** Subclass of Application for type checking an Apply node, where
@@ -430,6 +442,8 @@ trait Applications extends Compatibility { self: Typer =>
typedArgBuf += seqToRepeated(seqLit)
}
+ def harmonizeArgs(args: List[TypedArg]) = harmonize(args)
+
override def appPos = app.pos
def fail(msg: => String, arg: Trees.Tree[T]) = {
@@ -1025,25 +1039,34 @@ trait Applications extends Compatibility { self: Typer =>
}
}
- def harmonize(trees: List[Tree])(implicit ctx: Context): List[Tree] = {
- def numericClasses(trees: List[Tree], acc: Set[Symbol]): Set[Symbol] = trees match {
- case tree :: trees1 =>
- val sym = tree.tpe.typeSymbol
- if (sym.isNumericValueClass && tree.tpe.isRef(sym))
- numericClasses(trees1, acc + sym)
- else
- Set()
+ private def harmonizeWith[T <: AnyRef](ts: List[T])(tpe: T => Type, adapt: (T, Type) => T)(implicit ctx: Context): List[T] = {
+ def numericClasses(ts: List[T], acc: Set[Symbol]): Set[Symbol] = ts match {
+ case t :: ts1 =>
+ val sym = tpe(t).widen.classSymbol
+ if (sym.isNumericValueClass) numericClasses(ts1, acc + sym)
+ else Set()
case Nil =>
acc
}
- val clss = numericClasses(trees, Set())
+ val clss = numericClasses(ts, Set())
if (clss.size > 1) {
val lub = defn.ScalaNumericValueClassList.find(lubCls =>
clss.forall(defn.isValueSubClass(_, lubCls))).get.typeRef
- trees.mapConserve(tree => adaptInterpolated(tree, lub, tree))
+ ts.mapConserve(adapt(_, lub))
}
- else trees
+ else ts
}
+
+ def harmonize(trees: List[Tree])(implicit ctx: Context): List[Tree] = {
+ def adapt(tree: Tree, pt: Type): Tree = tree match {
+ case cdef: CaseDef => tpd.cpy.CaseDef(cdef)(body = adapt(cdef.body, pt))
+ case _ => adaptInterpolated(tree, pt, tree)
+ }
+ harmonizeWith(trees)(_.tpe, adapt)
+ }
+
+ def harmonizeTypes(tpes: List[Type])(implicit ctx: Context): List[Type] =
+ harmonizeWith(tpes)(identity, (tp, pt) => pt)
}
/*