From 8d7b856a05e51b38b5a2b70572ea061482f085fe Mon Sep 17 00:00:00 2001 From: Vadim Chelyshov Date: Sun, 22 Aug 2021 14:41:12 +0300 Subject: [PATCH] Do not harmonize constant args if their type doesn't affect resType Fixes the following sample from #9939: ```scala scala> f"${3.14}%.2f rounds to ${3}%d" 1 |f"${3.14}%.2f rounds to ${3}%d" | ^ | type mismatch; | found : Double | required: Int | This location contains code that was inlined from rs$line$2:1 ``` At the moment when StringInterpolation transformation was performed instead of receiving `List(Constant(3.0), Constant(3))` arguments they were: `List(Constant(3.0), Constant(3.0))` (the second one was converted to double because of harmonization). That caused the reported type mismatch. In Scala2 harmonization doesn't happen if the resulting type is fully defined. For f-interp it shouldn't happen too as it's resulting type is a `String`: ```scala def f[A >: Any](args: A*): String = macro ??? ``` --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 5 ++++- tests/run-macros/f-interpolator-tests.check | 1 + tests/run-macros/f-interpolator-tests.scala | 1 + tests/run/i9939.check | 2 ++ tests/run/i9939.scala | 6 ++++++ 5 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/run/i9939.check create mode 100644 tests/run/i9939.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 008b96a4d174..9a83f9da4f02 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -744,7 +744,10 @@ trait Applications extends Compatibility { typedArgBuf += seqToRepeated(SeqLiteral(args, elemtpt)) } - def harmonizeArgs(args: List[TypedArg]): List[Tree] = harmonize(args) + def harmonizeArgs(args: List[TypedArg]): List[Tree] = + // harmonize args only if resType depends on parameter types + if (isFullyDefined(methodType.resType, ForceDegree.none)) args + else harmonize(args) override def appPos: SrcPos = app.srcPos diff --git a/tests/run-macros/f-interpolator-tests.check b/tests/run-macros/f-interpolator-tests.check index be5091b8ef39..4f2464fadae7 100644 --- a/tests/run-macros/f-interpolator-tests.check +++ b/tests/run-macros/f-interpolator-tests.check @@ -1,6 +1,7 @@ integer: 5 string: l 5, 6, hello +3.14 rounds to 3 5 6 Bob is 1 years old diff --git a/tests/run-macros/f-interpolator-tests.scala b/tests/run-macros/f-interpolator-tests.scala index ad712948a0d7..a50d22a4c022 100755 --- a/tests/run-macros/f-interpolator-tests.scala +++ b/tests/run-macros/f-interpolator-tests.scala @@ -10,6 +10,7 @@ object Test { println(f"integer: ${5}%d") println(f"string: ${"l"}%s") println(f"${5}%s, ${6}%d, ${"hello"}%s") + println(f"${3.14}%.2f rounds to ${3}%d") val x = 5 println(f"$x%d") diff --git a/tests/run/i9939.check b/tests/run/i9939.check new file mode 100644 index 000000000000..7040250edc75 --- /dev/null +++ b/tests/run/i9939.check @@ -0,0 +1,2 @@ +[3.0, 42] +[3.0, 42.0] diff --git a/tests/run/i9939.scala b/tests/run/i9939.scala new file mode 100644 index 000000000000..84ae5c2723c8 --- /dev/null +++ b/tests/run/i9939.scala @@ -0,0 +1,6 @@ +def nonHarmonized[A >: Any](args: A*): String = args.mkString("[", ", ", "]") +def harmonized[A >: Any](args: A*): List[A] = args.toList + +@main def Test = + println(nonHarmonized(3.0, 42)) + println(harmonized(3.0, 42).mkString("[", ", ", "]"))