Skip to content

Commit

Permalink
Implement SIP 64 as non-experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Sep 28, 2024
1 parent 5ec1e8b commit 14acdc0
Show file tree
Hide file tree
Showing 13 changed files with 53 additions and 36 deletions.
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
20 changes: 8 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,18 +2226,19 @@ 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 if in.token == VIEWBOUND then
Expand Down Expand Up @@ -4189,7 +4190,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 @@ -4293,11 +4294,6 @@ object Parsers {
// old-style abstract given
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.
|Or, if you intend to define a concrete given, follow the type with `()` arguments.""",
in.lastOffset)
DefDef(name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree)
else
// structural instance
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
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
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
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
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ val experimentalDefinitionInLibrary = Set(
// New feature: modularity
"scala.Precise",
"scala.annotation.internal.WitnessNames",
"scala.compiletime.package$package$.deferred",
"scala.runtime.stdLibPatches.Predef$.is",

// New feature: functions with erased parameters.
Expand Down
6 changes: 1 addition & 5 deletions tests/warn/abstract-givens-new.check
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
-- Warning: tests/warn/abstract-givens-new.scala:7:22 ------------------------------------------------------------------
7 | given intC: Int is C // warn
| ^
| This defines an abstract given, which is deprecated. Use a `deferred` given instead.
| Or, if you intend to define a concrete given, follow the type with `()` arguments.

3 changes: 2 additions & 1 deletion tests/warn/abstract-givens-new.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class C:

trait T:
given Int is C // ok
given intC: Int is C // warn
given intC: Int is C // ok for now, will be warning
given intC2: (Int is C)() // ok
given intC3: Int is C {} // also ok

0 comments on commit 14acdc0

Please sign in to comment.