Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,7 @@ object desugar {
str.toTermName.asSimpleName

/** Extract a synthesized given name from a type tree. This is used for
* both anonymous givens and (under x.modularity) deferred givens.
* both anonymous givens and deferred givens.
* @param followArgs if true include argument types in the name
*/
private class NameExtractor(followArgs: Boolean) extends UntypedTreeAccumulator[String] {
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @constructorOnly src: SourceFile) extends DefTree
case class ExtMethods(paramss: List[ParamClause], methods: List[Tree])(implicit @constructorOnly src: SourceFile) extends Tree
case class ContextBoundTypeTree(tycon: Tree, paramName: TypeName, ownName: TermName)(implicit @constructorOnly src: SourceFile) extends Tree
// `paramName: tycon as ownName`, ownName != EmptyTermName only under x.modularity
case class MacroTree(expr: Tree)(implicit @constructorOnly src: SourceFile) extends Tree

case class ImportSelector(imported: Ident, renamed: Tree = EmptyTree, bound: Tree = EmptyTree)(implicit @constructorOnly src: SourceFile) extends Tree {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enum MigrationVersion(val warnFrom: SourceVersion, val errorFrom: SourceVersion)
case ImportRename extends MigrationVersion(future, future)
case ParameterEnclosedByParenthesis extends MigrationVersion(future, future)
case XmlLiteral extends MigrationVersion(future, future)
case GivenSyntax extends MigrationVersion(future, never)

require(warnFrom.ordinal <= errorFrom.ordinal)

Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/config/SourceVersion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ enum SourceVersion:
// !!! Keep in sync with scala.runtime.stdlibPatches.language !!!
case `future-migration`, `future`

case `never` // needed for MigrationVersion.errorFrom if we never want to issue an error

val isMigrating: Boolean = toString.endsWith("-migration")

def stable: SourceVersion =
Expand Down
40 changes: 28 additions & 12 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -994,8 +994,8 @@ object Parsers {
skipParams()
lookahead.isColon
&& {
!in.featureEnabled(Feature.modularity)
|| { // with modularity language import, a `:` at EOL after an identifier represents a single identifier given
!sourceVersion.isAtLeast(`3.6`)
|| { // in the new given syntax, a `:` at EOL after an identifier represents a single identifier given
// Example:
// given C:
// def f = ...
Expand Down Expand Up @@ -1833,7 +1833,7 @@ object Parsers {
infixOps(t, canStartInfixTypeTokens, operand, Location.ElseWhere, ParseKind.Type,
isOperator = !followingIsVararg()
&& !isPureArrow
&& !(isIdent(nme.as) && in.featureEnabled(Feature.modularity))
&& !(isIdent(nme.as) && sourceVersion.isAtLeast(`3.6`))
&& nextCanFollowOperator(canStartInfixTypeTokens))

/** RefinedType ::= WithType {[nl] Refinement} [`^` CaptureSet]
Expand Down Expand Up @@ -2226,20 +2226,30 @@ object Parsers {
def contextBound(pname: TypeName): Tree =
val t = toplevelTyp()
val ownName =
if isIdent(nme.as) && in.featureEnabled(Feature.modularity) then
if isIdent(nme.as) && sourceVersion.isAtLeast(`3.6`) then
in.nextToken()
ident()
else EmptyTermName
ContextBoundTypeTree(t, pname, ownName)

/** ContextBounds ::= ContextBound | `{` ContextBound {`,` ContextBound} `}`
/** ContextBounds ::= ContextBound [`:` ContextBounds]
* | `{` ContextBound {`,` ContextBound} `}`
*/
def contextBounds(pname: TypeName): List[Tree] =
if in.isColon then
in.nextToken()
if in.token == LBRACE && in.featureEnabled(Feature.modularity)
if in.token == LBRACE && sourceVersion.isAtLeast(`3.6`)
then inBraces(commaSeparated(() => contextBound(pname)))
else contextBound(pname) :: contextBounds(pname)
else
val bound = contextBound(pname)
val rest =
if in.isColon then
report.errorOrMigrationWarning(
em"Multiple context bounds should be enclosed in `{ ... }`",
in.sourcePos(), MigrationVersion.GivenSyntax)
contextBounds(pname)
else Nil
bound :: rest
else if in.token == VIEWBOUND then
report.errorOrMigrationWarning(
em"view bounds `<%' are no longer supported, use a context bound `:' instead",
Expand Down Expand Up @@ -4014,7 +4024,7 @@ object Parsers {
case SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | OUTDENT | EOF =>
makeTypeDef(typeAndCtxBounds(tname))
case _ if (staged & StageKind.QuotedPattern) != 0
|| in.featureEnabled(Feature.modularity) && in.isColon =>
|| sourceVersion.isAtLeast(`3.6`) && in.isColon =>
makeTypeDef(typeAndCtxBounds(tname))
case _ =>
syntaxErrorOrIncomplete(ExpectedTypeBoundOrEquals(in.token))
Expand Down Expand Up @@ -4189,7 +4199,7 @@ object Parsers {
def givenDef(start: Offset, mods: Modifiers, givenMod: Mod) = atSpan(start, nameStart) {
var mods1 = addMod(mods, givenMod)
val nameStart = in.offset
var newSyntaxAllowed = in.featureEnabled(Feature.modularity)
var newSyntaxAllowed = sourceVersion.isAtLeast(`3.6`)
val hasEmbeddedColon = !in.isColon && followingIsGivenDefWithColon()
val name = if isIdent && hasEmbeddedColon then ident() else EmptyTermName

Expand Down Expand Up @@ -4260,6 +4270,9 @@ object Parsers {
in.nextToken()
newSignature()
else if hasEmbeddedColon then
report.errorOrMigrationWarning(
em"This old given syntax is no longer supported; use `=>` instead of `:`",
in.sourcePos(), MigrationVersion.GivenSyntax)
newSyntaxAllowed = false
val tparamsOld = typeParamClauseOpt(ParamOwner.Given)
newLineOpt()
Expand Down Expand Up @@ -4294,10 +4307,10 @@ object Parsers {
if name.isEmpty then
syntaxError(em"Anonymous given cannot be abstract, or maybe you want to define a concrete given and are missing a `()` argument?", in.lastOffset)
if newSyntaxAllowed then
warning(
em"""This defines an abstract given, which is deprecated. Use a `deferred` given instead.
report.errorOrMigrationWarning(
em"""This defines an abstract given, which is no longer supported. Use a `deferred` given instead.
|Or, if you intend to define a concrete given, follow the type with `()` arguments.""",
in.lastOffset)
in.sourcePos(in.lastOffset), MigrationVersion.GivenSyntax)
DefDef(name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree)
else
// structural instance
Expand Down Expand Up @@ -4487,6 +4500,9 @@ object Parsers {

/** with Template, with EOL <indent> interpreted */
def withTemplate(constr: DefDef, parents: List[Tree]): Template =
report.errorOrMigrationWarning(
em"Given member definitions starting with `with` are no longer supported; use `{...}` or `:` followed by newline instead",
in.sourcePos(), MigrationVersion.GivenSyntax)
accept(WITH)
val (self, stats) = templateBody(parents, rewriteWithColon = false)
Template(constr, parents, Nil, self, stats)
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import TypeApplications.*
import NameKinds.{WildcardParamName, DefaultGetterName}
import util.Chars.isOperatorPart
import config.{Config, Feature}
import config.Feature.sourceVersion
import config.SourceVersion.*

import dotty.tools.dotc.util.SourcePosition
import dotty.tools.dotc.ast.untpd.{MemberDef, Modifiers, PackageDef, RefTree, Template, TypeDef, ValOrDefDef}
Expand Down Expand Up @@ -751,7 +753,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case GenAlias(pat, expr) =>
toText(pat) ~ " = " ~ toText(expr)
case ContextBounds(bounds, cxBounds) =>
if Feature.enabled(Feature.modularity) then
if sourceVersion.isAtLeast(`3.6`) then
def boundsText(bounds: Tree) = bounds match
case ContextBoundTypeTree(tpt, _, ownName) =>
toText(tpt) ~ (" as " ~ toText(ownName) `provided` !ownName.isEmpty)
Expand Down
10 changes: 8 additions & 2 deletions docs/_docs/internals/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ TypeArgs ::= ‘[’ Types ‘]’
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>> ds
TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi)
TypeAndCtxBounds ::= TypeBounds [‘:’ ContextBounds] ContextBounds(typeBounds, tps)
ContextBounds ::= ContextBound | '{' ContextBound {',' ContextBound} '}'
ContextBounds ::= ContextBound
| ContextBound `:` ContextBounds -- to be deprecated
| '{' ContextBound {',' ContextBound} '}'
ContextBound ::= Type ['as' id]
Types ::= Type {‘,’ Type}
NamesAndTypes ::= NameAndType {‘,’ NameAndType}
Expand Down Expand Up @@ -464,7 +466,7 @@ TypeDef ::= id [HkTypeParamClause] {FunParamClause} TypeAndCtxBounds
TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef
| [‘case’] ‘object’ ObjectDef
| ‘enum’ EnumDef
| ‘given’ GivenDef
| ‘given’ (GivenDef | OldGivenDef)
ClassDef ::= id ClassConstr [Template] ClassDef(mods, name, tparams, templ)
ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
ConstrMods ::= {Annotation} [AccessModifier]
Expand All @@ -483,6 +485,10 @@ GivenConditional ::= DefTypeParamClause
| GivenType
GivenType ::= AnnotType1 {id [nl] AnnotType1}

OldGivenDef ::= [OldGivenSig] (AnnotType [‘=’ Expr] | StructuralInstance) -- syntax up to Scala 3.5, to be deprecated in the future
OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: consistent alignment

Suggested change
OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present
OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present

StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]

Extension ::= ‘extension’ [DefTypeParamClause] {UsingParamClause}
‘(’ DefTermParam ‘)’ {UsingParamClause} ExtMethods
ExtMethods ::= ExtMethod | [nl] <<< ExtMethod {semi ExtMethod} >>>
Expand Down
27 changes: 22 additions & 5 deletions docs/_docs/reference/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,11 @@ ParamValueType ::= Type [‘*’]
TypeArgs ::= ‘[’ Types ‘]’
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>>
TypeBounds ::= [‘>:’ Type] [‘<:’ Type]
TypeAndCtxBounds ::= TypeBounds {‘:’ Type}
TypeAndCtxBounds ::= TypeBounds [‘:’ ContextBounds]
ContextBounds ::= ContextBound
| ContextBound `:` ContextBounds -- to be deprecated
| '{' ContextBound {',' ContextBound} '}'
ContextBound ::= Type ['as' id]
Types ::= Type {‘,’ Type}
```

Expand Down Expand Up @@ -437,16 +441,29 @@ TypeDef ::= id [HkTypeParamClause] {FunParamClause}TypeBounds
TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef
| [‘case’] ‘object’ ObjectDef
| ‘enum’ EnumDef
| ‘given’ GivenDef
| ‘given’ (GivenDef | OldGivenDef)
ClassDef ::= id ClassConstr [Template]
ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses
ConstrMods ::= {Annotation} [AccessModifier]
ObjectDef ::= id [Template]
EnumDef ::= id ClassConstr InheritClauses EnumBody
GivenDef ::= [GivenSig] (AnnotType [‘=’ Expr] | StructuralInstance)
GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present
GivenType ::= AnnotType {id [nl] AnnotType}

GivenDef ::= [id ':'] GivenSig
GivenSig ::= GivenImpl
| '(' ')' '=>' GivenImpl
| GivenConditional '=>' GivenSig
GivenImpl ::= GivenType ([‘=’ Expr] | TemplateBody)
| ConstrApps TemplateBody
GivenConditional ::= DefTypeParamClause
| DefTermParamClause
| '(' FunArgTypes ')'
| GivenType
GivenType ::= AnnotType1 {id [nl] AnnotType1}

OldGivenDef ::= [OldGivenSig] (AnnotType [‘=’ Expr] | StructuralInstance) -- syntax up to Scala 3.5, to be deprecated in the future
OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OldGivenDef ::= [OldGivenSig] (AnnotType [‘=’ Expr] | StructuralInstance) -- syntax up to Scala 3.5, to be deprecated in the future
OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present
OldGivenDef ::= [OldGivenSig] (AnnotType ['=' Expr] | StructuralInstance) -- syntax up to Scala 3.5, to be deprecated in the future
OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ':' -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present

StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]

Extension ::= ‘extension’ [DefTypeParamClause] {UsingParamClause}
‘(’ DefTermParam ‘)’ {UsingParamClause} ExtMethods
ExtMethods ::= ExtMethod | [nl] <<< ExtMethod {semi ExtMethod} >>>
Expand Down
1 change: 0 additions & 1 deletion library/src/scala/compiletime/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ def uninitialized: Nothing = ???
* that implement the enclosing trait and that do not contain an explicit overriding
* definition of that given.
*/
@experimental
@compileTimeOnly("`deferred` can only be used as the right hand side of a given definition in a trait")
def deferred: Nothing = ???

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1089,11 +1089,13 @@ class AutoImplementAbstractMembersSuite extends BaseCodeActionSuite:
| def foo(x: Int): Int
| def bar(x: String): String
|
|given Foo with
|given Foo {
|
| override def foo(x: Int): Int = ???
|
| override def bar(x: String): String = ???
|
|}
|""".stripMargin
)

Expand Down
2 changes: 1 addition & 1 deletion tests/neg/cb-companion-leaks.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options -language:experimental.modularity -source future -explain
//> using options -language:experimental.modularity -explain

class C[Self]

Expand Down
4 changes: 4 additions & 0 deletions tests/neg/context-bounds-migration-future.check
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
| method foo does not take more parameters
|
| longer explanation available when compiling with `-explain`
-- Warning: tests/neg/context-bounds-migration-future.scala:6:6 --------------------------------------------------------
6 |given [T]: C[T] = C[T]()
| ^
| This old given syntax is no longer supported; use `=>` instead of `:`
2 changes: 1 addition & 1 deletion tests/neg/deferred-givens.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options -language:experimental.modularity -source future

import compiletime.deferred

class Ctx
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/deferredSummon.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options -language:experimental.modularity


object Test:
given Int = compiletime.deferred // error
Expand Down
4 changes: 2 additions & 2 deletions tests/neg/empty-given.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
given { // error
given {
def foo = 1 // error
} // error
}
6 changes: 3 additions & 3 deletions tests/neg/i12348.check
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-- [E040] Syntax Error: tests/neg/i12348.scala:2:15 --------------------------------------------------------------------
-- [E040] Syntax Error: tests/neg/i12348.scala:2:16 --------------------------------------------------------------------
2 | given inline x: Int = 0 // error
| ^
| 'with' expected, but identifier found
| ^
| an identifier expected, but ':' found
2 changes: 1 addition & 1 deletion tests/neg/infix.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class C:
def +(x: Int): Int = ???

object C:
given AnyRef with
given AnyRef:
extension (x: C)
infix def iop (y: Int) = ???
def mop (y: Int) = ???
Expand Down
8 changes: 4 additions & 4 deletions tests/neg/tracked.check
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
17 | tracked type T = Int // error // error
| ^^^^
| end of statement expected but 'type' found
-- Error: tests/neg/tracked.scala:20:29 --------------------------------------------------------------------------------
20 | given g2(using tracked val x: Int): C = C(x) // error
| ^^^^^^^^^^^^^^^^^^
| method parameter x may not be a `val`
-- Error: tests/neg/tracked.scala:20:25 --------------------------------------------------------------------------------
20 | given g2: (tracked val x: Int) => C = C(x) // error
| ^^^^^^^^^^^^^^^^^^
| method parameter x may not be a `val`
-- Error: tests/neg/tracked.scala:4:21 ---------------------------------------------------------------------------------
4 |class C2(tracked var x: Int) // error
| ^
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/tracked.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ object D:
tracked type T = Int // error // error

object E:
given g2(using tracked val x: Int): C = C(x) // error
given g2: (tracked val x: Int) => C = C(x) // error
1 change: 0 additions & 1 deletion tests/pos-custom-args/captures/logger.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import language.experimental.saferExceptions
import language.experimental.modularity

class FileSystem extends caps.Capability

Expand Down
1 change: 0 additions & 1 deletion tests/pos-custom-args/captures/nested-classes.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import language.experimental.captureChecking
import language.experimental.modularity
import annotation.{capability, constructorOnly}

class IO extends caps.Capability
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/FromString-cb-companion.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options -language:experimental.modularity -source future
//> using options -language:experimental.modularity

trait FromString[Self]:
def fromString(s: String): Self
Expand Down
1 change: 0 additions & 1 deletion tests/pos/FromString-typeparam.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//> using options -language:experimental.modularity -source future

trait FromString[A]:
def fromString(s: String): A
Expand Down
1 change: 0 additions & 1 deletion tests/pos/cb-companion-joins.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import language.experimental.modularity
import language.future

trait M[Self]:
extension (x: Self) def combine (y: Self): String
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/deferred-givens-singletons.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options -language:experimental.modularity -source future
// //> using options -language:experimental.modularity -source future
import compiletime.*

trait A:
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/deferred-givens.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options -language:experimental.modularity -source future

import compiletime.*
class Ord[Elem]
given Ord[Double]()
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/dep-context-bounds.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options -language:experimental.modularity -source future
//> using options -language:experimental.modularity
trait A:
type Self

Expand Down
2 changes: 0 additions & 2 deletions tests/pos/i21189-alt.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//> using options -source:future -language:experimental.modularity

class MySortedSet[T : Ord] extends SortedSet[T]

trait Ord[T]
Expand Down
2 changes: 0 additions & 2 deletions tests/pos/i21189.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//> using options -source:future -language:experimental.modularity

class MySortedSet[T : Ord] extends SortedSet[T]

trait Ord[T]
Expand Down
2 changes: 0 additions & 2 deletions tests/pos/typeclasses-arrow0.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//> using options -language:experimental.modularity -source future

class Common:

trait Ord[A]:
Expand Down
Loading
Loading