diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 48653ad96197..22eeee83be69 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1756,8 +1756,12 @@ object Parsers { if in.token == LBRACE || in.token == INDENT then t else - if sourceVersion.isAtLeast(future) then - deprecationWarning(DeprecatedWithOperator(), withOffset) + report.errorOrMigrationWarning( + DeprecatedWithOperator(rewriteNotice(`future-migration`)), + in.sourcePos(withOffset), + from = future) + if sourceVersion == `future-migration` then + patch(source, Span(withOffset, withOffset + 4), "&") atSpan(startOffset(t)) { makeAndType(t, withType()) } else t diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 3770d5f6f119..919b23cee8a2 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -138,10 +138,10 @@ extends EmptyCatchOrFinallyBlock(tryBody, EmptyCatchAndFinallyBlockID) { |its body in a block; no exceptions are handled.""" } -class DeprecatedWithOperator()(using Context) +class DeprecatedWithOperator(rewrite: String)(using Context) extends SyntaxMsg(DeprecatedWithOperatorID) { def msg(using Context) = - i"""${hl("with")} as a type operator has been deprecated; use ${hl("&")} instead""" + i"""${hl("with")} as a type operator has been deprecated; use ${hl("&")} instead$rewrite""" def explain(using Context) = i"""|Dotty introduces intersection types - ${hl("&")} types. These replace the |use of the ${hl("with")} keyword. There are a few differences in diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 2acb71ce62a8..798e998ef241 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -60,6 +60,7 @@ class CompilationTests { compileFile("tests/rewrites/rewrites.scala", defaultOptions.and("-source", "3.0-migration").and("-rewrite", "-indent")), compileFile("tests/rewrites/rewrites3x.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/rewrites3x-fatal-warnings.scala", defaultOptions.and("-rewrite", "-source", "future-migration", "-Xfatal-warnings")), + compileFile("tests/rewrites/with-type-operator.scala", defaultOptions.and("-rewrite", "-source", "future-migration")), compileFile("tests/rewrites/filtering-fors.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")), compileFile("tests/rewrites/refutable-pattern-bindings.scala", defaultOptions.and("-rewrite", "-source", "3.2-migration")), compileFile("tests/rewrites/i8982.scala", defaultOptions.and("-indent", "-rewrite")), diff --git a/tests/neg/with-type-operator-future-migration.check b/tests/neg/with-type-operator-future-migration.check new file mode 100644 index 000000000000..29ea1d5aad4c --- /dev/null +++ b/tests/neg/with-type-operator-future-migration.check @@ -0,0 +1,7 @@ +-- [E003] Syntax Error: tests/neg/with-type-operator-future-migration.scala:5:13 --------------------------------------- +5 |def foo: Int with String = ??? // error + | ^ + | with as a type operator has been deprecated; use & instead + | This construct can be rewritten automatically under -rewrite -source future-migration. + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/with-type-operator-future-migration.scala b/tests/neg/with-type-operator-future-migration.scala new file mode 100644 index 000000000000..3ed2e3a8f067 --- /dev/null +++ b/tests/neg/with-type-operator-future-migration.scala @@ -0,0 +1,5 @@ +//> using options -Werror + +import scala.language.`future-migration` + +def foo: Int with String = ??? // error diff --git a/tests/neg/with-type-operator-future.scala b/tests/neg/with-type-operator-future.scala new file mode 100644 index 000000000000..3f33ebde8708 --- /dev/null +++ b/tests/neg/with-type-operator-future.scala @@ -0,0 +1,3 @@ +import scala.language.`future` + +def foo: Int with String = ??? // error diff --git a/tests/pos/with-type-operator-future-migration.scala b/tests/pos/with-type-operator-future-migration.scala new file mode 100644 index 000000000000..d6fe5205fd3d --- /dev/null +++ b/tests/pos/with-type-operator-future-migration.scala @@ -0,0 +1,3 @@ +import scala.language.`future-migration` + +def foo: Int with String = ??? // warn diff --git a/tests/pos/with-type-operator.scala b/tests/pos/with-type-operator.scala new file mode 100644 index 000000000000..d1fa5e2c34b7 --- /dev/null +++ b/tests/pos/with-type-operator.scala @@ -0,0 +1,3 @@ +//> using options -Werror + +def foo: Int with String = ??? // warn diff --git a/tests/rewrites/with-type-operator.check b/tests/rewrites/with-type-operator.check new file mode 100644 index 000000000000..6d59e0eacb95 --- /dev/null +++ b/tests/rewrites/with-type-operator.check @@ -0,0 +1 @@ +def foo: Int & String = ??? diff --git a/tests/rewrites/with-type-operator.scala b/tests/rewrites/with-type-operator.scala new file mode 100644 index 000000000000..6dbd8ded14ee --- /dev/null +++ b/tests/rewrites/with-type-operator.scala @@ -0,0 +1 @@ +def foo: Int with String = ???