Skip to content

Commit 03a54a7

Browse files
authored
Rewrite underscore with optional space (#23525)
Fixes #23449 For the anomalous case where the usual space is missing, print the type bounds for the patch. This is not quite pretty printing, see the test of weird spaces inside the brackets.
2 parents 13fd5af + ae768dd commit 03a54a7

File tree

4 files changed

+40
-7
lines changed

4 files changed

+40
-7
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,15 +2006,19 @@ object Parsers {
20062006
Ident(tpnme.USCOREkw).withSpan(Span(start, in.lastOffset, start))
20072007
else
20082008
if !inMatchPattern then
2009-
report.errorOrMigrationWarning(
2010-
em"`_` is deprecated for wildcard arguments of types: use `?` instead${rewriteNotice(`3.4-migration`)}",
2011-
in.sourcePos(),
2012-
MigrationVersion.WildcardType)
2013-
if MigrationVersion.WildcardType.needsPatch then
2014-
patch(source, Span(in.offset, in.offset + 1), "?")
2015-
end if
2009+
val msg =
2010+
em"`_` is deprecated for wildcard arguments of types: use `?` instead${rewriteNotice(`3.4-migration`)}"
2011+
report.errorOrMigrationWarning(msg, in.sourcePos(), MigrationVersion.WildcardType)
20162012
val start = in.skipToken()
20172013
typeBounds().withSpan(Span(start, in.lastOffset, start))
2014+
.tap: tbt =>
2015+
if !inMatchPattern && MigrationVersion.WildcardType.needsPatch then
2016+
val offset_? = tbt.span.start
2017+
if Chars.isOperatorPart(source(offset_? + 1)) then
2018+
patch(source, tbt.span, "?" + ctx.printer.toText(tbt).mkString())
2019+
else
2020+
patch(source, Span(offset_?, offset_? + 1), "?")
2021+
20182022
// Allow symbols -_ and +_ through for compatibility with code written using kind-projector in Scala 3 underscore mode.
20192023
// While these signify variant type parameters in Scala 2 + kind-projector, we ignore their variance markers since variance is inferred.
20202024
else if (isIdent(nme.MINUS) || isIdent(nme.PLUS)) && in.lookahead.token == USCORE && ctx.settings.XkindProjector.value == "underscores" then

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class CompilationTests {
8888
compileFile("tests/rewrites/i22731b.scala", defaultOptions.and("-rewrite", "-source:3.7-migration")),
8989
compileFile("tests/rewrites/implicit-to-given.scala", defaultOptions.and("-rewrite", "-Yimplicit-to-given")),
9090
compileFile("tests/rewrites/i22792.scala", defaultOptions.and("-rewrite")),
91+
compileFile("tests/rewrites/i23449.scala", defaultOptions.and("-rewrite", "-source:3.4-migration")),
9192
).checkRewrites()
9293
}
9394

tests/rewrites/i23449.check

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
trait T
2+
class C[A]
3+
4+
def f(x: C[? <: T]) = ()
5+
6+
def g(x: C[? >: T]) = ()
7+
8+
def h(x: C[? <: T]) = ()
9+
10+
def k(x: C[? >: T]) = ()
11+
12+
def m(x: C[? >: Nothing <: T]) = ()
13+
14+
def n(x: C[ ? >: Nothing <: T ]) = ()

tests/rewrites/i23449.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
trait T
2+
class C[A]
3+
4+
def f(x: C[_<:T]) = ()
5+
6+
def g(x: C[_>:T]) = ()
7+
8+
def h(x: C[_<: T]) = ()
9+
10+
def k(x: C[_ >: T]) = ()
11+
12+
def m(x: C[_>:Nothing<:T]) = ()
13+
14+
def n(x: C[ _>:Nothing <:T ]) = ()

0 commit comments

Comments
 (0)