Skip to content

Commit

Permalink
Stabilise SIP-47
Browse files Browse the repository at this point in the history
  • Loading branch information
hamzaremmal committed Jul 3, 2024
1 parent aad6f7d commit 129713c
Show file tree
Hide file tree
Showing 31 changed files with 38 additions and 68 deletions.
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/config/Feature.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ object Feature:

def namedTypeArgsEnabled(using Context) = enabled(namedTypeArguments)

def clauseInterleavingEnabled(using Context) = enabled(clauseInterleaving)
def clauseInterleavingEnabled(using Context) =
sourceVersion.isAtLeast(`3.6`) || enabled(clauseInterleaving)

def genericNumberLiteralsEnabled(using Context) = enabled(genericNumberLiterals)

Expand Down
4 changes: 1 addition & 3 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3878,13 +3878,11 @@ object Parsers {
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"
if Feature.clauseInterleavingEnabled(using in.languageImportContext) then
typeOrTermParamClauses(ParamOwner.Def, numLeadParams)
else
val tparams = typeParamClauseOpt(ParamOwner.Def)
val vparamss = termParamClauses(ParamOwner.Def, numLeadParams)

joinParams(tparams, vparamss)

var tpt = fromWithinReturnType { typedOpt() }
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions library/src/scala/runtime/stdLibPatches/language.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
"""
Expand Down
2 changes: 0 additions & 2 deletions scaladoc-testcases/src/tests/extensionParams.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
= ???
Expand Down
2 changes: 0 additions & 2 deletions scaladoc-testcases/src/tests/methodsAndConstructors.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package tests.methodsAndConstructors

import scala.language.experimental.clauseInterleaving

class A
class B extends A
class C
Expand Down
3 changes: 1 addition & 2 deletions tests/neg/interleaving-ab.scala
Original file line number Diff line number Diff line change
@@ -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
1 change: 0 additions & 1 deletion tests/neg/interleaving-params.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

class Params{
def bar[T](x: T)[T]: String = ??? // error
Expand Down
1 change: 0 additions & 1 deletion tests/neg/interleaving-signatureCollision.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

object signatureCollision:
def f[T](x: T)[U](y: U) = (x,y)
Expand Down
28 changes: 14 additions & 14 deletions tests/neg/interleaving-typeApply.check
Original file line number Diff line number Diff line change
@@ -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
|
Expand Down
3 changes: 1 addition & 2 deletions tests/neg/interleaving-typeApply.scala
Original file line number Diff line number Diff line change
@@ -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 = ???
Expand Down
1 change: 0 additions & 1 deletion tests/neg/interleaving-unmatched.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

object unmatched:
def f1[T (x: T)] = ??? // error
Expand Down
4 changes: 4 additions & 0 deletions tests/neg/interleavingExperimental.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- [E040] Syntax Error: tests/neg/interleavingExperimental.scala:3:15 --------------------------------------------------
3 |def ba[A](x: A)[B](using B): B = summon[B] // error: clauseInterleaving was experimental until 3.6
| ^
| '=' expected, but '[' found
3 changes: 3 additions & 0 deletions tests/neg/interleavingExperimental.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//> using options --source 3.5

def ba[A](x: A)[B](using B): B = summon[B] // error: clauseInterleaving was experimental until 3.6
8 changes: 4 additions & 4 deletions tests/neg/namedTypeParams.check
Original file line number Diff line number Diff line change
Expand Up @@ -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.
1 change: 0 additions & 1 deletion tests/neg/namedTypeParams.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 0 additions & 6 deletions tests/neg/overrides.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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
}

Expand All @@ -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
}

Expand Down
1 change: 0 additions & 1 deletion tests/pos/interleaving-ba.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

object BA {
given String = ""
Expand Down
1 change: 0 additions & 1 deletion tests/pos/interleaving-chainedParams.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

object chainedParams{

Expand Down
1 change: 0 additions & 1 deletion tests/pos/interleaving-classless.scala
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
1 change: 0 additions & 1 deletion tests/pos/interleaving-functor.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

object functorInterleaving:
//taken from https://dotty.epfl.ch/docs/reference/contextual/type-classes.html
Expand Down
1 change: 0 additions & 1 deletion tests/pos/interleaving-newline.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

object newline {
def multipleLines
Expand Down
1 change: 0 additions & 1 deletion tests/pos/interleaving-overload.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

class A{

Expand Down
1 change: 0 additions & 1 deletion tests/pos/interleaving-params.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

class Params{
type U
Expand Down
1 change: 0 additions & 1 deletion tests/pos/interleaving-signatureCollision.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving
import scala.annotation.targetName

object signatureCollision:
Expand Down
2 changes: 0 additions & 2 deletions tests/pos/interleaving-typeApply.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

object typeApply:

Expand All @@ -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]()
Expand Down
5 changes: 5 additions & 0 deletions tests/pos/interleavingExperimental.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//> using options --source 3.5

import scala.language.experimental.clauseInterleaving

def ba[A](x: A)[B](using B): B = summon[B]
1 change: 0 additions & 1 deletion tests/pos/namedTypeParams.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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, "")
Expand Down
5 changes: 0 additions & 5 deletions tests/pos/overrides.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

}
Expand All @@ -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

}
1 change: 0 additions & 1 deletion tests/run/interleaving.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import scala.language.experimental.clauseInterleaving

object Test extends App {
trait Key { type Value }
Expand Down

0 comments on commit 129713c

Please sign in to comment.