Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SIP 64 as non-experimental #21668

Merged
merged 9 commits into from
Oct 4, 2024
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
bishabosha marked this conversation as resolved.
Show resolved Hide resolved

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]
odersky marked this conversation as resolved.
Show resolved Hide resolved
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)
odersky marked this conversation as resolved.
Show resolved Hide resolved
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