From 943f6636832cd46b51d5f31635ab26ea9d2964eb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 5 Jun 2019 15:03:33 +0200 Subject: [PATCH 1/2] Use `?` for wildcards Still missing: Use `*` as a placeholder parameter under -Ykind-projector --- .../tools/dotc/config/ScalaSettings.scala | 1 + .../src/dotty/tools/dotc/core/StdNames.scala | 2 + .../dotty/tools/dotc/parsing/Parsers.scala | 12 ++++++ .../dotty/tools/dotc/CompilationTests.scala | 3 +- .../reference/changed-features/wildcards.md | 43 +++++++++++++++++++ tests/neg-custom-args/wildcards.scala | 4 ++ tests/pos/wildcards.scala | 4 ++ 7 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 docs/docs/reference/changed-features/wildcards.md create mode 100644 tests/neg-custom-args/wildcards.scala create mode 100644 tests/pos/wildcards.scala diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 5a9bbc5eb84e..a3157b1fb396 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -125,6 +125,7 @@ class ScalaSettings extends Settings.SettingGroup { val YshowSuppressedErrors: Setting[Boolean] = BooleanSetting("-Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally suppressed.") val YdetailedStats: Setting[Boolean] = BooleanSetting("-Ydetailed-stats", "show detailed internal compiler stats (needs Stats.enabled to be set to true).") val Yheartbeat: Setting[Boolean] = BooleanSetting("-Yheartbeat", "show heartbeat stack trace of compiler operations (needs Stats.enabled to be set to true).") + val YkindProjector: Setting[Boolean] = BooleanSetting("-Ykind-projector", "allow `*` as wildcard to be compatible with kind projector") val YprintPos: Setting[Boolean] = BooleanSetting("-Yprint-pos", "show tree positions.") val YprintPosSyms: Setting[Boolean] = BooleanSetting("-Yprint-pos-syms", "show symbol definitions positions.") val YnoDeepSubtypes: Setting[Boolean] = BooleanSetting("-Yno-deep-subtypes", "throw an exception on deep subtyping call stacks.") diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index fafe9e4876fc..620a13de65e6 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -315,6 +315,8 @@ object StdNames { val _21 : N = "_21" val _22 : N = "_22" + val * : N = "*" + val ? : N = "?" val ??? : N = "???" val genericWrapArray: N = "genericWrapArray" diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index c323f891cfe3..fcb019bef9a5 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1069,9 +1069,21 @@ object Parsers { SingletonTypeTree(literal(negOffset = start)) } else if (in.token == USCORE) { + if (ctx.settings.strict.value) { + deprecationWarning(em"`_` is deprecated for wildcard arguments of types: use `?` instead") + patch(source, Span(in.offset, in.offset + 1), "?") + } val start = in.skipToken() typeBounds().withSpan(Span(start, in.lastOffset, start)) } + else if (isIdent(nme.?)) { + val start = in.skipToken() + typeBounds().withSpan(Span(start, in.lastOffset, start)) + } + else if (isIdent(nme.*) && ctx.settings.YkindProjector.value) { + syntaxError("`*` placeholders are not implemented yet") + typeIdent() + } else if (isSplice) splice(isType = true) else path(thisOK = false, handleSingletonType) match { diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index e8e750b7f22a..a0bdfa40c7d2 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -181,7 +181,8 @@ class CompilationTests extends ParallelTesting { defaultOptions), compileFile("tests/neg-custom-args/i6300.scala", allowDeepSubtypes), compileFile("tests/neg-custom-args/infix.scala", defaultOptions.and("-strict", "-deprecation", "-Xfatal-warnings")), - compileFile("tests/neg-custom-args/missing-alpha.scala", defaultOptions.and("-strict", "-deprecation", "-Xfatal-warnings")) + compileFile("tests/neg-custom-args/missing-alpha.scala", defaultOptions.and("-strict", "-deprecation", "-Xfatal-warnings")), + compileFile("tests/neg-custom-args/wildcards.scala", defaultOptions.and("-strict", "-deprecation", "-Xfatal-warnings")) ).checkExpectedErrors() } diff --git a/docs/docs/reference/changed-features/wildcards.md b/docs/docs/reference/changed-features/wildcards.md new file mode 100644 index 000000000000..1780f6b38ca7 --- /dev/null +++ b/docs/docs/reference/changed-features/wildcards.md @@ -0,0 +1,43 @@ +--- +layout: doc-page +title: Wildcard Arguments in Types +--- + +The syntax of wildcard arguments in types has changed from `_` to `?`. Example: +```scala +List[?] +Map[? <: AnyRef, ? >: Null] +``` + +### Motivation + +We would like to use the underscore syntax `_` to stand for an anonymous type parameter, aligning it with its meaning in +value parameter lists. So, just as `f(_)` is a shorthand for the lambda `x => f(x)`, in the future `C[_]` will be a shorthand +for the type lambda `[X] =>> C[X]`. This makes higher-kinded types easier to use. It also removes the wart that, used as a type +parameter, `F[_]` means `F` is a type constructor whereas used as a type, `F[_]` means it is a wildcard (i.e. existential) type. +In the future, `F[_]` will mean the same thing, no matter where it is used. + +We pick `?` as a replacement syntax for wildcard types, since it aligns with Java's syntax. + +### Migration Strategy + +The migration to the new scheme is complicated, in particular since the [kind projector](https://github.com/typelevel/kind-projector]) +compiler plugin still uses the reverse convention, with `?` meaning parameter placeholder instead of wildcard. Fortunately, kind projector has added `*` as an alternative syntax for `?`. + +A step-by-step migration is made possible with the following measures: + + 1. In Scala 3.0, both `_` and `?` are legal names for wildcards. + 2. In Scala 3.1, `_` is deprecated in favor of `?` as a name for a wildcard. A `-rewrite` option is + available to rewrite one to the other. + 3. In Scala 3.2, the meaning of `_` changes from wildcard to placeholder for type parameter. + 4. The Scala 3.1 behavior is already available today under the `-strict` setting. + +To smooth the transition for codebases that use kind-projector, we adopt the following measures under the command line +option `-Ykind-projector`: + + 1. In Scala 3.0, `*` is available as a type parameter placeholder. + 2. In Scala 3.2, `*` is deprecated in favor of `_`. A `-rewrite` option is + available to rewrite one to the other. + 3. In Scala 3.3, `*` is removed again, and all type parameter placeholders will be expressed with `_`. + +These rules make it possible to cross build between Scala 2 using the kind projector plugin and Scala 3.0 - 3.2 using option `-Ykind-projector`. diff --git a/tests/neg-custom-args/wildcards.scala b/tests/neg-custom-args/wildcards.scala new file mode 100644 index 000000000000..e8ac77c116be --- /dev/null +++ b/tests/neg-custom-args/wildcards.scala @@ -0,0 +1,4 @@ +object Test { + val xs: List[_] = List(1, 2, 3) // error + val ys: Map[_ <: AnyRef, _ >: Null] = Map() // error // error +} \ No newline at end of file diff --git a/tests/pos/wildcards.scala b/tests/pos/wildcards.scala new file mode 100644 index 000000000000..62441c612f71 --- /dev/null +++ b/tests/pos/wildcards.scala @@ -0,0 +1,4 @@ +object Test { + val xs: List[?] = List(1, 2, 3) + val ys: Map[? <: AnyRef, ? >: Null] = Map() +} \ No newline at end of file From 3db1f1442f543c51db1573bae4251820219f9c3f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 5 Jun 2019 15:48:32 +0200 Subject: [PATCH 2/2] add link to sidebar --- docs/sidebar.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sidebar.yml b/docs/sidebar.yml index 9064736fc12d..5cf4d3f3e28e 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -99,6 +99,8 @@ sidebar: url: docs/reference/changed-features/structural-types.html - title: Operators url: docs/reference/changed-features/operators.html + - title: Wildcard Types + url: docs/reference/changed-features/wildcards.html - title: Type Checking url: docs/reference/changed-features/type-checking.html - title: Type Inference