From d6cf0578a83cc0248fc69ff6fee7f1ce402aa0b5 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Tue, 21 Oct 2025 11:52:25 +0200 Subject: [PATCH] Deduplicate patches before applying them to sources (#24215) Fixes #24213 - deduplicate patches by content and span. Similar issues were spotted for code `using` rewrites resulting in invalid `using using` introduced by compiler. Issue might arise if some reason compiler typechecks the same code twice [Cherry-picked 2af74542b628e8e04d17e5d202f8258bd6417692] --- compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala | 4 ++-- compiler/test/dotty/tools/dotc/CompilationTests.scala | 1 + tests/rewrites/i24213.check | 5 +++++ tests/rewrites/i24213.scala | 5 +++++ 4 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/rewrites/i24213.check create mode 100644 tests/rewrites/i24213.scala diff --git a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index 272db26bdd3c..da6788901f0d 100644 --- a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala +++ b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala @@ -43,8 +43,8 @@ object Rewrites { pbuf.filterInPlace(x => !p(x.span)) def apply(cs: Array[Char]): Array[Char] = { - val delta = pbuf.map(_.delta).sum - val patches = pbuf.toList.sortBy(_.span.start) + val patches = pbuf.toList.distinct.sortBy(_.span.start) + val delta = patches.map(_.delta).sum if (patches.nonEmpty) patches.reduceLeft {(p1, p2) => assert(p1.span.end <= p2.span.start, s"overlapping patches in $source: $p1 and $p2") diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index de200a0f774a..cb8768a1cb81 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -89,6 +89,7 @@ class CompilationTests { compileFile("tests/rewrites/implicit-to-given.scala", defaultOptions.and("-rewrite", "-Yimplicit-to-given")), compileFile("tests/rewrites/i22792.scala", defaultOptions.and("-rewrite")), compileFile("tests/rewrites/i23449.scala", defaultOptions.and("-rewrite", "-source:3.4-migration")), + compileFile("tests/rewrites/i24213.scala", defaultOptions.and("-rewrite", "-source:3.4-migration")), ).checkRewrites() } diff --git a/tests/rewrites/i24213.check b/tests/rewrites/i24213.check new file mode 100644 index 000000000000..d06d2f63c7c2 --- /dev/null +++ b/tests/rewrites/i24213.check @@ -0,0 +1,5 @@ +def Test = + try () + catch { + case x: Throwable if x.getMessage `contains` "error" => ??? + } \ No newline at end of file diff --git a/tests/rewrites/i24213.scala b/tests/rewrites/i24213.scala new file mode 100644 index 000000000000..49148abace00 --- /dev/null +++ b/tests/rewrites/i24213.scala @@ -0,0 +1,5 @@ +def Test = + try () + catch { + case x: Throwable if x.getMessage contains "error" => ??? + } \ No newline at end of file