Skip to content

Commit 3fd727d

Browse files
committed
Under -source future, warn if old given and context bound syntax is used
1 parent 14acdc0 commit 3fd727d

11 files changed

+83
-9
lines changed

compiler/src/dotty/tools/dotc/config/MigrationVersion.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum MigrationVersion(val warnFrom: SourceVersion, val errorFrom: SourceVersion)
3030
case ImportRename extends MigrationVersion(future, future)
3131
case ParameterEnclosedByParenthesis extends MigrationVersion(future, future)
3232
case XmlLiteral extends MigrationVersion(future, future)
33+
case GivenSyntax extends MigrationVersion(future, never)
3334

3435
require(warnFrom.ordinal <= errorFrom.ordinal)
3536

compiler/src/dotty/tools/dotc/config/SourceVersion.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ enum SourceVersion:
1616
// !!! Keep in sync with scala.runtime.stdlibPatches.language !!!
1717
case `future-migration`, `future`
1818

19+
case `never` // needed for MigrationVersion.errorFrom if we never want to issue an error
20+
1921
val isMigrating: Boolean = toString.endsWith("-migration")
2022

2123
def stable: SourceVersion =

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2240,7 +2240,16 @@ object Parsers {
22402240
in.nextToken()
22412241
if in.token == LBRACE && sourceVersion.isAtLeast(`3.6`)
22422242
then inBraces(commaSeparated(() => contextBound(pname)))
2243-
else contextBound(pname) :: contextBounds(pname)
2243+
else
2244+
val bound = contextBound(pname)
2245+
val rest =
2246+
if in.isColon then
2247+
report.errorOrMigrationWarning(
2248+
em"Multiple context bounds should be enclosed in `{ ... }`",
2249+
in.sourcePos(), MigrationVersion.GivenSyntax)
2250+
contextBounds(pname)
2251+
else Nil
2252+
bound :: rest
22442253
else if in.token == VIEWBOUND then
22452254
report.errorOrMigrationWarning(
22462255
em"view bounds `<%' are no longer supported, use a context bound `:' instead",
@@ -4261,6 +4270,9 @@ object Parsers {
42614270
in.nextToken()
42624271
newSignature()
42634272
else if hasEmbeddedColon then
4273+
report.errorOrMigrationWarning(
4274+
em"This old given syntax is no longer supported; use `=>` instead of `:`",
4275+
in.sourcePos(), MigrationVersion.GivenSyntax)
42644276
newSyntaxAllowed = false
42654277
val tparamsOld = typeParamClauseOpt(ParamOwner.Given)
42664278
newLineOpt()
@@ -4294,6 +4306,11 @@ object Parsers {
42944306
// old-style abstract given
42954307
if name.isEmpty then
42964308
syntaxError(em"Anonymous given cannot be abstract, or maybe you want to define a concrete given and are missing a `()` argument?", in.lastOffset)
4309+
if newSyntaxAllowed then
4310+
report.errorOrMigrationWarning(
4311+
em"""This defines an abstract given, which is no longer supported. Use a `deferred` given instead.
4312+
|Or, if you intend to define a concrete given, follow the type with `()` arguments.""",
4313+
in.sourcePos(in.lastOffset), MigrationVersion.GivenSyntax)
42974314
DefDef(name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree)
42984315
else
42994316
// structural instance
@@ -4483,6 +4500,9 @@ object Parsers {
44834500

44844501
/** with Template, with EOL <indent> interpreted */
44854502
def withTemplate(constr: DefDef, parents: List[Tree]): Template =
4503+
report.errorOrMigrationWarning(
4504+
em"Given member definitions starting with `with` are no longer supported; use `{...}` or `:` followed by newline instead",
4505+
in.sourcePos(), MigrationVersion.GivenSyntax)
44864506
accept(WITH)
44874507
val (self, stats) = templateBody(parents, rewriteWithColon = false)
44884508
Template(constr, parents, Nil, self, stats)

tests/neg/context-bounds-migration-future.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
| method foo does not take more parameters
55
|
66
| longer explanation available when compiling with `-explain`
7+
-- Warning: tests/neg/context-bounds-migration-future.scala:6:6 --------------------------------------------------------
8+
6 |given [T]: C[T] = C[T]()
9+
| ^
10+
| This old given syntax is no longer supported; use `=>` instead of `:`

tests/neg/infix.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class C:
88
def +(x: Int): Int = ???
99

1010
object C:
11-
given AnyRef with
11+
given AnyRef:
1212
extension (x: C)
1313
infix def iop (y: Int) = ???
1414
def mop (y: Int) = ???

tests/neg/tracked.check

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
17 | tracked type T = Int // error // error
2323
| ^^^^
2424
| end of statement expected but 'type' found
25-
-- Error: tests/neg/tracked.scala:20:29 --------------------------------------------------------------------------------
26-
20 | given g2(using tracked val x: Int): C = C(x) // error
27-
| ^^^^^^^^^^^^^^^^^^
28-
| method parameter x may not be a `val`
25+
-- Error: tests/neg/tracked.scala:20:25 --------------------------------------------------------------------------------
26+
20 | given g2: (tracked val x: Int) => C = C(x) // error
27+
| ^^^^^^^^^^^^^^^^^^
28+
| method parameter x may not be a `val`
2929
-- Error: tests/neg/tracked.scala:4:21 ---------------------------------------------------------------------------------
3030
4 |class C2(tracked var x: Int) // error
3131
| ^

tests/neg/tracked.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ object D:
1717
tracked type T = Int // error // error
1818

1919
object E:
20-
given g2(using tracked val x: Int): C = C(x) // error
20+
given g2: (tracked val x: Int) => C = C(x) // error

tests/warn/abstract-givens-new.check

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
1+
-- Warning: tests/warn/abstract-givens-new.scala:7:22 ------------------------------------------------------------------
2+
7 | given intC: Int is C // warn
3+
| ^
4+
| This defines an abstract given, which is no longer supported. Use a `deferred` given instead.
5+
| Or, if you intend to define a concrete given, follow the type with `()` arguments.

tests/warn/abstract-givens-new.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class C:
44

55
trait T:
66
given Int is C // ok
7-
given intC: Int is C // ok for now, will be warning
7+
given intC: Int is C // warn
88
given intC2: (Int is C)() // ok
99
given intC3: Int is C {} // also ok
1010

tests/warn/old-givens.check

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-- Warning: tests/warn/old-givens.scala:8:20 ---------------------------------------------------------------------------
2+
8 | given intC: C[Int] // warn
3+
| ^
4+
| This defines an abstract given, which is no longer supported. Use a `deferred` given instead.
5+
| Or, if you intend to define a concrete given, follow the type with `()` arguments.
6+
-- Warning: tests/warn/old-givens.scala:11:8 ---------------------------------------------------------------------------
7+
11 | given [T]: Ord[T] with // warn // warn
8+
| ^
9+
| This old given syntax is no longer supported; use `=>` instead of `:`
10+
-- Warning: tests/warn/old-givens.scala:11:20 --------------------------------------------------------------------------
11+
11 | given [T]: Ord[T] with // warn // warn
12+
| ^
13+
|Given member definitions starting with `with` are no longer supported; use `{...}` or `:` followed by newline instead
14+
-- Warning: tests/warn/old-givens.scala:14:8 ---------------------------------------------------------------------------
15+
14 | given [T](using Ord[T]): Ord[List[T]] with // warn // warn
16+
| ^
17+
| This old given syntax is no longer supported; use `=>` instead of `:`
18+
-- Warning: tests/warn/old-givens.scala:14:40 --------------------------------------------------------------------------
19+
14 | given [T](using Ord[T]): Ord[List[T]] with // warn // warn
20+
| ^
21+
|Given member definitions starting with `with` are no longer supported; use `{...}` or `:` followed by newline instead
22+
-- Warning: tests/warn/old-givens.scala:17:15 --------------------------------------------------------------------------
23+
17 | def f[T: Ord : C]() = ??? // warn
24+
| ^
25+
| Multiple context bounds should be enclosed in `{ ... }`

tests/warn/old-givens.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//> using options -source future
2+
trait Ord[T]:
3+
def compare(x: T, y: T): Boolean
4+
5+
class C[T]
6+
7+
trait T:
8+
given intC: C[Int] // warn
9+
given intC2: C[Int] () // OK
10+
11+
given [T]: Ord[T] with // warn // warn
12+
def compare(x: T, y: T): Boolean = ???
13+
14+
given [T](using Ord[T]): Ord[List[T]] with // warn // warn
15+
def compare(x: List[T], y: List[T]): Boolean = ???
16+
17+
def f[T: Ord : C]() = ??? // warn
18+

0 commit comments

Comments
 (0)