diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index e4314b27a32c..2581c3d546a7 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2007,15 +2007,19 @@ object Parsers { Ident(tpnme.USCOREkw).withSpan(Span(start, in.lastOffset, start)) else if !inMatchPattern then - report.errorOrMigrationWarning( - em"`_` is deprecated for wildcard arguments of types: use `?` instead${rewriteNotice(`3.4-migration`)}", - in.sourcePos(), - MigrationVersion.WildcardType) - if MigrationVersion.WildcardType.needsPatch then - patch(source, Span(in.offset, in.offset + 1), "?") - end if + val msg = + em"`_` is deprecated for wildcard arguments of types: use `?` instead${rewriteNotice(`3.4-migration`)}" + report.errorOrMigrationWarning(msg, in.sourcePos(), MigrationVersion.WildcardType) val start = in.skipToken() typeBounds().withSpan(Span(start, in.lastOffset, start)) + .tap: tbt => + if !inMatchPattern && MigrationVersion.WildcardType.needsPatch then + val offset_? = tbt.span.start + if Chars.isOperatorPart(source(offset_? + 1)) then + patch(source, tbt.span, "?" + ctx.printer.toText(tbt).mkString()) + else + patch(source, Span(offset_?, offset_? + 1), "?") + // Allow symbols -_ and +_ through for compatibility with code written using kind-projector in Scala 3 underscore mode. // While these signify variant type parameters in Scala 2 + kind-projector, we ignore their variance markers since variance is inferred. else if (isIdent(nme.MINUS) || isIdent(nme.PLUS)) && in.lookahead.token == USCORE && ctx.settings.XkindProjector.value == "underscores" then diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 6c763dbdbd65..8ccfa43b1d41 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -88,6 +88,7 @@ class CompilationTests { compileFile("tests/rewrites/i22731b.scala", defaultOptions.and("-rewrite", "-source:3.7-migration")), 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")), ).checkRewrites() } diff --git a/tests/rewrites/i23449.check b/tests/rewrites/i23449.check new file mode 100644 index 000000000000..4c7476003ffe --- /dev/null +++ b/tests/rewrites/i23449.check @@ -0,0 +1,14 @@ +trait T +class C[A] + +def f(x: C[? <: T]) = () + +def g(x: C[? >: T]) = () + +def h(x: C[? <: T]) = () + +def k(x: C[? >: T]) = () + +def m(x: C[? >: Nothing <: T]) = () + +def n(x: C[ ? >: Nothing <: T ]) = () diff --git a/tests/rewrites/i23449.scala b/tests/rewrites/i23449.scala new file mode 100644 index 000000000000..64a29d7ea35c --- /dev/null +++ b/tests/rewrites/i23449.scala @@ -0,0 +1,14 @@ +trait T +class C[A] + +def f(x: C[_<:T]) = () + +def g(x: C[_>:T]) = () + +def h(x: C[_<: T]) = () + +def k(x: C[_ >: T]) = () + +def m(x: C[_>:Nothing<:T]) = () + +def n(x: C[ _>:Nothing <:T ]) = ()