From 7ff2398cb4b6b889a90f0eeb98630dc2180265f2 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Fri, 28 Jun 2024 18:00:23 +0200 Subject: [PATCH] Stabilise SIP-47 --- .../src/dotty/tools/dotc/config/Feature.scala | 4 --- .../dotty/tools/dotc/parsing/Parsers.scala | 11 +------- .../generalized-method-syntax.md | 10 ++----- .../runtime/stdLibPatches/language.scala | 1 + .../SignatureHelpInterleavingSuite.scala | 3 -- .../src/tests/extensionParams.scala | 2 -- .../src/tests/methodsAndConstructors.scala | 2 -- tests/neg/interleaving-ab.scala | 3 +- tests/neg/interleaving-params.scala | 1 - .../neg/interleaving-signatureCollision.scala | 1 - tests/neg/interleaving-typeApply.check | 28 +++++++++---------- tests/neg/interleaving-typeApply.scala | 3 +- tests/neg/interleaving-unmatched.scala | 1 - tests/neg/namedTypeParams.check | 8 +++--- tests/neg/namedTypeParams.scala | 1 - tests/neg/overrides.scala | 6 ---- tests/pos/interleaving-ba.scala | 1 - tests/pos/interleaving-chainedParams.scala | 1 - tests/pos/interleaving-classless.scala | 1 - tests/pos/interleaving-functor.scala | 1 - tests/pos/interleaving-newline.scala | 1 - tests/pos/interleaving-overload.scala | 1 - tests/pos/interleaving-params.scala | 1 - .../pos/interleaving-signatureCollision.scala | 1 - tests/pos/interleaving-typeApply.scala | 2 -- tests/pos/namedTypeParams.scala | 1 - tests/pos/overrides.scala | 5 ---- tests/run/interleaving.scala | 1 - 28 files changed, 24 insertions(+), 78 deletions(-) rename docs/_docs/reference/{experimental => other-new-features}/generalized-method-syntax.md (92%) diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index c04c58b419c9..fe97d020b2a0 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -30,7 +30,6 @@ object Feature: val symbolLiterals = deprecated("symbolLiterals") val fewerBraces = experimental("fewerBraces") val saferExceptions = experimental("saferExceptions") - val clauseInterleaving = experimental("clauseInterleaving") val pureFunctions = experimental("pureFunctions") val captureChecking = experimental("captureChecking") val into = experimental("into") @@ -60,7 +59,6 @@ object Feature: (symbolLiterals, "Allow symbol literals"), (fewerBraces, "Enable support for using indentation for arguments"), (saferExceptions, "Enable safer exceptions"), - (clauseInterleaving, "Enable clause interleaving"), (pureFunctions, "Enable pure functions for capture checking"), (captureChecking, "Enable experimental capture checking"), (into, "Allow into modifier on parameter types"), @@ -121,8 +119,6 @@ object Feature: def namedTypeArgsEnabled(using Context) = enabled(namedTypeArguments) - def clauseInterleavingEnabled(using Context) = enabled(clauseInterleaving) - def genericNumberLiteralsEnabled(using Context) = enabled(genericNumberLiterals) def scala2ExperimentalMacroEnabled(using Context) = enabled(scala2macros) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 4c13934f3473..3c50117a82b8 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3877,16 +3877,7 @@ object Parsers { val mods1 = addFlag(mods, Method) val ident = termIdent() var name = ident.name.asTermName - val paramss = - if in.featureEnabled(Feature.clauseInterleaving) then - // If you are making interleaving stable manually, please refer to the PR introducing it instead, section "How to make non-experimental" - typeOrTermParamClauses(ParamOwner.Def, numLeadParams) - else - val tparams = typeParamClauseOpt(ParamOwner.Def) - val vparamss = termParamClauses(ParamOwner.Def, numLeadParams) - - joinParams(tparams, vparamss) - + val paramss = typeOrTermParamClauses(ParamOwner.Def, numLeadParams) var tpt = fromWithinReturnType { typedOpt() } if (migrateTo3) newLineOptWhenFollowedBy(LBRACE) diff --git a/docs/_docs/reference/experimental/generalized-method-syntax.md b/docs/_docs/reference/other-new-features/generalized-method-syntax.md similarity index 92% rename from docs/_docs/reference/experimental/generalized-method-syntax.md rename to docs/_docs/reference/other-new-features/generalized-method-syntax.md index 072052c1ae10..2dd537cacdd8 100644 --- a/docs/_docs/reference/experimental/generalized-method-syntax.md +++ b/docs/_docs/reference/other-new-features/generalized-method-syntax.md @@ -1,15 +1,9 @@ --- layout: doc-page title: "Generalized Method Syntax" -nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/generalized-method-syntax.html +nightlyOf: https://docs.scala-lang.org/scala3/reference/other-new-features/generalized-method-syntax.html --- -This feature is not yet part of the Scala 3 language definition. It can be made available by a language import: - -```scala -import scala.language.experimental.clauseInterleaving -``` - The inclusion of using clauses is not the only way in which methods have been updated, type parameter clauses are now allowed in any number and at any position. ## Syntax Changes @@ -51,7 +45,7 @@ trait DB { } ``` -Note that simply replacing `V` by `k.Value` would not be equivalent. For example, if `k.Value` is `Some[Int]`, only the above allows: +Note that simply replacing `V` by `k.Value` would not be equivalent. For example, if `k.Value` is `Some[Int]`, only the above allows: `getOrElse(k)[Option[Int]](None)`, which returns a `Number`. ## Details diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index d89bd9dcf72e..6272970ab0ed 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -67,6 +67,7 @@ object language: * @see [[https://github.com/scala/improvement-proposals/blob/main/content/clause-interleaving.md]] */ @compileTimeOnly("`clauseInterleaving` can only be used at compile time in import statements") + @deprecated("`clauseInterleaving` is now standard, no language import is needed", since = "3.6") object clauseInterleaving /** Experimental support for pure function type syntax diff --git a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpInterleavingSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpInterleavingSuite.scala index 15546d086033..735a2eb13fab 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpInterleavingSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpInterleavingSuite.scala @@ -8,9 +8,6 @@ import java.nio.file.Path class SignatureHelpInterleavingSuite extends BaseSignatureHelpSuite: - override protected def scalacOptions(classpath: Seq[Path]): Seq[String] = - List("-language:experimental.clauseInterleaving") - @Test def `proper-position-1` = check( """ diff --git a/scaladoc-testcases/src/tests/extensionParams.scala b/scaladoc-testcases/src/tests/extensionParams.scala index 0e2225d8aa3c..12850778c793 100644 --- a/scaladoc-testcases/src/tests/extensionParams.scala +++ b/scaladoc-testcases/src/tests/extensionParams.scala @@ -61,8 +61,6 @@ extension (using Unit)(a: Int) def f14(): Any = ??? -import scala.language.experimental.clauseInterleaving - extension (using String)(using Int)(a: Animal)(using Unit)(using Number) def f16(b: Any)[T](c: T): T = ??? diff --git a/scaladoc-testcases/src/tests/methodsAndConstructors.scala b/scaladoc-testcases/src/tests/methodsAndConstructors.scala index cddd0f56e9fe..b4c354d174c4 100644 --- a/scaladoc-testcases/src/tests/methodsAndConstructors.scala +++ b/scaladoc-testcases/src/tests/methodsAndConstructors.scala @@ -1,7 +1,5 @@ package tests.methodsAndConstructors -import scala.language.experimental.clauseInterleaving - class A class B extends A class C diff --git a/tests/neg/interleaving-ab.scala b/tests/neg/interleaving-ab.scala index e446626a2982..afdb2f0a192f 100644 --- a/tests/neg/interleaving-ab.scala +++ b/tests/neg/interleaving-ab.scala @@ -1,11 +1,10 @@ -import scala.language.experimental.clauseInterleaving object Ab: given String = "" given Double = 0 def illegal[A][B](x: A)(using B): B = summon[B] // error: Type parameter lists must be separated by a term or using parameter list - + def ab[A](x: A)[B](using B): B = summon[B] def test = ab[Int](0: Int) // error diff --git a/tests/neg/interleaving-params.scala b/tests/neg/interleaving-params.scala index dc6762cf0214..20f6bbb98d3d 100644 --- a/tests/neg/interleaving-params.scala +++ b/tests/neg/interleaving-params.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving class Params{ def bar[T](x: T)[T]: String = ??? // error diff --git a/tests/neg/interleaving-signatureCollision.scala b/tests/neg/interleaving-signatureCollision.scala index a6a729ed3b62..096073e7bda8 100644 --- a/tests/neg/interleaving-signatureCollision.scala +++ b/tests/neg/interleaving-signatureCollision.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving object signatureCollision: def f[T](x: T)[U](y: U) = (x,y) diff --git a/tests/neg/interleaving-typeApply.check b/tests/neg/interleaving-typeApply.check index a50c1455bfbb..ca2ab6fa3f3e 100644 --- a/tests/neg/interleaving-typeApply.check +++ b/tests/neg/interleaving-typeApply.check @@ -1,29 +1,29 @@ --- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:10:11 -------------------------------------------- -10 | f3[String]() // error - | ^ - | Type argument String does not conform to upper bound Int - | - | longer explanation available when compiling with `-explain` --- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:11:16 -------------------------------------------- -11 | f5[Int][Unit] // error +-- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:9:11 --------------------------------------------- +9 | f3[String]() // error + | ^ + | Type argument String does not conform to upper bound Int + | + | longer explanation available when compiling with `-explain` +-- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:10:16 -------------------------------------------- +10 | f5[Int][Unit] // error | ^ | Type argument Unit does not conform to upper bound String | | longer explanation available when compiling with `-explain` --- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:12:19 -------------------------------------------- -12 | f5[String][Unit] // error // error +-- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:11:19 -------------------------------------------- +11 | f5[String][Unit] // error // error | ^ | Type argument Unit does not conform to upper bound String | | longer explanation available when compiling with `-explain` --- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:12:11 -------------------------------------------- -12 | f5[String][Unit] // error // error +-- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:11:11 -------------------------------------------- +11 | f5[String][Unit] // error // error | ^ | Type argument String does not conform to upper bound Int | | longer explanation available when compiling with `-explain` --- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:13:11 -------------------------------------------- -13 | f7[String]()[Unit] // error +-- [E057] Type Mismatch Error: tests/neg/interleaving-typeApply.scala:12:11 -------------------------------------------- +12 | f7[String]()[Unit] // error | ^ | Type argument String does not conform to upper bound Int | diff --git a/tests/neg/interleaving-typeApply.scala b/tests/neg/interleaving-typeApply.scala index ad21fe2f0329..5ad6e3dc148e 100644 --- a/tests/neg/interleaving-typeApply.scala +++ b/tests/neg/interleaving-typeApply.scala @@ -1,7 +1,6 @@ -import scala.language.experimental.clauseInterleaving object typeApply: - + def f3[T <: Int](using DummyImplicit)[U <: String](): T => T = ??? def f5[T <: Int](using DummyImplicit)[U <: String]: [X <: Unit] => X => X = ??? def f7[T <: Int](using DummyImplicit)[U <: String]()[X <: Unit]: X => X = ??? diff --git a/tests/neg/interleaving-unmatched.scala b/tests/neg/interleaving-unmatched.scala index 2ce3074d07fa..3a4371798a50 100644 --- a/tests/neg/interleaving-unmatched.scala +++ b/tests/neg/interleaving-unmatched.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving object unmatched: def f1[T (x: T)] = ??? // error diff --git a/tests/neg/namedTypeParams.check b/tests/neg/namedTypeParams.check index 5e0672f20f25..f203f482d117 100644 --- a/tests/neg/namedTypeParams.check +++ b/tests/neg/namedTypeParams.check @@ -92,11 +92,11 @@ | illegal repeated type application | You might have meant something like: | Test.f[Y = String, Int] --- [E102] Syntax Error: tests/neg/namedTypeParams.scala:33:9 ----------------------------------------------------------- -33 | f2[Y = String][X = Int](1, "") // error: Y is undefined +-- [E102] Syntax Error: tests/neg/namedTypeParams.scala:32:9 ----------------------------------------------------------- +32 | f2[Y = String][X = Int](1, "") // error: Y is undefined | ^^^^^^ | Type parameter Y is undefined. Expected one of X. --- [E102] Syntax Error: tests/neg/namedTypeParams.scala:34:9 ----------------------------------------------------------- -34 | f2[Y = String](1, "") // error: Y is undefined +-- [E102] Syntax Error: tests/neg/namedTypeParams.scala:33:9 ----------------------------------------------------------- +33 | f2[Y = String](1, "") // error: Y is undefined | ^^^^^^ | Type parameter Y is undefined. Expected one of X. diff --git a/tests/neg/namedTypeParams.scala b/tests/neg/namedTypeParams.scala index 53ef14188e12..489ac1e8cdb6 100644 --- a/tests/neg/namedTypeParams.scala +++ b/tests/neg/namedTypeParams.scala @@ -27,7 +27,6 @@ object Test: object TestInterleaving: import language.experimental.namedTypeArguments - import language.experimental.clauseInterleaving def f2[X](using DummyImplicit)[Y](x: X, y: Y): Int = ??? f2[Y = String][X = Int](1, "") // error: Y is undefined diff --git a/tests/neg/overrides.scala b/tests/neg/overrides.scala index 8016f5646d09..c8f577103a6a 100644 --- a/tests/neg/overrides.scala +++ b/tests/neg/overrides.scala @@ -44,8 +44,6 @@ class A[T] { def next: T = ??? - import scala.language.experimental.clauseInterleaving - def b[U <: T](x: Int)[V >: T](y: String) = false } @@ -57,8 +55,6 @@ class B extends A[Int] { override def next(): Int = ??? // error: incompatible type - import scala.language.experimental.clauseInterleaving - override def b[T <: Int](x: Int)(y: String) = true // error } @@ -68,8 +64,6 @@ class C extends A[String] { override def next: Int = ??? // error: incompatible type - import scala.language.experimental.clauseInterleaving - override def b[T <: String](x: Int)[U >: Int](y: String) = true // error: incompatible type } diff --git a/tests/pos/interleaving-ba.scala b/tests/pos/interleaving-ba.scala index 69fe2d9537a0..4a7d721c804e 100644 --- a/tests/pos/interleaving-ba.scala +++ b/tests/pos/interleaving-ba.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving object BA { given String = "" diff --git a/tests/pos/interleaving-chainedParams.scala b/tests/pos/interleaving-chainedParams.scala index a54885d28002..02dc7a5ccc9c 100644 --- a/tests/pos/interleaving-chainedParams.scala +++ b/tests/pos/interleaving-chainedParams.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving object chainedParams{ diff --git a/tests/pos/interleaving-classless.scala b/tests/pos/interleaving-classless.scala index 5aec92db3409..bddfc821385d 100644 --- a/tests/pos/interleaving-classless.scala +++ b/tests/pos/interleaving-classless.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving def f1[T]()[U](x: T, y: U): (T, U) = (x, y) def f2[T](x: T)[U](y: U): (T, U) = (x, y) diff --git a/tests/pos/interleaving-functor.scala b/tests/pos/interleaving-functor.scala index 35bed59f77f0..b588e35f60a2 100644 --- a/tests/pos/interleaving-functor.scala +++ b/tests/pos/interleaving-functor.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving object functorInterleaving: //taken from https://dotty.epfl.ch/docs/reference/contextual/type-classes.html diff --git a/tests/pos/interleaving-newline.scala b/tests/pos/interleaving-newline.scala index de8fb98a2f81..d71bdc910de2 100644 --- a/tests/pos/interleaving-newline.scala +++ b/tests/pos/interleaving-newline.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving object newline { def multipleLines diff --git a/tests/pos/interleaving-overload.scala b/tests/pos/interleaving-overload.scala index 1902551f9036..e1c3db1abe37 100644 --- a/tests/pos/interleaving-overload.scala +++ b/tests/pos/interleaving-overload.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving class A{ diff --git a/tests/pos/interleaving-params.scala b/tests/pos/interleaving-params.scala index 36963ff2e123..b12608f4b291 100644 --- a/tests/pos/interleaving-params.scala +++ b/tests/pos/interleaving-params.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving class Params{ type U diff --git a/tests/pos/interleaving-signatureCollision.scala b/tests/pos/interleaving-signatureCollision.scala index 77190284ae6d..be016e7bdbfe 100644 --- a/tests/pos/interleaving-signatureCollision.scala +++ b/tests/pos/interleaving-signatureCollision.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving import scala.annotation.targetName object signatureCollision: diff --git a/tests/pos/interleaving-typeApply.scala b/tests/pos/interleaving-typeApply.scala index 3c669cc76bfc..d8a7fd5d2ec1 100644 --- a/tests/pos/interleaving-typeApply.scala +++ b/tests/pos/interleaving-typeApply.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving object typeApply: @@ -12,7 +11,6 @@ object typeApply: def f7[T <: Int](using DummyImplicit)[U <: String]()[X <: Unit]: X => X = ??? @main def test = { - import scala.language.experimental.namedTypeArguments f0[Int][String] f1[Int][String] f2[Int][String]() diff --git a/tests/pos/namedTypeParams.scala b/tests/pos/namedTypeParams.scala index 388bcfa98bef..d538bef52a69 100644 --- a/tests/pos/namedTypeParams.scala +++ b/tests/pos/namedTypeParams.scala @@ -11,7 +11,6 @@ object Test { } object TestInterleaving{ - import language.experimental.clauseInterleaving def f2[X](using DummyImplicit)[Y](x: X, y: Y): Int = ??? f2[X = Int][Y = String](1, "") diff --git a/tests/pos/overrides.scala b/tests/pos/overrides.scala index c3b6235d7c1f..e56c4c941a7f 100644 --- a/tests/pos/overrides.scala +++ b/tests/pos/overrides.scala @@ -4,8 +4,6 @@ class A[T] { def f(x: T)(y: T = x) = y - import scala.language.experimental.clauseInterleaving - def b[U <: T](x: Int)[V >: T](y: String) = false } @@ -15,9 +13,6 @@ class B extends A[Int] { f(2)() - - import scala.language.experimental.clauseInterleaving - override def b[T <: Int](x: Int)[U >: Int](y: String) = true } diff --git a/tests/run/interleaving.scala b/tests/run/interleaving.scala index 6749e59168bc..cc52528486b1 100644 --- a/tests/run/interleaving.scala +++ b/tests/run/interleaving.scala @@ -1,4 +1,3 @@ -import scala.language.experimental.clauseInterleaving object Test extends App { trait Key { type Value }