Skip to content

Commit e70ea84

Browse files
authored
Fix insertion of using in applications with trailing lambda syntax (#22937)
Fixes #22731
2 parents f4847cc + b4a802a commit e70ea84

File tree

8 files changed

+159
-3
lines changed

8 files changed

+159
-3
lines changed

Diff for: compiler/src/dotty/tools/dotc/typer/Migrations.scala

+12-2
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,24 @@ trait Migrations:
130130
def implicitParams(tree: Tree, tp: MethodOrPoly, pt: FunProto)(using Context): Unit =
131131
val mversion = mv.ImplicitParamsWithoutUsing
132132
if tp.companion == ImplicitMethodType && pt.applyKind != ApplyKind.Using && pt.args.nonEmpty then
133-
val rewriteMsg = Message.rewriteNotice("This code", mversion.patchFrom)
133+
// The application can only be rewritten if it uses parentheses syntax.
134+
// See issue #22927 and related tests.
135+
val hasParentheses =
136+
ctx.source.content
137+
.slice(tree.span.end, pt.args.head.span.start)
138+
.exists(_ == '(')
139+
val rewriteMsg =
140+
if hasParentheses then
141+
Message.rewriteNotice("This code", mversion.patchFrom)
142+
else
143+
""
134144
report.errorOrMigrationWarning(
135145
em"""Implicit parameters should be provided with a `using` clause.$rewriteMsg
136146
|To disable the warning, please use the following option:
137147
| "-Wconf:msg=Implicit parameters should be provided with a `using` clause:s"
138148
|""",
139149
pt.args.head.srcPos, mversion)
140-
if mversion.needsPatch then
150+
if hasParentheses && mversion.needsPatch then
141151
patch(Span(pt.args.head.span.start), "using ")
142152
end implicitParams
143153

Diff for: compiler/test/dotty/tools/dotc/CompilationTests.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ class CompilationTests {
8383
compileFile("tests/rewrites/ambiguous-named-tuple-assignment.scala", defaultOptions.and("-rewrite", "-source:3.6-migration")),
8484
compileFile("tests/rewrites/i21382.scala", defaultOptions.and("-indent", "-rewrite")),
8585
compileFile("tests/rewrites/unused.scala", defaultOptions.and("-rewrite", "-Wunused:all")),
86-
compileFile("tests/rewrites/i22440.scala", defaultOptions.and("-rewrite"))
86+
compileFile("tests/rewrites/i22440.scala", defaultOptions.and("-rewrite")),
87+
compileFile("tests/rewrites/i22731.scala", defaultOptions.and("-rewrite", "-source:3.7-migration")),
88+
compileFile("tests/rewrites/i22731b.scala", defaultOptions.and("-rewrite", "-source:3.7-migration")),
8789
).checkRewrites()
8890
}
8991

Diff for: tests/rewrites/i22731.check

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Input(x: String)
2+
3+
trait Decoder[T]
4+
5+
object Decoder:
6+
inline def apply[T](implicit f: () => Unit): Decoder[T] = ???
7+
8+
object Input:
9+
given Decoder[Input] = Decoder { () =>
10+
Input("")
11+
}

Diff for: tests/rewrites/i22731.scala

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class Input(x: String)
2+
3+
trait Decoder[T]
4+
5+
object Decoder {
6+
inline def apply[T](implicit f: () => Unit): Decoder[T] = ???
7+
}
8+
9+
object Input {
10+
given Decoder[Input] = Decoder { () =>
11+
Input("")
12+
}
13+
}

Diff for: tests/rewrites/i22731b.check

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
def foo(implicit f: () => Unit): Unit = ???
2+
def bar(a: Int)(implicit f: () => Unit): Unit = ???
3+
4+
@main def main =
5+
// `using` can automatically be added when the application is done with parentheses
6+
foo ( using () => 43 )
7+
foo ( using () =>
8+
val x = 42
9+
43
10+
)
11+
foo( using () =>
12+
val x = 42
13+
43
14+
)
15+
foo (using () =>
16+
val x = 42
17+
43
18+
)
19+
bar(1) ( using () =>
20+
val x = 42
21+
43 )
22+
23+
// `using` cannot automatically be added when the application is done with trailing lambda syntax
24+
foo { () => 43 }
25+
foo { () => val x = 42; 43 }
26+
foo{ () => val x = 42; 43 }
27+
foo {() => val x = 42; 43}
28+
bar(1) { () =>
29+
val x = 42
30+
43 }
31+
foo: () =>
32+
43
33+
foo : () =>
34+
val x = 42
35+
43
36+
foo :() =>
37+
val x = 42
38+
43
39+
foo
40+
: () =>
41+
val x = 42
42+
43
43+
foo
44+
:
45+
() =>
46+
val x = 42
47+
43
48+
bar(1) : () =>
49+
val x = 42
50+
43

Diff for: tests/rewrites/i22731b.scala

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
def foo(implicit f: () => Unit): Unit = ???
2+
def bar(a: Int)(implicit f: () => Unit): Unit = ???
3+
4+
@main def main =
5+
// `using` can automatically be added when the application is done with parentheses
6+
foo ( () => 43 )
7+
foo ( () =>
8+
val x = 42
9+
43
10+
)
11+
foo( () =>
12+
val x = 42
13+
43
14+
)
15+
foo (() =>
16+
val x = 42
17+
43
18+
)
19+
bar(1) ( () =>
20+
val x = 42
21+
43 )
22+
23+
// `using` cannot automatically be added when the application is done with trailing lambda syntax
24+
foo { () => 43 }
25+
foo { () => val x = 42; 43 }
26+
foo{ () => val x = 42; 43 }
27+
foo {() => val x = 42; 43}
28+
bar(1) { () =>
29+
val x = 42
30+
43 }
31+
foo: () =>
32+
43
33+
foo : () =>
34+
val x = 42
35+
43
36+
foo :() =>
37+
val x = 42
38+
43
39+
foo
40+
: () =>
41+
val x = 42
42+
43
43+
foo
44+
:
45+
() =>
46+
val x = 42
47+
43
48+
bar(1) : () =>
49+
val x = 42
50+
43

Diff for: tests/warn/i22731.check

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- Warning: tests/warn/i22731.scala:5:11 -------------------------------------------------------------------------------
2+
5 | foo ( () => 43 ) // warn
3+
| ^^^^^^^^
4+
| Implicit parameters should be provided with a `using` clause.
5+
| This code can be rewritten automatically under -rewrite -source 3.7-migration.
6+
| To disable the warning, please use the following option:
7+
| "-Wconf:msg=Implicit parameters should be provided with a `using` clause:s"
8+
-- Warning: tests/warn/i22731.scala:7:6 --------------------------------------------------------------------------------
9+
7 | foo { () => 43 } // warn
10+
| ^^^^^^^^^^^^
11+
| Implicit parameters should be provided with a `using` clause.
12+
| To disable the warning, please use the following option:
13+
| "-Wconf:msg=Implicit parameters should be provided with a `using` clause:s"

Diff for: tests/warn/i22731.scala

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
def foo(implicit f: () => Unit): Unit = ???
2+
3+
@main def main =
4+
// `using` can automatically be added when the application is done with parentheses
5+
foo ( () => 43 ) // warn
6+
// `using` cannot automatically be added when the application is done with trailing lambda syntax
7+
foo { () => 43 } // warn

0 commit comments

Comments
 (0)