diff --git a/compiler/src/dotty/tools/dotc/typer/Migrations.scala b/compiler/src/dotty/tools/dotc/typer/Migrations.scala index 0e6dc27ecf7f..acf9e7668917 100644 --- a/compiler/src/dotty/tools/dotc/typer/Migrations.scala +++ b/compiler/src/dotty/tools/dotc/typer/Migrations.scala @@ -130,14 +130,24 @@ trait Migrations: def implicitParams(tree: Tree, tp: MethodOrPoly, pt: FunProto)(using Context): Unit = val mversion = mv.ImplicitParamsWithoutUsing if tp.companion == ImplicitMethodType && pt.applyKind != ApplyKind.Using && pt.args.nonEmpty then - val rewriteMsg = Message.rewriteNotice("This code", mversion.patchFrom) + // The application can only be rewritten if it uses parentheses syntax. + // See issue #22927 and related tests. + val hasParentheses = + ctx.source.content + .slice(tree.span.end, pt.args.head.span.start) + .exists(_ == '(') + val rewriteMsg = + if hasParentheses then + Message.rewriteNotice("This code", mversion.patchFrom) + else + "" report.errorOrMigrationWarning( em"""Implicit parameters should be provided with a `using` clause.$rewriteMsg |To disable the warning, please use the following option: | "-Wconf:msg=Implicit parameters should be provided with a `using` clause:s" |""", pt.args.head.srcPos, mversion) - if mversion.needsPatch then + if hasParentheses && mversion.needsPatch then patch(Span(pt.args.head.span.start), "using ") end implicitParams diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 47ed2aa6564d..2d6d78f47916 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -88,7 +88,9 @@ class CompilationTests { compileFile("tests/rewrites/ambiguous-named-tuple-assignment.scala", defaultOptions.and("-rewrite", "-source:3.6-migration")), compileFile("tests/rewrites/i21382.scala", defaultOptions.and("-indent", "-rewrite")), compileFile("tests/rewrites/unused.scala", defaultOptions.and("-rewrite", "-Wunused:all")), - compileFile("tests/rewrites/i22440.scala", defaultOptions.and("-rewrite")) + compileFile("tests/rewrites/i22440.scala", defaultOptions.and("-rewrite")), + compileFile("tests/rewrites/i22731.scala", defaultOptions.and("-rewrite", "-source:3.7-migration")), + compileFile("tests/rewrites/i22731b.scala", defaultOptions.and("-rewrite", "-source:3.7-migration")), ).checkRewrites() } diff --git a/tests/rewrites/i22731.check b/tests/rewrites/i22731.check new file mode 100644 index 000000000000..366abac7f062 --- /dev/null +++ b/tests/rewrites/i22731.check @@ -0,0 +1,11 @@ +class Input(x: String) + +trait Decoder[T] + +object Decoder: + inline def apply[T](implicit f: () => Unit): Decoder[T] = ??? + +object Input: + given Decoder[Input] = Decoder { () => + Input("") + } diff --git a/tests/rewrites/i22731.scala b/tests/rewrites/i22731.scala new file mode 100644 index 000000000000..fbc23404bb8e --- /dev/null +++ b/tests/rewrites/i22731.scala @@ -0,0 +1,13 @@ +class Input(x: String) + +trait Decoder[T] + +object Decoder { + inline def apply[T](implicit f: () => Unit): Decoder[T] = ??? +} + +object Input { + given Decoder[Input] = Decoder { () => + Input("") + } +} diff --git a/tests/rewrites/i22731b.check b/tests/rewrites/i22731b.check new file mode 100644 index 000000000000..ae3c4660dc10 --- /dev/null +++ b/tests/rewrites/i22731b.check @@ -0,0 +1,50 @@ +def foo(implicit f: () => Unit): Unit = ??? +def bar(a: Int)(implicit f: () => Unit): Unit = ??? + +@main def main = + // `using` can automatically be added when the application is done with parentheses + foo ( using () => 43 ) + foo ( using () => + val x = 42 + 43 + ) + foo( using () => + val x = 42 + 43 + ) + foo (using () => + val x = 42 + 43 + ) + bar(1) ( using () => + val x = 42 + 43 ) + + // `using` cannot automatically be added when the application is done with trailing lambda syntax + foo { () => 43 } + foo { () => val x = 42; 43 } + foo{ () => val x = 42; 43 } + foo {() => val x = 42; 43} + bar(1) { () => + val x = 42 + 43 } + foo: () => + 43 + foo : () => + val x = 42 + 43 + foo :() => + val x = 42 + 43 + foo + : () => + val x = 42 + 43 + foo + : + () => + val x = 42 + 43 + bar(1) : () => + val x = 42 + 43 diff --git a/tests/rewrites/i22731b.scala b/tests/rewrites/i22731b.scala new file mode 100644 index 000000000000..cd9de61fd719 --- /dev/null +++ b/tests/rewrites/i22731b.scala @@ -0,0 +1,50 @@ +def foo(implicit f: () => Unit): Unit = ??? +def bar(a: Int)(implicit f: () => Unit): Unit = ??? + +@main def main = + // `using` can automatically be added when the application is done with parentheses + foo ( () => 43 ) + foo ( () => + val x = 42 + 43 + ) + foo( () => + val x = 42 + 43 + ) + foo (() => + val x = 42 + 43 + ) + bar(1) ( () => + val x = 42 + 43 ) + + // `using` cannot automatically be added when the application is done with trailing lambda syntax + foo { () => 43 } + foo { () => val x = 42; 43 } + foo{ () => val x = 42; 43 } + foo {() => val x = 42; 43} + bar(1) { () => + val x = 42 + 43 } + foo: () => + 43 + foo : () => + val x = 42 + 43 + foo :() => + val x = 42 + 43 + foo + : () => + val x = 42 + 43 + foo + : + () => + val x = 42 + 43 + bar(1) : () => + val x = 42 + 43 diff --git a/tests/warn/i22731.check b/tests/warn/i22731.check new file mode 100644 index 000000000000..f7b25eb3b384 --- /dev/null +++ b/tests/warn/i22731.check @@ -0,0 +1,13 @@ +-- Warning: tests/warn/i22731.scala:5:11 ------------------------------------------------------------------------------- +5 | foo ( () => 43 ) // warn + | ^^^^^^^^ + | Implicit parameters should be provided with a `using` clause. + | This code can be rewritten automatically under -rewrite -source 3.7-migration. + | To disable the warning, please use the following option: + | "-Wconf:msg=Implicit parameters should be provided with a `using` clause:s" +-- Warning: tests/warn/i22731.scala:7:6 -------------------------------------------------------------------------------- +7 | foo { () => 43 } // warn + | ^^^^^^^^^^^^ + | Implicit parameters should be provided with a `using` clause. + | To disable the warning, please use the following option: + | "-Wconf:msg=Implicit parameters should be provided with a `using` clause:s" diff --git a/tests/warn/i22731.scala b/tests/warn/i22731.scala new file mode 100644 index 000000000000..388bbc8448b3 --- /dev/null +++ b/tests/warn/i22731.scala @@ -0,0 +1,7 @@ +def foo(implicit f: () => Unit): Unit = ??? + +@main def main = + // `using` can automatically be added when the application is done with parentheses + foo ( () => 43 ) // warn + // `using` cannot automatically be added when the application is done with trailing lambda syntax + foo { () => 43 } // warn