From 1b3d6bc93ca529742f2ea6d8d92fa880d3d62394 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Fri, 12 Dec 2025 00:39:35 +0100 Subject: [PATCH 01/11] Add error codes E001-E100 (excluding inactive) --- docs/_docs/reference/error-codes/E001.md | 83 ++++++++++++++ docs/_docs/reference/error-codes/E002.md | 85 +++++++++++++++ docs/_docs/reference/error-codes/E003.md | 52 +++++++++ docs/_docs/reference/error-codes/E004.md | 47 ++++++++ docs/_docs/reference/error-codes/E005.md | 55 ++++++++++ docs/_docs/reference/error-codes/E006.md | 58 ++++++++++ docs/_docs/reference/error-codes/E007.md | 51 +++++++++ docs/_docs/reference/error-codes/E008.md | 53 +++++++++ docs/_docs/reference/error-codes/E009.md | 56 ++++++++++ docs/_docs/reference/error-codes/E011.md | 52 +++++++++ docs/_docs/reference/error-codes/E012.md | 65 +++++++++++ docs/_docs/reference/error-codes/E013.md | 58 ++++++++++ docs/_docs/reference/error-codes/E015.md | 41 +++++++ docs/_docs/reference/error-codes/E016.md | 54 +++++++++ docs/_docs/reference/error-codes/E017.md | 64 +++++++++++ docs/_docs/reference/error-codes/E018.md | 54 +++++++++ docs/_docs/reference/error-codes/E019.md | 51 +++++++++ docs/_docs/reference/error-codes/E020.md | 71 ++++++++++++ docs/_docs/reference/error-codes/E021.md | 65 +++++++++++ docs/_docs/reference/error-codes/E022.md | 60 ++++++++++ docs/_docs/reference/error-codes/E023.md | 58 ++++++++++ docs/_docs/reference/error-codes/E024.md | 57 ++++++++++ docs/_docs/reference/error-codes/E025.md | 53 +++++++++ docs/_docs/reference/error-codes/E026.md | 43 ++++++++ docs/_docs/reference/error-codes/E027.md | 40 +++++++ docs/_docs/reference/error-codes/E028.md | 52 +++++++++ docs/_docs/reference/error-codes/E029.md | 62 +++++++++++ docs/_docs/reference/error-codes/E030.md | 45 ++++++++ docs/_docs/reference/error-codes/E031.md | 46 ++++++++ docs/_docs/reference/error-codes/E032.md | 75 +++++++++++++ docs/_docs/reference/error-codes/E033.md | 51 +++++++++ docs/_docs/reference/error-codes/E034.md | 52 +++++++++ docs/_docs/reference/error-codes/E035.md | 52 +++++++++ docs/_docs/reference/error-codes/E037.md | 57 ++++++++++ docs/_docs/reference/error-codes/E038.md | 53 +++++++++ docs/_docs/reference/error-codes/E039.md | 51 +++++++++ docs/_docs/reference/error-codes/E040.md | 41 +++++++ docs/_docs/reference/error-codes/E041.md | 65 +++++++++++ docs/_docs/reference/error-codes/E042.md | 65 +++++++++++ docs/_docs/reference/error-codes/E043.md | 51 +++++++++ docs/_docs/reference/error-codes/E044.md | 51 +++++++++ docs/_docs/reference/error-codes/E045.md | 35 ++++++ docs/_docs/reference/error-codes/E046.md | 49 +++++++++ docs/_docs/reference/error-codes/E047.md | 42 +++++++ docs/_docs/reference/error-codes/E048.md | 62 +++++++++++ docs/_docs/reference/error-codes/E049.md | 66 +++++++++++ docs/_docs/reference/error-codes/E050.md | 57 ++++++++++ docs/_docs/reference/error-codes/E051.md | 56 ++++++++++ docs/_docs/reference/error-codes/E052.md | 52 +++++++++ docs/_docs/reference/error-codes/E053.md | 50 +++++++++ docs/_docs/reference/error-codes/E055.md | 48 ++++++++ docs/_docs/reference/error-codes/E056.md | 41 +++++++ docs/_docs/reference/error-codes/E057.md | 47 ++++++++ docs/_docs/reference/error-codes/E058.md | 68 ++++++++++++ docs/_docs/reference/error-codes/E059.md | 66 +++++++++++ docs/_docs/reference/error-codes/E060.md | 44 ++++++++ docs/_docs/reference/error-codes/E062.md | 47 ++++++++ docs/_docs/reference/error-codes/E063.md | 45 ++++++++ docs/_docs/reference/error-codes/E064.md | 55 ++++++++++ docs/_docs/reference/error-codes/E065.md | 49 +++++++++ docs/_docs/reference/error-codes/E066.md | 44 ++++++++ docs/_docs/reference/error-codes/E067.md | 47 ++++++++ docs/_docs/reference/error-codes/E068.md | 45 ++++++++ docs/_docs/reference/error-codes/E069.md | 45 ++++++++ docs/_docs/reference/error-codes/E070.md | 46 ++++++++ docs/_docs/reference/error-codes/E071.md | 44 ++++++++ docs/_docs/reference/error-codes/E072.md | 46 ++++++++ docs/_docs/reference/error-codes/E073.md | 54 +++++++++ docs/_docs/reference/error-codes/E074.md | 44 ++++++++ docs/_docs/reference/error-codes/E075.md | 49 +++++++++ docs/_docs/reference/error-codes/E076.md | 47 ++++++++ docs/_docs/reference/error-codes/E077.md | 41 +++++++ docs/_docs/reference/error-codes/E078.md | 41 +++++++ docs/_docs/reference/error-codes/E081.md | 48 ++++++++ docs/_docs/reference/error-codes/E082.md | 54 +++++++++ docs/_docs/reference/error-codes/E083.md | 49 +++++++++ docs/_docs/reference/error-codes/E084.md | 57 ++++++++++ docs/_docs/reference/error-codes/E085.md | 41 +++++++ docs/_docs/reference/error-codes/E086.md | 41 +++++++ docs/_docs/reference/error-codes/E087.md | 44 ++++++++ docs/_docs/reference/error-codes/E088.md | 41 +++++++ docs/_docs/reference/error-codes/E089.md | 47 ++++++++ docs/_docs/reference/error-codes/E090.md | 47 ++++++++ docs/_docs/reference/error-codes/E091.md | 42 +++++++ docs/_docs/reference/error-codes/E092.md | 56 ++++++++++ docs/_docs/reference/error-codes/E093.md | 50 +++++++++ docs/_docs/reference/error-codes/E094.md | 47 ++++++++ docs/_docs/reference/error-codes/E095.md | 54 +++++++++ docs/_docs/reference/error-codes/E096.md | 56 ++++++++++ docs/_docs/reference/error-codes/E097.md | 60 ++++++++++ docs/_docs/reference/error-codes/E098.md | 55 ++++++++++ docs/_docs/reference/error-codes/E099.md | 36 ++++++ docs/_docs/reference/error-codes/E100.md | 47 ++++++++ .../reference/error-codes/error-codes.md | 3 + docs/sidebar.yml | 103 ++++++++++++++++++ 95 files changed, 4945 insertions(+) create mode 100644 docs/_docs/reference/error-codes/E001.md create mode 100644 docs/_docs/reference/error-codes/E002.md create mode 100644 docs/_docs/reference/error-codes/E003.md create mode 100644 docs/_docs/reference/error-codes/E004.md create mode 100644 docs/_docs/reference/error-codes/E005.md create mode 100644 docs/_docs/reference/error-codes/E006.md create mode 100644 docs/_docs/reference/error-codes/E007.md create mode 100644 docs/_docs/reference/error-codes/E008.md create mode 100644 docs/_docs/reference/error-codes/E009.md create mode 100644 docs/_docs/reference/error-codes/E011.md create mode 100644 docs/_docs/reference/error-codes/E012.md create mode 100644 docs/_docs/reference/error-codes/E013.md create mode 100644 docs/_docs/reference/error-codes/E015.md create mode 100644 docs/_docs/reference/error-codes/E016.md create mode 100644 docs/_docs/reference/error-codes/E017.md create mode 100644 docs/_docs/reference/error-codes/E018.md create mode 100644 docs/_docs/reference/error-codes/E019.md create mode 100644 docs/_docs/reference/error-codes/E020.md create mode 100644 docs/_docs/reference/error-codes/E021.md create mode 100644 docs/_docs/reference/error-codes/E022.md create mode 100644 docs/_docs/reference/error-codes/E023.md create mode 100644 docs/_docs/reference/error-codes/E024.md create mode 100644 docs/_docs/reference/error-codes/E025.md create mode 100644 docs/_docs/reference/error-codes/E026.md create mode 100644 docs/_docs/reference/error-codes/E027.md create mode 100644 docs/_docs/reference/error-codes/E028.md create mode 100644 docs/_docs/reference/error-codes/E029.md create mode 100644 docs/_docs/reference/error-codes/E030.md create mode 100644 docs/_docs/reference/error-codes/E031.md create mode 100644 docs/_docs/reference/error-codes/E032.md create mode 100644 docs/_docs/reference/error-codes/E033.md create mode 100644 docs/_docs/reference/error-codes/E034.md create mode 100644 docs/_docs/reference/error-codes/E035.md create mode 100644 docs/_docs/reference/error-codes/E037.md create mode 100644 docs/_docs/reference/error-codes/E038.md create mode 100644 docs/_docs/reference/error-codes/E039.md create mode 100644 docs/_docs/reference/error-codes/E040.md create mode 100644 docs/_docs/reference/error-codes/E041.md create mode 100644 docs/_docs/reference/error-codes/E042.md create mode 100644 docs/_docs/reference/error-codes/E043.md create mode 100644 docs/_docs/reference/error-codes/E044.md create mode 100644 docs/_docs/reference/error-codes/E045.md create mode 100644 docs/_docs/reference/error-codes/E046.md create mode 100644 docs/_docs/reference/error-codes/E047.md create mode 100644 docs/_docs/reference/error-codes/E048.md create mode 100644 docs/_docs/reference/error-codes/E049.md create mode 100644 docs/_docs/reference/error-codes/E050.md create mode 100644 docs/_docs/reference/error-codes/E051.md create mode 100644 docs/_docs/reference/error-codes/E052.md create mode 100644 docs/_docs/reference/error-codes/E053.md create mode 100644 docs/_docs/reference/error-codes/E055.md create mode 100644 docs/_docs/reference/error-codes/E056.md create mode 100644 docs/_docs/reference/error-codes/E057.md create mode 100644 docs/_docs/reference/error-codes/E058.md create mode 100644 docs/_docs/reference/error-codes/E059.md create mode 100644 docs/_docs/reference/error-codes/E060.md create mode 100644 docs/_docs/reference/error-codes/E062.md create mode 100644 docs/_docs/reference/error-codes/E063.md create mode 100644 docs/_docs/reference/error-codes/E064.md create mode 100644 docs/_docs/reference/error-codes/E065.md create mode 100644 docs/_docs/reference/error-codes/E066.md create mode 100644 docs/_docs/reference/error-codes/E067.md create mode 100644 docs/_docs/reference/error-codes/E068.md create mode 100644 docs/_docs/reference/error-codes/E069.md create mode 100644 docs/_docs/reference/error-codes/E070.md create mode 100644 docs/_docs/reference/error-codes/E071.md create mode 100644 docs/_docs/reference/error-codes/E072.md create mode 100644 docs/_docs/reference/error-codes/E073.md create mode 100644 docs/_docs/reference/error-codes/E074.md create mode 100644 docs/_docs/reference/error-codes/E075.md create mode 100644 docs/_docs/reference/error-codes/E076.md create mode 100644 docs/_docs/reference/error-codes/E077.md create mode 100644 docs/_docs/reference/error-codes/E078.md create mode 100644 docs/_docs/reference/error-codes/E081.md create mode 100644 docs/_docs/reference/error-codes/E082.md create mode 100644 docs/_docs/reference/error-codes/E083.md create mode 100644 docs/_docs/reference/error-codes/E084.md create mode 100644 docs/_docs/reference/error-codes/E085.md create mode 100644 docs/_docs/reference/error-codes/E086.md create mode 100644 docs/_docs/reference/error-codes/E087.md create mode 100644 docs/_docs/reference/error-codes/E088.md create mode 100644 docs/_docs/reference/error-codes/E089.md create mode 100644 docs/_docs/reference/error-codes/E090.md create mode 100644 docs/_docs/reference/error-codes/E091.md create mode 100644 docs/_docs/reference/error-codes/E092.md create mode 100644 docs/_docs/reference/error-codes/E093.md create mode 100644 docs/_docs/reference/error-codes/E094.md create mode 100644 docs/_docs/reference/error-codes/E095.md create mode 100644 docs/_docs/reference/error-codes/E096.md create mode 100644 docs/_docs/reference/error-codes/E097.md create mode 100644 docs/_docs/reference/error-codes/E098.md create mode 100644 docs/_docs/reference/error-codes/E099.md create mode 100644 docs/_docs/reference/error-codes/E100.md create mode 100644 docs/_docs/reference/error-codes/error-codes.md diff --git a/docs/_docs/reference/error-codes/E001.md b/docs/_docs/reference/error-codes/E001.md new file mode 100644 index 000000000000..7e759ee2f919 --- /dev/null +++ b/docs/_docs/reference/error-codes/E001.md @@ -0,0 +1,83 @@ +--- +title: E001: Empty Catch Block +kind: Error +--- + +# E001: Empty Catch Block + +This error is emitted when a `try` expression has a `catch` block that does not contain any case handlers. + +A `try` expression should be followed by some mechanism to handle any exceptions +thrown. Typically a `catch` expression follows the `try` and pattern matches +on any expected exceptions. For example: + +```scala +try { + println("hello") +} catch { + case e: Exception => ??? +} +``` + +It is also possible to follow a `try` immediately by a `finally` - letting the +exception propagate - but still allowing for some clean up in `finally`: + +```scala +try { + println("hello") +} finally { + // perform your cleanup here! +} +``` + +It is recommended to use the `NonFatal` extractor to catch all exceptions as it +correctly handles transfer functions like `return`. + +--- + +## Example + +```scala sc:fail +@main def test() = + try { + println("hello") + } catch { } +``` + +### Error + +```scala sc:nocompile +-- [E001] Syntax Error: example.scala:4:4 +4 | } catch { } + | ^^^^^^^^^ + | The catch block does not contain a valid expression, try + | adding a case like - case e: Exception => to the block +``` + +### Solution + +```scala sc:compile +// Remove redundant 'try' block +println("hello") +``` + +```scala sc:compile +// Alternative: Add a case handler to catch exceptions +import scala.util.control.NonFatal + +try { + println("hello") +} catch { + case NonFatal(e) => println(s"Caught: $e") +} +``` + +```scala sc:compile +// Alternative: use finally instead if you only need cleanup +try { + println("hello") +} finally { + println("cleanup") +} +``` + diff --git a/docs/_docs/reference/error-codes/E002.md b/docs/_docs/reference/error-codes/E002.md new file mode 100644 index 000000000000..752fd4d45861 --- /dev/null +++ b/docs/_docs/reference/error-codes/E002.md @@ -0,0 +1,85 @@ +--- +title: E002: Empty Catch And Finally Block +kind: Warning +--- + +# E002: Empty Catch And Finally Block + +This warning is emitted when a `try` expression has neither a `catch` block nor a `finally` block. Such a `try` is redundant since no exceptions are handled. + +A `try` expression should be followed by some mechanism to handle any exceptions +thrown. Typically a `catch` expression follows the `try` and pattern matches +on any expected exceptions. For example: + +```scala +try { + println("hello") +} catch { + case e: Exception => ??? +} +``` + +It is also possible to follow a `try` immediately by a `finally` - letting the +exception propagate - but still allowing for some clean up in `finally`: + +```scala +try { + println("hello") +} finally { + // perform your cleanup here! +} +``` + +It is recommended to use the `NonFatal` extractor to catch all exceptions as it +correctly handles transfer functions like `return`. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +@main def test() = + try { + println("hello") + } +``` + +### Warning + +```scala sc:nocompile +-- [E002] Syntax Warning: example.scala:2:2 +2 | try { + | ^ + | A try without catch or finally is equivalent to putting + | its body in a block; no exceptions are handled. +3 | println("hello") +4 | } +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Remove redundant 'try' block +println("hello") +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Add a catch block to handle exceptions +import scala.util.control.NonFatal + +try { + println("hello") +} catch { + case NonFatal(e) => println(s"Caught: $e") +} +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Add a finally block for cleanup +try { + println("hello") +} finally { + println("cleanup") +} +``` + diff --git a/docs/_docs/reference/error-codes/E003.md b/docs/_docs/reference/error-codes/E003.md new file mode 100644 index 000000000000..a6aa121348ad --- /dev/null +++ b/docs/_docs/reference/error-codes/E003.md @@ -0,0 +1,52 @@ +--- +title: E003: Deprecated With Operator +kind: Warning +--- + +# E003: Deprecated With Operator + +This warning is emitted when using `with` as a type operator to create compound types. In Scala 3, `with` has been deprecated in favor of intersection types using `&`. + +Dotty introduces intersection types - `&` types. These replace the +use of the `with` keyword. There are a few differences in +semantics between intersection types and using `with`. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +trait A +trait B +def test(x: A with B): Unit = () +``` + +### Warning + +```scala sc:nocompile +-- [E003] Syntax Warning: example.scala:3:14 +3 |def test(x: A with B): Unit = () + | ^^^^ + |with as a type operator has been deprecated; use & instead + |This construct can be rewritten automatically under -rewrite -source 3.4-migration. +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use intersection type operator & instead of with +trait A +trait B +def test(x: A & B): Unit = () +``` + +```scala sc:compile sc-opts:-Werror +// The change also applies to type aliases and class definitions +trait Readable +trait Writable + +type ReadWrite = Readable & Writable + +class File extends Readable, Writable +``` + diff --git a/docs/_docs/reference/error-codes/E004.md b/docs/_docs/reference/error-codes/E004.md new file mode 100644 index 000000000000..4f11b09e418a --- /dev/null +++ b/docs/_docs/reference/error-codes/E004.md @@ -0,0 +1,47 @@ +--- +title: E004: Case Class Missing Param List +kind: Error +--- + +# E004: Case Class Missing Param List + +This error is emitted when a `case class` is defined without any parameter list. In Scala 3, case classes must have at least one parameter list. + +`Empty` must have at least one parameter list. If you would rather +have a singleton representation of `Empty`, use a `case object`. +Or, add an explicit `()` as a parameter list to `Empty`. + +--- + +## Example + +```scala sc:fail +case class Empty +``` + +### Error + +```scala sc:nocompile +-- [E004] Syntax Error: example.scala:1:11 +1 |case class Empty + | ^^^^^ + | A case class must have at least one parameter list +``` + +### Solution + +```scala sc:compile +// Use case object for singleton representation +case object Empty +``` + +```scala sc:compile +// Add an explicit empty parameter list +case class Empty() +``` + +```scala sc:compile +// Or define actual parameters +case class Empty(value: String) +``` + diff --git a/docs/_docs/reference/error-codes/E005.md b/docs/_docs/reference/error-codes/E005.md new file mode 100644 index 000000000000..c6ea5996f302 --- /dev/null +++ b/docs/_docs/reference/error-codes/E005.md @@ -0,0 +1,55 @@ +--- +title: E005: Duplicate Bind +kind: Error +--- + +# E005: Duplicate Bind + +This error is emitted when the same variable name is used more than once in a pattern match case. Each bound variable in a `case` pattern must have a unique name. + +For each `case` bound variable names have to be unique. In: + +```scala +case (a, a) => a +``` + +`a` is not unique. Rename one of the bound variables! + +--- + +## Example + +```scala sc:fail +def test(x: Any) = x match + case (a, a) => a +``` + +### Error + +```scala sc:nocompile +-- [E005] Naming Error: example.scala:2:11 +2 | case (a, a) => a + | ^ + | duplicate pattern variable: a +``` + +### Solution + +```scala sc:compile +// Use unique names for each bound variable +def test(x: Any) = x match + case (a, b) => (a, b) +``` + +```scala sc:compile +// Use wildcard _ if you don't need the value +def test(x: Any) = x match + case (a, _) => a +``` + +```scala sc:compile +// Use a guard if you want to match equal values +def test(x: Any) = x match + case (a, b) if a == b => a +``` + diff --git a/docs/_docs/reference/error-codes/E006.md b/docs/_docs/reference/error-codes/E006.md new file mode 100644 index 000000000000..fbb1903506ed --- /dev/null +++ b/docs/_docs/reference/error-codes/E006.md @@ -0,0 +1,58 @@ +--- +title: E006: Missing Ident +kind: Error +--- + +# E006: Missing Ident + +This error is emitted when a referenced identifier (value, method, type, etc.) cannot be found in the current scope. + +Each identifier in Scala needs a matching declaration. There are two kinds of +identifiers: type identifiers and value identifiers. Value identifiers are introduced +by `val`, `def`, or `object` declarations. Type identifiers are introduced by `type`, +`class`, `enum`, or `trait` declarations. + +Identifiers refer to matching declarations in their environment, or they can be +imported from elsewhere. + +Possible reasons why no matching declaration was found: +* The declaration or the use is mis-spelt. +* An import is missing. + +--- + +## Example + +```scala sc:fail +val result = unknownIdentifier +``` + +### Error + +```scala sc:nocompile +-- [E006] Not Found Error: example.scala:1:13 +1 |val result = unknownIdentifier + | ^^^^^^^^^^^^^^^^^ + | Not found: unknownIdentifier +``` + +### Solution + +```scala sc:compile +// Declare the identifier before using it +val unknownIdentifier = 42 +val result = unknownIdentifier +``` + +```scala sc:compile +// Or import it from another scope +import scala.math.Pi +val result = Pi +``` + +```scala sc:compile +// Fix the spelling if it was a typo +val knownIdentifier = 42 +val result = knownIdentifier +``` + diff --git a/docs/_docs/reference/error-codes/E007.md b/docs/_docs/reference/error-codes/E007.md new file mode 100644 index 000000000000..5bceb70f9a55 --- /dev/null +++ b/docs/_docs/reference/error-codes/E007.md @@ -0,0 +1,51 @@ +--- +title: E007: Type Mismatch +kind: Error +--- + +# E007: Type Mismatch + +This error is emitted when an expression has a different type than what is expected in that context. + +The compiler found an expression of one type where a different type was expected. +This commonly occurs when: + +* Assigning a value to a variable with an incompatible type annotation +* Passing an argument to a function that expects a different type +* Returning a value from a method with an incompatible return type + +--- + +## Example + +```scala sc:fail +val x: String = 42 +``` + +### Error + +```scala sc:nocompile +-- [E007] Type Mismatch Error: example.scala:1:16 +1 |val x: String = 42 + | ^^ + | Found: (42 : Int) + | Required: String +``` + +### Solution + +```scala sc:compile +// Convert the value to the expected type +val x: String = 42.toString +``` + +```scala sc:compile +// Or change the type annotation to match the value +val x: Int = 42 +``` + +```scala sc:compile +// Or use a value of the correct type +val x: String = "42" +``` + diff --git a/docs/_docs/reference/error-codes/E008.md b/docs/_docs/reference/error-codes/E008.md new file mode 100644 index 000000000000..649b0171a433 --- /dev/null +++ b/docs/_docs/reference/error-codes/E008.md @@ -0,0 +1,53 @@ +--- +title: E008: Not A Member +kind: Error +--- + +# E008: Not A Member + +This error is emitted when trying to access a member (method, field, or type) that does not exist on the given type. + +The compiler cannot find a member with the specified name on the given type. +This commonly occurs when: + +* Misspelling a method or field name +* Using a method that doesn't exist on the type +* Forgetting to import an extension method + +--- + +## Example + +```scala sc:fail +val result = "hello".unknownMethod +``` + +### Error + +```scala sc:nocompile +-- [E008] Not Found Error: example.scala:1:13 +1 |val result = "hello".unknownMethod + | ^^^^^^^^^^^^^^^^^^^^^ + | value unknownMethod is not a member of String +``` + +### Solution + +```scala sc:compile +// Use a method that exists on the type +val result = "hello".toUpperCase +``` + +```scala sc:compile +// Check the spelling and use the correct method name +val result = "hello".length +``` + +```scala sc:compile +// Import extension methods if needed +extension (s: String) + def unknownMethod: String = s.reverse + +val result = "hello".unknownMethod +``` + diff --git a/docs/_docs/reference/error-codes/E009.md b/docs/_docs/reference/error-codes/E009.md new file mode 100644 index 000000000000..d0b022cfea59 --- /dev/null +++ b/docs/_docs/reference/error-codes/E009.md @@ -0,0 +1,56 @@ +--- +title: E009: Early Definitions Not Supported +kind: Error +--- + +# E009: Early Definitions Not Supported + +This error is emitted when using early definitions (early initializers), which were a feature in Scala 2 but are no longer supported in Scala 3. Use trait parameters instead. + +Earlier versions of Scala did not support trait parameters and "early definitions" +(also known as "early initializers") were used as an alternative to initialize values +before the superclass constructor runs. + +In Scala 3, trait parameters provide a cleaner solution to this problem. + +--- + +## Example + +```scala sc:fail +trait Logging: + val logFile: String + println(s"Logging to $logFile") + +class App extends { val logFile = "app.log" } with Logging +``` + +### Error + +```scala sc:nocompile +-- [E009] Syntax Error: example.scala:5:49 +5 |class App extends { val logFile = "app.log" } with Logging + | ^^^^ + | Early definitions are not supported; use trait parameters instead +``` + +### Solution + +```scala sc:compile +// Use trait parameters instead of early definitions +trait Logging(logFile: String): + println(s"Logging to $logFile") + +class App extends Logging("app.log") +``` + +```scala sc:compile +// Alternative: Use a lazy val to defer initialization +trait Logging: + def logFile: String + lazy val logger = s"Logging to $logFile" + +class App extends Logging: + val logFile = "app.log" +``` + diff --git a/docs/_docs/reference/error-codes/E011.md b/docs/_docs/reference/error-codes/E011.md new file mode 100644 index 000000000000..71a8aface0a6 --- /dev/null +++ b/docs/_docs/reference/error-codes/E011.md @@ -0,0 +1,52 @@ +--- +title: E011: Implicit Case Class +kind: Error +--- + +# E011: Implicit Case Class + +This error is emitted when a `case class` is defined with the `implicit` modifier. Case classes cannot be implicit in Scala. + +Implicit classes may not be case classes. Case classes automatically generate companion +objects and various methods (like `apply`, `unapply`, `copy`, etc.) that would conflict +with implicit class semantics. + +If you want implicit conversions, use a plain implicit class instead. + +--- + +## Example + +```scala sc:fail +implicit case class Wrapper(value: String) +``` + +### Error + +```scala sc:nocompile +-- [E011] Syntax Error: example.scala:1:20 +1 |implicit case class Wrapper(value: String) + |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |A case class may not be defined as implicit +``` + +### Solution + +```scala sc:compile +// Use a regular implicit class +object Implicits: + implicit class Wrapper(val value: String): + def doubled: String = value + value + +import Implicits.* +val result = "hello".doubled +``` + +```scala sc:compile +// In Scala 3, prefer extension methods over implicit classes +extension (value: String) + def doubled: String = value + value + +val result = "hello".doubled +``` + diff --git a/docs/_docs/reference/error-codes/E012.md b/docs/_docs/reference/error-codes/E012.md new file mode 100644 index 000000000000..f460a72c6f30 --- /dev/null +++ b/docs/_docs/reference/error-codes/E012.md @@ -0,0 +1,65 @@ +--- +title: E012: Implicit Class Primary Constructor Arity +kind: Error +--- + +# E012: Implicit Class Primary Constructor Arity + +This error is emitted when an implicit class has more than one non-implicit parameter in its primary constructor. Implicit classes must accept exactly one primary constructor parameter. + +Implicit classes may only take one non-implicit argument in their constructor. +This restriction exists because implicit classes are designed for implicit conversions, +which convert a single value of one type to another type. + +While it's possible to create an implicit class with more than one non-implicit argument, +such classes aren't used during implicit lookup. + +--- + +## Example + +```scala sc:fail +object Implicits: + implicit class Wrapper(a: Int, b: String): + def combined: String = s"$a-$b" +``` + +### Error + +```scala sc:nocompile +-- [E012] Syntax Error: example.scala:2:17 +2 | implicit class Wrapper(a: Int, b: String): + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Implicit classes must accept exactly one primary constructor parameter +``` + +### Solution + +```scala sc:compile +// Use exactly one parameter +object Implicits: + implicit class RichInt(val value: Int): + def doubled: Int = value * 2 + +import Implicits.* +val result = 42.doubled +``` + +```scala sc:compile +// Additional parameters can be implicit +object Implicits: + implicit class Formatter(val value: Int)(using format: String = "%d"): + def formatted: String = format.format(value) + +import Implicits.* +val result = 42.formatted +``` + +```scala sc:compile +// In Scala 3, prefer extension methods +extension (value: Int) + def doubled: Int = value * 2 + +val result = 42.doubled +``` + diff --git a/docs/_docs/reference/error-codes/E013.md b/docs/_docs/reference/error-codes/E013.md new file mode 100644 index 000000000000..b608f06db38c --- /dev/null +++ b/docs/_docs/reference/error-codes/E013.md @@ -0,0 +1,58 @@ +--- +title: E013: Object May Not Have Self Type +kind: Error +--- + +# E013: Object May Not Have Self Type + +This error is emitted when an `object` definition includes a self type annotation. Objects in Scala cannot have self types. + +Self types are used to declare that a class or trait requires another trait to be mixed in. +However, objects are singleton instances and cannot be extended or mixed with other traits +after their definition, making self types meaningless for objects. + +--- + +## Example + +```scala sc:fail +trait Foo + +object Test { self: Foo => } +``` + +### Error + +```scala sc:nocompile +-- [E013] Syntax Error: example.scala:3:14 +3 |object Test { self: Foo => } + | ^^^^^^^^^^^^ + | objects must not have a self type +``` + +### Solution + +```scala sc:compile +// Create a trait or class instead of an object +trait Foo + +class Test extends Foo +``` + +```scala sc:compile +// Or let the object extend the trait directly +trait Foo + +object Test extends Foo +``` + +```scala sc:compile +// Or use a class with a self type if you need the pattern +trait Foo +trait Bar + +class Test { self: Foo with Bar => + // ... +} +``` + diff --git a/docs/_docs/reference/error-codes/E015.md b/docs/_docs/reference/error-codes/E015.md new file mode 100644 index 000000000000..928c10a9ef23 --- /dev/null +++ b/docs/_docs/reference/error-codes/E015.md @@ -0,0 +1,41 @@ +--- +title: E015: Repeated Modifier +kind: Error +--- + +# E015: Repeated Modifier + +This error is emitted when the same modifier is specified more than once on a definition. + +This happens when you accidentally specify the same modifier twice on a definition. +Each modifier should only appear once. + +--- + +## Example + +```scala sc:fail +private private val x = 1 +``` + +### Error + +```scala sc:nocompile +-- [E015] Syntax Error: example.scala:1:8 +1 |private private val x = 1 + | ^^^^^^^ + | Repeated modifier private +``` + +### Solution + +```scala sc:compile +// Remove the duplicate modifier +private val x = 1 +``` + +```scala sc:compile +// If you meant to use different modifiers, use the correct combination +private final val x = 1 +``` + diff --git a/docs/_docs/reference/error-codes/E016.md b/docs/_docs/reference/error-codes/E016.md new file mode 100644 index 000000000000..2ba3a8e9f5b2 --- /dev/null +++ b/docs/_docs/reference/error-codes/E016.md @@ -0,0 +1,54 @@ +--- +title: E016: Interpolated String Error +kind: Error +--- + +# E016: Interpolated String Error + +This error is emitted when an interpolated string contains invalid syntax after a `$` sign. An identifier or a block expression `${...}` is expected. + +In string interpolation, the `$` character is used to embed expressions in strings. +After `$`, you can use either: + +* A simple identifier: `$name` +* A block expression: `${expression}` + +If you need to include a complex expression (like `new Object()`), you must wrap it in braces. + +--- + +## Example + +```scala sc:fail +val x = s"$new Object()" +``` + +### Error + +```scala sc:nocompile +-- [E016] Syntax Error: example.scala:1:11 +1 |val x = s"$new Object()" + | ^ + | Error in interpolated string: identifier or block expected +``` + +### Solution + +```scala sc:compile +// Wrap complex expressions in braces +val x = s"${new Object()}" +``` + +```scala sc:compile +// Simple identifiers don't need braces +val name = "World" +val greeting = s"Hello, $name!" +``` + +```scala sc:compile +// Use braces for member access +case class Person(name: String) +val person = Person("Alice") +val greeting = s"Hello, ${person.name}!" +``` + diff --git a/docs/_docs/reference/error-codes/E017.md b/docs/_docs/reference/error-codes/E017.md new file mode 100644 index 000000000000..67caada27a87 --- /dev/null +++ b/docs/_docs/reference/error-codes/E017.md @@ -0,0 +1,64 @@ +--- +title: E017: Unbound Placeholder Parameter +kind: Error +--- + +# E017: Unbound Placeholder Parameter + +This error is emitted when the underscore (`_`) placeholder syntax is used in a context where it cannot be bound to a parameter. + +The `_` placeholder syntax was used where it could not be bound. +Consider explicitly writing the variable binding. + +This can be done by replacing `_` with a variable (eg. `x`) +and adding `x =>` where applicable. + +Common incorrect uses: + +* Using `_` in a `val` definition instead of in a lambda +* Using `_` outside of a function context +* Using `_` without a type annotation where type cannot be inferred + +--- + +## Example + +```scala sc:fail +val x = _ +``` + +### Error + +```scala sc:nocompile +-- [E017] Syntax Error: example.scala:1:8 +1 |val x = _ + | ^ + | Unbound placeholder parameter; incorrect use of _ +``` + +### Solution + +```scala sc:compile +// Use an explicit lambda with a named parameter +val f: Int => Int = x => x + 1 +``` + +```scala sc:compile +// The placeholder syntax works in lambda contexts with clear types +val f: Int => Int = _ + 1 +``` + +```scala sc:compile +// For uninitialized fields, use var (only in classes, not local scope) +class Example: + var x: Int = _ // Uninitialized field, defaults to 0 +``` + +```scala sc:compile +// Use wildcard in pattern matching +val list = List(1, 2, 3) +val head = list match + case h :: _ => h + case _ => 0 +``` + diff --git a/docs/_docs/reference/error-codes/E018.md b/docs/_docs/reference/error-codes/E018.md new file mode 100644 index 000000000000..e8eae8bfa944 --- /dev/null +++ b/docs/_docs/reference/error-codes/E018.md @@ -0,0 +1,54 @@ +--- +title: E018: Illegal Start Simple Expr +kind: Error +--- + +# E018: Illegal Start Simple Expr + +This error is emitted when the compiler expects an expression but finds a token that cannot start an expression. + +An expression cannot start with certain tokens like keywords used in other contexts, +or when the expression is missing entirely. This commonly happens when: + +* An expression is incomplete (missing the else branch, missing operand, etc.) +* A keyword is used where an expression is expected +* There's a syntax error that confuses the parser + +--- + +## Example + +```scala sc:fail +val x = if true then 1 else +``` + +### Error + +```scala sc:nocompile +-- [E018] Syntax Error: example.scala:2:0 +2 | + |^ + |expression expected but eof found +``` + +### Solution + +```scala sc:compile +// Complete the expression +val x = if true then 1 else 2 +``` + +```scala sc:compile +// Ensure all branches have expressions +val result = + if true then + "yes" + else + "no" +``` + +```scala sc:compile +// Check for missing operands +val sum = 1 + 2 // not: val sum = 1 + +``` + diff --git a/docs/_docs/reference/error-codes/E019.md b/docs/_docs/reference/error-codes/E019.md new file mode 100644 index 000000000000..e19c9a508d41 --- /dev/null +++ b/docs/_docs/reference/error-codes/E019.md @@ -0,0 +1,51 @@ +--- +title: E019: Missing Return Type +kind: Error +--- + +# E019: Missing Return Type + +This error is emitted when an abstract method declaration is missing its return type. Abstract declarations must have explicit return types. + +An abstract declaration must have a return type. Without a body, the compiler +cannot infer the type of the method, so it must be explicitly specified. + +--- + +## Example + +```scala sc:fail +trait Foo: + def bar +``` + +### Error + +```scala sc:nocompile +-- [E019] Syntax Error: example.scala:2:9 +2 | def bar + | ^ + | Missing return type +``` + +### Solution + +```scala sc:compile +// Add an explicit return type +trait Foo: + def bar: Unit +``` + +```scala sc:compile +// Or provide an implementation (then type can be inferred) +trait Foo: + def bar = println("hello") +``` + +```scala sc:compile +// For methods with parameters +trait Calculator: + def add(a: Int, b: Int): Int + def multiply(a: Int, b: Int): Int +``` + diff --git a/docs/_docs/reference/error-codes/E020.md b/docs/_docs/reference/error-codes/E020.md new file mode 100644 index 000000000000..d1ad40c24bfa --- /dev/null +++ b/docs/_docs/reference/error-codes/E020.md @@ -0,0 +1,71 @@ +--- +title: E020: Yield Or Do Expected In For Comprehension +kind: Error +--- + +# E020: Yield Or Do Expected In For Comprehension + +This error is emitted when a `for` comprehension without parentheses around the enumerators is missing a `yield` or `do` keyword. + +When the enumerators in a for comprehension are not placed in parentheses or +braces, a `do` or `yield` statement is required after the enumerators section. + +You can save some keystrokes by omitting the parentheses and writing: + +```scala +val numbers = for i <- 1 to 3 yield i +``` + +instead of: + +```scala +val numbers = for (i <- 1 to 3) yield i +``` + +but the `yield` keyword is still required. + +For comprehensions that simply perform a side effect without yielding anything +can also be written without parentheses but a `do` keyword has to be included. + +--- + +## Example + +```scala sc:fail +val xs = for i <- 1 to 10 i * 2 +``` + +### Error + +```scala sc:nocompile +-- [E020] Syntax Error: example.scala:1:30 +1 |val xs = for i <- 1 to 10 i * 2 + | ^ + | yield or do expected +``` + +### Solution + +```scala sc:compile +// Add yield to produce a collection +val xs = for i <- 1 to 10 yield i * 2 +``` + +```scala sc:compile +// Use do for side effects +for i <- 1 to 10 do println(i * 2) +``` + +```scala sc:compile +// Or use parentheses (then yield is optional for producing values) +val xs = for (i <- 1 to 10) yield i * 2 +``` + +```scala sc:compile +// With braces for multiple generators +val pairs = for { + i <- 1 to 3 + j <- 1 to 3 +} yield (i, j) +``` + diff --git a/docs/_docs/reference/error-codes/E021.md b/docs/_docs/reference/error-codes/E021.md new file mode 100644 index 000000000000..df236f1a4dce --- /dev/null +++ b/docs/_docs/reference/error-codes/E021.md @@ -0,0 +1,65 @@ +--- +title: E021: Proper Definition Not Found +kind: Error +--- + +# E021: Proper Definition Not Found + +This error is emitted when a `@usecase` annotation in a Scaladoc comment does not contain a proper `def` definition. + +Usecases are only supported for `def`s. They exist because with Scala's +advanced type-system, we sometimes end up with seemingly scary signatures. +The usage of these methods, however, needs not be scary. + +For instance, the `map` function: + +```scala +List(1, 2, 3).map(2 * _) // res: List(2, 4, 6) +``` + +is easy to understand and use - but has a rather bulky signature: + +```scala +def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That +``` + +The `@usecase` annotation allows documenting a simplified signature: + +```scala +/** Map from List[A] => List[B] + * + * @usecase def map[B](f: A => B): List[B] + */ +def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That +``` + +--- + +## Example + +```scala sc:fail +/** + * @usecase val x: Int + */ +def complexMethod[A, B](f: A => B)(implicit ev: Ordering[A]): B = ??? +``` + +### Error + +```scala sc:nocompile +-- DocComment Error: example.scala:2:3 +2 | * @usecase val x: Int + | ^^^^^^^^^^^^^^^^^^^^ + | Proper definition was not found in @usecase +``` + +### Solution + +```scala sc:compile +/** + * Transforms elements. + * @usecase def transform(f: Int => Int): List[Int] + */ +def transform[A, B](f: A => B)(implicit ev: Ordering[A]): List[B] = ??? +``` + diff --git a/docs/_docs/reference/error-codes/E022.md b/docs/_docs/reference/error-codes/E022.md new file mode 100644 index 000000000000..14525bd3819b --- /dev/null +++ b/docs/_docs/reference/error-codes/E022.md @@ -0,0 +1,60 @@ +--- +title: E022: By Name Parameter Not Supported +kind: Error +--- + +# E022: By Name Parameter Not Supported + +This error is emitted when a by-name parameter type (`=> T`) is used in a context where it is not allowed, such as in tuple types. + +By-name parameters act like functions that are only evaluated when referenced, +allowing for lazy evaluation of a parameter. + +By-name parameter types (`=> T`) are only allowed in specific contexts: + +* Method parameters: `def func(f: => Boolean)` +* Function type parameters: `(=> Int) => String` + +They are not allowed in: + +* Tuple types +* Type arguments to generic types (except function types) +* Other contexts where a regular type is expected + +--- + +## Example + +```scala sc:fail +type LazyPair = (=> Int, String) +``` + +### Error + +```scala sc:nocompile +-- [E022] Syntax Error: example.scala:1:17 +1 |type LazyPair = (=> Int, String) + | ^^^^^^ + | By-name parameter type => Int not allowed here. +``` + +### Solution + +```scala sc:compile +// Use a function type instead +type LazyPair = (() => Int, String) +``` + +```scala sc:compile +// By-name is allowed in function types +type LazyFunction = (=> Int) => String + +def example(f: LazyFunction): String = f(42) +``` + +```scala sc:compile +// By-name is allowed in method parameters +def lazyEval(x: => Int, y: String): Unit = + println(s"$y: $x") +``` + diff --git a/docs/_docs/reference/error-codes/E023.md b/docs/_docs/reference/error-codes/E023.md new file mode 100644 index 000000000000..cfde69bcf15c --- /dev/null +++ b/docs/_docs/reference/error-codes/E023.md @@ -0,0 +1,58 @@ +--- +title: E023: Wrong Number Of Type Args +kind: Error +--- + +# E023: Wrong Number Of Type Args + +This error is emitted when a type constructor is applied with the wrong number of type arguments. + +Each generic type has a specific number of type parameters. For example: + +* `List[A]` takes exactly one type parameter +* `Map[K, V]` takes exactly two type parameters +* `Either[L, R]` takes exactly two type parameters + +You must provide exactly the number of type arguments that the type expects. + +--- + +## Example + +```scala sc:fail +val x: List[Int, String] = List() +``` + +### Error + +```scala sc:nocompile +-- [E023] Syntax Error: example.scala:1:7 +1 |val x: List[Int, String] = List() + | ^^^^^^^^^^^^^^^^^ + | Too many type arguments for List[A] + | expected: [A] + | actual: [Int, String] +``` + +### Solution + +```scala sc:compile +// Use the correct number of type arguments +val x: List[Int] = List() +``` + +```scala sc:compile +// For multiple types, use a tuple or a different container +val x: List[(Int, String)] = List() +``` + +```scala sc:compile +// Or use a type that takes multiple parameters +val x: Map[Int, String] = Map() +``` + +```scala sc:compile +// Or use Either for two alternatives +val x: Either[Int, String] = Right("hello") +``` + diff --git a/docs/_docs/reference/error-codes/E024.md b/docs/_docs/reference/error-codes/E024.md new file mode 100644 index 000000000000..77b0fddfb1ee --- /dev/null +++ b/docs/_docs/reference/error-codes/E024.md @@ -0,0 +1,57 @@ +--- +title: E024: Illegal Variable In Pattern Alternative +kind: Error +--- + +# E024: Illegal Variable In Pattern Alternative + +This error is emitted when a variable binding is used in a pattern alternative (`|`). Variables are not allowed in alternative patterns. + +Variables are not allowed within alternate pattern matches. When you use the `|` +operator to combine patterns, each alternative must match independently, and +Scala cannot guarantee that a variable bound in one alternative would have the +same value or even be bound in another alternative. + +--- + +## Example + +```scala sc:fail +def test(pair: (Int, Int)): Int = pair match + case (1, n) | (n, 1) => n + case _ => 0 +``` + +### Error + +```scala sc:nocompile +-- [E024] Syntax Error: example.scala:2:9 +2 | case (1, n) | (n, 1) => n + | ^ + | Illegal variable n in pattern alternative +``` + +### Solution + +```scala sc:compile +// Split into separate cases +def test(pair: (Int, Int)): Int = pair match + case (1, n) => n + case (n, 1) => n + case _ => 0 +``` + +```scala sc:compile +// Use wildcards if you don't need the value +def isEdge(pair: (Int, Int)): Boolean = pair match + case (1, _) | (_, 1) => true + case _ => false +``` + +```scala sc:compile +// Use a guard for more complex conditions +def test(pair: (Int, Int)): Int = pair match + case (a, b) if a == 1 || b == 1 => if a == 1 then b else a + case _ => 0 +``` + diff --git a/docs/_docs/reference/error-codes/E025.md b/docs/_docs/reference/error-codes/E025.md new file mode 100644 index 000000000000..6b498673c77d --- /dev/null +++ b/docs/_docs/reference/error-codes/E025.md @@ -0,0 +1,53 @@ +--- +title: E025: Identifier Expected +kind: Error +--- + +# E025: Identifier Expected + +This error is emitted when the compiler expects a type identifier but finds something that cannot be converted to a type identifier, such as a complex expression. + +An identifier was expected, but a different construct was found. This could be because +an expression or keyword was used where a type identifier is required. + +As a workaround, if the issue is in a return type position, the compiler might be +able to infer the type for you. + +--- + +## Example + +```scala sc:fail +class Foo extends (if true then Int else String) +``` + +### Error + +```scala sc:nocompile +-- [E025] Syntax Error: example.scala:1:17 +1 |class Foo extends (if true then Int else String) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | identifier expected +``` + +### Solution + +```scala sc:compile +// Use a proper type identifier +class Foo extends AnyRef +``` + +```scala sc:compile +// For conditional types, use match types or type aliases +type MyType = Int + +class Foo extends AnyRef: + type T = MyType +``` + +```scala sc:compile +// Or use a union type for alternatives +class Foo: + def getValue: Int | String = 42 +``` + diff --git a/docs/_docs/reference/error-codes/E026.md b/docs/_docs/reference/error-codes/E026.md new file mode 100644 index 000000000000..b517e3a6b357 --- /dev/null +++ b/docs/_docs/reference/error-codes/E026.md @@ -0,0 +1,43 @@ +--- +title: E026: Auxiliary Constructor Needs Non-Implicit Parameter +kind: Error +--- + +# E026: Auxiliary Constructor Needs Non-Implicit Parameter + +This error is emitted when an auxiliary constructor (secondary constructor) only has implicit parameter lists without any non-implicit parameters. + +Only the primary constructor is allowed to have an implicit-only parameter list. Auxiliary constructors must have at least one non-implicit parameter list. When a primary constructor has an implicit argslist, auxiliary constructors that call the primary constructor must specify the implicit value explicitly. + +--- + +## Example + +```scala sc:fail +class Example(implicit x: Int): + def this(implicit x: String, y: Int) = this() +``` + +### Error + +```scala sc:nocompile +-- [E026] Syntax Error: example.scala:2:6 +2 | def this(implicit x: String, y: Int) = this() + | ^^^^ + | Auxiliary constructor needs non-implicit parameter list +``` + +### Solution + +```scala sc:compile +// Add an empty non-implicit parameter list before the implicit one +class Example(implicit x: Int): + def this()(implicit x: String, y: Int) = this()(using y) +``` + +```scala sc:compile +// Alternative: use an explicit non-implicit parameter with a different type +class Example(implicit x: Int): + def this(x: String, y: Int) = this()(using y) +``` + diff --git a/docs/_docs/reference/error-codes/E027.md b/docs/_docs/reference/error-codes/E027.md new file mode 100644 index 000000000000..52e0d5931a11 --- /dev/null +++ b/docs/_docs/reference/error-codes/E027.md @@ -0,0 +1,40 @@ +--- +title: E027: Varargs Parameter Must Come Last +kind: Error +--- + +# E027: Varargs Parameter Must Come Last + +This error is emitted when a varargs parameter (repeated parameter) is not placed at the end of a parameter list. + +The varargs field must be the last parameter in the method signature. Attempting to define a parameter after a varargs field in the same parameter list is not allowed. + +--- + +## Example + +```scala sc:fail +def example(xs: Int*, y: Int) = xs.sum + y +``` + +### Error + +```scala sc:nocompile +-- [E027] Syntax Error: example.scala:1:16 +1 |def example(xs: Int*, y: Int) = xs.sum + y + | ^ + | varargs parameter must come last +``` + +### Solution + +```scala sc:compile +// Place the varargs parameter last +def example(y: Int, xs: Int*) = xs.sum + y +``` + +```scala sc:compile +// Alternative: use a separate parameter list +def example(y: Int)(xs: Int*) = xs.sum + y +``` + diff --git a/docs/_docs/reference/error-codes/E028.md b/docs/_docs/reference/error-codes/E028.md new file mode 100644 index 000000000000..b9dd3e1440e7 --- /dev/null +++ b/docs/_docs/reference/error-codes/E028.md @@ -0,0 +1,52 @@ +--- +title: E028: Illegal Literal +kind: Error +--- + +# E028: Illegal Literal + +This error is emitted when the compiler encounters an invalid literal value that does not conform to Scala's literal syntax rules. + +Available literals can be divided into several groups: +- Integer literals: `0`, `21`, `0xFFFFFFFF`, `-42L` +- Floating Point Literals: `0.0`, `1e30f`, `3.14159f`, `1.0e-100`, `.1` +- Boolean Literals: `true`, `false` +- Character Literals: `'a'`, `'\u0041'`, `'\n'` +- String Literals: `"Hello, World!"` +- `null` + +--- + +## Example + +```scala sc:fail +def example = '\u000' +``` + +### Error + +```scala sc:nocompile +-- [E028] Syntax Error: example.scala:1:14 +1 |def example = '\u000' + | ^ + | Illegal literal +``` + +### Solution + +```scala sc:compile +// Use a valid Unicode escape sequence (4 hex digits) +def example = '\u0000' +``` + +```scala sc:compile +// Use a regular character literal +def example = 'a' +``` + +```scala sc:compile +// Use escape sequences for special characters +def newline = '\n' +def tab = '\t' +``` + diff --git a/docs/_docs/reference/error-codes/E029.md b/docs/_docs/reference/error-codes/E029.md new file mode 100644 index 000000000000..f23de9370945 --- /dev/null +++ b/docs/_docs/reference/error-codes/E029.md @@ -0,0 +1,62 @@ +--- +title: E029: Pattern Match Exhaustivity +kind: Warning +--- + +# E029: Pattern Match Exhaustivity + +This warning is emitted when a pattern match expression may not handle all possible input values. The compiler detects cases that are not covered by any of the match cases. + +There are several ways to make the match exhaustive: +- Add missing cases as shown in the warning +- If an extractor always returns `Some(...)`, write `Some[X]` for its return type +- Add a `case _ => ...` at the end to match all remaining cases + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +enum Color: + case Red, Green, Blue + +def describe(c: Color): String = c match + case Color.Red => "red" + case Color.Green => "green" +``` + +### Warning + +```scala sc:nocompile +-- [E029] Pattern Match Exhaustivity Warning: example.scala:5:33 +5 |def describe(c: Color): String = c match + | ^ + | match may not be exhaustive. + | + | It would fail on pattern case: Color.Blue +``` + +### Solution + +```scala sc:compile +// Add the missing case +enum Color: + case Red, Green, Blue + +def describe(c: Color): String = c match + case Color.Red => "red" + case Color.Green => "green" + case Color.Blue => "blue" +``` + +```scala sc:compile +// Alternative: add a wildcard case for remaining patterns +enum Color: + case Red, Green, Blue + +def describe(c: Color): String = c match + case Color.Red => "red" + case Color.Green => "green" + case _ => "other" +``` + diff --git a/docs/_docs/reference/error-codes/E030.md b/docs/_docs/reference/error-codes/E030.md new file mode 100644 index 000000000000..664e91323916 --- /dev/null +++ b/docs/_docs/reference/error-codes/E030.md @@ -0,0 +1,45 @@ +--- +title: E030: Match Case Unreachable +kind: Warning +--- + +# E030: Match Case Unreachable + +This warning is emitted when a case in a pattern match expression can never be reached because it is shadowed by a previous case that matches all the same values. + +Unreachable code is typically a sign of a logic error. You should review the order of your cases or remove the redundant case. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +def example(x: Int): String = x match + case _ => "any" + case 1 => "one" +``` + +### Warning + +```scala sc:nocompile +-- [E030] Match case Unreachable Warning: example.scala:3:7 +3 | case 1 => "one" + | ^ + | Unreachable case +``` + +### Solution + +```scala sc:compile +// Reorder cases - put specific patterns before general ones +def example(x: Int): String = x match + case 1 => "one" + case _ => "any" +``` + +```scala sc:compile +// Alternative: remove the unreachable case if it's not needed +def example(x: Int): String = x match + case _ => "any" +``` + diff --git a/docs/_docs/reference/error-codes/E031.md b/docs/_docs/reference/error-codes/E031.md new file mode 100644 index 000000000000..bad8f8a9de84 --- /dev/null +++ b/docs/_docs/reference/error-codes/E031.md @@ -0,0 +1,46 @@ +--- +title: E031: Sequence Wildcard Pattern Position +kind: Error +--- + +# E031: Sequence Wildcard Pattern Position + +This error is emitted when the sequence wildcard pattern (`*`) is used in a position other than the last element in a pattern sequence. + +The sequence wildcard pattern is expected at the end of an argument list. This pattern matches any remaining elements in a sequence. + +--- + +## Example + +```scala sc:fail +def example(list: List[Int]): Int = list match + case List(x*, second, third) => second + case _ => 0 +``` + +### Error + +```scala sc:nocompile +-- [E031] Syntax Error: example.scala:2:12 +2 | case List(x*, second, third) => second + | ^^ + | * can be used only for last argument +``` + +### Solution + +```scala sc:compile +// Place the sequence wildcard at the end +def example(list: List[Int]): Int = list match + case List(first, second, rest*) => second + case _ => 0 +``` + +```scala sc:compile +// Alternative: match the exact number of elements you need +def example(list: List[Int]): Int = list match + case first :: second :: _ => second + case _ => 0 +``` + diff --git a/docs/_docs/reference/error-codes/E032.md b/docs/_docs/reference/error-codes/E032.md new file mode 100644 index 000000000000..28a022adf04f --- /dev/null +++ b/docs/_docs/reference/error-codes/E032.md @@ -0,0 +1,75 @@ +--- +title: E032: Illegal Start Of Simple Pattern +kind: Error +--- + +# E032: Illegal Start Of Simple Pattern + +This error is emitted when the compiler encounters a token that cannot begin a valid pattern in a pattern matching context. + +Simple patterns can be divided into several groups: + +- **Variable Patterns**: `case x => ...` or `case _ => ...` + Matches any value and binds the variable name to that value. The wildcard pattern `_` is treated as if it was a fresh variable on each occurrence. + +- **Typed Patterns**: `case x: Int => ...` or `case _: Int => ...` + Matches any value matched by the specified type and binds the variable name to that value. + +- **Given Patterns**: `case given ExecutionContext => ...` + Matches any value matched by the specified type and binds a `given` instance to that value. + +- **Literal Patterns**: `case 123 => ...` or `case 'A' => ...` + Matches any value that is equal to the specified literal. + +- **Stable Identifier Patterns**: Using backticks to match against a variable + `case \`y\` => ...` + +- **Constructor Patterns**: `case Person(name, age) => ...` + Binds all object's fields to the variable names. + +- **Tuple Patterns**: `case (a, b) => ...` + +- **Pattern Sequences**: `case List(first, second, rest*) => ...` + +--- + +## Example + +```scala sc:fail +def example(x: Any) = x match + case class => "class" +``` + +### Error + +```scala sc:nocompile +-- [E032] Syntax Error: example.scala:2:7 +2 | case class => "class" + | ^^^^^ + | pattern expected +``` + +### Solution + +```scala sc:compile +// Use a valid pattern - typed pattern +def example(x: Any) = x match + case _: String => "string" + case _ => "other" +``` + +```scala sc:compile +// Use a variable pattern +def example(x: Any) = x match + case y => s"value: $y" +``` + +```scala sc:compile +// Use a constructor pattern +case class Person(name: String) + +def example(x: Any) = x match + case Person(name) => s"person: $name" + case _ => "not a person" +``` + diff --git a/docs/_docs/reference/error-codes/E033.md b/docs/_docs/reference/error-codes/E033.md new file mode 100644 index 000000000000..33643335f91a --- /dev/null +++ b/docs/_docs/reference/error-codes/E033.md @@ -0,0 +1,51 @@ +--- +title: E033: Package Duplicate Symbol +kind: Error +--- + +# E033: Package Duplicate Symbol + +This error is emitted when you try to define a package with the same name as an existing symbol (such as an object, class, or trait) in the same scope. + +Package names must be unique and cannot conflict with other top-level definitions in the same compilation unit. + +--- + +## Example + +```scala sc:fail +object foo + +package foo: + class Bar +``` + +### Error + +```scala sc:nocompile +-- [E033] Naming Error: example.scala:3:8 +3 |package foo: + | ^^^ + | Trying to define package with same name as object foo +``` + +### Solution + +Use a different package name: + +```scala sc:nocompile +package bar: + class Bar + +object foo +``` + +Alternative: rename the object to avoid conflict: + +```scala sc:nocompile +package foo: + class Bar + +object myFoo +``` + diff --git a/docs/_docs/reference/error-codes/E034.md b/docs/_docs/reference/error-codes/E034.md new file mode 100644 index 000000000000..2ba4c287d9fc --- /dev/null +++ b/docs/_docs/reference/error-codes/E034.md @@ -0,0 +1,52 @@ +--- +title: E034: Existential Types No Longer Supported +kind: Error +--- + +# E034: Existential Types No Longer Supported + +This error is emitted when existential types syntax (using `forSome`) is used. Existential types are no longer supported in Scala 3. + +Existential types were a feature in Scala 2 that allowed abstracting over unknown types using the `forSome` syntax. In Scala 3, this feature has been removed in favor of simpler and more principled alternatives. + +Instead of existential types, you should use: + +- **Wildcard types**: Use `?` (or `_` in Scala 2 compatibility mode) for unknown type parameters +- **Type parameters**: Use generic methods or classes with explicit type parameters +- **Dependent types**: For more advanced use cases + +--- + +## Example + +```scala sc:fail +def example: List[T forSome { type T }] = List() +``` + +### Error + +```scala sc:nocompile +-- [E034] Syntax Error: example.scala:1:17 +1 |def example: List[T forSome { type T }] = List() + | ^ + | Existential types are no longer supported - + | use a wildcard or dependent type instead +``` + +### Solution + +```scala sc:compile +// Use a wildcard type +def example: List[?] = List() +``` + +```scala sc:compile +// Alternative: use a type parameter +def example[T]: List[T] = List() +``` + +```scala sc:compile +// Alternative: use Any if the type doesn't matter +def example: List[Any] = List() +``` + diff --git a/docs/_docs/reference/error-codes/E035.md b/docs/_docs/reference/error-codes/E035.md new file mode 100644 index 000000000000..84b61ce8be4c --- /dev/null +++ b/docs/_docs/reference/error-codes/E035.md @@ -0,0 +1,52 @@ +--- +title: E035: Unbound Wildcard Type +kind: Error +--- + +# E035: Unbound Wildcard Type + +This error is emitted when the wildcard type syntax (`_` or `?`) is used in a position where it cannot be bound to a concrete type. + +The wildcard type syntax was used where it could not be bound. Replace the wildcard with a non-wildcard type. If the type doesn't matter, try replacing the wildcard with `Any`. + +This typically happens in: + +- **Parameter lists**: `def foo(x: _) = ...` +- **Type arguments in constructors**: `val foo = List[?](1, 2)` +- **Type bounds**: `def foo[T <: _](x: T) = ...` +- **val and def types**: `val foo: _ = 3` + +--- + +## Example + +```scala sc:fail +def example(x: ?) = x +``` + +### Error + +```scala sc:nocompile +-- [E035] Syntax Error: example.scala:1:15 +1 |def example(x: ?) = x + | ^ + | Unbound wildcard type +``` + +### Solution + +```scala sc:compile +// Use Any if the type doesn't matter +def example(x: Any) = x +``` + +```scala sc:compile +// Use a type parameter for generic behavior +def example[T](x: T): T = x +``` + +```scala sc:compile +// Specify a concrete type +def example(x: Int) = x +``` + diff --git a/docs/_docs/reference/error-codes/E037.md b/docs/_docs/reference/error-codes/E037.md new file mode 100644 index 000000000000..d04db15c7de8 --- /dev/null +++ b/docs/_docs/reference/error-codes/E037.md @@ -0,0 +1,57 @@ +--- +title: E037: Overrides Nothing +kind: Error +--- + +# E037: Overrides Nothing + +This error is emitted when a member is declared with the `override` modifier but there is no corresponding member in a superclass to override. + +There must be a field or method with the same name in a super class to override it. This error typically occurs when: + +- The member name is misspelled +- The wrong class is being extended +- The parent class doesn't have a member with that name + +--- + +## Example + +```scala sc:fail +class Parent: + def greet(): String = "Hello" + +class Child extends Parent: + override def greeet(): String = "Hi" +``` + +### Error + +```scala sc:nocompile +-- [E037] Declaration Error: example.scala:5:15 +5 | override def greeet(): String = "Hi" + | ^^^^^^ + | method greeet overrides nothing +``` + +### Solution + +```scala sc:compile +// Fix the spelling to match the parent method +class Parent: + def greet(): String = "Hello" + +class Child extends Parent: + override def greet(): String = "Hi" +``` + +```scala sc:compile +// Or remove the override modifier if not overriding +class Parent: + def greet(): String = "Hello" + +class Child extends Parent: + def greeet(): String = "Hi" +``` + + diff --git a/docs/_docs/reference/error-codes/E038.md b/docs/_docs/reference/error-codes/E038.md new file mode 100644 index 000000000000..2db0208e6a9f --- /dev/null +++ b/docs/_docs/reference/error-codes/E038.md @@ -0,0 +1,53 @@ +--- +title: E038: Overrides Nothing But Name Exists +kind: Error +--- + +# E038: Overrides Nothing But Name Exists + +This error is emitted when a member is declared with the `override` modifier and a member with the same name exists in the parent class, but the signatures don't match. + +There must be a non-final field or method with the same name and the same parameter list in a super class to override it. This error indicates that while the name matches, either the parameter types or the return type differ. + +--- + +## Example + +```scala sc:fail +class Parent: + def process(x: Int): String = x.toString + +class Child extends Parent: + override def process(x: String): String = x +``` + +### Error + +```scala sc:nocompile +-- [E038] Declaration Error: example.scala:5:15 +5 | override def process(x: String): String = x + | ^^^^^^^ + | method process has a different signature than the overridden declaration +``` + +### Solution + +```scala sc:compile +// Match the parameter types of the parent method +class Parent: + def process(x: Int): String = x.toString + +class Child extends Parent: + override def process(x: Int): String = s"Child: $x" +``` + +```scala sc:compile +// Or use overloading instead of overriding +class Parent: + def process(x: Int): String = x.toString + +class Child extends Parent: + def process(x: String): String = x +``` + + diff --git a/docs/_docs/reference/error-codes/E039.md b/docs/_docs/reference/error-codes/E039.md new file mode 100644 index 000000000000..38a02debd549 --- /dev/null +++ b/docs/_docs/reference/error-codes/E039.md @@ -0,0 +1,51 @@ +--- +title: E039: Forward Reference Extends Over Definition +kind: Error +--- + +# E039: Forward Reference Extends Over Definition + +This error is emitted when a forward reference to a value extends over the definition of another value. + +Forward references are allowed only if there are no value definitions between the reference and the definition that is referred to. Specifically, any statement between the reference and the definition cannot be a variable definition, and if it's a value definition, it must be lazy. + +--- + +## Example + +```scala sc:fail +def example = + def a: Int = b + val b: Int = a + a +``` + +### Error + +```scala sc:nocompile +-- [E039] Reference Error: example.scala:2:10 +2 | def a: Int = b + | ^ + | b is a forward reference extending over the definition of b +``` + +### Solution + +```scala sc:compile +// Make the forward dependency lazy +// Warning: It still might fail at runtime +def example = + def a: Int = b + lazy val b: Int = a + a +``` + +```scala sc:compile +// Even better ensure to always break the dependecny chain +def example = + lazy val a: Int = if b == 0 then 1 else b + lazy val b: Int = 0 + a +``` + + diff --git a/docs/_docs/reference/error-codes/E040.md b/docs/_docs/reference/error-codes/E040.md new file mode 100644 index 000000000000..381b6b665892 --- /dev/null +++ b/docs/_docs/reference/error-codes/E040.md @@ -0,0 +1,41 @@ +--- +title: E040: Expected Token But Found +kind: Error +--- + +# E040: Expected Token But Found + +This error is emitted when the compiler expects a specific token (like a keyword, symbol, or identifier) but finds a different token instead. + +This is a general syntax error that indicates the code structure doesn't match what the parser expected at that position. Common causes include missing punctuation, mismatched brackets, or using a keyword where an identifier is expected. + +--- + +## Example + +```scala sc:fail +def example(x: Int y: Int) = x + y +``` + +### Error + +```scala sc:nocompile +-- [E040] Syntax Error: example.scala:1:19 +1 |def example(x: Int y: Int) = x + y + | ^ + | ',' expected, but identifier found +``` + +### Solution + +```scala sc:compile +// Add the missing comma between parameters +def example(x: Int, y: Int) = x + y +``` + +```scala sc:compile +// Or use separate parameter lists +def example(x: Int)(y: Int) = x + y +``` + + diff --git a/docs/_docs/reference/error-codes/E041.md b/docs/_docs/reference/error-codes/E041.md new file mode 100644 index 000000000000..5c7912588e44 --- /dev/null +++ b/docs/_docs/reference/error-codes/E041.md @@ -0,0 +1,65 @@ +--- +title: E041: Mixed Left And Right Associative Ops +kind: Error +--- + +# E041: Mixed Left And Right Associative Ops + +This error is emitted when operators with different associativity (left vs right) but the same precedence are used together in an expression without parentheses. + +In Scala, operators ending in a colon (`:`) are right-associative. All other operators are left-associative. When two operators have the same precedence but different associativity, the compiler cannot determine the evaluation order. + +Infix operator precedence is determined by the operator's first character. Characters are listed below in increasing order of precedence: +- (all letters) +- `|` +- `^` +- `&` +- `= !` +- `< >` +- `:` +- `+ -` +- `* / %` +- (all other special characters) + +--- + +## Example + +```scala sc:fail +extension (x: Int) + def +: (y: Int): Int = x + y + def +* (y: Int): Int = x * y + +def example = 1 +: 2 +* 3 +``` + +### Error + +```scala sc:nocompile +-- [E041] Syntax Error: example.scala:5:14 +5 |def example = 1 +: 2 +* 3 + | ^^^^^^^^^^^ + | +: (which is right-associative) and +* (which is left-associative) have same precedence and may not be mixed +``` + +### Solution + +```scala sc:compile +// Use parentheses to make the order explicit +extension (x: Int) + def +: (y: Int): Int = x + y + def +* (y: Int): Int = x * y + +def example = (1 +: 2) +* 3 +``` + +```scala sc:compile +// Or use method call syntax +extension (x: Int) + def +: (y: Int): Int = x + y + def +* (y: Int): Int = x * y + +def example = (1.+:(2)).+*(3) +``` + + diff --git a/docs/_docs/reference/error-codes/E042.md b/docs/_docs/reference/error-codes/E042.md new file mode 100644 index 000000000000..70db29300053 --- /dev/null +++ b/docs/_docs/reference/error-codes/E042.md @@ -0,0 +1,65 @@ +--- +title: E042: Cannot Instantiate Abstract Class Or Trait +kind: Error +--- + +# E042: Cannot Instantiate Abstract Class Or Trait + +This error is emitted when attempting to directly instantiate an abstract class or a trait using `new`. + +Abstract classes and traits need to be extended by a concrete class or object to make their functionality accessible. You cannot create instances of them directly. + +--- + +## Example + +```scala sc:fail +trait Animal: + def speak(): String + +val pet = new Animal +``` + +### Error + +```scala sc:nocompile +-- [E042] Type Error: example.scala:4:14 +4 |val pet = new Animal + | ^^^^^^ + | Animal is a trait; it cannot be instantiated +``` + +### Solution + +```scala sc:compile +// Create an anonymous class implementing the trait +trait Animal: + def speak(): String + +val pet = new Animal: + def speak(): String = "Woof!" +``` + +```scala sc:compile +// Or create a concrete class that extends the trait +trait Animal: + def speak(): String + +class Dog extends Animal: + def speak(): String = "Woof!" + +val pet = new Dog +``` + +```scala sc:compile +// For abstract classes, same approach applies +abstract class Animal: + def speak(): String + +class Cat extends Animal: + def speak(): String = "Meow!" + +val pet = new Cat +``` + + diff --git a/docs/_docs/reference/error-codes/E043.md b/docs/_docs/reference/error-codes/E043.md new file mode 100644 index 000000000000..c87dc4a1b247 --- /dev/null +++ b/docs/_docs/reference/error-codes/E043.md @@ -0,0 +1,51 @@ +--- +title: E043: Unreducible Application +kind: Error +--- + +# E043: Unreducible Application + +This error is emitted when an abstract type constructor (higher-kinded type) is applied to wildcard type arguments. + +Such applications are equivalent to existential types, which are not supported in Scala 3. An abstract type constructor cannot be applied to wildcard arguments because the compiler cannot determine what concrete type would result. + +--- + +## Example + +```scala sc:fail +trait Container[F[_]]: + def create: F[?] +``` + +### Error + +```scala sc:nocompile +-- [E043] Type Error: example.scala:2:13 +2 | def create: F[?] + | ^^^^ + | unreducible application of higher-kinded type F to wildcard arguments +``` + +### Solution + +```scala sc:compile +// Use a concrete type argument +trait Container[F[_]]: + def create[A]: F[A] +``` + +```scala sc:compile +// Or use a type member +trait Container[F[_]]: + type Element + def create: F[Element] +``` + +```scala sc:compile +// Or make the type concrete in implementations +trait Container[F[_]]: + def create: F[Int] +``` + + diff --git a/docs/_docs/reference/error-codes/E044.md b/docs/_docs/reference/error-codes/E044.md new file mode 100644 index 000000000000..9d1855635dc0 --- /dev/null +++ b/docs/_docs/reference/error-codes/E044.md @@ -0,0 +1,51 @@ +--- +title: E044: Overloaded Or Recursive Method Needs Result Type +kind: Error +--- + +# E044: Overloaded Or Recursive Method Needs Result Type + +This error is emitted when an overloaded or recursive method is defined without an explicit return type. + +**Case 1: Overloaded methods** - If there are multiple methods with the same name and at least one definition calls another, you need to specify the calling method's return type. + +**Case 2: Recursive methods** - If a method calls itself on any path (even through mutual recursion), you need to specify the return type of that method or of a definition it's mutually recursive with. + +--- + +## Example + +```scala sc:fail +def factorial(n: Int) = + if n <= 1 then 1 + else n * factorial(n - 1) +``` + +### Error + +```scala sc:nocompile +-- [E044] Cyclic Error: example.scala:1:4 +1 |def factorial(n: Int) = + | ^^^^^^^^^ + | Overloaded or recursive method factorial needs return type +``` + +### Solution + +```scala sc:compile +// Add an explicit return type +def factorial(n: Int): Int = + if n <= 1 then 1 + else n * factorial(n - 1) +``` + +```scala sc:compile +// For mutually recursive methods, at least one needs a return type +def isEven(n: Int): Boolean = + if n == 0 then true else isOdd(n - 1) + +def isOdd(n: Int): Boolean = + if n == 0 then false else isEven(n - 1) +``` + + diff --git a/docs/_docs/reference/error-codes/E045.md b/docs/_docs/reference/error-codes/E045.md new file mode 100644 index 000000000000..988421ee9ffa --- /dev/null +++ b/docs/_docs/reference/error-codes/E045.md @@ -0,0 +1,35 @@ +--- +title: E045: Recursive Value Needs Result Type +kind: Error +--- + +# E045: Recursive Value Needs Result Type + +This error is emitted when a recursive value definition doesn't have an explicit type annotation. + +When a value references itself in its definition (either directly or through lazy evaluation), the compiler needs an explicit type to break the cycle and determine the value's type. + +--- + +## Example + +```scala sc:fail +lazy val ones = 1 #:: ones +``` + +### Error + +```scala sc:nocompile +-- [E045] Cyclic Error: example.scala:2:4 +1 |lazy val ones = 1 #:: ones + | ^ + | Recursive lazy value ones needs type +``` + +### Solution + +```scala sc:compile +// Add an explicit type annotation +lazy val ones: LazyList[Int] = 1 #:: ones +``` + diff --git a/docs/_docs/reference/error-codes/E046.md b/docs/_docs/reference/error-codes/E046.md new file mode 100644 index 000000000000..e2d8e2e320fe --- /dev/null +++ b/docs/_docs/reference/error-codes/E046.md @@ -0,0 +1,49 @@ +--- +title: E046: Cyclic Reference Involving +kind: Error +--- + +# E046: Cyclic Reference Involving + +This error is emitted when there is a cyclic reference in type definitions that makes it impossible for the compiler to determine the types involved. + +A cyclic reference occurs when the definition of a type or value depends on itself, either directly or through a chain of other definitions. To resolve this, try giving the involved definitions explicit types. + +--- + +## Example + +```scala sc:fail +class A extends B +class B extends A +``` + +### Error + +```scala sc:nocompile +-- [E046] Cyclic Error: example.scala:1:6 +1 |class A extends B + | ^ + | Cyclic reference involving class A +``` + +### Solution + +```scala sc:compile +// Break the cycle by using a common parent +trait Common + +class A extends Common +class B extends Common +``` + +```scala sc:compile +// Or use composition instead of inheritance +class A: + var b: B = null + +class B: + var a: A = null +``` + + diff --git a/docs/_docs/reference/error-codes/E047.md b/docs/_docs/reference/error-codes/E047.md new file mode 100644 index 000000000000..c4f9fcabd3bf --- /dev/null +++ b/docs/_docs/reference/error-codes/E047.md @@ -0,0 +1,42 @@ +--- +title: E047: Cyclic Reference Involving Implicit +kind: Error +--- + +# E047: Cyclic Reference Involving Implicit + +This error is emitted when there is a cyclic reference involving an implicit (or given) definition. + +This typically happens when the right-hand side of an implicit definition involves an implicit search that depends on the definition being defined. To avoid this error, give the implicit definition an explicit type. + +--- + +## Example + +```scala sc:fail +given a: Int = summon[Int] + 1 +``` + +### Error + +```scala sc:nocompile +-- [E047] Cyclic Error: example.scala:1:6 +1 |given a: Int = summon[Int] + 1 + | ^ + | Cyclic reference involving given a +``` + +### Solution + +```scala sc:compile +// Provide a concrete value instead of relying on implicit search +given a: Int = 42 +``` + +```scala sc:compile +// Or define separate givens if you need layered implicits +given base: Int = 1 +given derived(using b: Int): Int = b + 1 +``` + + diff --git a/docs/_docs/reference/error-codes/E048.md b/docs/_docs/reference/error-codes/E048.md new file mode 100644 index 000000000000..b40c4b32516d --- /dev/null +++ b/docs/_docs/reference/error-codes/E048.md @@ -0,0 +1,62 @@ +--- +title: E048: Super Qualifier Must Be Parent +kind: Error +--- + +# E048: Super Qualifier Must Be Parent + +This error is emitted when a qualifier used in a `super` prefix does not name a parent type of the class. + +When a qualifier `T` is used in a `super` prefix of the form `C.super[T]`, `T` must be a direct parent type of `C`. This syntax is used to disambiguate which parent's implementation to call when a class has multiple parents with the same method. + +--- + +## Example + +```scala sc:fail +trait A: + def greet: String = "A" + +trait B: + def greet: String = "B" + +class C extends A, B: + override def greet: String = super[String].greet +``` + +### Error + +```scala sc:nocompile +-- [E048] Reference Error: example.scala:8:37 +8 | override def greet: String = super[String].greet + | ^^^^^^ + | String does not name a parent of class C +``` + +### Solution + +```scala sc:compile +// Use an actual parent type in the super qualifier +trait A: + def greet: String = "A" + +trait B: + def greet: String = "B" + +class C extends A, B: + override def greet: String = super[A].greet +``` + +```scala sc:compile +// Or call a specific parent's method +trait A: + def greet: String = "A" + +trait B: + def greet: String = "B" + +class C extends A, B: + override def greet: String = super[B].greet +``` + + diff --git a/docs/_docs/reference/error-codes/E049.md b/docs/_docs/reference/error-codes/E049.md new file mode 100644 index 000000000000..9a65dc50ffc8 --- /dev/null +++ b/docs/_docs/reference/error-codes/E049.md @@ -0,0 +1,66 @@ +--- +title: E049: Ambiguous Reference +kind: Error +--- + +# E049: Ambiguous Reference + +This error is emitted when an identifier could refer to multiple different definitions and the compiler cannot determine which one to use. + +The precedence of the different kinds of name bindings, from highest to lowest, is: +1. Definitions in an enclosing scope +2. Inherited definitions and top-level definitions in packages +3. Names introduced by import of a specific name +4. Names introduced by wildcard import +5. Definitions from packages in other files + +Note that definitions take precedence over imports, and a binding in an inner scope cannot shadow a binding with higher precedence in an outer scope. + +--- + +## Example + +```scala sc:fail +import scala.collection.immutable.Seq +import scala.collection.mutable.Seq + +val items = Seq(1, 2, 3) +``` + +### Error + +```scala sc:nocompile +-- [E049] Reference Error: example.scala:4:12 +4 |val items = Seq(1, 2, 3) + | ^^^ + | Reference to Seq is ambiguous. + | It is both imported by name by import scala.collection.immutable.Seq + | and imported by name subsequently by import scala.collection.mutable.Seq +``` + +### Solution + +```scala sc:compile +// Use a rename to avoid the conflict +import scala.collection.immutable.Seq +import scala.collection.mutable.{Seq as MutableSeq} + +val items = Seq(1, 2, 3) +val mutableItems = MutableSeq(1, 2, 3) +``` + +```scala sc:compile +import scala.collection.{immutable, mutable} +// Or use qualified names +val items = immutable.Seq(1, 2, 3) +val mutableItems = mutable.Seq(1, 2, 3) +``` + +```scala sc:compile +// Or import only what you need +import scala.collection.immutable.Seq + +val items = Seq(1, 2, 3) +``` + + diff --git a/docs/_docs/reference/error-codes/E050.md b/docs/_docs/reference/error-codes/E050.md new file mode 100644 index 000000000000..d9d4c1b8c7a2 --- /dev/null +++ b/docs/_docs/reference/error-codes/E050.md @@ -0,0 +1,57 @@ +--- +title: E050: Method Does Not Take Parameters +kind: Error +--- + +# E050: Method Does Not Take Parameters + +This error is emitted when you try to pass arguments to a method or expression that doesn't accept parameters. + +This can happen when: +- Calling a nullary method (no parameter list) with arguments +- Calling a method with more argument lists than it accepts +- Applying arguments to an expression that is not a function + +--- + +## Example + +```scala sc:fail +def greet: String = "Hello" + +val message = greet("World") +``` + +### Error + +```scala sc:nocompile +-- [E050] Type Error: example.scala:3:14 +3 |val message = greet("World") + | ^^^^^^^^^^^^^^ + | method greet does not take parameters +``` + +### Solution + +```scala sc:compile +// Add a parameter to the method definition +def greet(name: String): String = s"Hello, $name" + +val message = greet("World") +``` + +```scala sc:compile +// Or call the method without arguments +def greet: String = "Hello" + +val message = greet +``` + +```scala sc:compile +// Or use string interpolation if you want to combine +def greet: String = "Hello" + +val message = s"$greet, World" +``` + + diff --git a/docs/_docs/reference/error-codes/E051.md b/docs/_docs/reference/error-codes/E051.md new file mode 100644 index 000000000000..0a2afa4b43fa --- /dev/null +++ b/docs/_docs/reference/error-codes/E051.md @@ -0,0 +1,56 @@ +--- +title: E051: Ambiguous Overload +kind: Error +--- + +# E051: Ambiguous Overload + +This error is emitted when there are multiple overloaded methods that match the given arguments and the compiler cannot determine which one to call. + +There are multiple methods that could be referenced because the compiler knows too little about the expected type. You may specify the expected type by: +- Assigning the result to a value with a specified type +- Adding a type ascription as in `instance.myMethod: String => Int` + +--- + +## Example + +```scala sc:fail +def process(x: Int): String = x.toString +def process(x: Long): String = x.toString + +val result = process(1: Int | Long) +``` + +### Error + +```scala sc:nocompile +-- [E051] Reference Error: example.scala:4:13 +4 |val result = process(1: Int | Long) + | ^^^^^^^ + | Ambiguous overload. The overloaded alternatives of method process with types + | (x: Long): String + | (x: Int): String + | both match arguments ((1 : Int | Long)) +``` + +### Solution + +```scala sc:compile +// Specify the exact type of the argument +def process(x: Int): String = x.toString +def process(x: Long): String = x.toString + +val result = process(1: Int) +``` + +```scala sc:compile +// Or assign to a variable with a specific type first +def process(x: Int): String = x.toString +def process(x: Long): String = x.toString + +val n: Int = 1 +val result = process(n) +``` + + diff --git a/docs/_docs/reference/error-codes/E052.md b/docs/_docs/reference/error-codes/E052.md new file mode 100644 index 000000000000..58f294709b2c --- /dev/null +++ b/docs/_docs/reference/error-codes/E052.md @@ -0,0 +1,52 @@ +--- +title: E052: Reassignment To Val +kind: Error +--- + +# E052: Reassignment To Val + +This error is emitted when attempting to reassign a value to an immutable variable declared with `val`. + +You cannot assign a new value to a `val` as values cannot be changed after initialization. Reassignment is only permitted if the variable is declared with `var`. + +If you're seeing this error in a boolean context, you may have accidentally used `=` (assignment) instead of `==` (equality test). + +--- + +## Example + +```scala sc:fail +val x = 1 +x = 2 +``` + +### Error + +```scala sc:nocompile +-- [E052] Type Error: example.scala:2:0 +2 |x = 2 + |^^^^^ + |Reassignment to val x +``` + +### Solution + +```scala sc:compile +// Use var if you need to reassign +var x = 1 +x = 2 +``` + +```scala sc:compile +// Or use a new val with a different name +val x = 1 +val y = 2 +``` + +```scala sc:compile +// If you meant to compare values, use == +val x = 1 +val isTwo = x == 2 +``` + + diff --git a/docs/_docs/reference/error-codes/E053.md b/docs/_docs/reference/error-codes/E053.md new file mode 100644 index 000000000000..6630df238280 --- /dev/null +++ b/docs/_docs/reference/error-codes/E053.md @@ -0,0 +1,50 @@ +--- +title: E053: Type Does Not Take Parameters +kind: Error +--- + +# E053: Type Does Not Take Parameters + +This error is emitted when type parameters are provided to a type that doesn't accept any type parameters. + +You specified type parameters for a type that is not declared to take any. This can happen when: +- Applying type arguments to a non-generic type +- Confusing a type alias with its underlying parameterized type +- Using F-bounds where type lambdas are not allowed + +--- + +## Example + +```scala sc:fail +val x: Int[String] = 42 +``` + +### Error + +```scala sc:nocompile +-- [E053] Type Error: example.scala:1:7 +1 |val x: Int[String] = 42 + | ^^^^^^^^^^^ + | Int does not take type parameters +``` + +### Solution + +```scala sc:compile +// Remove the type parameters from non-generic types +val x: Int = 42 +``` + +```scala sc:compile +// Use a type that does accept parameters +val x: List[Int] = List(42) +``` + +```scala sc:compile +// Or define your own generic type +class Box[T](value: T) +val x: Box[Int] = Box(42) +``` + + diff --git a/docs/_docs/reference/error-codes/E055.md b/docs/_docs/reference/error-codes/E055.md new file mode 100644 index 000000000000..d9a99012d476 --- /dev/null +++ b/docs/_docs/reference/error-codes/E055.md @@ -0,0 +1,48 @@ +--- +title: E055: Var Val Parameters May Not Be Call By Name +kind: Error +--- + +# E055: Var Val Parameters May Not Be Call By Name + +This error is emitted when a `val` or `var` parameter of a class or trait is declared as call-by-name (using `=> T` syntax). + +`var` and `val` parameters of classes and traits may not be call-by-name because they need to be stored as fields. If you want the parameter to be evaluated on demand, consider making it just a parameter and providing a `def` in the class. + +--- + +## Example + +```scala sc:fail +class LazyHolder(val value: => Int) +``` + +### Error + +```scala sc:nocompile +-- [E055] Syntax Error: example.scala:1:18 +1 |class LazyHolder(val value: => Int) + | ^^^^^^^^^^ + | val parameters may not be call-by-name +``` + +### Solution + +```scala sc:compile +// Use a regular parameter and a lazy val +class LazyHolder(valueInit: => Int): + lazy val value: Int = valueInit +``` + +```scala sc:compile +// Or use a function type +class LazyHolder(getValue: () => Int): + def value: Int = getValue() +``` + +```scala sc:compile +// Or simply use a regular val parameter +class LazyHolder(val value: Int) +``` + + diff --git a/docs/_docs/reference/error-codes/E056.md b/docs/_docs/reference/error-codes/E056.md new file mode 100644 index 000000000000..3082f37358c9 --- /dev/null +++ b/docs/_docs/reference/error-codes/E056.md @@ -0,0 +1,41 @@ +--- +title: E056: Missing Type Parameter For +kind: Error +--- + +# E056: Missing Type Parameter For + +This error is emitted when a higher-kinded type or type constructor is used where a fully applied type is expected. + +A type constructor (like `List` or `Option`) needs to be applied to type arguments before it can be used as a value type. For example, `List` by itself is a type constructor, but `List[Int]` is a proper type. + +--- + +## Example + +```scala sc:fail +val items: List = List(1, 2, 3) +``` + +### Error + +```scala sc:nocompile +-- [E056] Syntax Error: example.scala:1:11 +1 |val items: List = List(1, 2, 3) + | ^^^^ + | Missing type parameter for List +``` + +### Solution + +```scala sc:compile +// Provide the type parameter +val items: List[Int] = List(1, 2, 3) +``` + +```scala sc:compile +// Or let the compiler infer the type +val items = List(1, 2, 3) +``` + + diff --git a/docs/_docs/reference/error-codes/E057.md b/docs/_docs/reference/error-codes/E057.md new file mode 100644 index 000000000000..925734c616da --- /dev/null +++ b/docs/_docs/reference/error-codes/E057.md @@ -0,0 +1,47 @@ +--- +title: E057: Does Not Conform To Bound +kind: Error +--- + +# E057: Does Not Conform To Bound + +This error is emitted when a type argument does not conform to the declared type bounds of a type parameter. + +Type parameters can have upper bounds (`<:`) and lower bounds (`>:`). When you provide a type argument, it must satisfy these bounds. An upper bound means the type argument must be a subtype of the bound, while a lower bound means it must be a supertype. + +--- + +## Example + +```scala sc:fail +def process[T <: Number](value: T): T = value + +val result = process("hello") +``` + +### Error + +```scala sc:nocompile +-- [E057] Type Error: example.scala:3:21 +3 |val result = process("hello") + | ^^^^^^^ + | Type argument String does not conform to upper bound Number +``` + +### Solution + +```scala sc:compile +// Use a type that conforms to the bound +def process[T <: Number](value: T): T = value + +val result = process(Integer.valueOf(42)) +``` + +```scala sc:compile +// Or change the type bound if appropriate +def process[T](value: T): T = value + +val result = process("hello") +``` + + diff --git a/docs/_docs/reference/error-codes/E058.md b/docs/_docs/reference/error-codes/E058.md new file mode 100644 index 000000000000..edea0848ee3e --- /dev/null +++ b/docs/_docs/reference/error-codes/E058.md @@ -0,0 +1,68 @@ +--- +title: E058: Does Not Conform To Self Type +kind: Error +--- + +# E058: Does Not Conform To Self Type + +This error is emitted when a class's self type does not conform to the self type of a trait it extends. + +A self type annotation (like `self: SomeType =>`) declares that any concrete class implementing this trait must also conform to `SomeType`. When extending such a trait, the extending class must satisfy this requirement. + +--- + +## Example + +```scala sc:fail +trait HasLogger: + self: Logger => + def log(msg: String): Unit + +trait Logger: + def write(msg: String): Unit + +class MyClass extends HasLogger: + def log(msg: String): Unit = println(msg) +``` + +### Error + +```scala sc:nocompile +-- [E058] Type Error: example.scala:8:6 +8 |class MyClass extends HasLogger: + | ^ + | illegal inheritance: self type MyClass of class MyClass does not conform to + | self type Logger of parent trait HasLogger +``` + +### Solution + +```scala sc:compile +// Mix in the required trait +trait HasLogger: + self: Logger => + def log(msg: String): Unit + +trait Logger: + def write(msg: String): Unit + +class MyClass extends HasLogger with Logger: + def log(msg: String): Unit = println(msg) + def write(msg: String): Unit = println(msg) +``` + +```scala sc:compile +// Or add a matching self type to the extending class +trait HasLogger: + self: Logger => + def log(msg: String): Unit + +trait Logger: + def write(msg: String): Unit + +abstract class MyClass extends HasLogger: + self: Logger => + def log(msg: String): Unit = println(msg) +``` + + diff --git a/docs/_docs/reference/error-codes/E059.md b/docs/_docs/reference/error-codes/E059.md new file mode 100644 index 000000000000..ccae0ad65136 --- /dev/null +++ b/docs/_docs/reference/error-codes/E059.md @@ -0,0 +1,66 @@ +--- +title: E059: Does Not Conform To Self Type Cannot Be Instantiated +kind: Error +--- + +# E059: Does Not Conform To Self Type Cannot Be Instantiated + +This error is emitted when attempting to instantiate a class that has a self type which the class itself doesn't satisfy. + +When a class declares a self type, it promises that any instance will conform to that type. If the class doesn't implement or mix in the required types, it cannot be instantiated. + +--- + +## Example + +```scala sc:fail +trait Database: + def query(sql: String): String + +class Repository: + self: Database => + def findAll(): String = query("SELECT *") + +val repo = new Repository +``` + +### Error + +```scala sc:nocompile +-- [E059] Type Error: example.scala:8:15 +8 |val repo = new Repository + | ^^^^^^^^^^ + | Repository does not conform to its self type Database; cannot be instantiated +``` + +### Solution + +```scala sc:compile +// Implement the required self type when instantiating +trait Database: + def query(sql: String): String + +class Repository: + self: Database => + def findAll(): String = query("SELECT *") + +val repo = new Repository with Database: + def query(sql: String): String = s"Executed: $sql" +``` + +```scala sc:compile +// Or create a concrete class that mixes in the required trait +trait Database: + def query(sql: String): String + +class Repository: + self: Database => + def findAll(): String = query("SELECT *") + +class SqlRepository extends Repository with Database: + def query(sql: String): String = s"Executed: $sql" + +val repo = new SqlRepository +``` + + diff --git a/docs/_docs/reference/error-codes/E060.md b/docs/_docs/reference/error-codes/E060.md new file mode 100644 index 000000000000..9d570431654a --- /dev/null +++ b/docs/_docs/reference/error-codes/E060.md @@ -0,0 +1,44 @@ +--- +title: E060: Abstract Member May Not Have Modifier +kind: Error +--- + +# E060: Abstract Member May Not Have Modifier + +This error is emitted when an abstract member is declared with a modifier that is incompatible with being abstract, such as `final` or `private`. + +Abstract members are meant to be implemented by subclasses, so they cannot be `final` (which prevents overriding) or `private` (which prevents access by subclasses). + +--- + +## Example + +```scala sc:fail +trait Example: + final def abstractMethod: Int +``` + +### Error + +```scala sc:nocompile +-- [E060] Syntax Error: example.scala:2:12 +2 | final def abstractMethod: Int + | ^ + | abstract method abstractMethod may not have `final` modifier +``` + +### Solution + +```scala sc:compile +// Remove the incompatible modifier +trait Example: + def abstractMethod: Int +``` + +```scala sc:compile +// Or provide an implementation if you want final +trait Example: + final def concreteMethod: Int = 42 +``` + + diff --git a/docs/_docs/reference/error-codes/E062.md b/docs/_docs/reference/error-codes/E062.md new file mode 100644 index 000000000000..75e81b401de9 --- /dev/null +++ b/docs/_docs/reference/error-codes/E062.md @@ -0,0 +1,47 @@ +--- +title: E062: Types And Traits Cannot Be Implicit +kind: Error +--- + +# E062: Types And Traits Cannot Be Implicit + +This error is emitted when the `implicit` modifier is used on a type alias or trait definition. + +The `implicit` modifier can only be used on values, methods, and classes (for implicit conversions). Types and traits cannot be implicit because they don't represent values that can be passed implicitly. + +--- + +## Example + +```scala sc:fail +implicit trait MyTrait +``` + +### Error + +```scala sc:nocompile +-- [E062] Syntax Error: example.scala:1:0 +1 |implicit trait MyTrait + |^^^^^^^^ + |implicit modifier cannot be used for types or traits +``` + +### Solution + +```scala sc:compile +// Remove implicit from trait definitions +trait MyTrait + +// Use given instances instead +given myInstance: MyTrait = new MyTrait {} +``` + +```scala sc:compile +// For implicit conversions, use a given Conversion +trait Target +class Source + +given Conversion[Source, Target] = (s: Source) => new Target {} +``` + + diff --git a/docs/_docs/reference/error-codes/E063.md b/docs/_docs/reference/error-codes/E063.md new file mode 100644 index 000000000000..3319aecb32f2 --- /dev/null +++ b/docs/_docs/reference/error-codes/E063.md @@ -0,0 +1,45 @@ +--- +title: E063: Only Classes Can Be Abstract +kind: Error +--- + +# E063: Only Classes Can Be Abstract + +This error is emitted when the `abstract` modifier is used on something other than a class, such as a method or value. + +The `abstract` modifier can only be used for classes. For abstract members (methods, values), simply omit the implementation - they are implicitly abstract when declared without a body in a trait or abstract class. + +--- + +## Example + +```scala sc:fail +trait Example: + abstract def method: Int +``` + +### Error + +```scala sc:nocompile +-- [E063] Syntax Error: example.scala:2:2 +2 | abstract def method: Int + | ^^^^^^^^ + | abstract modifier can be used only for classes; it should be omitted for abstract members +``` + +### Solution + +```scala sc:compile +// Simply omit abstract for member declarations +trait Example: + def method: Int +``` + +```scala sc:compile +// Use abstract only for class definitions +abstract class Example: + def method: Int + def concreteMethod: Int = 42 +``` + + diff --git a/docs/_docs/reference/error-codes/E064.md b/docs/_docs/reference/error-codes/E064.md new file mode 100644 index 000000000000..7591d3806dba --- /dev/null +++ b/docs/_docs/reference/error-codes/E064.md @@ -0,0 +1,55 @@ +--- +title: E064: Abstract Override Only In Traits +kind: Error +--- + +# E064: Abstract Override Only In Traits + +This error is emitted when `abstract override` is used on a member outside of a trait. + +The `abstract override` modifier is only allowed for members of traits. It indicates that the member will override a concrete member from a superclass but requires further implementation when the trait is mixed into a class. + +--- + +## Example + +```scala sc:fail +class Base: + def greet: String = "Hello" + +class Child extends Base: + abstract override def greet: String = super.greet + "!" +``` + +### Error + +```scala sc:nocompile +-- [E064] Syntax Error: example.scala:5:2 +5 | abstract override def greet: String = super.greet + "!" + | ^^^^^^^^^^^^^^^^^ + | abstract override modifier only allowed for members of traits +``` + +### Solution + +```scala sc:compile +// Use abstract override in a trait +class Base: + def greet: String = "Hello" + +trait Greeter extends Base: + abstract override def greet: String = super.greet + "!" + +class Child extends Base with Greeter +``` + +```scala sc:compile +// Or use a regular override in a class +class Base: + def greet: String = "Hello" + +class Child extends Base: + override def greet: String = super.greet + "!" +``` + + diff --git a/docs/_docs/reference/error-codes/E065.md b/docs/_docs/reference/error-codes/E065.md new file mode 100644 index 000000000000..51fe9b40d833 --- /dev/null +++ b/docs/_docs/reference/error-codes/E065.md @@ -0,0 +1,49 @@ +--- +title: E065: Traits May Not Be Final +kind: Error +--- + +# E065: Traits May Not Be Final + +This error is emitted when a trait is declared with the `final` modifier. + +A trait can never be final since it is abstract by nature and must be extended or mixed in to be useful. The `final` modifier prevents inheritance, which contradicts the purpose of a trait. + +--- + +## Example + +```scala sc:fail +final trait MyTrait +``` + +### Error + +```scala sc:nocompile +-- [E065] Syntax Error: example.scala:1:12 +1 |final trait MyTrait + | ^^^^^^^ + | trait MyTrait may not be final +``` + +### Solution + +```scala sc:compile +// Remove final from trait definitions +trait MyTrait: + def method: Int +``` + +```scala sc:compile +// If you want a final implementation, use a final class +final class MyFinalClass: + def method: Int = 42 +``` + +```scala sc:compile +// Or use a sealed trait if you want to restrict implementations +sealed trait MyTrait +final class Implementation extends MyTrait +``` + + diff --git a/docs/_docs/reference/error-codes/E066.md b/docs/_docs/reference/error-codes/E066.md new file mode 100644 index 000000000000..e23d01dcab66 --- /dev/null +++ b/docs/_docs/reference/error-codes/E066.md @@ -0,0 +1,44 @@ +--- +title: E066: Native Members May Not Have Implementation +kind: Error +--- + +# E066: Native Members May Not Have Implementation + +This error is emitted when a method marked with `@native` annotation has an implementation body. + +The `@native` annotation indicates that the method's implementation is provided by the runtime or a native library (like JNI). Native methods must be declared without a body because their implementation exists outside of Scala code. + +--- + +## Example + +```scala sc:fail +class Example: + @native def nativeMethod(): Int = 42 +``` + +### Error + +```scala sc:nocompile +-- [E066] Syntax Error: example.scala:4:14 +4 | @native def nativeMethod(): Int = 42 + | ^^^^^^^^^^^^ + | @native members may not have an implementation +``` + +### Solution + +```scala sc:compile +// Remove the implementation from native methods +class Example: + @native def nativeMethod(): Int +``` + +```scala sc:compile +// Or remove @native if you want to provide an implementation +class Example: + def normalMethod(): Int = 42 +``` + + diff --git a/docs/_docs/reference/error-codes/E067.md b/docs/_docs/reference/error-codes/E067.md new file mode 100644 index 000000000000..82ea024678b3 --- /dev/null +++ b/docs/_docs/reference/error-codes/E067.md @@ -0,0 +1,47 @@ +--- +title: E067: Only Classes Can Have Declared But Undefined Members +kind: Error +--- + +# E067: Only Classes Can Have Declared But Undefined Members + +This error is emitted when an abstract member (a declaration without implementation) appears outside of a class or trait context, such as in an object. + +Only classes and traits can have abstract members. Objects, being concrete singleton instances, must have all members fully implemented. Variables also need to be initialized to be defined. + +--- + +## Example + +```scala sc:fail +object Example: + def abstractMethod: Int +``` + +### Error + +```scala sc:nocompile +-- [E067] Syntax Error: example.scala:2:6 +2 | def abstractMethod: Int + | ^^^^^^^^^^^^^^ + | Declaration of method abstractMethod not allowed here: only classes can have declared but undefined members +``` + +### Solution + +```scala sc:compile +// Provide an implementation in objects +object Example: + def concreteMethod: Int = 42 +``` + +```scala sc:compile +// Or use a trait or abstract class for abstract members +trait Example: + def abstractMethod: Int + +object ConcreteExample extends Example: + def abstractMethod: Int = 42 +``` + + diff --git a/docs/_docs/reference/error-codes/E068.md b/docs/_docs/reference/error-codes/E068.md new file mode 100644 index 000000000000..b9de63f8a13e --- /dev/null +++ b/docs/_docs/reference/error-codes/E068.md @@ -0,0 +1,45 @@ +--- +title: E068: Cannot Extend AnyVal +kind: Error +--- + +# E068: Cannot Extend AnyVal + +This error is emitted when a trait or object attempts to extend `AnyVal`. + +Only classes can extend `AnyVal` to become value classes. Traits may extend `Any` to become "universal traits" which may only have `def` members. Universal traits can be mixed into classes that extend `AnyVal`. + +--- + +## Example + +```scala sc:fail +trait MyValueTrait extends AnyVal +``` + +### Error + +```scala sc:nocompile +-- [E068] Syntax Error: example.scala:1:6 +1 |trait MyValueTrait extends AnyVal + | ^^^^^^^^^^^^^^ + | trait MyValueTrait cannot extend AnyVal +``` + +### Solution + +```scala sc:compile +// Use a class for value classes +class MyValueClass(val value: Int) extends AnyVal +``` + +```scala sc:compile +// For traits, extend Any to create a universal trait +trait MyUniversalTrait extends Any: + def method: Int + +class MyValueClass(val value: Int) extends AnyVal with MyUniversalTrait: + def method: Int = value +``` + + diff --git a/docs/_docs/reference/error-codes/E069.md b/docs/_docs/reference/error-codes/E069.md new file mode 100644 index 000000000000..d1397db5a354 --- /dev/null +++ b/docs/_docs/reference/error-codes/E069.md @@ -0,0 +1,45 @@ +--- +title: E069: Cannot Have Same Name As +kind: Error +--- + +# E069: Cannot Have Same Name As + +This error is emitted when a member has the same name as another definition in a way that creates an illegal conflict. + +This typically happens when: +- A member tries to override a class definition (class definitions cannot be overridden) +- A member in a class has the same name as a member defined in a self-type reference + +--- + +## Example + +```scala sc:fail +class Outer: + class Inner + +class Child extends Outer: + override class Inner +``` + +### Error + +```scala sc:nocompile +-- [E069] Naming Error: example.scala:5:17 +5 | override class Inner + | ^^^^^ + | class Inner cannot have the same name as class Inner in class Outer -- class definitions cannot be overridden +``` + +### Solution + +```scala sc:compile +// Use an abstract type member with optional interface +abstract class Outer: + trait Interface + type Inner <: Interface + +class Child extends Outer: + class Inner extends Interface +``` diff --git a/docs/_docs/reference/error-codes/E070.md b/docs/_docs/reference/error-codes/E070.md new file mode 100644 index 000000000000..680f1f8a894a --- /dev/null +++ b/docs/_docs/reference/error-codes/E070.md @@ -0,0 +1,46 @@ +--- +title: E070: Value Classes May Not Define Inner Class +kind: Error +--- + +# E070: Value Classes May Not Define Inner Class + +This error is emitted when a value class (a class extending `AnyVal`) contains an inner class definition. + +Value classes have strict limitations to ensure they can be optimized by the compiler. They may not define inner classes, traits, or objects because the runtime representation of a value class is its wrapped value, not a full object. + +--- + +## Example + +```scala sc:fail +class Wrapper(val value: Int) extends AnyVal: + class Inner +``` + +### Error + +```scala sc:nocompile +-- [E070] Syntax Error: example.scala:2:8 +2 | class Inner + | ^^^^^ + | Value classes may not define an inner class +``` + +### Solution + +```scala sc:compile +// Move the inner class outside the value class +class Inner + +class Wrapper(val value: Int) extends AnyVal: + def process: Int = value * 2 +``` + +```scala sc:compile +// Or use a regular class if you need inner classes +class Wrapper(val value: Int): + class Inner +``` + + diff --git a/docs/_docs/reference/error-codes/E071.md b/docs/_docs/reference/error-codes/E071.md new file mode 100644 index 000000000000..0a6a76bd319f --- /dev/null +++ b/docs/_docs/reference/error-codes/E071.md @@ -0,0 +1,44 @@ +--- +title: E071: Value Classes May Not Define Non Parameter Field +kind: Error +--- + +# E071: Value Classes May Not Define Non Parameter Field + +This error is emitted when a value class (a class extending `AnyVal`) defines a `val` or `var` field that is not the primary constructor parameter. + +Value classes can only have the single `val` parameter from their primary constructor. Additional fields would require object allocation, defeating the purpose of value classes. + +--- + +## Example + +```scala sc:fail +class Wrapper(val value: Int) extends AnyVal: + val doubled = value * 2 +``` + +### Error + +```scala sc:nocompile +-- [E071] Syntax Error: example.scala:2:6 +2 | val doubled = value * 2 + | ^^^^^^^ + | Value classes may not define non-parameter field +``` + +### Solution + +```scala sc:compile +// Use a def instead of val +class Wrapper(val value: Int) extends AnyVal: + def doubled: Int = value * 2 +``` + +```scala sc:compile +// Or use a regular class if you need fields +class Wrapper(val value: Int): + val doubled = value * 2 +``` + + diff --git a/docs/_docs/reference/error-codes/E072.md b/docs/_docs/reference/error-codes/E072.md new file mode 100644 index 000000000000..79207226d1db --- /dev/null +++ b/docs/_docs/reference/error-codes/E072.md @@ -0,0 +1,46 @@ +--- +title: E072: Value Classes May Not Define A Secondary Constructor +kind: Error +--- + +# E072: Value Classes May Not Define A Secondary Constructor + +This error is emitted when a value class (a class extending `AnyVal`) defines a secondary constructor. + +Value classes can only have one primary constructor with exactly one `val` parameter. Secondary constructors are not allowed because they would complicate the optimization of value classes. + +--- + +## Example + +```scala sc:fail +class Wrapper(val value: Int) extends AnyVal: + def this(s: String) = this(s.toInt) +``` + +### Error + +```scala sc:nocompile +-- [E072] Syntax Error: example.scala:2:6 +2 | def this(s: String) = this(s.toInt) + | ^^^^ + | Value classes may not define a secondary constructor +``` + +### Solution + +```scala sc:compile +// Use a companion object factory method instead +class Wrapper(val value: Int) extends AnyVal + +object Wrapper: + def fromString(s: String): Wrapper = new Wrapper(s.toInt) +``` + +```scala sc:compile +// Or use a regular class if you need multiple constructors +class Wrapper(val value: Int): + def this(s: String) = this(s.toInt) +``` + + diff --git a/docs/_docs/reference/error-codes/E073.md b/docs/_docs/reference/error-codes/E073.md new file mode 100644 index 000000000000..d0439b25cdb6 --- /dev/null +++ b/docs/_docs/reference/error-codes/E073.md @@ -0,0 +1,54 @@ +--- +title: E073: Value Classes May Not Contain Initialization +kind: Error +--- + +# E073: Value Classes May Not Contain Initialization + +This error is emitted when a value class (a class extending `AnyVal`) contains initialization statements in its body. + +Value classes may not contain initialization statements because they are meant to be completely inlined by the compiler. Any initialization code would prevent this optimization. + +--- + +## Example + +```scala sc:fail +class Wrapper(val value: Int) extends AnyVal: + println(s"Created wrapper with $value") +``` + +### Error + +```scala sc:nocompile +-- [E073] Syntax Error: example.scala:2:2 +2 | println(s"Created wrapper with $value") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Value classes may not contain initialization statements +``` + +### Solution + +```scala sc:compile +// Remove initialization statements +class Wrapper(val value: Int) extends AnyVal: + def show: String = s"Wrapper($value)" +``` + +```scala sc:compile +// Or use a companion object for factory logic +class Wrapper(val value: Int) extends AnyVal + +object Wrapper: + def create(value: Int): Wrapper = + println(s"Creating wrapper with $value") + new Wrapper(value) +``` + +```scala sc:compile +// Or use a regular class if you need initialization +class Wrapper(val value: Int): + println(s"Created wrapper with $value") +``` + + diff --git a/docs/_docs/reference/error-codes/E074.md b/docs/_docs/reference/error-codes/E074.md new file mode 100644 index 000000000000..ff0f0626d428 --- /dev/null +++ b/docs/_docs/reference/error-codes/E074.md @@ -0,0 +1,44 @@ +--- +title: E074: Value Classes May Not Be Abstract +kind: Error +--- + +# E074: Value Classes May Not Be Abstract + +This error is emitted when a value class (a class extending `AnyVal`) is declared as abstract. + +Value classes must be concrete because they are meant to be inlined by the compiler. An abstract value class cannot be instantiated and therefore cannot serve its purpose of avoiding object allocation. + +--- + +## Example + +```scala sc:fail +abstract class Wrapper(val value: Int) extends AnyVal +``` + +### Error + +```scala sc:nocompile +-- [E074] Syntax Error: example.scala:1:15 +1 |abstract class Wrapper(val value: Int) extends AnyVal + | ^^^^^^^ + | Value classes may not be abstract +``` + +### Solution + +```scala sc:compile +// Remove the abstract modifier +class Wrapper(val value: Int) extends AnyVal +``` + +```scala sc:compile +// For abstraction, use a universal trait +trait Numeric extends Any: + def value: Int + +class Wrapper(val value: Int) extends AnyVal with Numeric +``` + + diff --git a/docs/_docs/reference/error-codes/E075.md b/docs/_docs/reference/error-codes/E075.md new file mode 100644 index 000000000000..5fc3ecc1a238 --- /dev/null +++ b/docs/_docs/reference/error-codes/E075.md @@ -0,0 +1,49 @@ +--- +title: E075: Value Classes May Not Be Contained +kind: Error +--- + +# E075: Value Classes May Not Be Contained + +This error is emitted when a value class (a class extending `AnyVal`) is defined as a local class or as a member of another class. + +Value classes must be top-level classes or members of an object. They cannot be local classes (defined inside a method) or member classes (defined inside another class) because they need to be fully resolved at compile time for optimization. + +--- + +## Example + +```scala sc:fail +class Outer: + class Wrapper(val value: Int) extends AnyVal +``` + +### Error + +```scala sc:nocompile +-- [E075] Syntax Error: example.scala:2:8 +2 | class Wrapper(val value: Int) extends AnyVal + | ^^^^^^^ + | Value classes may not be a member of another class +``` + +### Solution + +```scala sc:compile +// Define the value class at the top level +class Wrapper(val value: Int) extends AnyVal + +class Outer: + def wrap(x: Int): Wrapper = new Wrapper(x) +``` + +```scala sc:compile +// Or define it inside an object +object Types: + class Wrapper(val value: Int) extends AnyVal + +class Outer: + def wrap(x: Int): Types.Wrapper = new Types.Wrapper(x) +``` + + diff --git a/docs/_docs/reference/error-codes/E076.md b/docs/_docs/reference/error-codes/E076.md new file mode 100644 index 000000000000..fdee83eb811b --- /dev/null +++ b/docs/_docs/reference/error-codes/E076.md @@ -0,0 +1,47 @@ +--- +title: E076: Value Classes May Not Wrap Another Value Class +kind: Error +--- + +# E076: Value Classes May Not Wrap Another Value Class + +This error is emitted when a value class (a class extending `AnyVal`) has a parameter whose type is another user-defined value class. + +A value class may not wrap another user-defined value class because it would complicate the JVM representation and optimization of value classes. + +--- + +## Example + +```scala sc:fail +class Meters(val value: Double) extends AnyVal +class Distance(val meters: Meters) extends AnyVal +``` + +### Error + +```scala sc:nocompile +-- [E076] Syntax Error: example.scala:2:6 +2 |class Distance(val meters: Meters) extends AnyVal + | ^^^^^^^^ + | A value class may not wrap another user-defined value class +``` + +### Solution + +```scala sc:compile +// Wrap the underlying primitive type directly +class Meters(val value: Double) extends AnyVal +class Distance(val value: Double) extends AnyVal + +object Distance: + def fromMeters(m: Meters): Distance = new Distance(m.value) +``` + +```scala sc:compile +// Or use a regular class for the outer wrapper +class Meters(val value: Double) extends AnyVal +class Distance(val meters: Meters) +``` + + diff --git a/docs/_docs/reference/error-codes/E077.md b/docs/_docs/reference/error-codes/E077.md new file mode 100644 index 000000000000..16933d35faaa --- /dev/null +++ b/docs/_docs/reference/error-codes/E077.md @@ -0,0 +1,41 @@ +--- +title: E077: Value Class Parameter May Not Be A Var +kind: Error +--- + +# E077: Value Class Parameter May Not Be A Var + +This error is emitted when a value class (a class extending `AnyVal`) has its parameter declared as `var` instead of `val`. + +A value class must have exactly one `val` parameter. Using `var` would imply mutability, which is incompatible with how value classes are represented at runtime. + +--- + +## Example + +```scala sc:fail +class Wrapper(var value: Int) extends AnyVal +``` + +### Error + +```scala sc:nocompile +-- [E077] Syntax Error: example.scala:1:14 +1 |class Wrapper(var value: Int) extends AnyVal + | ^^^^^^^^^^^^^ + | A value class parameter may not be a var +``` + +### Solution + +```scala sc:compile +// Use val instead of var +class Wrapper(val value: Int) extends AnyVal +``` + +```scala sc:compile +// If you need mutability, use a regular class +class Wrapper(var value: Int) +``` + + diff --git a/docs/_docs/reference/error-codes/E078.md b/docs/_docs/reference/error-codes/E078.md new file mode 100644 index 000000000000..cdfb0bca82b3 --- /dev/null +++ b/docs/_docs/reference/error-codes/E078.md @@ -0,0 +1,41 @@ +--- +title: E078: Value Class Needs Exactly One Val Parameter +kind: Error +--- + +# E078: Value Class Needs Exactly One Val Parameter + +This error is emitted when a value class (a class extending `AnyVal`) doesn't have exactly one `val` parameter. + +Value classes must have exactly one `val` parameter in their primary constructor. This single parameter is the wrapped value that the value class represents at runtime. + +--- + +## Example + +```scala sc:fail +class Wrapper() extends AnyVal +``` + +### Error + +```scala sc:nocompile +-- [E078] Syntax Error: example.scala:1:6 +1 |class Wrapper() extends AnyVal + | ^^^^^^^ + | Value class needs one val parameter +``` + +### Solution + +```scala sc:compile +// Add exactly one val parameter +class Wrapper(val value: Int) extends AnyVal +``` + +```scala sc:compile +// For multiple values, use a regular class or case class +case class Wrapper(x: Int, y: Int) +``` + + diff --git a/docs/_docs/reference/error-codes/E081.md b/docs/_docs/reference/error-codes/E081.md new file mode 100644 index 000000000000..de8feda211f0 --- /dev/null +++ b/docs/_docs/reference/error-codes/E081.md @@ -0,0 +1,48 @@ +--- +title: E081: Anonymous Function Missing Parameter Type +kind: Error +--- + +# E081: Anonymous Function Missing Parameter Type + +This error is emitted when the compiler cannot infer the type of a parameter in an anonymous function (lambda) and no explicit type is provided. + +The compiler needs to know the types of function parameters to properly type-check the function body. When there's not enough context to infer the type, you must provide an explicit type annotation. + +--- + +## Example + +```scala sc:fail +val f = (x) => x + 1 +``` + +### Error + +```scala sc:nocompile +-- [E081] Type Error: example.scala:1:10 +1 |val f = (x) => x + 1 + | ^ + | Missing parameter type + | + | I could not infer the type of the parameter x. +``` + +### Solution + +```scala sc:compile +// Add an explicit type annotation to the parameter +val f = (x: Int) => x + 1 +``` + +```scala sc:compile +// Or provide type context through the variable declaration +val f: Int => Int = x => x + 1 +``` + +```scala sc:compile +// Or use the function in a context that provides type information +List(1, 2, 3).map(x => x + 1) +``` + + diff --git a/docs/_docs/reference/error-codes/E082.md b/docs/_docs/reference/error-codes/E082.md new file mode 100644 index 000000000000..fe515c58f8eb --- /dev/null +++ b/docs/_docs/reference/error-codes/E082.md @@ -0,0 +1,54 @@ +--- +title: E082: Super Calls Not Allowed In Inlineable +kind: Error +--- + +# E082: Super Calls Not Allowed In Inlineable + +This error is emitted when an `inline` method contains a call to `super`. + +Method inlining prohibits calling superclass methods because when the method is inlined at the call site, the `super` reference would be ambiguous or invalid - it would no longer refer to the superclass of the defining class. + +--- + +## Example + +```scala sc:fail +class Parent: + def greet: String = "Hello" + +class Child extends Parent: + inline def greetLoud: String = super.greet + "!" +``` + +### Error + +```scala sc:nocompile +-- [E082] Syntax Error: example.scala:5:33 +5 | inline def greetLoud: String = super.greet + "!" + | ^^^^^^^^^^^ + | Super call not allowed in inlineable method greetLoud +``` + +### Solution + +```scala sc:compile +// Remove the inline modifier +class Parent: + def greet: String = "Hello" + +class Child extends Parent: + def greetLoud: String = super.greet + "!" +``` + +```scala sc:compile +// Or use a helper method for the super call +class Parent: + def greet: String = "Hello" + +class Child extends Parent: + private def parentGreet: String = super.greet + inline def greetLoud: String = parentGreet + "!" +``` + + diff --git a/docs/_docs/reference/error-codes/E083.md b/docs/_docs/reference/error-codes/E083.md new file mode 100644 index 000000000000..7f389f2e36d4 --- /dev/null +++ b/docs/_docs/reference/error-codes/E083.md @@ -0,0 +1,49 @@ +--- +title: E083: Not A Path +kind: Error +--- + +# E083: Not A Path + +This error is emitted when an expression is used where a stable path is required, but the expression is not an immutable path. + +An immutable path is: +- A reference to an immutable value (`val`), or +- A reference to `this`, or +- A selection of an immutable path with an immutable value + +Paths are required in certain contexts like singleton types, type projections, and some pattern matches. + +--- + +## Example + +```scala sc:fail +var x = 1 +def example: x.type = x +``` + +### Error + +```scala sc:nocompile +-- [E083] Type Error: example.scala:2:13 +2 |def example: x.type = x + | ^^^^^^ + | x.type is not a valid type, since it is not an immutable path +``` + +### Solution + +```scala sc:compile +// Use val instead of var for stable paths +val x = 1 +def example: x.type = x +``` + +```scala sc:compile +// Or don't use singleton types for mutable values +var x = 1 +def example: Int = x +``` + + diff --git a/docs/_docs/reference/error-codes/E084.md b/docs/_docs/reference/error-codes/E084.md new file mode 100644 index 000000000000..edc19d4e0b1a --- /dev/null +++ b/docs/_docs/reference/error-codes/E084.md @@ -0,0 +1,57 @@ +--- +title: E084: Wildcard On Type Argument Not Allowed On New +kind: Error +--- + +# E084: Wildcard On Type Argument Not Allowed On New + +This error is emitted when a wildcard type argument (`?` or `_`) is used in a `new` expression. + +When creating a new instance, the compiler needs to know the exact types to allocate and initialize the object. Wildcard types are unknown types that can't be instantiated directly. + +--- + +## Example + +```scala sc:fail +class Box[T](value: T) + +val box = new Box[?](42) +``` + +### Error + +```scala sc:nocompile +-- [E084] Syntax Error: example.scala:3:18 +3 |val box = new Box[?](42) + | ^ + | Type argument must be fully defined +``` + +### Solution + +```scala sc:compile +// Use a concrete type argument +class Box[T](value: T) + +val box = new Box[Int](42) +``` + +```scala sc:compile +// Or let the compiler infer the type +class Box[T](value: T) + +val box = new Box(42) +``` + +```scala sc:compile +// Or use a factory method if you need more flexibility +class Box[T](value: T) + +object Box: + def apply[T](value: T): Box[T] = new Box(value) + +val box = Box(42) +``` + + diff --git a/docs/_docs/reference/error-codes/E085.md b/docs/_docs/reference/error-codes/E085.md new file mode 100644 index 000000000000..e4e87994ac38 --- /dev/null +++ b/docs/_docs/reference/error-codes/E085.md @@ -0,0 +1,41 @@ +--- +title: E085: Function Type Needs Non Empty Parameter List +kind: Error +--- + +# E085: Function Type Needs Non Empty Parameter List + +This error is emitted when a function type syntax is used incorrectly, typically when trying to create a function type with improper syntax. + +Function types in Scala follow the form `(A, B) => C` for multi-parameter functions, `A => B` for single-parameter functions, and `() => A` for nullary functions. + +--- + +## Example + +```scala sc:fail +type Invalid = => Int +``` + +### Error + +```scala sc:nocompile +-- [E085] Syntax Error: example.scala:1:15 +1 |type Invalid = => Int + | ^^ + | Function type needs non-empty parameter list +``` + +### Solution + +```scala sc:compile +// Use () for nullary functions +type Valid = () => Int +``` + +```scala sc:compile +// Or use a by-name parameter type in method signatures +def delayed(x: => Int): Int = x +``` + + diff --git a/docs/_docs/reference/error-codes/E086.md b/docs/_docs/reference/error-codes/E086.md new file mode 100644 index 000000000000..156d4386f4a8 --- /dev/null +++ b/docs/_docs/reference/error-codes/E086.md @@ -0,0 +1,41 @@ +--- +title: E086: Wrong Number Of Parameters +kind: Error +--- + +# E086: Wrong Number Of Parameters + +This error is emitted when a function literal has a different number of parameters than what is expected by the context. + +When you provide a function literal where a specific function type is expected, the number of parameters in your literal must match the expected function type. + +--- + +## Example + +```scala sc:fail +val f: (Int, Int) => Int = x => x + 1 +``` + +### Error + +```scala sc:nocompile +-- [E086] Syntax Error: example.scala:1:27 +1 |val f: (Int, Int) => Int = x => x + 1 + | ^^^^^^^^^^ + | Wrong number of parameters, expected: 2 +``` + +### Solution + +```scala sc:compile +// Provide the correct number of parameters +val f: (Int, Int) => Int = (x, y) => x + y +``` + +```scala sc:compile +// Or change the expected type +val f: Int => Int = x => x + 1 +``` + + diff --git a/docs/_docs/reference/error-codes/E087.md b/docs/_docs/reference/error-codes/E087.md new file mode 100644 index 000000000000..bd97d175702e --- /dev/null +++ b/docs/_docs/reference/error-codes/E087.md @@ -0,0 +1,44 @@ +--- +title: E087: Duplicate Private Protected Qualifier +kind: Error +--- + +# E087: Duplicate Private Protected Qualifier + +This error is emitted when both `private` and `protected` modifiers are used on the same definition. + +It is not allowed to combine `private` and `protected` modifiers even if they are qualified to different scopes. A member can only have one visibility modifier. + +--- + +## Example + +```scala sc:fail +class Example: + private protected def method: Int = 42 +``` + +### Error + +```scala sc:nocompile +-- [E087] Syntax Error: example.scala:2:10 +2 | private protected def method: Int = 42 + | ^^^^^^^^^ + | Duplicate private/protected modifier +``` + +### Solution + +```scala sc:compile +// Use only one access modifier +class Example: + private def method: Int = 42 +``` + +```scala sc:compile +// Or use protected with a qualifier if needed +class Example: + protected[Example] def method: Int = 42 +``` + + diff --git a/docs/_docs/reference/error-codes/E088.md b/docs/_docs/reference/error-codes/E088.md new file mode 100644 index 000000000000..2b56a3b70848 --- /dev/null +++ b/docs/_docs/reference/error-codes/E088.md @@ -0,0 +1,41 @@ +--- +title: E088: Expected Start Of Top Level Definition +kind: Error +--- + +# E088: Expected Start Of Top Level Definition + +This error is emitted when modifiers are provided but no valid definition follows them. + +After using modifiers like `private`, `protected`, `final`, `abstract`, etc., you must provide a definition such as `class`, `trait`, `object`, `enum`, `def`, `val`, or `var`. + +--- + +## Example + +```scala sc:fail +final +``` + +### Error + +```scala sc:nocompile +-- [E088] Syntax Error: example.scala:1:0 +1 |final + |^^^^^ + |Expected start of definition +``` + +### Solution + +```scala sc:compile +// Add a definition after the modifier +final class Example +``` + +```scala sc:compile +// Or for methods/values +final val x = 42 +``` + + diff --git a/docs/_docs/reference/error-codes/E089.md b/docs/_docs/reference/error-codes/E089.md new file mode 100644 index 000000000000..625354932dfb --- /dev/null +++ b/docs/_docs/reference/error-codes/E089.md @@ -0,0 +1,47 @@ +--- +title: E089: Missing Return Type With Return Statement +kind: Error +--- + +# E089: Missing Return Type With Return Statement + +This error is emitted when a method contains a `return` statement but doesn't have an explicit return type. + +If a method contains a `return` statement, it must have an explicit return type. The compiler needs to know the return type to properly type-check the `return` expression. + +--- + +## Example + +```scala sc:fail +def example(x: Int) = + if x > 0 then return x + 0 +``` + +### Error + +```scala sc:nocompile +-- [E089] Syntax Error: example.scala:1:4 +1 |def example(x: Int) = + | ^^^^^^^ + | method example has a return statement; it needs a result type +``` + +### Solution + +```scala sc:compile +// Add an explicit return type +def example(x: Int): Int = + if x > 0 then return x + 0 +``` + +```scala sc:compile +// Or avoid using return (preferred in Scala) +def example(x: Int): Int = + if x > 0 then x + else 0 +``` + + diff --git a/docs/_docs/reference/error-codes/E090.md b/docs/_docs/reference/error-codes/E090.md new file mode 100644 index 000000000000..9d3e25afcf2f --- /dev/null +++ b/docs/_docs/reference/error-codes/E090.md @@ -0,0 +1,47 @@ +--- +title: E090: No Return From Inlineable +kind: Error +--- + +# E090: No Return From Inlineable + +This error is emitted when an `inline` method contains an explicit `return` statement. + +Methods marked with `inline` modifier may not use `return` statements because when the method is inlined, the return would not behave as expected. Instead, rely on the last expression's value being returned. + +--- + +## Example + +```scala sc:fail +inline def example(x: Int): Int = + if x < 0 then return 0 + x * 2 +``` + +### Error + +```scala sc:nocompile +-- [E090] Syntax Error: example.scala:2:16 +2 | if x < 0 then return 0 + | ^^^^^^^^ + | No explicit return allowed from inlineable method example +``` + +### Solution + +```scala sc:compile +// Use if-else expression instead of return +inline def example(x: Int): Int = + if x < 0 then 0 + else x * 2 +``` + +```scala sc:compile +// Or remove inline if you need return +def example(x: Int): Int = + if x < 0 then return 0 + x * 2 +``` + + diff --git a/docs/_docs/reference/error-codes/E091.md b/docs/_docs/reference/error-codes/E091.md new file mode 100644 index 000000000000..6c443d88d501 --- /dev/null +++ b/docs/_docs/reference/error-codes/E091.md @@ -0,0 +1,42 @@ +--- +title: E091: Return Outside Method Definition +kind: Error +--- + +# E091: Return Outside Method Definition + +This error is emitted when a `return` statement is used outside of a method definition. + +The `return` keyword may only be used within method definitions. It cannot be used in constructors, anonymous functions, or at the top level. + +--- + +## Example + +```scala sc:fail +val x = return 42 +``` + +### Error + +```scala sc:nocompile +-- [E091] Syntax Error: example.scala:1:8 +1 |val x = return 42 + | ^^^^^^^^^ + | return outside method definition +``` + +### Solution + +```scala sc:compile +// Simply use the value directly +val x = 42 +``` + +```scala sc:compile +// Use return only inside methods +def getValue: Int = return 42 // but even here, avoid return +def getBetterValue: Int = 42 // preferred style +``` + + diff --git a/docs/_docs/reference/error-codes/E092.md b/docs/_docs/reference/error-codes/E092.md new file mode 100644 index 000000000000..1b29bd90b73d --- /dev/null +++ b/docs/_docs/reference/error-codes/E092.md @@ -0,0 +1,56 @@ +--- +title: E092: Unchecked Type Pattern +kind: Warning +--- + +# E092: Unchecked Type Pattern + +This warning is emitted when a type pattern cannot be fully checked at runtime due to type erasure. + +Type arguments and type refinements are erased during compile time, making it impossible to check them at run-time. This can lead to unexpected behavior if the actual type doesn't match the pattern. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +def example(x: Any): Unit = x match + case list: List[String] => println("strings") + case _ => println("other") +``` + +### Error + +```scala sc:nocompile +-- [E092] Pattern Match Unchecked Warning: example.scala:2:8 +2 | case list: List[String] => println("strings") + | ^^^^^^^^^^^^ + | the type test for List[String] cannot be checked at runtime because its type arguments can't be determined from Any +``` + +### Solution + +```scala sc:compile +// Use a wildcard for the type argument +def example(x: Any): Unit = x match + case list: List[?] => println("some list") + case _ => println("other") +``` + +```scala sc:compile +// Or use @unchecked if you're certain about the type +import scala.unchecked +def example(x: Any): Unit = x match + case list: List[String @unchecked] => println("strings") + case _ => println("other") +``` + +```scala sc:compile +// Or check the element types explicitly +def example(x: Any): Unit = x match + case list: List[?] if list.forall(_.isInstanceOf[String]) => + println("strings") + case _ => println("other") +``` + + diff --git a/docs/_docs/reference/error-codes/E093.md b/docs/_docs/reference/error-codes/E093.md new file mode 100644 index 000000000000..b51d45263e7f --- /dev/null +++ b/docs/_docs/reference/error-codes/E093.md @@ -0,0 +1,50 @@ +--- +title: E093: Extend Final Class +kind: Error +--- + +# E093: Extend Final Class + +This error is emitted when attempting to extend a class that is marked as `final`. + +A class marked with the `final` keyword cannot be extended by any other class. This is used to prevent inheritance when the class design doesn't support or intend for subclassing. + +--- + +## Example + +```scala sc:fail +final class Parent + +class Child extends Parent +``` + +### Error + +```scala sc:nocompile +-- [E093] Syntax Error: example.scala:3:6 +3 |class Child extends Parent + | ^^^^^ + | class Child cannot extend final class Parent +``` + +### Solution + +```scala sc:compile +// Remove final from the parent if inheritance is intended +class Parent + +class Child extends Parent +``` + +```scala sc:compile +// Or use composition instead of inheritance +final class Parent: + def greet: String = "Hello" + +class Child: + private val parent = new Parent + def greet: String = parent.greet +``` + + diff --git a/docs/_docs/reference/error-codes/E094.md b/docs/_docs/reference/error-codes/E094.md new file mode 100644 index 000000000000..3376339dfa6a --- /dev/null +++ b/docs/_docs/reference/error-codes/E094.md @@ -0,0 +1,47 @@ +--- +title: E094: Enum Case Definition In Non Enum Owner +kind: Error +--- + +# E094: Enum Case Definition In Non Enum Owner + +This error is emitted when a `case` is defined outside of an `enum` definition. + +Enum cases can only be defined inside an `enum` body. They represent the possible values of that enumeration type. + +--- + +## Example + +```scala sc:fail +object Colors: + case Red +``` + +### Error + +```scala sc:nocompile +-- [E094] Syntax Error: example.scala:2:2 +2 | case Red + | ^^^^ + | Enum case not allowed here; case may only appear inside an enum definition +``` + +### Solution + +```scala sc:compile +// Define cases inside an enum +enum Colors: + case Red, Green, Blue +``` + +```scala sc:compile +// Or use case objects for similar functionality outside enums +object Colors: + sealed trait Color + case object Red extends Color + case object Green extends Color + case object Blue extends Color +``` + + diff --git a/docs/_docs/reference/error-codes/E095.md b/docs/_docs/reference/error-codes/E095.md new file mode 100644 index 000000000000..0a607fd26cb1 --- /dev/null +++ b/docs/_docs/reference/error-codes/E095.md @@ -0,0 +1,54 @@ +--- +title: E095: Expected Type Bound Or Equals +kind: Error +--- + +# E095: Expected Type Bound Or Equals + +This error is emitted when a type parameter or type member definition has invalid syntax - expecting `=`, `>:`, or `<:` but finding something else. + +Type parameters and abstract types may be constrained by type bounds: +- `=` for type aliases +- `<:` for upper type bounds (subtype constraint) +- `>:` for lower type bounds (supertype constraint) + +--- + +## Example + +```scala sc:fail +type MyType : Int +``` + +### Error + +```scala sc:nocompile +-- [E095] Syntax Error: example.scala:1:12 +1 |type MyType : Int + | ^ + | '=', '>:', or '<:' expected, but ':' found +``` + +### Solution + +```scala sc:compile +// Use = for type alias +type MyType = Int +``` + +```scala sc:compile +// Use <: for upper bound +type MyType <: AnyVal +``` + +```scala sc:compile +// Use >: for lower bound +type MyType >: Nothing +``` + +```scala sc:compile +// Combine bounds +type MyType >: Nothing <: AnyVal +``` + + diff --git a/docs/_docs/reference/error-codes/E096.md b/docs/_docs/reference/error-codes/E096.md new file mode 100644 index 000000000000..8c24b82b57c7 --- /dev/null +++ b/docs/_docs/reference/error-codes/E096.md @@ -0,0 +1,56 @@ +--- +title: E096: Class And Companion Name Clash +kind: Error +--- + +# E096: Class And Companion Name Clash + +This error is emitted when both a class/trait and its companion object define a class, trait, or object with the same name. + +A class and its companion object share the same namespace for nested types, so they cannot both define a type with the same name. + +--- + +## Example + +```scala sc:fail +class Outer: + class Inner + +object Outer: + class Inner +``` + +### Error + +```scala sc:nocompile +-- [E096] Naming Error: example.scala:5:8 +5 | class Inner + | ^^^^^ + | Name clash: both class Outer and its companion object defines Inner +``` + +### Solution + +```scala sc:compile +// Use different names for the nested types +class Outer: + class InnerClass + +object Outer: + class InnerObject +``` + +```scala sc:compile +// Or define the type in only one place +class Outer: + class Inner + +object Outer: + // Use Outer#Inner or define something else here + def create(): Outer#Inner = + val out = new Outer() + new out.Inner() +``` + + diff --git a/docs/_docs/reference/error-codes/E097.md b/docs/_docs/reference/error-codes/E097.md new file mode 100644 index 000000000000..f8a15e57ce22 --- /dev/null +++ b/docs/_docs/reference/error-codes/E097.md @@ -0,0 +1,60 @@ +--- +title: E097: Tailrec Not Applicable +kind: Error +--- + +# E097: Tailrec Not Applicable + +This error is emitted when the `@tailrec` annotation is used on a method that cannot be optimized for tail recursion. + +Tail recursion optimization requires that: +- The annotated symbol is a method +- The method is not abstract +- The method is either `private` or `final` (so it can't be overridden) +- The method contains recursive calls in tail position + +--- + +## Example + +```scala sc:fail +import scala.annotation.tailrec + +class Example: + @tailrec def factorial(n: Int, acc: Int = 1): Int = + if n <= 1 then acc + else factorial(n - 1, n * acc) +``` + +### Error + +```scala sc:nocompile +-- [E097] Syntax Error: example.scala:4:14 +4 | @tailrec def factorial(n: Int, acc: Int = 1): Int = + | ^^^^^^^^^ + | TailRec optimisation not applicable, method factorial is neither private nor final so can be overridden +``` + +### Solution + +```scala sc:compile +// Make the method final or private +import scala.annotation.tailrec + +class Example: + @tailrec final def factorial(n: Int, acc: Int = 1): Int = + if n <= 1 then acc + else factorial(n - 1, n * acc) +``` + +```scala sc:compile +// Or use private +import scala.annotation.tailrec + +class Example: + @tailrec private def factorial(n: Int, acc: Int = 1): Int = + if n <= 1 then acc + else factorial(n - 1, n * acc) +``` + + diff --git a/docs/_docs/reference/error-codes/E098.md b/docs/_docs/reference/error-codes/E098.md new file mode 100644 index 000000000000..6e80f4cc83a3 --- /dev/null +++ b/docs/_docs/reference/error-codes/E098.md @@ -0,0 +1,55 @@ +--- +title: E098: Failure To Eliminate Existential +kind: Warning +--- + +# E098: Failure To Eliminate Existential + +This warning is emitted when an existential type from a Scala 2 classfile cannot be accurately mapped to a Scala 3 equivalent. + +Existential types in their full generality are no longer supported in Scala 3. When reading Scala 2 classfiles that contain existential types, Scala 3 attempts to approximate them, but sometimes this approximation may not be accurate. + +--- + +## Example + +This error typically occurs when loading classes compiled with Scala 2 that use existential types: + +```scala sc:nocompile +// From a Scala 2 library +class Container { + def get: List[T] forSome { type T } = ??? +} +``` + +### Error + +```scala sc:nocompile +-- [E098] Compatibility Warning: + An existential type that came from a Scala-2 classfile for Container + cannot be mapped accurately to a Scala-3 equivalent. + original type : List[T] forSome { type T } + reduces to : List[?] + type used instead: List[Any] + This choice can cause follow-on type errors or hide type errors. + Proceed at own risk. +``` + +### Solution + +```scala sc:nocompile +// If you control the library, recompile it with Scala 3 +// Replace existential types with wildcards or type parameters: + +// Instead of: List[T] forSome { type T } +// Use: List[?] or List[_] or add type parameter +def get[T]: List[T] = ??? +def getAny: List[?] = ??? +``` + +```scala sc:nocompile +// If you don't control the library, be aware of potential +// type mismatches and use explicit type annotations where needed +``` + + diff --git a/docs/_docs/reference/error-codes/E099.md b/docs/_docs/reference/error-codes/E099.md new file mode 100644 index 000000000000..22d0d47232da --- /dev/null +++ b/docs/_docs/reference/error-codes/E099.md @@ -0,0 +1,36 @@ +--- +title: E099: Only Functions Can Be Followed By Underscore +kind: Error +--- + +# E099: Only Functions Can Be Followed By Underscore + +This error is emitted when the eta-expansion syntax `x _` is used on an expression that is not a method. + +The syntax `x _` for converting a method to a function value is deprecated and only works with methods. For non-method expressions, you need to explicitly write `() => x` to create a function value. + +--- + +## Example + +```scala sc:fail +val x = 42 +val f = x _ +``` + +### Error + +```scala sc:nocompile +-- [E099] Syntax Error: example.scala:2:8 +2 |val f = x _ + | ^^^ + | Only function types can be followed by _ but the current expression has type Int +``` + +### Solution + +```scala sc:compile +// Use explicit function syntax +val x = 42 +val f = () => x +``` diff --git a/docs/_docs/reference/error-codes/E100.md b/docs/_docs/reference/error-codes/E100.md new file mode 100644 index 000000000000..db1fb55c1fb2 --- /dev/null +++ b/docs/_docs/reference/error-codes/E100.md @@ -0,0 +1,47 @@ +--- +title: E100: Missing Empty Argument List +kind: Error +--- + +# E100: Missing Empty Argument List + +This error is emitted when a nullary method (a method with an empty parameter list `()`) is called without the empty argument list. + +In Scala 3, the application syntax must follow exactly the parameter syntax. If a method is defined with `()`, it must be called with `()`. This rule doesn't apply to methods defined in Java or that override Java methods. + +--- + +## Example + +```scala sc:fail +def next(): Int = 42 + +val n = next +``` + +### Error + +```scala sc:nocompile +-- [E100] Type Error: example.scala:3:8 +3 |val n = next + | ^^^^ + | method next must be called with () argument +``` + +### Solution + +```scala sc:compile +// Include the empty argument list +def next(): Int = 42 + +val n = next() +``` + +```scala sc:compile +// Or define without () if no arguments are needed +def next: Int = 42 + +val n = next +``` + + diff --git a/docs/_docs/reference/error-codes/error-codes.md b/docs/_docs/reference/error-codes/error-codes.md new file mode 100644 index 000000000000..f93145b0f4de --- /dev/null +++ b/docs/_docs/reference/error-codes/error-codes.md @@ -0,0 +1,3 @@ +--- +title: Error codes +--- \ No newline at end of file diff --git a/docs/sidebar.yml b/docs/sidebar.yml index db10c2280a85..7741ab57df46 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -190,3 +190,106 @@ subsection: - page: reference/language-versions/binary-compatibility.md - page: reference/soft-modifier.md - page: reference/features-classification.md + - title: Error Codes + index: reference/error-codes/error-codes.md + subsection: + - page: reference/error-codes/E001.md + - page: reference/error-codes/E002.md + - page: reference/error-codes/E003.md + - page: reference/error-codes/E004.md + - page: reference/error-codes/E005.md + - page: reference/error-codes/E006.md + - page: reference/error-codes/E007.md + - page: reference/error-codes/E008.md + - page: reference/error-codes/E009.md + # - page: reference/error-codes/E010.md + - page: reference/error-codes/E011.md + - page: reference/error-codes/E012.md + - page: reference/error-codes/E013.md + # - page: reference/error-codes/E014.md + - page: reference/error-codes/E015.md + - page: reference/error-codes/E016.md + - page: reference/error-codes/E017.md + - page: reference/error-codes/E018.md + - page: reference/error-codes/E019.md + - page: reference/error-codes/E020.md + - page: reference/error-codes/E021.md + - page: reference/error-codes/E022.md + - page: reference/error-codes/E023.md + - page: reference/error-codes/E024.md + - page: reference/error-codes/E025.md + - page: reference/error-codes/E026.md + - page: reference/error-codes/E027.md + - page: reference/error-codes/E028.md + - page: reference/error-codes/E029.md + - page: reference/error-codes/E030.md + - page: reference/error-codes/E031.md + - page: reference/error-codes/E032.md + - page: reference/error-codes/E033.md + - page: reference/error-codes/E034.md + - page: reference/error-codes/E035.md + # - page: reference/error-codes/E036.md + - page: reference/error-codes/E037.md + - page: reference/error-codes/E038.md + - page: reference/error-codes/E039.md + - page: reference/error-codes/E040.md + - page: reference/error-codes/E041.md + - page: reference/error-codes/E042.md + - page: reference/error-codes/E043.md + - page: reference/error-codes/E044.md + - page: reference/error-codes/E045.md + - page: reference/error-codes/E046.md + - page: reference/error-codes/E047.md + - page: reference/error-codes/E048.md + - page: reference/error-codes/E049.md + - page: reference/error-codes/E050.md + - page: reference/error-codes/E051.md + - page: reference/error-codes/E052.md + - page: reference/error-codes/E053.md + # - page: reference/error-codes/E054.md + - page: reference/error-codes/E055.md + - page: reference/error-codes/E056.md + - page: reference/error-codes/E057.md + - page: reference/error-codes/E058.md + - page: reference/error-codes/E059.md + - page: reference/error-codes/E060.md + # - page: reference/error-codes/E061.md + - page: reference/error-codes/E062.md + - page: reference/error-codes/E063.md + - page: reference/error-codes/E064.md + - page: reference/error-codes/E065.md + - page: reference/error-codes/E066.md + - page: reference/error-codes/E067.md + - page: reference/error-codes/E068.md + - page: reference/error-codes/E069.md + - page: reference/error-codes/E070.md + - page: reference/error-codes/E071.md + - page: reference/error-codes/E072.md + - page: reference/error-codes/E073.md + - page: reference/error-codes/E074.md + - page: reference/error-codes/E075.md + - page: reference/error-codes/E076.md + - page: reference/error-codes/E077.md + - page: reference/error-codes/E078.md + # - page: reference/error-codes/E079.md + # - page: reference/error-codes/E080.md + - page: reference/error-codes/E081.md + - page: reference/error-codes/E082.md + - page: reference/error-codes/E083.md + - page: reference/error-codes/E084.md + - page: reference/error-codes/E085.md + - page: reference/error-codes/E086.md + - page: reference/error-codes/E087.md + - page: reference/error-codes/E088.md + - page: reference/error-codes/E089.md + - page: reference/error-codes/E090.md + - page: reference/error-codes/E091.md + - page: reference/error-codes/E092.md + - page: reference/error-codes/E093.md + - page: reference/error-codes/E094.md + - page: reference/error-codes/E095.md + - page: reference/error-codes/E096.md + - page: reference/error-codes/E097.md + - page: reference/error-codes/E098.md + - page: reference/error-codes/E099.md + - page: reference/error-codes/E100.md \ No newline at end of file From cc89c51366aebdf8a727d999e615a06f6e023dd6 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 19:06:45 +0100 Subject: [PATCH 02/11] Add scripts to validate, update and test error code snippets --- project/scripts/checkErrorCodeSnippets.scala | 779 ++++++++++++++++++ .../scripts/checkErrorCodeSnippets.test.scala | 267 ++++++ 2 files changed, 1046 insertions(+) create mode 100644 project/scripts/checkErrorCodeSnippets.scala create mode 100644 project/scripts/checkErrorCodeSnippets.test.scala diff --git a/project/scripts/checkErrorCodeSnippets.scala b/project/scripts/checkErrorCodeSnippets.scala new file mode 100644 index 000000000000..acdb86566f51 --- /dev/null +++ b/project/scripts/checkErrorCodeSnippets.scala @@ -0,0 +1,779 @@ +//> using scala 3.8.0-RC3 +//> using dep org.scala-lang::scala3-compiler:3.8.0-RC3 +//> using dep com.vladsch.flexmark:flexmark-all:0.64.8 +//> using toolkit default +//> using option -Wunused:all +//> using mainClass checkErrorCodeSnippets +// scalafmt: { maxColumn = 120 } + +/** Non-reproducible error codes that cannot be triggered with pure Scala 3 source code. + * + * These error codes are used in the compiler but require special circumstances that cannot be reproduced with simple + * source code (e.g., reading Scala 2 classfiles, specific bytecode patterns, runtime conditions). + * + * Documentation for these codes should still exist but uses `sc:nocompile` snippets. Tests will show warnings but pass + * for these codes. + * + * TODO: These need manual review by the compiler team to find reproducible examples. + * + * Note: Error codes that have no message class should be marked `isActive = false` in ErrorMessageID.scala - those + * don't need to be listed here. + */ +object NonReproducibleErrorCodes: + val codes: Set[Int] = Set( + 25, // E025: IdentifierExpectedID - triggered by parser in specific contexts, needs investigation + 27, // E027: VarArgsParamMustComeLastID - triggered when varargs not last, needs correct syntax + 28, // E028: IllegalLiteralID - triggered by invalid literals, needs investigation + 33, // E033: PkgDuplicateSymbolID - requires package statements (not compatible with Scaladoc snippets) + 47, // E047: CyclicReferenceInvolvingImplicitID - triggered by implicit cycles, needs investigation + 98, // E098: FailureToEliminateExistential - only triggers when reading Scala 2 classfiles with existential types + 103, // E103: IllegalStartOfStatementID - requires top-level code (not compatible with Scaladoc snippets) + 105, // E105: TraitRedefinedFinalMethodFromAnyRefID - message class exists but never instantiated + 106, // E106: PackageNameAlreadyDefinedID - triggers in incremental compilation with classfile conflicts + 111, // E111: BadSymbolicReferenceID - requires missing classfiles on classpath + 113, // E113: SymbolHasUnparsableVersionNumberID - requires @migration annotation with invalid version + 114, // E114: SymbolChangedSemanticsInVersionID - requires @migration annotation with specific conditions + 138, // E138: TraitParameterUsedAsParentPrefixID - caught earlier by PostTyper with different message + 143, // E143: ErasedTypesCanOnlyBeFunctionTypesID - hard to reproduce, + 152 // E152: ExtensionCanOnlyHaveDefsID - never emitted + ) + + def isNonReproducible(errorCode: Int): Boolean = codes.contains(errorCode) +end NonReproducibleErrorCodes + +object IgnoredInactiveErrorCodes: + val codes: Set[Int] = Set( + 0 // E000: EmptyCatchOrFinallyBlockID - never used + ) + def isIgnored(errorCode: Int): Boolean = codes.contains(errorCode) +end IgnoredInactiveErrorCodes + +val Scala3_0_0_MaxErrorCode = 166 // CannotExtendFunctionID - the last error code in Scala 3.0.0 + +import scala.util.matching.Regex +import scala.util.CommandLineParser.FromString + +import dotty.tools.dotc.* +import dotty.tools.dotc.core.Contexts.* +import dotty.tools.dotc.core.Comments.{ContextDoc, ContextDocstrings} +import dotty.tools.dotc.reporting.* +import dotty.tools.io.VirtualFile +import dotty.tools.dotc.config.Settings.ArgsSummary +import dotty.tools.dotc.config.{ScalaVersion, SpecificScalaVersion} + +import com.vladsch.flexmark.parser.Parser +import com.vladsch.flexmark.ast.{Heading, FencedCodeBlock} +import com.vladsch.flexmark.util.ast.Node +import com.vladsch.flexmark.formatter.Formatter +import com.vladsch.flexmark.util.sequence.BasedSequence +import com.vladsch.flexmark.util.data.MutableDataSet + +/** Logger trait for verbose output */ +trait Logger: + def debug(message: String): Unit + def warn(message: String): Unit + def info(message: String): Unit + def error(message: String): Unit + +object Logger: + def console(isVerbose: Boolean): Logger = new Logger: + def debug(message: String): Unit = if isVerbose then println(s"\u001b[90m$message${Console.RESET}") + def info(message: String): Unit = println(message) + def warn(message: String): Unit = println(s"${Console.YELLOW}$message${Console.RESET}") + def error(message: String): Unit = println(s"${Console.RED}$message${Console.RESET}") + +/** Check if an error code should be skipped based on its 'since' version */ +def isFutureErrorCode(sinceVersion: Option[ScalaVersion]): Boolean = + val currentCompilerVersion = getScriptCompilerVersion() + sinceVersion.exists { sinceVer => + // Compare major.minor.rev only, treating RC/Milestone as part of the same version + // e.g., 3.8.0-RC3 can test errors introduced in 3.8.0 + (currentCompilerVersion, sinceVer) match + case ( + SpecificScalaVersion(currMaj, currMin, currRev, _), + SpecificScalaVersion(sinceMaj, sinceMin, sinceRev, _) + ) => + currMaj < sinceMaj || + (currMaj == sinceMaj && currMin < sinceMin) || + (currMaj == sinceMaj && currMin == sinceMin && currRev < sinceRev) + case _ => currentCompilerVersion < sinceVer + } + +/** Check if an error code is inactive based on its 'until' version */ +def isInactiveErrorCode(untilVersion: Option[ScalaVersion]): Boolean = + lazy val currentCompilerVersion = getScriptCompilerVersion() + untilVersion.exists { untilVer => + // Compare major.minor.rev only, treating RC/Milestone as part of the same version + // If current version >= until version, the error code is inactive + (currentCompilerVersion, untilVer) match + case ( + dotty.tools.dotc.config.SpecificScalaVersion(currMaj, currMin, currRev, _), + dotty.tools.dotc.config.SpecificScalaVersion(untilMaj, untilMin, untilRev, _) + ) => + currMaj > untilMaj || + (currMaj == untilMaj && currMin > untilMin) || + (currMaj == untilMaj && currMin == untilMin && currRev >= untilRev) + case _ => currentCompilerVersion >= untilVer + } + +/** Validates error code documentation snippets. + * + * Usage: scala --with-compiler checkErrorCodeSnippets.scala -- --verbose + * + * Validates that: + * - Example snippets fail with the expected error code + * - Error section matches actual compiler output + * - Solution snippets compile without warnings + * + * Arguments: mdFile Path to error code markdown file verbose Pass "verbose" or "true" to print all compiler outputs + */ +@main def checkErrorCodeSnippets( + mdFile: os.Path, + varArgs: String* +): Unit = + val isVerbose = varArgs.contains("--verbose") + val updateOutput = varArgs.contains("--update-output") + + // Create the appropriate log based on verbose mode + given log: Logger = Logger.console(isVerbose = isVerbose) + + val fileName = mdFile.last + val expectedErrorCode = extractErrorCode(fileName).getOrElse { + log.error(s"Error: Could not extract error code from filename: $fileName") + sys.exit(1) + } + val expectedErrorCodeStr = formatErrorCode(expectedErrorCode) + log.info(s"Checking error code documentation: $fileName") + log.debug(s"Expected error code: $expectedErrorCodeStr") + log.info("=" * 60) + + val content = os.read(mdFile) + val parsed = parseMarkdown(content) + + // Check if error code is from a newer compiler version + if isFutureErrorCode(parsed.sinceVersion) then + val currentCompilerVersion = getScriptCompilerVersion() + log.warn( + s"⚠ Skipping validation: Error code introduced in ${parsed.sinceVersion.get.unparse}, " + + s"current compiler is ${currentCompilerVersion.unparse}" + ) + log.info(" Documentation will be validated once the error code is available in the released compiler") + sys.exit(0) + + // Check if error code is inactive (was removed in a previous compiler version) + if isInactiveErrorCode(parsed.untilVersion) then + val currentCompilerVersion = getScriptCompilerVersion() + log.warn( + s"⚠ Skipping validation: Error code was made inactive in ${parsed.untilVersion.get.unparse}, " + + s"current compiler is ${currentCompilerVersion.unparse}" + ) + log.info(" This error code is no longer emitted by the compiler") + sys.exit(0) + + var hasErrors = false + + // Check example snippets - they should fail + log.info("\n[1/3] Checking Example snippets (should fail with expected error)...") + + parsed.exampleSnippets.zipWithIndex.foreach { case (snippet, idx) => + val result = checkExampleSnippet(snippet, expectedErrorCode, idx + 1, collectDiagnostics = updateOutput) + if !result then hasErrors = true + } + + log.info(s"\n[2/3] Validating Error section output...") + // Handle non-reproducible error codes + val isNonReproducible = NonReproducibleErrorCodes.isNonReproducible(expectedErrorCode) + + // Handle update-output mode + if parsed.exampleSnippets.isEmpty && parsed.exampleNoCompileSnippets.isEmpty then + if isNonReproducible then + log.warn(s" ⚠ $expectedErrorCodeStr is marked as non-reproducible in NonReproducibleErrorCodes.codes") + log.warn(s" No example snippets expected for this error code") + else + log.error(s" ✗ No example snippets found to verify") + hasErrors = true + else if parsed.exampleSnippets.isEmpty && parsed.exampleNoCompileSnippets.nonEmpty then + if isNonReproducible then + log.warn(s" ⚠ $expectedErrorCodeStr is marked as non-reproducible in NonReproducibleErrorCodes.codes") + else + log.warn(s" ⚠ All example snippets are marked 'sc:nocompile' - cannot verify error code") + log.warn(s" Consider adding this error to NonReproducibleErrorCodes.codes if it cannot be reproduced") + else if updateOutput then + log.info(s"\n Updating Error section output...") + val snippet = parsed.exampleSnippets.head // Use first example snippet + val result = compileSnippet(snippet) + + // Verify compilation produced the expected error code before updating + if !result.errorCodes.contains(expectedErrorCode) then + log.error(s" ✗ Cannot update: compilation did not produce expected error code $expectedErrorCodeStr") + log.error(s" Found error codes: ${result.errorCodes.map(formatErrorCode).mkString(", ")}") + log.debug(s" Messages:\n${result.messages.map(" " + _).mkString("\n")}") + hasErrors = true + else + val newErrorOutput = getFormattedOutputForComparison(result.diagnostics) + val updatedContent = updateErrorSection(content, newErrorOutput) + os.write.over(mdFile, updatedContent) + log.info(s" ✓ Updated error section in $mdFile") + else // check only + log.info(s"\nChecking Error section output...") + log.debug(s" Documented error output:\n${parsed.errorOutput}") + val errorCodePattern = s"\\[${Regex.quote(expectedErrorCodeStr)}\\]".r + + // For non-reproducible error codes, skip output validation (error code may not be in released compiler) + val hasCustomSnippets = parsed.exampleSnippets.exists(_.options.contains("custom-sc:fail")) + if isNonReproducible && hasCustomSnippets then + log.warn(s" ⚠ $expectedErrorCodeStr is non-reproducible - skipping error output validation") + log.warn(s" Error output was manually verified when documentation was created") + else if errorCodePattern.findFirstIn(parsed.errorOutput).isEmpty then + log.error(s" ✗ Error section does not contain expected error code $expectedErrorCodeStr") + hasErrors = true + else + log.info(s" ✓ Error section contains expected error code $expectedErrorCodeStr") + // Collect all diagnostics from example snippets + val allDiagnostics = parsed.exampleSnippets.flatMap { snippet => + compileSnippet(snippet).diagnostics + } + val actualOutput = getFormattedOutputForComparison(allDiagnostics) + log.debug(s" Actual compiler output:\n$actualOutput") + + // Exact match comparison + compareOutputs(parsed.errorOutput, actualOutput) match + case None => + log.info(s" ✓ Error section matches compiler output exactly") + case Some(diff) => + log.error(s" ✗ Error section does not match compiler output") + log.info(s" Diff (- documented, + actual):\n$diff") + log.info( + s"\n Update with: scala project/scripts/checkErrorCodeSnippets.scala --with-compiler -- $mdFile --update-output" + ) + hasErrors = true + + // Check solution snippets - they should compile without warnings + log.info("\n[3/3] Checking Solution snippets (should compile without warnings)...") + parsed.solutionSnippets.zipWithIndex.foreach { case (snippet, idx) => + val result = checkSolutionSnippet(snippet, idx + 1) + if !result then hasErrors = true + } + + if parsed.solutionSnippets.isEmpty then + if isNonReproducible then log.warn(s" ⚠ No solution snippets found (acceptable for non-reproducible error code)") + else log.warn(" ⚠ No solution snippets found with 'sc:compile' or 'custom-sc:compile' marker") + + log.info("\n" + "=" * 60) + if hasErrors then + log.error("FAILED: Some checks did not pass") + sys.exit(1) + else + log.info(s"${Console.GREEN}SUCCESS: All checks passed${Console.RESET}") + sys.exit(0) +end checkErrorCodeSnippets + +/** Updates error outputs for all error code documentation files. + * + * Usage: scala --with-compiler checkErrorCodeSnippets.scala --main-class updateAllErrorCodeOutputs + */ +@main def updateAllErrorCodeOutputs(varArgs: String*): Unit = + val isVerbose = varArgs.contains("--verbose") + + given log: Logger = Logger.console(isVerbose = isVerbose) + + val errorCodesDir = os.pwd / "docs" / "_docs" / "reference" / "error-codes" + + if !os.exists(errorCodesDir) then + log.error(s"Error codes directory not found: $errorCodesDir") + sys.exit(1) + + val errorCodeFiles = os + .list(errorCodesDir) + .filter(_.last.matches("E\\d+\\.md")) + .sorted + + log.info(s"Found ${errorCodeFiles.size} error code documentation files") + log.info("=" * 60) + + var updated = 0 + var skipped = 0 + var failed = 0 + + errorCodeFiles.foreach { mdFile => + val fileName = mdFile.last + extractErrorCode(fileName) match + case None => + log.warn(s" ⚠ Skipping $fileName: could not extract error code") + skipped += 1 + + case Some(expectedErrorCode) => + val expectedErrorCodeStr = formatErrorCode(expectedErrorCode) + log.info(s"\n$expectedErrorCodeStr: $fileName") + + val content = os.read(mdFile) + val parsed = parseMarkdown(content) + + if isInactiveErrorCode(parsed.untilVersion) then + log.warn(s" ⚠ Skipping: error code is inactive") + skipped += 1 + else if isFutureErrorCode(parsed.sinceVersion) then + log.warn(s" ⚠ Skipping: error code is future") + skipped += 1 + else if parsed.exampleSnippets.isEmpty then + log.warn(s" ⚠ Skipping: no example snippets found") + skipped += 1 + else + val snippet = parsed.exampleSnippets.head + val result = compileSnippet(snippet) + + if !result.errorCodes.contains(expectedErrorCode) then + log.error(s" ✗ Compilation did not produce expected error code $expectedErrorCodeStr") + log.error(s" Found: ${result.errorCodes.map(formatErrorCode).mkString(", ")}") + failed += 1 + else + val newErrorOutput = getFormattedOutputForComparison(result.diagnostics) + val currentOutput = parsed.errorOutput + + // Check if update is needed + compareOutputs(currentOutput, newErrorOutput) match + case None => + log.info(s" ✓ Already up to date") + skipped += 1 + case Some(_) => + val updatedContent = updateErrorSection(content, newErrorOutput) + os.write.over(mdFile, updatedContent) + log.info(s" ✓ Updated") + updated += 1 + } + + log.info("\n" + "=" * 60) + log.info(s"Summary: $updated updated, $skipped skipped, $failed failed") + + if failed > 0 then + log.error("Some files could not be updated") + sys.exit(1) + else log.info(s"${Console.GREEN}Done${Console.RESET}") +end updateAllErrorCodeOutputs + +given FromString[os.Path] = os.Path(_, os.pwd) + +case class Snippet(code: String, options: List[String]) + +case class ParsedMarkdown( + exampleSnippets: List[Snippet], + exampleNoCompileSnippets: List[Snippet], + errorOutput: String, + solutionSnippets: List[Snippet], + sinceVersion: Option[ScalaVersion], + untilVersion: Option[ScalaVersion] +) + +def extractErrorCode(fileName: String): Option[Int] = + val pattern = """E(\d+)\.md""".r + fileName match + case pattern(num) => Some(num.toInt) + case _ => None + +def formatErrorCode(code: Int): String = f"E$code%03d" + +/** Extract the 'since' version from YAML frontmatter */ +def extractSinceVersion(content: String): Option[ScalaVersion] = + val yamlPattern = """(?s)^---\n(.*?)\n---""".r + yamlPattern.findFirstMatchIn(content).flatMap { m => + val yaml = m.group(1) + val sincePattern = """since:\s*([0-9.]+(?:-[A-Za-z0-9]+)?)""".r + sincePattern.findFirstMatchIn(yaml).flatMap { versionMatch => + val versionStr = versionMatch.group(1) + ScalaVersion.parse(versionStr).toOption + } + } + +/** Extract the 'until' version from YAML frontmatter */ +def extractUntilVersion(content: String): Option[ScalaVersion] = + val yamlPattern = """(?s)^---\n(.*?)\n---""".r + yamlPattern.findFirstMatchIn(content).flatMap { m => + val yaml = m.group(1) + val untilPattern = """until:\s*([0-9.]+(?:-[A-Za-z0-9]+)?)""".r + untilPattern.findFirstMatchIn(yaml).flatMap { versionMatch => + val versionStr = versionMatch.group(1) + ScalaVersion.parse(versionStr).toOption + } + } + +/** Get the compiler version used by this script (from //> using scala directive) */ +def getScriptCompilerVersion(): ScalaVersion = + // The script uses //> using scala 3.7.4 and //> using dep org.scala-lang::scala3-compiler:3.7.4 + // We extract it from the compiler artifact version + val compilerVersion = dotty.tools.dotc.config.Properties.versionNumberString + ScalaVersion.parse(compilerVersion).getOrElse(ScalaVersion.current) + +/** Run scala compile --server=false on code and capture output */ +def runScalaCompile(code: String): String = + val compilerVersion = scala.util.Properties.versionNumberString match { + case s"2.${_}" => "3.8.0-RC3" + case version => version + } + os.proc( + "scala", + "compile", + "--server=false", + s"--scala-version=$compilerVersion", + "-color:never", + "-explain", + "-explain-types", + "-explain-cyclic", + "_" + ).call(stderr = os.Pipe, mergeErrIntoOut = true, stdin = code.getBytes("UTF-8"), check = false) + .out + .text() + +/** Format scala compile output for documentation */ +def formatScalaCompileOutput(compileOutput: String): String = + stripAnsi(compileOutput) + .replaceAll(raw"(/[^:\s]+(?:/[^:\s]+)*\.scala)", "example.scala") + .linesIterator + .takeWhile(!_.matches(raw"^\d+ error(s)? found")) + .mkString("\n") + +/** Format compiler output for documentation, normalizing paths */ +def formatCompilerOutput(diagnostic: DiagnosticMessage, expectedErrorCodeStr: String): String = + val lines = diagnostic.message.linesIterator.toList + + // Format the first line with the error code, keeping original positions but normalizing file path + val formattedLines = lines match + case firstLine :: rest => + // Replace the file path with example.scala but keep line:col positions + val formattedFirst = firstLine.replaceAll("/.*/[^/]*\\.scala", "example.scala") + s"-- [$expectedErrorCodeStr] $formattedFirst" :: rest + case Nil => + throw new RuntimeException("No compiler output received for error formatting") + + formattedLines.mkString("\n") + +/** Update the error section in markdown content */ +def updateErrorSection(content: String, newErrorOutput: String): String = + // Preserve YAML front matter - flexmark modifies it during rendering + val yamlPattern = """(?s)^(---\n.*?\n---\n)(.*)$""".r + val (yamlFrontMatter, bodyContent) = content match + case yamlPattern(yaml, body) => (Some(yaml), body) + case _ => (None, content) + + // Configure formatter to preserve whitespace in fenced code blocks + val options = new MutableDataSet() + options.set(Formatter.FENCED_CODE_MINIMIZE_INDENT, java.lang.Boolean.FALSE) + options.set(Formatter.INDENTED_CODE_MINIMIZE_INDENT, java.lang.Boolean.FALSE) + + val parser = Parser.builder(options).build() + val formatter = Formatter.builder(options).build() + val document = parser.parse(bodyContent) + + // Find: ### Error or ### Warning + var n: Node | Null = document.getFirstChild + while n != null do + n match + case h: Heading + if h.getLevel == 3 && (h.getText.toString.trim == "Error" || h.getText.toString.trim == "Warning") => + // Scan forward until next heading of level <= 3, looking for fenced sc:nocompile + var m: Node | Null = h.getNext + var updated = false + while m != null && !updated do + m match + case hh: Heading if hh.getLevel <= 3 => + // stop scanning this section + updated = true // "done", but without changing anything + case cb: FencedCodeBlock if cb.getInfo.toString.contains("sc:nocompile") => + // Update the content of the fenced code block + val seq = BasedSequence.of(newErrorOutput + "\n") + cb.setContent(seq, java.util.List.of(seq)) + updated = true + case _ => + m = m.getNext + n = h.getNext // continue after heading + case _ => + n = n.getNext + + val renderedBody = formatter.render(document) + yamlFrontMatter.fold(renderedBody)(_ + renderedBody) + +def parseMarkdown(content: String): ParsedMarkdown = + val parser = Parser.builder().build() + val document = parser.parse(content) + + var currentSection: Option["example" | "output" | "solution"] = None + var exampleSnippets = List.empty[Snippet] + var exampleNoCompileSnippets = List.empty[Snippet] + var errorOutput = "" + var solutionSnippets = List.empty[Snippet] + + // Extract since and until versions from YAML frontmatter + val sinceVersion = extractSinceVersion(content) + val untilVersion = extractUntilVersion(content) + + // Iterate through all nodes in document order + var node: Node = document.getFirstChild + while node != null do + node match + case heading: Heading => + val text = heading.getText.toString.toLowerCase + val level = heading.getLevel + currentSection = (level, text) match + case (2, "example") => Some("example") + case (3, "error" | "warning") => Some("output") + case (3, "solution") => Some("solution") + case (1 | 2, _) => None // Reset on new top-level sections + case _ => currentSection // Keep current section for other headings + + case codeBlock: FencedCodeBlock => + val info = codeBlock.getInfo.toString.trim + val code = codeBlock.getContentChars.toString.trim + val parts = info.split("\\s+").toList + // Parse both sc: and custom-sc: options + val options = parts.filter(p => p.startsWith("sc:") || p.startsWith("sc-") || p.startsWith("custom-sc:")) + + // custom-sc: attributes override sc:nocompile for our snippet compiler + // This allows snippets to be ignored by Scaladoc but still tested by us + currentSection match + case Some("example") if options.contains("sc:fail") || options.contains("custom-sc:fail") => + exampleSnippets = exampleSnippets :+ Snippet(code, options) + case Some("example") if options.contains("sc:nocompile") => + exampleNoCompileSnippets = exampleNoCompileSnippets :+ Snippet(code, options) + case Some("output") => + errorOutput = code + case Some("solution") if options.contains("sc:compile") || options.contains("custom-sc:compile") => + solutionSnippets = solutionSnippets :+ Snippet(code, options) + case _ => // ignore other code blocks + + case _ => // ignore other node types + + node = node.getNext + end while + + ParsedMarkdown(exampleSnippets, exampleNoCompileSnippets, errorOutput, solutionSnippets, sinceVersion, untilVersion) +end parseMarkdown + +def extractScalacOptions(options: List[String]): List[String] = + options + .filter(_.startsWith("sc-opts:")) + .flatMap(_.stripPrefix("sc-opts:").split(",").toList) + +/** Strip ANSI escape codes from a string */ +def stripAnsi(s: String): String = + s.replaceAll("\u001b\\[[0-9;]*m", "") + +/** Messages to filter out when comparing outputs (added by -Werror compilation) */ +val filteredMessages: Set[String] = Set( + "No warnings can be incurred under -Werror" +) + +/** Get the formatted compiler output for comparison, filtering out -Werror messages */ +def getFormattedOutputForComparison(diagnostics: List[DiagnosticMessage]): String = + diagnostics + .filterNot(d => filteredMessages.exists(d.message.contains)) + .map(_.formattedOutput) + .mkString("\n") + .trim + +/** Normalize whitespace for comparison (trim lines, normalize line endings) */ +def normalizeWhitespace(s: String): String = + s.linesIterator + .map(_.stripTrailing()) + .mkString("\n") + .trim + +/** Compare documented error output with actual compiler output. Returns None if they match, or Some(diff) with the + * differences. + */ +def compareOutputs(documented: String, actual: String): Option[String] = + val normalizedDocumented = normalizeWhitespace(documented) + val normalizedActual = normalizeWhitespace(actual) + + if normalizedDocumented == normalizedActual then None + else + // Generate a simple line-by-line diff + val docLines = normalizedDocumented.linesIterator.toVector + val actLines = normalizedActual.linesIterator.toVector + val maxLines = math.max(docLines.length, actLines.length) + + val diffLines = (0 until maxLines).flatMap { i => + val docLine = docLines.lift(i) + val actLine = actLines.lift(i) + (docLine, actLine) match + case (Some(d), Some(a)) if d == a => + Seq(s" $d") + case (Some(d), Some(a)) => + Seq(s"${Console.RED}- $d${Console.RESET}", s"${Console.GREEN}+ $a${Console.RESET}") + case (Some(d), None) => + Seq(s"${Console.RED}- $d${Console.RESET}") + case (None, Some(a)) => + Seq(s"${Console.GREEN}+ $a${Console.RESET}") + case (None, None) => + Seq.empty + } + Some(diffLines.mkString("\n")) + +/** A diagnostic message with its associated error code and formatted output */ +case class DiagnosticMessage(errorCode: Option[Int], message: String, formattedOutput: String) + +/** Result of compiling a snippet */ +case class CompileResult( + hasErrors: Boolean, + hasWarnings: Boolean, + diagnostics: List[DiagnosticMessage] +): + def errorCodes: Set[Int] = diagnostics.flatMap(_.errorCode).toSet + def messages: List[String] = diagnostics.map(_.message) + + /** Get full formatted output like scala compile produces */ + def formattedOutput: String = diagnostics.map(_.formattedOutput).mkString("\n") + +/** Helper for formatting diagnostics like console output */ +object DiagnosticFormatter extends MessageRendering + +/** Snippet compiler with dedicated output directory */ +object SnippetCompiler: + // Dedicated temp directory for compilation outputs (cached to avoid creating many dirs) + private lazy val outputDir = os.temp.dir(prefix = "snippet-compile-") + + // Base options used for all compilations + private val baseOpts = List("-usejavacp", "-color:never", "-explain") + + def compile(code: String, extraOpts: List[String]): CompileResult = + // Create fresh compiler infrastructure for each compilation + // (ContextBase and Compiler cannot be reused due to stale symbol issues) + val base = new ContextBase + val compiler = new Compiler + + // Create fresh reporter + val reporter = new StoreReporter(null) with UniqueMessagePositions with HideNonSensicalMessages + + // Create virtual source file + val virtualFile = VirtualFile("snippet.scala", code.getBytes("UTF-8")) + val sourceFile = dotty.tools.dotc.util.SourceFile(virtualFile, scala.io.Codec.UTF8) + + // Process all options + val allOpts = baseOpts ++ List("-d", outputDir.toString) ++ extraOpts + val ArgsSummary(sstate, _, _, _) = + base.initialCtx.settings.processArguments(allOpts, processAll = true, base.initialCtx.settingsState) + + given ctx: Context = base.initialCtx.fresh + .setReporter(reporter) + .setSettings(sstate) + .setProperty(ContextDoc, new ContextDocstrings) + + // Compile + val run = compiler.newRun + run.compileSources(List(sourceFile)) + + // Extract results + val runCtx = run.runContext + val rawMessages = reporter.removeBufferedMessages(using runCtx) + + val diagnostics = rawMessages.map { diag => + val errorNumber = diag.msg.errorId.errorNumber + val errorCode = Option.when(errorNumber >= 0)(errorNumber) + // Get the raw message and the formatted console-style output + val rawMessage = stripAnsi(diag.msg.message) + val formattedOutput = stripAnsi(DiagnosticFormatter.messageAndPos(diag)(using runCtx)) + .replaceAll("snippet\\.scala", "example.scala") // Normalize file name + DiagnosticMessage(errorCode, rawMessage, formattedOutput) + }.toList + + CompileResult( + hasErrors = reporter.hasErrors, + hasWarnings = reporter.hasWarnings, + diagnostics = diagnostics + ) + end compile +end SnippetCompiler + +/** Compile a snippet using the Scala 3 compiler */ +def compileSnippet(snippet: Snippet): CompileResult = + val extraOpts = extractScalacOptions(snippet.options) + try SnippetCompiler.compile(snippet.code, extraOpts) + catch + case exception: Exception => + System.err.println(s"Crash when compiling snippet:") + System.err.println(snippet.code) + exception.printStackTrace() + throw exception + +def checkExampleSnippet(snippet: Snippet, expectedErrorCode: Int, index: Int, collectDiagnostics: Boolean = false)(using + log: Logger +): Boolean = + print(s" Example #$index: ") + + log.debug("") + log.debug(" Snippet code:") + log.debug(" ```scala") + snippet.code.linesIterator.foreach(line => log.debug(s" $line")) + log.debug(" ```") + if snippet.options.nonEmpty then log.debug(s" Options: ${snippet.options.mkString(", ")}") + + val result = compileSnippet(snippet) + val isCustomSnippet = snippet.options.contains("custom-sc:fail") + val isNonReproducible = NonReproducibleErrorCodes.isNonReproducible(expectedErrorCode) + + log.debug(" Compiler output:") + result.diagnostics.foreach(d => d.formattedOutput.linesIterator.foreach(line => log.debug(s" $line"))) + + if collectDiagnostics then + // In collect diagnostics mode, just check that compilation fails and print basic status + val success = result.hasErrors || result.hasWarnings + if success then log.info(s"✓ Compilation failed (collecting diagnostics)") + else log.error(s"✗ Expected compilation to fail, but it succeeded") + success + else if isCustomSnippet && isNonReproducible then + // For custom snippets with non-reproducible error codes, just verify compilation produces warnings/errors + // The error code may not be available in the released compiler version + if !result.hasErrors && !result.hasWarnings then + log.error("✗ Expected compilation to fail, but it succeeded") + false + else + log.info(s"✓ Compilation produces warnings/errors (non-reproducible error code, skipping code validation)") + true + else + // Normal validation mode + if !result.hasErrors && !result.hasWarnings then + log.error("✗ Expected compilation to fail, but it succeeded") + false + else + def unexpectedCodes = result.errorCodes - expectedErrorCode + if !result.errorCodes.contains(expectedErrorCode) then + log.error(s"✗ Expected error code ${formatErrorCode(expectedErrorCode)} not found in output") + log.error(s" Found error codes: ${result.errorCodes.map(formatErrorCode).mkString(", ")}") + log.debug(s" Messages:\n${result.messages.map(" " + _).mkString("\n")}") + false + else if unexpectedCodes.nonEmpty then + log.error(s"✗ Found unexpected error codes: ${unexpectedCodes.map(formatErrorCode).mkString(", ")}") + log.error(s" Expected only: ${formatErrorCode(expectedErrorCode)}") + false + else + log.info(s"✓ Fails with expected error code ${formatErrorCode(expectedErrorCode)}") + true +end checkExampleSnippet + +def checkSolutionSnippet(snippet: Snippet, index: Int)(using log: Logger): Boolean = + log.info(s" Solution #$index: ") + + log.debug("") + log.debug(" Snippet code:") + log.debug(" ```scala") + snippet.code.linesIterator.foreach(line => log.debug(s" $line")) + log.debug(" ```") + if snippet.options.nonEmpty then log.debug(s" Options: ${snippet.options.mkString(", ")}") + + // Always compile solutions with -Werror to catch warnings + val snippetWithWerror = snippet.copy( + options = snippet.options.filterNot(_.contains("-Werror")) :+ "sc-opts:-Werror" + ) + + val result = compileSnippet(snippetWithWerror) + + val outputLabel = if result.diagnostics.isEmpty then "(none)" else "" + log.debug(s" Compiler output: $outputLabel") + result.diagnostics.foreach(d => d.formattedOutput.linesIterator.foreach(line => log.debug(s" $line"))) + + if !result.hasErrors && !result.hasWarnings then + log.info("✓ Compiles successfully without warnings") + true + else + log.error("✗ Failed to compile or has warnings") + log.debug(s" Messages:\n${result.messages.map(" " + _).mkString("\n")}") + false +end checkSolutionSnippet diff --git a/project/scripts/checkErrorCodeSnippets.test.scala b/project/scripts/checkErrorCodeSnippets.test.scala new file mode 100644 index 000000000000..2e0782346285 --- /dev/null +++ b/project/scripts/checkErrorCodeSnippets.test.scala @@ -0,0 +1,267 @@ +//> using file checkErrorCodeSnippets.scala +// scalafmt: { maxColumn = 120 } + +import scala.util.matching.Regex +import dotty.tools.dotc.reporting.ErrorMessageID +import dotty.tools.dotc.config.{ScalaVersion, SpecificScalaVersion} + +class ErrorCodeSnippetsTest extends munit.FunSuite: + + // Check if an error code should be skipped based on its 'since' version + def isFutureErrorCode(sinceVersion: Option[ScalaVersion]): Boolean = + val currentCompilerVersion = getScriptCompilerVersion() + sinceVersion.exists { sinceVer => + (currentCompilerVersion, sinceVer) match + case ( + SpecificScalaVersion(currMaj, currMin, currRev, _), + SpecificScalaVersion(sinceMaj, sinceMin, sinceRev, _) + ) => + currMaj < sinceMaj || + (currMaj == sinceMaj && currMin < sinceMin) || + (currMaj == sinceMaj && currMin == sinceMin && currRev < sinceRev) + case _ => currentCompilerVersion < sinceVer + } + + // Check if an error code is inactive based on its 'until' version + def isInactiveErrorCode(untilVersion: Option[ScalaVersion]): Boolean = + val currentCompilerVersion = getScriptCompilerVersion() + untilVersion.exists { untilVer => + // If current version >= until version, the error code is inactive + (currentCompilerVersion, untilVer) match + case ( + SpecificScalaVersion(currMaj, currMin, currRev, _), + SpecificScalaVersion(untilMaj, untilMin, untilRev, _) + ) => + currMaj > untilMaj || + (currMaj == untilMaj && currMin > untilMin) || + (currMaj == untilMaj && currMin == untilMin && currRev >= untilRev) + case _ => currentCompilerVersion >= untilVer + } + + /** Helper to check assumptions and print skip reason if assumption fails */ + def assumeWithLogging(condition: Boolean, message: => String): Unit = + if !condition then + println(s"${Console.YELLOW} ⚠ Skipping: $message${Console.RESET}") + assume(false, message) + + // Find all error code documentation files + val errorCodesDir: os.Path = os.pwd / "docs" / "_docs" / "reference" / "error-codes" + + val errorCodeFiles: Seq[os.Path] = + if !os.exists(errorCodesDir) then sys.error(s"Error codes directory not found: $errorCodesDir") + os.list(errorCodesDir) + .filter(_.last.matches("E\\d+\\.md")) + .sorted + + // Get all error message IDs from the compiler + val allErrorIds: Seq[ErrorMessageID] = + ErrorMessageID.values.toSeq.filterNot(_ == ErrorMessageID.NoExplanationID) + + val activeErrorIds: Seq[ErrorMessageID] = allErrorIds.filter(_.isActive) + val inactiveErrorIds: Seq[ErrorMessageID] = allErrorIds.filterNot(_.isActive) + + // Extract documented error codes from file names (as Int) + val documentedErrorCodes: Map[Int, os.Path] = + errorCodeFiles + .flatMap: f => + extractErrorCode(f.last).map: errorCode => + (errorCode, f) + .toMap + + val (inactiveDocumentedErrorCodes, activeDocumentedErrorCodes) = documentedErrorCodes.partition { (errorCode, _) => + inactiveErrorIds.exists(_.errorNumber == errorCode) + } + + extension (id: ErrorMessageID) + def isIgnored: Boolean = + inactiveErrorIds.contains(id.errorNumber) || IgnoredInactiveErrorCodes.isIgnored(id.errorNumber) + + // Test: All active error codes should have documentation + test("All active error codes must have documentation") { + val missingDocs = activeErrorIds.filterNot { id => + documentedErrorCodes.contains(id.errorNumber) + } + + if missingDocs.nonEmpty then + val missing = missingDocs.map(id => s"${formatErrorCode(id.errorNumber)} (${id.toString})").mkString("\n - ") + fail(s"Missing documentation for active error codes:\n - $missing") + } + + test("Inactive error codes must have documentation") { + val missingDocs = inactiveErrorIds.filterNot { id => + documentedErrorCodes.contains(id.errorNumber) || IgnoredInactiveErrorCodes.isIgnored(id.errorNumber) + } + if missingDocs.nonEmpty then + val missing = missingDocs.map(id => s"${formatErrorCode(id.errorNumber)} (${id.toString})").mkString("\n - ") + fail(s"Missing documentation for inactive error codes:\n - $missing") + + } + inactiveDocumentedErrorCodes.foreach: (errorCode, mdFile) => + test(s"${formatErrorCode(errorCode)} inactive has 'until' version") { + os.read(mdFile).linesIterator.find(_.startsWith("until: ")) match { + case Some(s"until: $version") => + assert(ScalaVersion.parse(version).isSuccess, s"Invalid until version: $version") + case None => fail(s"No until version found in $mdFile") + case Some(line) => fail(s"Unexpected line in $mdFile: $line") + } + } + + test("Documentation files must correspond to valid error codes") { + val validErrorCodes = allErrorIds.map(_.errorNumber).toSet + + // Filter out error codes that have a 'since' version higher than current compiler + val invalidDocs = documentedErrorCodes.filterNot { (errorCode, mdFile) => + validErrorCodes.contains(errorCode) || { + // Check if this error code has a 'since' version that's newer than current compiler + os.exists(mdFile) && { + val content = os.read(mdFile) + val parsed = parseMarkdown(content) + isFutureErrorCode(parsed.sinceVersion) + } + } + } + + if invalidDocs.nonEmpty then + val invalid = invalidDocs.keys.toSeq.sorted.map(formatErrorCode).mkString(", ") + fail(s"Found documentation for non-existent error codes: $invalid") + } + + // Generate two tests for each error code file + errorCodeFiles.foreach { mdFile => + val fileName = mdFile.last + extractErrorCode(fileName).foreach { errorCode => + val errorCodeStr = formatErrorCode(errorCode) + + // Test 1: Check example snippets fail with expected error + test(s"$errorCodeStr - examples must fail with expected error") { + val content = os.read(mdFile) + val parsed = parseMarkdown(content) + + // Skip validation for error codes from future compiler versions + assumeWithLogging( + !isFutureErrorCode(parsed.sinceVersion), + s"$errorCodeStr introduced in ${parsed.sinceVersion.get.unparse}, current compiler is ${getScriptCompilerVersion().unparse}" + ) + + // Skip validation for inactive error codes + assumeWithLogging( + !isInactiveErrorCode(parsed.untilVersion), + s"$errorCodeStr was made inactive in ${parsed.untilVersion.get.unparse}, current compiler is ${getScriptCompilerVersion().unparse}" + ) + + // Skip validation for non-reproducible error codes + assumeWithLogging( + !NonReproducibleErrorCodes.isNonReproducible(errorCode), + s"$errorCodeStr is non-reproducible - cannot be triggered with pure Scala 3 source code" + ) + + // If all example snippets are sc:nocompile, skip validation with a note + assumeWithLogging( + parsed.exampleSnippets.nonEmpty || parsed.exampleNoCompileSnippets.isEmpty, + s"$errorCodeStr has only sc:nocompile snippets - requires special circumstances" + ) + + assert(parsed.exampleSnippets.nonEmpty, s"No example snippets found in $mdFile") + + // Collect all diagnostics from compiling example snippets + val allDiagnostics = parsed.exampleSnippets.zipWithIndex.flatMap { case (snippet, idx) => + val result = compileSnippet(snippet) + + assert( + result.hasErrors || result.hasWarnings, + s"Example #${idx + 1} should fail compilation but succeeded" + ) + + assert( + result.errorCodes.contains(errorCode), + s"Example #${idx + 1} should emit error code $errorCodeStr.\nFound: ${result.errorCodes.map(formatErrorCode).mkString(", ")}\nMessages:\n${result.messages.mkString("\n")}" + ) + + // Check for unexpected error codes + val unexpectedCodes = result.errorCodes - errorCode + assert( + unexpectedCodes.isEmpty, + s"Example #${idx + 1} emitted unexpected error codes: ${unexpectedCodes.map(formatErrorCode).mkString(", ")}. Expected only $errorCodeStr" + ) + + result.diagnostics + } + + // Check error section contains expected error code + assert(parsed.errorOutput.nonEmpty, s"No error output found in $mdFile") + val errorCodePattern = s"\\[${Regex.quote(errorCodeStr)}\\]".r + assert( + errorCodePattern.findFirstIn(parsed.errorOutput).isDefined, + s"Error section should contain error code $errorCodeStr" + ) + + // Exact match comparison of documented vs actual compiler output + val actualOutput = getFormattedOutputForComparison(allDiagnostics) + + compareOutputs(parsed.errorOutput, actualOutput) match + case None => // Output matches exactly + case Some(diff) => + fail( + s"""Error section does not match compiler output exactly. + | + |Diff (- documented, + actual): + |$diff + | + |Update expected output with: scala project/scripts/checkErrorCodeSnippets.scala --with-compiler -- $mdFile --update-output + |""".stripMargin + ) + } + + // Test 2: Check solution snippets compile without warnings + test(s"$errorCodeStr - solutions must compile") { + val content = os.read(mdFile) + val parsed = parseMarkdown(content) + + // Skip validation for error codes from future compiler versions + assumeWithLogging( + !isFutureErrorCode(parsed.sinceVersion), + s"$errorCodeStr introduced in ${parsed.sinceVersion.get.unparse}, current compiler is ${getScriptCompilerVersion().unparse}" + ) + + // Skip validation for inactive error codes + assumeWithLogging( + !isInactiveErrorCode(parsed.untilVersion), + s"$errorCodeStr was made inactive in ${parsed.untilVersion.get.unparse}, current compiler is ${getScriptCompilerVersion().unparse}" + ) + + // Skip validation for non-reproducible error codes + assumeWithLogging( + !NonReproducibleErrorCodes.isNonReproducible(errorCode), + s"$errorCodeStr is non-reproducible - cannot be triggered with pure Scala 3 source code" + ) + + // If all example snippets are sc:nocompile and there are no sc:compile solutions, skip + assumeWithLogging( + parsed.solutionSnippets.nonEmpty || parsed.exampleNoCompileSnippets.isEmpty, + s"$errorCodeStr has only sc:nocompile snippets - requires special circumstances" + ) + + assert(parsed.solutionSnippets.nonEmpty, s"No solution snippets found in $mdFile") + + parsed.solutionSnippets.zipWithIndex.foreach { case (snippet, idx) => + val snippetWithWerror = snippet.copy( + options = snippet.options.filterNot(_.contains("-Werror")) :+ "sc-opts:-Werror" + ) + val result = compileSnippet(snippetWithWerror) + assert( + !result.hasErrors && !result.hasWarnings, + s"Solution #${idx + 1} should compile without warnings.\nMessages:\n${result.messages.mkString("\n")}" + ) + } + } + + if errorCode > Scala3_0_0_MaxErrorCode then + test(s"$errorCodeStr - must have 'since' version attirubte") { + os.read(mdFile).linesIterator.find(_.startsWith("since: ")) match { + case Some(s"since: $version") => + assert(ScalaVersion.parse(version).isSuccess, s"Invalid since version: $version") + case _ => fail(s"No 'from' version attribute found in $mdFile") + } + } + } + } From 1b7a3e626e279932625714bdd35e92b4fcabd7bf Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 19:07:26 +0100 Subject: [PATCH 03/11] Fix existing and document remaining error codes --- docs/_docs/reference/error-codes/E001.md | 63 +++++++---- docs/_docs/reference/error-codes/E002.md | 63 ++++++++--- docs/_docs/reference/error-codes/E003.md | 16 ++- docs/_docs/reference/error-codes/E004.md | 24 ++-- docs/_docs/reference/error-codes/E005.md | 28 +++-- docs/_docs/reference/error-codes/E006.md | 32 ++++-- docs/_docs/reference/error-codes/E007.md | 36 ++++-- docs/_docs/reference/error-codes/E008.md | 17 ++- docs/_docs/reference/error-codes/E009.md | 59 ++++++++-- docs/_docs/reference/error-codes/E010.md | 70 ++++++++++++ docs/_docs/reference/error-codes/E011.md | 20 ++-- docs/_docs/reference/error-codes/E012.md | 32 ++++-- docs/_docs/reference/error-codes/E013.md | 30 +++-- docs/_docs/reference/error-codes/E014.md | 38 +++++++ docs/_docs/reference/error-codes/E015.md | 26 +++-- docs/_docs/reference/error-codes/E016.md | 28 +++-- docs/_docs/reference/error-codes/E017.md | 66 +++++++++-- docs/_docs/reference/error-codes/E018.md | 37 +++--- docs/_docs/reference/error-codes/E019.md | 25 ++-- docs/_docs/reference/error-codes/E020.md | 58 +++++++--- docs/_docs/reference/error-codes/E021.md | 69 +++++++++--- docs/_docs/reference/error-codes/E022.md | 36 ++++-- docs/_docs/reference/error-codes/E023.md | 34 ++++-- docs/_docs/reference/error-codes/E024.md | 65 +++++++++-- docs/_docs/reference/error-codes/E025.md | 50 ++------ docs/_docs/reference/error-codes/E026.md | 33 ++++-- docs/_docs/reference/error-codes/E027.md | 35 +----- docs/_docs/reference/error-codes/E028.md | 53 ++------- docs/_docs/reference/error-codes/E029.md | 25 ++-- docs/_docs/reference/error-codes/E030.md | 13 +-- docs/_docs/reference/error-codes/E031.md | 43 ++++--- docs/_docs/reference/error-codes/E032.md | 87 ++++++++++++-- docs/_docs/reference/error-codes/E033.md | 54 +++++---- docs/_docs/reference/error-codes/E034.md | 44 +++++--- docs/_docs/reference/error-codes/E035.md | 58 ++++++++-- docs/_docs/reference/error-codes/E036.md | 55 +++++++++ docs/_docs/reference/error-codes/E037.md | 23 ++-- docs/_docs/reference/error-codes/E038.md | 30 +++-- docs/_docs/reference/error-codes/E039.md | 32 ++++-- docs/_docs/reference/error-codes/E040.md | 18 ++- docs/_docs/reference/error-codes/E041.md | 46 ++++++-- docs/_docs/reference/error-codes/E042.md | 32 ++++-- docs/_docs/reference/error-codes/E043.md | 27 +++-- docs/_docs/reference/error-codes/E044.md | 37 ++++-- docs/_docs/reference/error-codes/E045.md | 24 ++-- docs/_docs/reference/error-codes/E046.md | 58 ++++++---- docs/_docs/reference/error-codes/E047.md | 39 ++----- docs/_docs/reference/error-codes/E048.md | 29 +++-- docs/_docs/reference/error-codes/E049.md | 37 ++++-- docs/_docs/reference/error-codes/E050.md | 53 +++++---- docs/_docs/reference/error-codes/E051.md | 62 +++++----- docs/_docs/reference/error-codes/E052.md | 50 ++++---- docs/_docs/reference/error-codes/E053.md | 24 ++-- docs/_docs/reference/error-codes/E054.md | 46 ++++++++ docs/_docs/reference/error-codes/E055.md | 32 ++++-- docs/_docs/reference/error-codes/E056.md | 14 +-- docs/_docs/reference/error-codes/E057.md | 67 ++++++++--- docs/_docs/reference/error-codes/E058.md | 31 +++-- docs/_docs/reference/error-codes/E059.md | 29 +++-- docs/_docs/reference/error-codes/E060.md | 14 +-- docs/_docs/reference/error-codes/E061.md | 40 +++++++ docs/_docs/reference/error-codes/E062.md | 16 ++- docs/_docs/reference/error-codes/E063.md | 18 ++- docs/_docs/reference/error-codes/E064.md | 18 ++- docs/_docs/reference/error-codes/E065.md | 25 ++-- docs/_docs/reference/error-codes/E066.md | 18 ++- docs/_docs/reference/error-codes/E067.md | 18 ++- docs/_docs/reference/error-codes/E068.md | 23 ++-- docs/_docs/reference/error-codes/E069.md | 16 +-- docs/_docs/reference/error-codes/E070.md | 18 ++- docs/_docs/reference/error-codes/E071.md | 18 ++- docs/_docs/reference/error-codes/E072.md | 18 ++- docs/_docs/reference/error-codes/E073.md | 18 ++- docs/_docs/reference/error-codes/E074.md | 16 ++- docs/_docs/reference/error-codes/E075.md | 16 ++- docs/_docs/reference/error-codes/E076.md | 16 ++- docs/_docs/reference/error-codes/E077.md | 23 ++-- docs/_docs/reference/error-codes/E078.md | 16 ++- docs/_docs/reference/error-codes/E079.md | 52 +++++++++ docs/_docs/reference/error-codes/E080.md | 56 +++++++++ docs/_docs/reference/error-codes/E081.md | 26 ++--- docs/_docs/reference/error-codes/E082.md | 23 ++-- docs/_docs/reference/error-codes/E083.md | 24 ++-- docs/_docs/reference/error-codes/E084.md | 67 ++++++----- docs/_docs/reference/error-codes/E085.md | 46 ++++---- docs/_docs/reference/error-codes/E086.md | 27 +++-- docs/_docs/reference/error-codes/E087.md | 32 +++--- docs/_docs/reference/error-codes/E088.md | 23 ++-- docs/_docs/reference/error-codes/E089.md | 28 +++-- docs/_docs/reference/error-codes/E090.md | 21 ++-- docs/_docs/reference/error-codes/E091.md | 20 ++-- docs/_docs/reference/error-codes/E092.md | 30 +++-- docs/_docs/reference/error-codes/E093.md | 21 ++-- docs/_docs/reference/error-codes/E094.md | 50 +++----- docs/_docs/reference/error-codes/E095.md | 54 +++++---- docs/_docs/reference/error-codes/E096.md | 27 +++-- docs/_docs/reference/error-codes/E097.md | 18 ++- docs/_docs/reference/error-codes/E098.md | 56 ++++----- docs/_docs/reference/error-codes/E099.md | 20 ++-- docs/_docs/reference/error-codes/E100.md | 25 ++-- docs/_docs/reference/error-codes/E101.md | 42 +++++++ docs/_docs/reference/error-codes/E102.md | 42 +++++++ docs/_docs/reference/error-codes/E103.md | 50 ++++++++ docs/_docs/reference/error-codes/E104.md | 67 +++++++++++ docs/_docs/reference/error-codes/E105.md | 17 +++ docs/_docs/reference/error-codes/E106.md | 25 ++++ docs/_docs/reference/error-codes/E107.md | 64 +++++++++++ docs/_docs/reference/error-codes/E108.md | 105 +++++++++++++++++ docs/_docs/reference/error-codes/E109.md | 53 +++++++++ docs/_docs/reference/error-codes/E110.md | 52 +++++++++ docs/_docs/reference/error-codes/E111.md | 28 +++++ docs/_docs/reference/error-codes/E112.md | 50 ++++++++ docs/_docs/reference/error-codes/E113.md | 21 ++++ docs/_docs/reference/error-codes/E114.md | 21 ++++ docs/_docs/reference/error-codes/E115.md | 113 +++++++++++++++++++ docs/_docs/reference/error-codes/E116.md | 53 +++++++++ docs/_docs/reference/error-codes/E117.md | 49 ++++++++ docs/_docs/reference/error-codes/E118.md | 39 +++++++ docs/_docs/reference/error-codes/E119.md | 40 +++++++ docs/_docs/reference/error-codes/E120.md | 96 ++++++++++++++++ docs/_docs/reference/error-codes/E121.md | 47 ++++++++ docs/_docs/reference/error-codes/E122.md | 39 +++++++ docs/_docs/reference/error-codes/E123.md | 39 +++++++ docs/_docs/reference/error-codes/E124.md | 55 +++++++++ docs/_docs/reference/error-codes/E125.md | 50 ++++++++ docs/_docs/reference/error-codes/E126.md | 40 +++++++ docs/_docs/reference/error-codes/E127.md | 78 +++++++++++++ docs/_docs/reference/error-codes/E128.md | 57 ++++++++++ docs/_docs/reference/error-codes/E129.md | 56 +++++++++ docs/_docs/reference/error-codes/E130.md | 64 +++++++++++ docs/_docs/reference/error-codes/E131.md | 54 +++++++++ docs/_docs/reference/error-codes/E132.md | 63 +++++++++++ docs/_docs/reference/error-codes/E133.md | 55 +++++++++ docs/_docs/reference/error-codes/E134.md | 58 ++++++++++ docs/_docs/reference/error-codes/E135.md | 53 +++++++++ docs/_docs/reference/error-codes/E136.md | 61 ++++++++++ docs/_docs/reference/error-codes/E137.md | 89 +++++++++++++++ docs/_docs/reference/error-codes/E138.md | 11 ++ docs/_docs/reference/error-codes/E139.md | 54 +++++++++ docs/_docs/reference/error-codes/E140.md | 50 ++++++++ docs/_docs/reference/error-codes/E141.md | 62 ++++++++++ docs/_docs/reference/error-codes/E142.md | 108 ++++++++++++++++++ docs/_docs/reference/error-codes/E143.md | 12 ++ docs/_docs/reference/error-codes/E144.md | 51 +++++++++ docs/_docs/reference/error-codes/E145.md | 50 ++++++++ docs/_docs/reference/error-codes/E146.md | 66 +++++++++++ docs/_docs/reference/error-codes/E147.md | 41 +++++++ docs/_docs/reference/error-codes/E148.md | 56 +++++++++ docs/_docs/reference/error-codes/E149.md | 48 ++++++++ docs/_docs/reference/error-codes/E150.md | 11 ++ docs/_docs/reference/error-codes/E151.md | 11 ++ docs/_docs/reference/error-codes/E152.md | 11 ++ docs/_docs/reference/error-codes/E153.md | 69 ++++++++++++ docs/_docs/reference/error-codes/E154.md | 43 +++++++ docs/_docs/reference/error-codes/E155.md | 76 +++++++++++++ docs/_docs/reference/error-codes/E156.md | 51 +++++++++ docs/_docs/reference/error-codes/E157.md | 45 ++++++++ docs/_docs/reference/error-codes/E158.md | 37 ++++++ docs/_docs/reference/error-codes/E159.md | 49 ++++++++ docs/_docs/reference/error-codes/E160.md | 38 +++++++ docs/_docs/reference/error-codes/E161.md | 48 ++++++++ docs/_docs/reference/error-codes/E162.md | 53 +++++++++ docs/_docs/reference/error-codes/E163.md | 77 +++++++++++++ docs/_docs/reference/error-codes/E164.md | 72 ++++++++++++ docs/_docs/reference/error-codes/E165.md | 71 ++++++++++++ docs/_docs/reference/error-codes/E166.md | 43 +++++++ docs/_docs/reference/error-codes/E167.md | 41 +++++++ docs/_docs/reference/error-codes/E168.md | 58 ++++++++++ docs/_docs/reference/error-codes/E169.md | 69 ++++++++++++ docs/_docs/reference/error-codes/E170.md | 50 ++++++++ docs/_docs/reference/error-codes/E171.md | 46 ++++++++ docs/_docs/reference/error-codes/E172.md | 51 +++++++++ docs/_docs/reference/error-codes/E173.md | 64 +++++++++++ docs/_docs/reference/error-codes/E174.md | 61 ++++++++++ docs/_docs/reference/error-codes/E175.md | 60 ++++++++++ docs/_docs/reference/error-codes/E176.md | 59 ++++++++++ docs/_docs/reference/error-codes/E177.md | 103 +++++++++++++++++ docs/_docs/reference/error-codes/E178.md | 57 ++++++++++ docs/_docs/reference/error-codes/E179.md | 50 ++++++++ docs/_docs/reference/error-codes/E180.md | 89 +++++++++++++++ docs/_docs/reference/error-codes/E181.md | 62 ++++++++++ docs/_docs/reference/error-codes/E182.md | 49 ++++++++ docs/_docs/reference/error-codes/E183.md | 52 +++++++++ docs/_docs/reference/error-codes/E184.md | 79 +++++++++++++ docs/_docs/reference/error-codes/E185.md | 58 ++++++++++ docs/_docs/reference/error-codes/E186.md | 77 +++++++++++++ docs/_docs/reference/error-codes/E187.md | 70 ++++++++++++ docs/_docs/reference/error-codes/E188.md | 53 +++++++++ docs/_docs/reference/error-codes/E189.md | 85 ++++++++++++++ docs/_docs/reference/error-codes/E190.md | 55 +++++++++ docs/_docs/reference/error-codes/E191.md | 57 ++++++++++ docs/_docs/reference/error-codes/E192.md | 86 ++++++++++++++ docs/_docs/reference/error-codes/E193.md | 45 ++++++++ docs/_docs/reference/error-codes/E194.md | 67 +++++++++++ docs/_docs/reference/error-codes/E195.md | 70 ++++++++++++ docs/_docs/reference/error-codes/E196.md | 55 +++++++++ docs/_docs/reference/error-codes/E197.md | 61 ++++++++++ docs/_docs/reference/error-codes/E198.md | 70 ++++++++++++ docs/_docs/reference/error-codes/E199.md | 74 ++++++++++++ docs/_docs/reference/error-codes/E200.md | 47 ++++++++ docs/_docs/reference/error-codes/E201.md | 58 ++++++++++ docs/_docs/reference/error-codes/E202.md | 69 ++++++++++++ docs/_docs/reference/error-codes/E203.md | 44 ++++++++ docs/_docs/reference/error-codes/E204.md | 50 ++++++++ docs/_docs/reference/error-codes/E205.md | 63 +++++++++++ docs/_docs/reference/error-codes/E206.md | 47 ++++++++ docs/_docs/reference/error-codes/E207.md | 49 ++++++++ docs/_docs/reference/error-codes/E208.md | 62 ++++++++++ docs/_docs/reference/error-codes/E209.md | 59 ++++++++++ docs/_docs/reference/error-codes/E210.md | 47 ++++++++ docs/_docs/reference/error-codes/E211.md | 80 +++++++++++++ docs/_docs/reference/error-codes/E212.md | 60 ++++++++++ docs/_docs/reference/error-codes/E213.md | 72 ++++++++++++ docs/_docs/reference/error-codes/E214.md | 55 +++++++++ docs/_docs/reference/error-codes/E215.md | 64 +++++++++++ docs/_docs/reference/error-codes/E216.md | 61 ++++++++++ docs/_docs/reference/error-codes/E217.md | 79 +++++++++++++ docs/_docs/reference/error-codes/E218.md | 62 ++++++++++ docs/_docs/reference/error-codes/E219.md | 68 +++++++++++ docs/_docs/reference/error-codes/E220.md | 69 ++++++++++++ docs/_docs/reference/error-codes/E221.md | 61 ++++++++++ docs/_docs/reference/error-codes/E222.md | 62 ++++++++++ docs/sidebar.yml | 138 +++++++++++++++++++++-- 223 files changed, 9257 insertions(+), 1224 deletions(-) create mode 100644 docs/_docs/reference/error-codes/E010.md create mode 100644 docs/_docs/reference/error-codes/E014.md create mode 100644 docs/_docs/reference/error-codes/E036.md create mode 100644 docs/_docs/reference/error-codes/E054.md create mode 100644 docs/_docs/reference/error-codes/E061.md create mode 100644 docs/_docs/reference/error-codes/E079.md create mode 100644 docs/_docs/reference/error-codes/E080.md create mode 100644 docs/_docs/reference/error-codes/E101.md create mode 100644 docs/_docs/reference/error-codes/E102.md create mode 100644 docs/_docs/reference/error-codes/E103.md create mode 100644 docs/_docs/reference/error-codes/E104.md create mode 100644 docs/_docs/reference/error-codes/E105.md create mode 100644 docs/_docs/reference/error-codes/E106.md create mode 100644 docs/_docs/reference/error-codes/E107.md create mode 100644 docs/_docs/reference/error-codes/E108.md create mode 100644 docs/_docs/reference/error-codes/E109.md create mode 100644 docs/_docs/reference/error-codes/E110.md create mode 100644 docs/_docs/reference/error-codes/E111.md create mode 100644 docs/_docs/reference/error-codes/E112.md create mode 100644 docs/_docs/reference/error-codes/E113.md create mode 100644 docs/_docs/reference/error-codes/E114.md create mode 100644 docs/_docs/reference/error-codes/E115.md create mode 100644 docs/_docs/reference/error-codes/E116.md create mode 100644 docs/_docs/reference/error-codes/E117.md create mode 100644 docs/_docs/reference/error-codes/E118.md create mode 100644 docs/_docs/reference/error-codes/E119.md create mode 100644 docs/_docs/reference/error-codes/E120.md create mode 100644 docs/_docs/reference/error-codes/E121.md create mode 100644 docs/_docs/reference/error-codes/E122.md create mode 100644 docs/_docs/reference/error-codes/E123.md create mode 100644 docs/_docs/reference/error-codes/E124.md create mode 100644 docs/_docs/reference/error-codes/E125.md create mode 100644 docs/_docs/reference/error-codes/E126.md create mode 100644 docs/_docs/reference/error-codes/E127.md create mode 100644 docs/_docs/reference/error-codes/E128.md create mode 100644 docs/_docs/reference/error-codes/E129.md create mode 100644 docs/_docs/reference/error-codes/E130.md create mode 100644 docs/_docs/reference/error-codes/E131.md create mode 100644 docs/_docs/reference/error-codes/E132.md create mode 100644 docs/_docs/reference/error-codes/E133.md create mode 100644 docs/_docs/reference/error-codes/E134.md create mode 100644 docs/_docs/reference/error-codes/E135.md create mode 100644 docs/_docs/reference/error-codes/E136.md create mode 100644 docs/_docs/reference/error-codes/E137.md create mode 100644 docs/_docs/reference/error-codes/E138.md create mode 100644 docs/_docs/reference/error-codes/E139.md create mode 100644 docs/_docs/reference/error-codes/E140.md create mode 100644 docs/_docs/reference/error-codes/E141.md create mode 100644 docs/_docs/reference/error-codes/E142.md create mode 100644 docs/_docs/reference/error-codes/E143.md create mode 100644 docs/_docs/reference/error-codes/E144.md create mode 100644 docs/_docs/reference/error-codes/E145.md create mode 100644 docs/_docs/reference/error-codes/E146.md create mode 100644 docs/_docs/reference/error-codes/E147.md create mode 100644 docs/_docs/reference/error-codes/E148.md create mode 100644 docs/_docs/reference/error-codes/E149.md create mode 100644 docs/_docs/reference/error-codes/E150.md create mode 100644 docs/_docs/reference/error-codes/E151.md create mode 100644 docs/_docs/reference/error-codes/E152.md create mode 100644 docs/_docs/reference/error-codes/E153.md create mode 100644 docs/_docs/reference/error-codes/E154.md create mode 100644 docs/_docs/reference/error-codes/E155.md create mode 100644 docs/_docs/reference/error-codes/E156.md create mode 100644 docs/_docs/reference/error-codes/E157.md create mode 100644 docs/_docs/reference/error-codes/E158.md create mode 100644 docs/_docs/reference/error-codes/E159.md create mode 100644 docs/_docs/reference/error-codes/E160.md create mode 100644 docs/_docs/reference/error-codes/E161.md create mode 100644 docs/_docs/reference/error-codes/E162.md create mode 100644 docs/_docs/reference/error-codes/E163.md create mode 100644 docs/_docs/reference/error-codes/E164.md create mode 100644 docs/_docs/reference/error-codes/E165.md create mode 100644 docs/_docs/reference/error-codes/E166.md create mode 100644 docs/_docs/reference/error-codes/E167.md create mode 100644 docs/_docs/reference/error-codes/E168.md create mode 100644 docs/_docs/reference/error-codes/E169.md create mode 100644 docs/_docs/reference/error-codes/E170.md create mode 100644 docs/_docs/reference/error-codes/E171.md create mode 100644 docs/_docs/reference/error-codes/E172.md create mode 100644 docs/_docs/reference/error-codes/E173.md create mode 100644 docs/_docs/reference/error-codes/E174.md create mode 100644 docs/_docs/reference/error-codes/E175.md create mode 100644 docs/_docs/reference/error-codes/E176.md create mode 100644 docs/_docs/reference/error-codes/E177.md create mode 100644 docs/_docs/reference/error-codes/E178.md create mode 100644 docs/_docs/reference/error-codes/E179.md create mode 100644 docs/_docs/reference/error-codes/E180.md create mode 100644 docs/_docs/reference/error-codes/E181.md create mode 100644 docs/_docs/reference/error-codes/E182.md create mode 100644 docs/_docs/reference/error-codes/E183.md create mode 100644 docs/_docs/reference/error-codes/E184.md create mode 100644 docs/_docs/reference/error-codes/E185.md create mode 100644 docs/_docs/reference/error-codes/E186.md create mode 100644 docs/_docs/reference/error-codes/E187.md create mode 100644 docs/_docs/reference/error-codes/E188.md create mode 100644 docs/_docs/reference/error-codes/E189.md create mode 100644 docs/_docs/reference/error-codes/E190.md create mode 100644 docs/_docs/reference/error-codes/E191.md create mode 100644 docs/_docs/reference/error-codes/E192.md create mode 100644 docs/_docs/reference/error-codes/E193.md create mode 100644 docs/_docs/reference/error-codes/E194.md create mode 100644 docs/_docs/reference/error-codes/E195.md create mode 100644 docs/_docs/reference/error-codes/E196.md create mode 100644 docs/_docs/reference/error-codes/E197.md create mode 100644 docs/_docs/reference/error-codes/E198.md create mode 100644 docs/_docs/reference/error-codes/E199.md create mode 100644 docs/_docs/reference/error-codes/E200.md create mode 100644 docs/_docs/reference/error-codes/E201.md create mode 100644 docs/_docs/reference/error-codes/E202.md create mode 100644 docs/_docs/reference/error-codes/E203.md create mode 100644 docs/_docs/reference/error-codes/E204.md create mode 100644 docs/_docs/reference/error-codes/E205.md create mode 100644 docs/_docs/reference/error-codes/E206.md create mode 100644 docs/_docs/reference/error-codes/E207.md create mode 100644 docs/_docs/reference/error-codes/E208.md create mode 100644 docs/_docs/reference/error-codes/E209.md create mode 100644 docs/_docs/reference/error-codes/E210.md create mode 100644 docs/_docs/reference/error-codes/E211.md create mode 100644 docs/_docs/reference/error-codes/E212.md create mode 100644 docs/_docs/reference/error-codes/E213.md create mode 100644 docs/_docs/reference/error-codes/E214.md create mode 100644 docs/_docs/reference/error-codes/E215.md create mode 100644 docs/_docs/reference/error-codes/E216.md create mode 100644 docs/_docs/reference/error-codes/E217.md create mode 100644 docs/_docs/reference/error-codes/E218.md create mode 100644 docs/_docs/reference/error-codes/E219.md create mode 100644 docs/_docs/reference/error-codes/E220.md create mode 100644 docs/_docs/reference/error-codes/E221.md create mode 100644 docs/_docs/reference/error-codes/E222.md diff --git a/docs/_docs/reference/error-codes/E001.md b/docs/_docs/reference/error-codes/E001.md index 7e759ee2f919..c6813f23fcf2 100644 --- a/docs/_docs/reference/error-codes/E001.md +++ b/docs/_docs/reference/error-codes/E001.md @@ -2,7 +2,6 @@ title: E001: Empty Catch Block kind: Error --- - # E001: Empty Catch Block This error is emitted when a `try` expression has a `catch` block that does not contain any case handlers. @@ -37,8 +36,8 @@ correctly handles transfer functions like `return`. ## Example -```scala sc:fail -@main def test() = +```scala sc:fail sc-opts:-explain +def example() = try { println("hello") } catch { } @@ -47,37 +46,61 @@ correctly handles transfer functions like `return`. ### Error ```scala sc:nocompile --- [E001] Syntax Error: example.scala:4:4 +-- [E001] Syntax Error: example.scala:4:4 -------------------------------------- 4 | } catch { } | ^^^^^^^^^ | The catch block does not contain a valid expression, try | adding a case like - case e: Exception => to the block + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A try expression should be followed by some mechanism to handle any exceptions + | thrown. Typically a catch expression follows the try and pattern matches + | on any expected exceptions. For example: + | + | import scala.util.control.NonFatal + | + | try { + | println("hello") + | } catch { + | case NonFatal(e) => ??? + | } + | + | It is also possible to follow a try immediately by a finally - letting the + | exception propagate - but still allowing for some clean up in finally: + | + | try { + | println("hello") + | } finally { + | // perform your cleanup here! + | } + | + | It is recommended to use the NonFatal extractor to catch all exceptions as it + | correctly handles transfer functions like return. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove redundant 'try' block -println("hello") -``` +def example() = + println("hello") +``` -```scala sc:compile +```scala sc:compile // Alternative: Add a case handler to catch exceptions import scala.util.control.NonFatal -try { - println("hello") -} catch { - case NonFatal(e) => println(s"Caught: $e") -} -``` +def example() = + try println("hello") + catch { case NonFatal(e) => println(s"Caught: $e") } +``` ```scala sc:compile // Alternative: use finally instead if you only need cleanup -try { - println("hello") -} finally { - println("cleanup") -} +def example() = + try println("hello") + finally println("cleanup") ``` diff --git a/docs/_docs/reference/error-codes/E002.md b/docs/_docs/reference/error-codes/E002.md index 752fd4d45861..6bba2a6fe92d 100644 --- a/docs/_docs/reference/error-codes/E002.md +++ b/docs/_docs/reference/error-codes/E002.md @@ -2,7 +2,6 @@ title: E002: Empty Catch And Finally Block kind: Warning --- - # E002: Empty Catch And Finally Block This warning is emitted when a `try` expression has neither a `catch` block nor a `finally` block. Such a `try` is redundant since no exceptions are handled. @@ -37,8 +36,8 @@ correctly handles transfer functions like `return`. ## Example -```scala sc:fail sc-opts:-Werror -@main def test() = +```scala sc:fail sc-opts:-explain,-Werror +@main def example() = try { println("hello") } @@ -47,39 +46,67 @@ correctly handles transfer functions like `return`. ### Warning ```scala sc:nocompile --- [E002] Syntax Warning: example.scala:2:2 +-- [E002] Syntax Warning: example.scala:2:2 ------------------------------------ 2 | try { | ^ | A try without catch or finally is equivalent to putting | its body in a block; no exceptions are handled. 3 | println("hello") 4 | } + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A try expression should be followed by some mechanism to handle any exceptions + | thrown. Typically a catch expression follows the try and pattern matches + | on any expected exceptions. For example: + | + | import scala.util.control.NonFatal + | + | try { + | println("hello") + | } catch { + | case NonFatal(e) => ??? + | } + | + | It is also possible to follow a try immediately by a finally - letting the + | exception propagate - but still allowing for some clean up in finally: + | + | try { + | println("hello") + | } finally { + | // perform your cleanup here! + | } + | + | It is recommended to use the NonFatal extractor to catch all exceptions as it + | correctly handles transfer functions like return. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution ```scala sc:compile sc-opts:-Werror // Remove redundant 'try' block -println("hello") -``` +def example() = + println("hello") +``` ```scala sc:compile sc-opts:-Werror // Alternative: Add a catch block to handle exceptions import scala.util.control.NonFatal -try { - println("hello") -} catch { - case NonFatal(e) => println(s"Caught: $e") -} -``` +def example() = + try + println("hello") + catch + case NonFatal(e) => println(s"Caught: $e") +``` ```scala sc:compile sc-opts:-Werror // Alternative: Add a finally block for cleanup -try { - println("hello") -} finally { - println("cleanup") -} +def example() = + try + println("hello") + finally + println("cleanup") ``` diff --git a/docs/_docs/reference/error-codes/E003.md b/docs/_docs/reference/error-codes/E003.md index a6aa121348ad..34020b644a5e 100644 --- a/docs/_docs/reference/error-codes/E003.md +++ b/docs/_docs/reference/error-codes/E003.md @@ -2,7 +2,6 @@ title: E003: Deprecated With Operator kind: Warning --- - # E003: Deprecated With Operator This warning is emitted when using `with` as a type operator to create compound types. In Scala 3, `with` has been deprecated in favor of intersection types using `&`. @@ -15,7 +14,7 @@ semantics between intersection types and using `with`. ## Example -```scala sc:fail sc-opts:-Werror +```scala sc:fail sc-opts:-explain,-Werror trait A trait B def test(x: A with B): Unit = () @@ -24,21 +23,28 @@ def test(x: A with B): Unit = () ### Warning ```scala sc:nocompile --- [E003] Syntax Warning: example.scala:3:14 +-- [E003] Syntax Warning: example.scala:3:14 ----------------------------------- 3 |def test(x: A with B): Unit = () | ^^^^ |with as a type operator has been deprecated; use & instead |This construct can be rewritten automatically under -rewrite -source 3.4-migration. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Dotty introduces intersection types - & types. These replace the + | use of the with keyword. There are a few differences in + | semantics between intersection types and using with. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution ```scala sc:compile sc-opts:-Werror // Use intersection type operator & instead of with trait A trait B def test(x: A & B): Unit = () -``` +``` ```scala sc:compile sc-opts:-Werror // The change also applies to type aliases and class definitions diff --git a/docs/_docs/reference/error-codes/E004.md b/docs/_docs/reference/error-codes/E004.md index 4f11b09e418a..6bd66c7eb258 100644 --- a/docs/_docs/reference/error-codes/E004.md +++ b/docs/_docs/reference/error-codes/E004.md @@ -2,7 +2,6 @@ title: E004: Case Class Missing Param List kind: Error --- - # E004: Case Class Missing Param List This error is emitted when a `case class` is defined without any parameter list. In Scala 3, case classes must have at least one parameter list. @@ -15,32 +14,39 @@ Or, add an explicit `()` as a parameter list to `Empty`. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain case class Empty ``` ### Error ```scala sc:nocompile --- [E004] Syntax Error: example.scala:1:11 +-- [E004] Syntax Error: example.scala:1:11 ------------------------------------- 1 |case class Empty | ^^^^^ | A case class must have at least one parameter list + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Empty must have at least one parameter list, if you would rather + | have a singleton representation of Empty, use a "case object". + | Or, add an explicit () as a parameter list to Empty. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use case object for singleton representation case object Empty -``` +``` -```scala sc:compile +```scala sc:compile // Add an explicit empty parameter list case class Empty() -``` +``` -```scala sc:compile +```scala sc:compile // Or define actual parameters case class Empty(value: String) ``` diff --git a/docs/_docs/reference/error-codes/E005.md b/docs/_docs/reference/error-codes/E005.md index c6ea5996f302..3d30c630e650 100644 --- a/docs/_docs/reference/error-codes/E005.md +++ b/docs/_docs/reference/error-codes/E005.md @@ -2,7 +2,6 @@ title: E005: Duplicate Bind kind: Error --- - # E005: Duplicate Bind This error is emitted when the same variable name is used more than once in a pattern match case. Each bound variable in a `case` pattern must have a unique name. @@ -19,7 +18,7 @@ case (a, a) => a ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def test(x: Any) = x match case (a, a) => a ``` @@ -27,27 +26,38 @@ def test(x: Any) = x match ### Error ```scala sc:nocompile --- [E005] Naming Error: example.scala:2:11 +-- [E005] Naming Error: example.scala:2:11 ------------------------------------- 2 | case (a, a) => a | ^ | duplicate pattern variable: a + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | For each case bound variable names have to be unique. In: + | + | case (a, a) => { + | a + | } + | + | a is not unique. Rename one of the bound variables! + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use unique names for each bound variable def test(x: Any) = x match case (a, b) => (a, b) -``` +``` -```scala sc:compile +```scala sc:compile // Use wildcard _ if you don't need the value def test(x: Any) = x match case (a, _) => a -``` +``` -```scala sc:compile +```scala sc:compile // Use a guard if you want to match equal values def test(x: Any) = x match case (a, b) if a == b => a diff --git a/docs/_docs/reference/error-codes/E006.md b/docs/_docs/reference/error-codes/E006.md index fbb1903506ed..1f3e4fdd8e23 100644 --- a/docs/_docs/reference/error-codes/E006.md +++ b/docs/_docs/reference/error-codes/E006.md @@ -2,7 +2,6 @@ title: E006: Missing Ident kind: Error --- - # E006: Missing Ident This error is emitted when a referenced identifier (value, method, type, etc.) cannot be found in the current scope. @@ -23,34 +22,49 @@ Possible reasons why no matching declaration was found: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val result = unknownIdentifier ``` ### Error ```scala sc:nocompile --- [E006] Not Found Error: example.scala:1:13 +-- [E006] Not Found Error: example.scala:1:13 ---------------------------------- 1 |val result = unknownIdentifier | ^^^^^^^^^^^^^^^^^ | Not found: unknownIdentifier + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Each identifier in Scala needs a matching declaration. There are two kinds of + | identifiers: type identifiers and value identifiers. Value identifiers are introduced + | by `val`, `def`, or `object` declarations. Type identifiers are introduced by `type`, + | `class`, `enum`, or `trait` declarations. + | + | Identifiers refer to matching declarations in their environment, or they can be + | imported from elsewhere. + | + | Possible reasons why no matching declaration was found: + | - The declaration or the use is mis-spelt. + | - An import is missing. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Declare the identifier before using it val unknownIdentifier = 42 val result = unknownIdentifier -``` +``` -```scala sc:compile +```scala sc:compile // Or import it from another scope import scala.math.Pi val result = Pi -``` +``` -```scala sc:compile +```scala sc:compile // Fix the spelling if it was a typo val knownIdentifier = 42 val result = knownIdentifier diff --git a/docs/_docs/reference/error-codes/E007.md b/docs/_docs/reference/error-codes/E007.md index 5bceb70f9a55..d7a56eed0d04 100644 --- a/docs/_docs/reference/error-codes/E007.md +++ b/docs/_docs/reference/error-codes/E007.md @@ -2,7 +2,6 @@ title: E007: Type Mismatch kind: Error --- - # E007: Type Mismatch This error is emitted when an expression has a different type than what is expected in that context. @@ -18,33 +17,52 @@ This commonly occurs when: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val x: String = 42 ``` ### Error ```scala sc:nocompile --- [E007] Type Mismatch Error: example.scala:1:16 +-- [E007] Type Mismatch Error: example.scala:1:16 ------------------------------ 1 |val x: String = 42 | ^^ | Found: (42 : Int) | Required: String + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | + | Tree: + | + | 42 + | + | I tried to show that + | (42 : Int) + | conforms to + | String + | but none of the attempts shown below succeeded: + | + | ==> (42 : Int) <: String + | ==> Int <: String = false + | + | The tests were made under the empty constraint + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Convert the value to the expected type val x: String = 42.toString -``` +``` -```scala sc:compile +```scala sc:compile // Or change the type annotation to match the value val x: Int = 42 -``` +``` -```scala sc:compile +```scala sc:compile // Or use a value of the correct type val x: String = "42" ``` diff --git a/docs/_docs/reference/error-codes/E008.md b/docs/_docs/reference/error-codes/E008.md index 649b0171a433..c6e7e0696f6b 100644 --- a/docs/_docs/reference/error-codes/E008.md +++ b/docs/_docs/reference/error-codes/E008.md @@ -2,7 +2,6 @@ title: E008: Not A Member kind: Error --- - # E008: Not A Member This error is emitted when trying to access a member (method, field, or type) that does not exist on the given type. @@ -18,32 +17,32 @@ This commonly occurs when: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val result = "hello".unknownMethod ``` ### Error ```scala sc:nocompile --- [E008] Not Found Error: example.scala:1:13 +-- [E008] Not Found Error: example.scala:1:21 ---------------------------------- 1 |val result = "hello".unknownMethod | ^^^^^^^^^^^^^^^^^^^^^ | value unknownMethod is not a member of String ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a method that exists on the type val result = "hello".toUpperCase -``` +``` -```scala sc:compile +```scala sc:compile // Check the spelling and use the correct method name val result = "hello".length -``` +``` -```scala sc:compile +```scala sc:compile // Import extension methods if needed extension (s: String) def unknownMethod: String = s.reverse diff --git a/docs/_docs/reference/error-codes/E009.md b/docs/_docs/reference/error-codes/E009.md index d0b022cfea59..4bd3b8b87dd0 100644 --- a/docs/_docs/reference/error-codes/E009.md +++ b/docs/_docs/reference/error-codes/E009.md @@ -2,12 +2,11 @@ title: E009: Early Definitions Not Supported kind: Error --- - # E009: Early Definitions Not Supported This error is emitted when using early definitions (early initializers), which were a feature in Scala 2 but are no longer supported in Scala 3. Use trait parameters instead. -Earlier versions of Scala did not support trait parameters and "early definitions" +Earlier versions of Scala did not support trait parameters and "early definitions" (also known as "early initializers") were used as an alternative to initialize values before the superclass constructor runs. @@ -17,7 +16,7 @@ In Scala 3, trait parameters provide a cleaner solution to this problem. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait Logging: val logFile: String println(s"Logging to $logFile") @@ -28,23 +27,65 @@ class App extends { val logFile = "app.log" } with Logging ### Error ```scala sc:nocompile --- [E009] Syntax Error: example.scala:5:49 +-- Error: example.scala:5:18 --------------------------------------------------- +5 |class App extends { val logFile = "app.log" } with Logging + | ^ + | `extends` must be followed by at least one parent +-- [E009] Syntax Error: example.scala:5:46 ------------------------------------- 5 |class App extends { val logFile = "app.log" } with Logging - | ^^^^ + | ^^^^ | Early definitions are not supported; use trait parameters instead + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Earlier versions of Scala did not support trait parameters and "early + | definitions" (also known as "early initializers") were used as an alternative. + | + | Example of old syntax: + | + | trait Logging { + | val f: File + | f.open() + | onExit(f.close()) + | def log(msg: String) = f.write(msg) + | } + | + | class B extends Logging { + | val f = new File("log.data") // triggers a NullPointerException + | } + | + | // early definition gets around the NullPointerException + | class C extends { + | val f = new File("log.data") + | } with Logging + | + | The above code can now be written as: + | + | trait Logging(f: File) { + | f.open() + | onExit(f.close()) + | def log(msg: String) = f.write(msg) + | } + | + | class C extends Logging(new File("log.data")) + ----------------------------------------------------------------------------- +-- Error: example.scala:5:51 --------------------------------------------------- +5 |class App extends { val logFile = "app.log" } with Logging + | ^^^^^^^ + | end of toplevel definition expected but identifier found ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use trait parameters instead of early definitions trait Logging(logFile: String): println(s"Logging to $logFile") class App extends Logging("app.log") -``` +``` -```scala sc:compile +```scala sc:compile // Alternative: Use a lazy val to defer initialization trait Logging: def logFile: String diff --git a/docs/_docs/reference/error-codes/E010.md b/docs/_docs/reference/error-codes/E010.md new file mode 100644 index 000000000000..25e342161814 --- /dev/null +++ b/docs/_docs/reference/error-codes/E010.md @@ -0,0 +1,70 @@ +--- +title: "E010: Top Level Implicit Class" +kind: Error +until: 3.2.0 +--- +# E010: Top Level Implicit Class + +**Note:** This error code was made inactive in Scala 3.2.0. Implicit classes are now allowed at the top level. + +This error occurred in earlier versions of Scala 3 when an implicit class was defined at the top level of a file, rather than being nested inside an object, class, or package object. + +In Scala 2 and early Scala 3, implicit classes had to be defined inside another definition (such as an object or package object) to prevent potential issues with implicit resolution and scope. This restriction was later lifted in Scala 3.2.0. + +--- + +## Example (Scala 3.0.x - 3.1.x) + +```scala sc:nocompile +// Top-level implicit class - not allowed in Scala 3.0-3.1 +implicit class RichInt(val x: Int) { + def square: Int = x * x +} +``` + +### Error + +```scala sc:nocompile +-- [E010] Syntax Error: example.scala:2:0 ------------------------------------ +2 |implicit class RichInt(val x: Int) { + |^ + |An implicit class may not be top-level +``` + +### Solution (Scala 3.0.x - 3.1.x) + +```scala sc:nocompile +// Wrap in an object +object Extensions { + implicit class RichInt(val x: Int) { + def square: Int = x * x + } +} + +// Usage +import Extensions._ +val result = 5.square +``` + +```scala sc:nocompile +// Or use a package object +package object mypackage { + implicit class RichInt(val x: Int) { + def square: Int = x * x + } +} +``` + +### Solution (Scala 3.2.0+) + +```scala sc:nocompile +// Top-level implicit classes are now allowed +implicit class RichInt(val x: Int) { + def square: Int = x * x +} + +// However, prefer using extension methods in Scala 3 +extension (x: Int) + def square: Int = x * x +``` + diff --git a/docs/_docs/reference/error-codes/E011.md b/docs/_docs/reference/error-codes/E011.md index 71a8aface0a6..6973029f687a 100644 --- a/docs/_docs/reference/error-codes/E011.md +++ b/docs/_docs/reference/error-codes/E011.md @@ -2,7 +2,6 @@ title: E011: Implicit Case Class kind: Error --- - # E011: Implicit Case Class This error is emitted when a `case class` is defined with the `implicit` modifier. Case classes cannot be implicit in Scala. @@ -17,22 +16,29 @@ If you want implicit conversions, use a plain implicit class instead. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain implicit case class Wrapper(value: String) ``` ### Error ```scala sc:nocompile --- [E011] Syntax Error: example.scala:1:20 +-- [E011] Syntax Error: example.scala:1:20 ------------------------------------- 1 |implicit case class Wrapper(value: String) |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |A case class may not be defined as implicit + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Implicit classes may not be case classes. Instead use a plain class: + | + | implicit class Wrapper... + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a regular implicit class object Implicits: implicit class Wrapper(val value: String): @@ -40,9 +46,9 @@ object Implicits: import Implicits.* val result = "hello".doubled -``` +``` -```scala sc:compile +```scala sc:compile // In Scala 3, prefer extension methods over implicit classes extension (value: String) def doubled: String = value + value diff --git a/docs/_docs/reference/error-codes/E012.md b/docs/_docs/reference/error-codes/E012.md index f460a72c6f30..d91d68cf22ad 100644 --- a/docs/_docs/reference/error-codes/E012.md +++ b/docs/_docs/reference/error-codes/E012.md @@ -2,7 +2,6 @@ title: E012: Implicit Class Primary Constructor Arity kind: Error --- - # E012: Implicit Class Primary Constructor Arity This error is emitted when an implicit class has more than one non-implicit parameter in its primary constructor. Implicit classes must accept exactly one primary constructor parameter. @@ -18,7 +17,7 @@ such classes aren't used during implicit lookup. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain object Implicits: implicit class Wrapper(a: Int, b: String): def combined: String = s"$a-$b" @@ -27,15 +26,26 @@ object Implicits: ### Error ```scala sc:nocompile --- [E012] Syntax Error: example.scala:2:17 +-- [E012] Syntax Error: example.scala:2:17 ------------------------------------- 2 | implicit class Wrapper(a: Int, b: String): - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | Implicit classes must accept exactly one primary constructor parameter + | ^ + | Implicit classes must accept exactly one primary constructor parameter +3 | def combined: String = s"$a-$b" + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Implicit classes may only take one non-implicit argument in their constructor. For example: + | + | implicit class RichDate(date: java.util.Date) + | + | While it’s possible to create an implicit class with more than one non-implicit argument, + | such classes aren’t used during implicit lookup. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use exactly one parameter object Implicits: implicit class RichInt(val value: Int): @@ -43,9 +53,9 @@ object Implicits: import Implicits.* val result = 42.doubled -``` +``` -```scala sc:compile +```scala sc:compile // Additional parameters can be implicit object Implicits: implicit class Formatter(val value: Int)(using format: String = "%d"): @@ -53,9 +63,9 @@ object Implicits: import Implicits.* val result = 42.formatted -``` +``` -```scala sc:compile +```scala sc:compile // In Scala 3, prefer extension methods extension (value: Int) def doubled: Int = value * 2 diff --git a/docs/_docs/reference/error-codes/E013.md b/docs/_docs/reference/error-codes/E013.md index b608f06db38c..cbc3f241e9be 100644 --- a/docs/_docs/reference/error-codes/E013.md +++ b/docs/_docs/reference/error-codes/E013.md @@ -2,7 +2,6 @@ title: E013: Object May Not Have Self Type kind: Error --- - # E013: Object May Not Have Self Type This error is emitted when an `object` definition includes a self type annotation. Objects in Scala cannot have self types. @@ -15,7 +14,7 @@ after their definition, making self types meaningless for objects. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait Foo object Test { self: Foo => } @@ -24,34 +23,45 @@ object Test { self: Foo => } ### Error ```scala sc:nocompile --- [E013] Syntax Error: example.scala:3:14 +-- [E013] Syntax Error: example.scala:3:14 ------------------------------------- 3 |object Test { self: Foo => } | ^^^^^^^^^^^^ | objects must not have a self type + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | objects must not have a self type: + | + | Consider these alternative solutions: + | - Create a trait or a class instead of an object + | - Let the object extend a trait containing the self type: + | + | object Test extends Foo + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Create a trait or class instead of an object trait Foo class Test extends Foo -``` +``` -```scala sc:compile +```scala sc:compile // Or let the object extend the trait directly trait Foo object Test extends Foo -``` +``` -```scala sc:compile +```scala sc:compile // Or use a class with a self type if you need the pattern trait Foo trait Bar -class Test { self: Foo with Bar => +class Test { self: Foo & Bar => // ... } ``` diff --git a/docs/_docs/reference/error-codes/E014.md b/docs/_docs/reference/error-codes/E014.md new file mode 100644 index 000000000000..5e415772db41 --- /dev/null +++ b/docs/_docs/reference/error-codes/E014.md @@ -0,0 +1,38 @@ +--- +title: "E014: Tuple Too Long" +kind: Error +until: 3.0.0 +--- + +This error was removed before Scala 3.0.0 was released and was never emitted by the Scala 3 compiler. + +## What it did + +This error was triggered when creating a tuple literal with more than 22 elements. + +### Example + +```scala sc:nocompile +val t = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23) +``` + +### Error + +```scala sc:nocompile +-- [E014] Syntax Error: example.scala:1:8 -------------------------------------- +1 |val t = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23) + | ^ + | A tuple cannot have more than 22 members +``` + +## Explanation + +In early versions of Dotty (before Scala 3.0.0), tuples were limited to 22 elements, similar to Scala 2. The error message suggested using nested tuples as a workaround: + +```scala sc:nocompile +// Workaround with nested tuples (no longer needed) +val t = ((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22), (23)) +``` + +This restriction was removed in commit 2d1427d5aa (August 2018) with "Allow tuple literals to extend beyond 22". Since Scala 3.0.0, tuples can have any number of elements without restriction. + diff --git a/docs/_docs/reference/error-codes/E015.md b/docs/_docs/reference/error-codes/E015.md index 928c10a9ef23..0b38ae9a939e 100644 --- a/docs/_docs/reference/error-codes/E015.md +++ b/docs/_docs/reference/error-codes/E015.md @@ -2,7 +2,6 @@ title: E015: Repeated Modifier kind: Error --- - # E015: Repeated Modifier This error is emitted when the same modifier is specified more than once on a definition. @@ -14,27 +13,40 @@ Each modifier should only appear once. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain private private val x = 1 ``` ### Error ```scala sc:nocompile --- [E015] Syntax Error: example.scala:1:8 +-- [E015] Syntax Error: example.scala:1:8 -------------------------------------- 1 |private private val x = 1 | ^^^^^^^ | Repeated modifier private + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | This happens when you accidentally specify the same modifier twice. + | + | Example: + | + | private private val Origin = Point(0, 0) + | + | instead of + | + | private final val Origin = Point(0, 0) + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove the duplicate modifier private val x = 1 -``` +``` -```scala sc:compile +```scala sc:compile // If you meant to use different modifiers, use the correct combination private final val x = 1 ``` diff --git a/docs/_docs/reference/error-codes/E016.md b/docs/_docs/reference/error-codes/E016.md index 2ba3a8e9f5b2..97ec2cafc25b 100644 --- a/docs/_docs/reference/error-codes/E016.md +++ b/docs/_docs/reference/error-codes/E016.md @@ -2,7 +2,6 @@ title: E016: Interpolated String Error kind: Error --- - # E016: Interpolated String Error This error is emitted when an interpolated string contains invalid syntax after a `$` sign. An identifier or a block expression `${...}` is expected. @@ -19,33 +18,44 @@ If you need to include a complex expression (like `new Object()`), you must wrap ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val x = s"$new Object()" ``` ### Error ```scala sc:nocompile --- [E016] Syntax Error: example.scala:1:11 +-- [E016] Syntax Error: example.scala:1:11 ------------------------------------- 1 |val x = s"$new Object()" | ^ | Error in interpolated string: identifier or block expected + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | This usually happens when you forget to place your expressions inside curly braces. + | + | s"$new Point(0, 0)" + | + | should be written as + | + | s"${new Point(0, 0)}" + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Wrap complex expressions in braces val x = s"${new Object()}" -``` +``` -```scala sc:compile +```scala sc:compile // Simple identifiers don't need braces val name = "World" val greeting = s"Hello, $name!" -``` +``` -```scala sc:compile +```scala sc:compile // Use braces for member access case class Person(name: String) val person = Person("Alice") diff --git a/docs/_docs/reference/error-codes/E017.md b/docs/_docs/reference/error-codes/E017.md index 67caada27a87..96639e0072eb 100644 --- a/docs/_docs/reference/error-codes/E017.md +++ b/docs/_docs/reference/error-codes/E017.md @@ -2,7 +2,6 @@ title: E017: Unbound Placeholder Parameter kind: Error --- - # E017: Unbound Placeholder Parameter This error is emitted when the underscore (`_`) placeholder syntax is used in a context where it cannot be bound to a parameter. @@ -23,38 +22,81 @@ Common incorrect uses: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val x = _ ``` ### Error ```scala sc:nocompile --- [E017] Syntax Error: example.scala:1:8 +-- [E017] Syntax Error: example.scala:1:8 -------------------------------------- 1 |val x = _ | ^ | Unbound placeholder parameter; incorrect use of _ + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The _ placeholder syntax was used where it could not be bound. + | Consider explicitly writing the variable binding. + | + | This can be done by replacing _ with a variable (eg. x) + | and adding x => where applicable. + | + | Example before: + | + | { _ } + | + | Example after: + | + | x => { x } + | + | Another common occurrence for this error is defining a val with _: + | + | val a = _ + | + | But this val definition isn't very useful, it can never be assigned + | another value. And thus will always remain uninitialized. + | Consider replacing the val with var: + | + | var a = _ + | + | Note that this use of _ is not placeholder syntax, + | but an uninitialized var definition. + | Only fields can be left uninitialized in this manner; local variables + | must be initialized. + | + | Another occurrence for this error is self type definition. + | The _ can be replaced with this. + | + | Example before: + | + | trait A { _: B => ... + | + | Example after: + | + | trait A { this: B => ... + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use an explicit lambda with a named parameter val f: Int => Int = x => x + 1 -``` +``` -```scala sc:compile +```scala sc:compile // The placeholder syntax works in lambda contexts with clear types val f: Int => Int = _ + 1 -``` +``` -```scala sc:compile +```scala sc:compile // For uninitialized fields, use var (only in classes, not local scope) class Example: - var x: Int = _ // Uninitialized field, defaults to 0 -``` + var x: Int = scala.compiletime.uninitialized // Uninitialized field, defaults to 0 +``` -```scala sc:compile +```scala sc:compile // Use wildcard in pattern matching val list = List(1, 2, 3) val head = list match diff --git a/docs/_docs/reference/error-codes/E018.md b/docs/_docs/reference/error-codes/E018.md index e8eae8bfa944..cc756b562b6e 100644 --- a/docs/_docs/reference/error-codes/E018.md +++ b/docs/_docs/reference/error-codes/E018.md @@ -2,7 +2,6 @@ title: E018: Illegal Start Simple Expr kind: Error --- - # E018: Illegal Start Simple Expr This error is emitted when the compiler expects an expression but finds a token that cannot start an expression. @@ -18,36 +17,44 @@ or when the expression is missing entirely. This commonly happens when: ## Example -```scala sc:fail -val x = if true then 1 else +```scala sc:fail sc-opts:-explain +val `given` = 2 +def example = if true then 1 else given ``` ### Error ```scala sc:nocompile --- [E018] Syntax Error: example.scala:2:0 -2 | - |^ - |expression expected but eof found +-- [E018] Syntax Error: example.scala:2:34 ------------------------------------- +2 |def example = if true then 1 else given + | ^^^^^ + | expression expected but given found + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | An expression cannot start with given. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution + +```scala sc:compile +// If using identifiers that are a keywords use backticks +val `given` = 2 +def example = if true then 1 else `given` -```scala sc:compile -// Complete the expression -val x = if true then 1 else 2 -``` +``` -```scala sc:compile +```scala sc:compile // Ensure all branches have expressions val result = if true then "yes" else "no" -``` +``` -```scala sc:compile +```scala sc:compile // Check for missing operands val sum = 1 + 2 // not: val sum = 1 + ``` diff --git a/docs/_docs/reference/error-codes/E019.md b/docs/_docs/reference/error-codes/E019.md index e19c9a508d41..8ec3b694658d 100644 --- a/docs/_docs/reference/error-codes/E019.md +++ b/docs/_docs/reference/error-codes/E019.md @@ -2,7 +2,6 @@ title: E019: Missing Return Type kind: Error --- - # E019: Missing Return Type This error is emitted when an abstract method declaration is missing its return type. Abstract declarations must have explicit return types. @@ -14,7 +13,7 @@ cannot infer the type of the method, so it must be explicitly specified. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait Foo: def bar ``` @@ -22,27 +21,35 @@ trait Foo: ### Error ```scala sc:nocompile --- [E019] Syntax Error: example.scala:2:9 +-- [E019] Syntax Error: example.scala:2:9 -------------------------------------- 2 | def bar | ^ | Missing return type + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | An abstract declaration must have a return type. For example: + | + | trait Shape: + | def area: Double // abstract declaration returning a Double + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add an explicit return type trait Foo: def bar: Unit -``` +``` -```scala sc:compile +```scala sc:compile // Or provide an implementation (then type can be inferred) trait Foo: def bar = println("hello") -``` +``` -```scala sc:compile +```scala sc:compile // For methods with parameters trait Calculator: def add(a: Int, b: Int): Int diff --git a/docs/_docs/reference/error-codes/E020.md b/docs/_docs/reference/error-codes/E020.md index d1ad40c24bfa..f752ce8edd14 100644 --- a/docs/_docs/reference/error-codes/E020.md +++ b/docs/_docs/reference/error-codes/E020.md @@ -2,7 +2,6 @@ title: E020: Yield Or Do Expected In For Comprehension kind: Error --- - # E020: Yield Or Do Expected In For Comprehension This error is emitted when a `for` comprehension without parentheses around the enumerators is missing a `yield` or `do` keyword. @@ -31,37 +30,64 @@ can also be written without parentheses but a `do` keyword has to be included. ## Example -```scala sc:fail -val xs = for i <- 1 to 10 i * 2 +```scala sc:fail sc-opts:-explain +val xs = for i <- 1 to 10 ``` ### Error ```scala sc:nocompile --- [E020] Syntax Error: example.scala:1:30 -1 |val xs = for i <- 1 to 10 i * 2 - | ^ - | yield or do expected +-- [E020] Syntax Error: example.scala:1:25 ------------------------------------- +1 |val xs = for i <- 1 to 10 + | ^ + | yield or do expected + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | When the enumerators in a for comprehension are not placed in parentheses or + | braces, a do or yield statement is required after the enumerators + | section of the comprehension. + | + | You can save some keystrokes by omitting the parentheses and writing + | + | val numbers = for i <- 1 to 3 yield i + | + | instead of + | + | val numbers = for (i <- 1 to 3) yield i + | + | but the yield keyword is still required. + | + | For comprehensions that simply perform a side effect without yielding anything + | can also be written without parentheses but a do keyword has to be + | included. For example, + | + | for (i <- 1 to 3) println(i) + | + | can be written as + | + | for i <- 1 to 3 do println(i) // notice the 'do' keyword + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add yield to produce a collection val xs = for i <- 1 to 10 yield i * 2 -``` +``` -```scala sc:compile +```scala sc:compile // Use do for side effects -for i <- 1 to 10 do println(i * 2) -``` +def example() = for i <- 1 to 10 do println(i * 2) +``` -```scala sc:compile +```scala sc:compile // Or use parentheses (then yield is optional for producing values) val xs = for (i <- 1 to 10) yield i * 2 -``` +``` -```scala sc:compile +```scala sc:compile // With braces for multiple generators val pairs = for { i <- 1 to 3 diff --git a/docs/_docs/reference/error-codes/E021.md b/docs/_docs/reference/error-codes/E021.md index df236f1a4dce..600fa80ec903 100644 --- a/docs/_docs/reference/error-codes/E021.md +++ b/docs/_docs/reference/error-codes/E021.md @@ -2,7 +2,6 @@ title: E021: Proper Definition Not Found kind: Error --- - # E021: Proper Definition Not Found This error is emitted when a `@usecase` annotation in a Scaladoc comment does not contain a proper `def` definition. @@ -37,29 +36,65 @@ def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That ## Example -```scala sc:fail -/** - * @usecase val x: Int - */ -def complexMethod[A, B](f: A => B)(implicit ev: Ordering[A]): B = ??? +```scala sc:fail sc-opts:-Xcook-comments +//> using options -Xcook-comments + +class Example: + /** + * @usecase val x: Int + */ + def complexMethod[A, B](f: A => B)(implicit ev: Ordering[A]): B = ??? ``` ### Error ```scala sc:nocompile --- DocComment Error: example.scala:2:3 -2 | * @usecase val x: Int - | ^^^^^^^^^^^^^^^^^^^^ - | Proper definition was not found in @usecase +-- [E021] Doc Comment Error: example.scala:5:14 -------------------------------- +5 | * @usecase val x: Int + | ^ + | Proper definition was not found in @usecase +6 | */ +7 | def complexMethod[A, B](f: A => B)(implicit ev: Ordering[A]): B = ??? + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Usecases are only supported for defs. They exist because with Scala's + | advanced type-system, we sometimes end up with seemingly scary signatures. + | The usage of these methods, however, needs not be - for instance the map + | function + | + | List(1, 2, 3).map(2 * _) // res: List(2, 4, 6) + | + | is easy to understand and use - but has a rather bulky signature: + | + | def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That + | + | to mitigate this and ease the usage of such functions we have the @usecase + | annotation for docstrings. Which can be used like this: + | + | /** Map from List[A] => List[B] + | * + | * @usecase def map[B](f: A => B): List[B] + | */ + | def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That + | + | + | When creating the docs, the signature of the method is substituted by the + | usecase and the compiler makes sure that it is valid. Because of this, you're + | only allowed to use defs when defining usecases. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile -/** - * Transforms elements. - * @usecase def transform(f: Int => Int): List[Int] - */ -def transform[A, B](f: A => B)(implicit ev: Ordering[A]): List[B] = ??? +```scala sc:compile +//> using options -Xcook-comments + +class Example: + /** + * Transforms elements. + * @usecase def transform(f: Int => Int): List[Int] + */ + def transform[A, B](f: A => B)(implicit ev: Ordering[A]): List[B] = ??? ``` diff --git a/docs/_docs/reference/error-codes/E022.md b/docs/_docs/reference/error-codes/E022.md index 14525bd3819b..c9bc5624c27c 100644 --- a/docs/_docs/reference/error-codes/E022.md +++ b/docs/_docs/reference/error-codes/E022.md @@ -2,7 +2,6 @@ title: E022: By Name Parameter Not Supported kind: Error --- - # E022: By Name Parameter Not Supported This error is emitted when a by-name parameter type (`=> T`) is used in a context where it is not allowed, such as in tuple types. @@ -25,34 +24,53 @@ They are not allowed in: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain type LazyPair = (=> Int, String) ``` ### Error ```scala sc:nocompile --- [E022] Syntax Error: example.scala:1:17 +-- [E022] Syntax Error: example.scala:1:17 ------------------------------------- 1 |type LazyPair = (=> Int, String) | ^^^^^^ | By-name parameter type => Int not allowed here. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | By-name parameters act like functions that are only evaluated when referenced, + | allowing for lazy evaluation of a parameter. + | + | An example of using a by-name parameter would look like: + | def func(f: => Boolean) = f // 'f' is evaluated when referenced within the function + | + | An example of the syntax of passing an actual function as a parameter: + | def func(f: (Boolean => Boolean)) = f(true) + | + | or: + | + | def func(f: Boolean => Boolean) = f(true) + | + | And the usage could be as such: + | func(bool => // do something...) + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a function type instead type LazyPair = (() => Int, String) -``` +``` -```scala sc:compile +```scala sc:compile // By-name is allowed in function types type LazyFunction = (=> Int) => String def example(f: LazyFunction): String = f(42) -``` +``` -```scala sc:compile +```scala sc:compile // By-name is allowed in method parameters def lazyEval(x: => Int, y: String): Unit = println(s"$y: $x") diff --git a/docs/_docs/reference/error-codes/E023.md b/docs/_docs/reference/error-codes/E023.md index cfde69bcf15c..37c017b31671 100644 --- a/docs/_docs/reference/error-codes/E023.md +++ b/docs/_docs/reference/error-codes/E023.md @@ -2,7 +2,6 @@ title: E023: Wrong Number Of Type Args kind: Error --- - # E023: Wrong Number Of Type Args This error is emitted when a type constructor is applied with the wrong number of type arguments. @@ -19,39 +18,52 @@ You must provide exactly the number of type arguments that the type expects. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val x: List[Int, String] = List() ``` ### Error ```scala sc:nocompile --- [E023] Syntax Error: example.scala:1:7 +-- [E023] Syntax Error: example.scala:1:7 -------------------------------------- 1 |val x: List[Int, String] = List() | ^^^^^^^^^^^^^^^^^ | Too many type arguments for List[A] | expected: [A] | actual: [Int, String] + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | You have supplied too many type parameters + | + | For example List takes a single type parameter (List[A]) + | If you need to hold more types in a list then you need to combine them + | into another data type that can contain the number of types you need, + | In this example one solution would be to use a Tuple: + | + | val tuple2: (Int, String) = (1, "one") + | val list: List[(Int, String)] = List(tuple2) + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use the correct number of type arguments val x: List[Int] = List() -``` +``` -```scala sc:compile +```scala sc:compile // For multiple types, use a tuple or a different container val x: List[(Int, String)] = List() -``` +``` -```scala sc:compile +```scala sc:compile // Or use a type that takes multiple parameters val x: Map[Int, String] = Map() -``` +``` -```scala sc:compile +```scala sc:compile // Or use Either for two alternatives val x: Either[Int, String] = Right("hello") ``` diff --git a/docs/_docs/reference/error-codes/E024.md b/docs/_docs/reference/error-codes/E024.md index 77b0fddfb1ee..f558fbe4d136 100644 --- a/docs/_docs/reference/error-codes/E024.md +++ b/docs/_docs/reference/error-codes/E024.md @@ -2,13 +2,12 @@ title: E024: Illegal Variable In Pattern Alternative kind: Error --- - # E024: Illegal Variable In Pattern Alternative This error is emitted when a variable binding is used in a pattern alternative (`|`). Variables are not allowed in alternative patterns. Variables are not allowed within alternate pattern matches. When you use the `|` -operator to combine patterns, each alternative must match independently, and +operator to combine patterns, each alternative must match independently, and Scala cannot guarantee that a variable bound in one alternative would have the same value or even be bound in another alternative. @@ -16,7 +15,7 @@ same value or even be bound in another alternative. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def test(pair: (Int, Int)): Int = pair match case (1, n) | (n, 1) => n case _ => 0 @@ -25,30 +24,72 @@ def test(pair: (Int, Int)): Int = pair match ### Error ```scala sc:nocompile --- [E024] Syntax Error: example.scala:2:9 +-- [E024] Syntax Error: example.scala:2:11 ------------------------------------- +2 | case (1, n) | (n, 1) => n + | ^ + | Illegal variable n in pattern alternative + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Variables are not allowed within alternate pattern matches. You can workaround + | this issue by adding additional cases for each alternative. For example, the + | illegal function: + | + | def g(pair: (Int,Int)): Int = pair match { + | case (1, n) | (n, 1) => n + | case _ => 0 + | } + | could be implemented by moving each alternative into a separate case: + | + | def g(pair: (Int,Int)): Int = pair match { + | case (1, n) => n + | case (n, 1) => n + | case _ => 0 + | } + ----------------------------------------------------------------------------- +-- [E024] Syntax Error: example.scala:2:17 ------------------------------------- 2 | case (1, n) | (n, 1) => n - | ^ - | Illegal variable n in pattern alternative + | ^ + | Illegal variable n in pattern alternative + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Variables are not allowed within alternate pattern matches. You can workaround + | this issue by adding additional cases for each alternative. For example, the + | illegal function: + | + | def g(pair: (Int,Int)): Int = pair match { + | case (1, n) | (n, 1) => n + | case _ => 0 + | } + | could be implemented by moving each alternative into a separate case: + | + | def g(pair: (Int,Int)): Int = pair match { + | case (1, n) => n + | case (n, 1) => n + | case _ => 0 + | } + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Split into separate cases def test(pair: (Int, Int)): Int = pair match case (1, n) => n case (n, 1) => n case _ => 0 -``` +``` -```scala sc:compile +```scala sc:compile // Use wildcards if you don't need the value def isEdge(pair: (Int, Int)): Boolean = pair match case (1, _) | (_, 1) => true case _ => false -``` +``` -```scala sc:compile +```scala sc:compile // Use a guard for more complex conditions def test(pair: (Int, Int)): Int = pair match case (a, b) if a == 1 || b == 1 => if a == 1 then b else a diff --git a/docs/_docs/reference/error-codes/E025.md b/docs/_docs/reference/error-codes/E025.md index 6b498673c77d..d708bdfa7cf0 100644 --- a/docs/_docs/reference/error-codes/E025.md +++ b/docs/_docs/reference/error-codes/E025.md @@ -2,52 +2,16 @@ title: E025: Identifier Expected kind: Error --- - # E025: Identifier Expected -This error is emitted when the compiler expects a type identifier but finds something that cannot be converted to a type identifier, such as a complex expression. - -An identifier was expected, but a different construct was found. This could be because -an expression or keyword was used where a type identifier is required. - -As a workaround, if the issue is in a return type position, the compiler might be -able to infer the type for you. - ---- - -## Example - -```scala sc:fail -class Foo extends (if true then Int else String) -``` - -### Error - -```scala sc:nocompile --- [E025] Syntax Error: example.scala:1:17 -1 |class Foo extends (if true then Int else String) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | identifier expected -``` - -### Solution - -```scala sc:compile -// Use a proper type identifier -class Foo extends AnyRef -``` +This error is emitted when the parser expects an identifier but finds something else, typically when an invalid token is used where a name is required. -```scala sc:compile -// For conditional types, use match types or type aliases -type MyType = Int +The compiler message states: **"identifier expected"** -class Foo extends AnyRef: - type T = MyType -``` +This can occur when: +- An invalid token is used where an identifier is expected +- A type annotation uses something that is not a valid identifier -```scala sc:compile -// Or use a union type for alternatives -class Foo: - def getValue: Int | String = 42 -``` +As the compiler explains: An identifier is expected, but something else was found. This could be because the token found is not a valid identifier. As a workaround, the compiler could infer the type for you. For example, instead of using an invalid type annotation like `def foo: = {...}`, you can write `def foo = {...}` and let the compiler infer the type. +**Note:** This error code is active in the compiler but requires specific parsing contexts that are difficult to reproduce with simple source code examples. The error is triggered in both Scala and Java source parsing when a type reference cannot be converted to a valid identifier. diff --git a/docs/_docs/reference/error-codes/E026.md b/docs/_docs/reference/error-codes/E026.md index b517e3a6b357..c4dfa3875145 100644 --- a/docs/_docs/reference/error-codes/E026.md +++ b/docs/_docs/reference/error-codes/E026.md @@ -2,7 +2,6 @@ title: E026: Auxiliary Constructor Needs Non-Implicit Parameter kind: Error --- - # E026: Auxiliary Constructor Needs Non-Implicit Parameter This error is emitted when an auxiliary constructor (secondary constructor) only has implicit parameter lists without any non-implicit parameters. @@ -13,29 +12,41 @@ Only the primary constructor is allowed to have an implicit-only parameter list. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Example(implicit x: Int): - def this(implicit x: String, y: Int) = this() + def this(implicit x: String, y: Int) = this()(using y) ``` ### Error ```scala sc:nocompile --- [E026] Syntax Error: example.scala:2:6 -2 | def this(implicit x: String, y: Int) = this() - | ^^^^ - | Auxiliary constructor needs non-implicit parameter list +-- [E026] Syntax Error: example.scala:2:39 ------------------------------------- +2 | def this(implicit x: String, y: Int) = this()(using y) + | ^ + | Auxiliary constructor needs non-implicit parameter list + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Only the primary constructor is allowed an implicit parameter list; + | auxiliary constructors need non-implicit parameter lists. When a primary + | constructor has an implicit argslist, auxiliary constructors that call the + | primary constructor must specify the implicit value. + | + | To resolve this issue check for: + | - Forgotten parenthesis on this (def this() = { ... }) + | - Auxiliary constructors specify the implicit value + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add an empty non-implicit parameter list before the implicit one class Example(implicit x: Int): def this()(implicit x: String, y: Int) = this()(using y) -``` +``` -```scala sc:compile +```scala sc:compile // Alternative: use an explicit non-implicit parameter with a different type class Example(implicit x: Int): def this(x: String, y: Int) = this()(using y) diff --git a/docs/_docs/reference/error-codes/E027.md b/docs/_docs/reference/error-codes/E027.md index 52e0d5931a11..1e6981c8c5ff 100644 --- a/docs/_docs/reference/error-codes/E027.md +++ b/docs/_docs/reference/error-codes/E027.md @@ -2,39 +2,14 @@ title: E027: Varargs Parameter Must Come Last kind: Error --- - # E027: Varargs Parameter Must Come Last -This error is emitted when a varargs parameter (repeated parameter) is not placed at the end of a parameter list. - -The varargs field must be the last parameter in the method signature. Attempting to define a parameter after a varargs field in the same parameter list is not allowed. - ---- - -## Example - -```scala sc:fail -def example(xs: Int*, y: Int) = xs.sum + y -``` - -### Error - -```scala sc:nocompile --- [E027] Syntax Error: example.scala:1:16 -1 |def example(xs: Int*, y: Int) = xs.sum + y - | ^ - | varargs parameter must come last -``` +This error is emitted when a varargs (variable arguments) parameter is not the last parameter in a method's parameter list. -### Solution +The compiler message states: **"varargs parameter must come last"** -```scala sc:compile -// Place the varargs parameter last -def example(y: Int, xs: Int*) = xs.sum + y -``` +In Scala, a varargs parameter is declared using `*` after the type (e.g., `args: String*`). The varargs field must be the last field in the method signature. Attempting to define a field in a method signature after a varargs field is an error. -```scala sc:compile -// Alternative: use a separate parameter list -def example(y: Int)(xs: Int*) = xs.sum + y -``` +This restriction exists because varargs can accept zero or more arguments at runtime, so having additional parameters after it would make the call syntax ambiguous. +**Note:** This error code is active in the compiler and is triggered during parsing when validating parameter lists. The exact syntax to reproduce this error in modern Scala 3 requires further investigation, as the parser may produce different errors for malformed parameter lists. diff --git a/docs/_docs/reference/error-codes/E028.md b/docs/_docs/reference/error-codes/E028.md index b9dd3e1440e7..10d7b7840bc1 100644 --- a/docs/_docs/reference/error-codes/E028.md +++ b/docs/_docs/reference/error-codes/E028.md @@ -2,51 +2,20 @@ title: E028: Illegal Literal kind: Error --- - # E028: Illegal Literal -This error is emitted when the compiler encounters an invalid literal value that does not conform to Scala's literal syntax rules. - -Available literals can be divided into several groups: -- Integer literals: `0`, `21`, `0xFFFFFFFF`, `-42L` -- Floating Point Literals: `0.0`, `1e30f`, `3.14159f`, `1.0e-100`, `.1` -- Boolean Literals: `true`, `false` -- Character Literals: `'a'`, `'\u0041'`, `'\n'` -- String Literals: `"Hello, World!"` -- `null` - ---- - -## Example - -```scala sc:fail -def example = '\u000' -``` - -### Error - -```scala sc:nocompile --- [E028] Syntax Error: example.scala:1:14 -1 |def example = '\u000' - | ^ - | Illegal literal -``` - -### Solution +This error is emitted when the parser encounters an invalid literal value that doesn't conform to Scala's literal syntax rules. -```scala sc:compile -// Use a valid Unicode escape sequence (4 hex digits) -def example = '\u0000' -``` +The compiler message states: **"Illegal literal"** -```scala sc:compile -// Use a regular character literal -def example = 'a' -``` +Available literals in Scala can be divided into several groups: +- **Integer literals**: `0`, `21`, `0xFFFFFFFF`, `-42L` +- **Floating Point Literals**: `0.0`, `1e30f`, `3.14159f`, `1.0e-100`, `.1` +- **Boolean Literals**: `true`, `false` +- **Character Literals**: `'a'`, `'\u0041'`, `'\n'` +- **String Literals**: `"Hello, World!"` +- **null** -```scala sc:compile -// Use escape sequences for special characters -def newline = '\n' -def tab = '\t' -``` +This error is triggered during parsing when a literal token is expected but the scanner encounters something that cannot be interpreted as any valid literal type. +**Note:** This error code is active in the compiler and is triggered in the parser's `literal` and `negativeLiteral` methods. The exact conditions to reproduce this error with source code require further investigation, as the scanner typically produces different errors for malformed input. diff --git a/docs/_docs/reference/error-codes/E029.md b/docs/_docs/reference/error-codes/E029.md index f23de9370945..79ff20fa0003 100644 --- a/docs/_docs/reference/error-codes/E029.md +++ b/docs/_docs/reference/error-codes/E029.md @@ -2,7 +2,6 @@ title: E029: Pattern Match Exhaustivity kind: Warning --- - # E029: Pattern Match Exhaustivity This warning is emitted when a pattern match expression may not handle all possible input values. The compiler detects cases that are not covered by any of the match cases. @@ -16,7 +15,7 @@ There are several ways to make the match exhaustive: ## Example -```scala sc:fail sc-opts:-Werror +```scala sc:fail sc-opts:-explain,-Werror enum Color: case Red, Green, Blue @@ -28,17 +27,25 @@ def describe(c: Color): String = c match ### Warning ```scala sc:nocompile --- [E029] Pattern Match Exhaustivity Warning: example.scala:5:33 -5 |def describe(c: Color): String = c match +-- [E029] Pattern Match Exhaustivity Warning: example.scala:4:33 --------------- +4 |def describe(c: Color): String = c match | ^ | match may not be exhaustive. | - | It would fail on pattern case: Color.Blue + | It would fail on pattern case: Blue + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | There are several ways to make the match exhaustive: + | - Add missing cases as shown in the warning + | - If an extractor always return Some(...), write Some[X] for its return type + | - Add a case _ => ... at the end to match all remaining cases + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add the missing case enum Color: case Red, Green, Blue @@ -47,9 +54,9 @@ def describe(c: Color): String = c match case Color.Red => "red" case Color.Green => "green" case Color.Blue => "blue" -``` +``` -```scala sc:compile +```scala sc:compile // Alternative: add a wildcard case for remaining patterns enum Color: case Red, Green, Blue diff --git a/docs/_docs/reference/error-codes/E030.md b/docs/_docs/reference/error-codes/E030.md index 664e91323916..a2c9cb2ca058 100644 --- a/docs/_docs/reference/error-codes/E030.md +++ b/docs/_docs/reference/error-codes/E030.md @@ -2,7 +2,6 @@ title: E030: Match Case Unreachable kind: Warning --- - # E030: Match Case Unreachable This warning is emitted when a case in a pattern match expression can never be reached because it is shadowed by a previous case that matches all the same values. @@ -13,7 +12,7 @@ Unreachable code is typically a sign of a logic error. You should review the ord ## Example -```scala sc:fail sc-opts:-Werror +```scala sc:fail sc-opts:-explain,-Werror def example(x: Int): String = x match case _ => "any" case 1 => "one" @@ -22,22 +21,22 @@ def example(x: Int): String = x match ### Warning ```scala sc:nocompile --- [E030] Match case Unreachable Warning: example.scala:3:7 +-- [E030] Match case Unreachable Warning: example.scala:3:7 -------------------- 3 | case 1 => "one" | ^ | Unreachable case ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Reorder cases - put specific patterns before general ones def example(x: Int): String = x match case 1 => "one" case _ => "any" -``` +``` -```scala sc:compile +```scala sc:compile // Alternative: remove the unreachable case if it's not needed def example(x: Int): String = x match case _ => "any" diff --git a/docs/_docs/reference/error-codes/E031.md b/docs/_docs/reference/error-codes/E031.md index bad8f8a9de84..49b4d97e5f4e 100644 --- a/docs/_docs/reference/error-codes/E031.md +++ b/docs/_docs/reference/error-codes/E031.md @@ -2,10 +2,9 @@ title: E031: Sequence Wildcard Pattern Position kind: Error --- - # E031: Sequence Wildcard Pattern Position -This error is emitted when the sequence wildcard pattern (`*`) is used in a position other than the last element in a pattern sequence. +This error is emitted when the sequence wildcard pattern (`_*`) is used in a position other than the last element in a pattern sequence. The sequence wildcard pattern is expected at the end of an argument list. This pattern matches any remaining elements in a sequence. @@ -13,31 +12,49 @@ The sequence wildcard pattern is expected at the end of an argument list. This p ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def example(list: List[Int]): Int = list match - case List(x*, second, third) => second + case List(x: _*, second, third) => second case _ => 0 ``` ### Error ```scala sc:nocompile --- [E031] Syntax Error: example.scala:2:12 -2 | case List(x*, second, third) => second - | ^^ - | * can be used only for last argument +-- [E031] Syntax Error: example.scala:2:15 ------------------------------------- +2 | case List(x: _*, second, third) => second + | ^ + | * can be used only for last argument + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Sequence wildcard pattern is expected at the end of an argument list. + | This pattern matches any remaining elements in a sequence. + | Consider the following example: + | + | def sumOfTheFirstTwo(list: List[Int]): Int = list match { + | | case List(first, second, x*) => first + second + | | case _ => 0 + | |} + | + | Calling: + | + | sumOfTheFirstTwo(List(1, 2, 10)) + | + | would give 3 as a result + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile -// Place the sequence wildcard at the end +```scala sc:compile +// Place the sequence wildcard at the end using modern syntax def example(list: List[Int]): Int = list match case List(first, second, rest*) => second case _ => 0 -``` +``` -```scala sc:compile +```scala sc:compile // Alternative: match the exact number of elements you need def example(list: List[Int]): Int = list match case first :: second :: _ => second diff --git a/docs/_docs/reference/error-codes/E032.md b/docs/_docs/reference/error-codes/E032.md index 28a022adf04f..d255a2433064 100644 --- a/docs/_docs/reference/error-codes/E032.md +++ b/docs/_docs/reference/error-codes/E032.md @@ -2,7 +2,6 @@ title: E032: Illegal Start Of Simple Pattern kind: Error --- - # E032: Illegal Start Of Simple Pattern This error is emitted when the compiler encounters a token that cannot begin a valid pattern in a pattern matching context. @@ -35,36 +34,100 @@ Simple patterns can be divided into several groups: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def example(x: Any) = x match - case class => "class" + case => "none" ``` ### Error ```scala sc:nocompile --- [E032] Syntax Error: example.scala:2:7 -2 | case class => "class" - | ^^^^^ +-- [E032] Syntax Error: example.scala:2:7 -------------------------------------- +2 | case => "none" + | ^^ | pattern expected + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Simple patterns can be divided into several groups: + | - Variable Patterns: case x => ... or case _ => ... + | It matches any value, and binds the variable name to that value. + | A special case is the wild-card pattern _ which is treated as if it was a fresh + | variable on each occurrence. + | + | - Typed Patterns: case x: Int => ... or case _: Int => ... + | This pattern matches any value matched by the specified type; it binds the variable + | name to that value. + | + | - Given Patterns: case given ExecutionContext => ... + | This pattern matches any value matched by the specified type; it binds a given + | instance with the same type to that value. + | + | - Literal Patterns: case 123 => ... or case 'A' => ... + | This type of pattern matches any value that is equal to the specified literal. + | + | - Stable Identifier Patterns: + | + | def f(x: Int, y: Int) = x match + | case `y` => ... + | + | the match succeeds only if the x argument and the y argument of f are equal. + | + | - Constructor Patterns: + | + | case class Person(name: String, age: Int) + | + | def test(p: Person) = p match + | case Person(name, age) => ... + | + | The pattern binds all object's fields to the variable names (name and age, in this + | case). + | + | - Tuple Patterns: + | + | def swap(tuple: (String, Int)): (Int, String) = tuple match + | case (text, number) => (number, text) + | + | Calling: + | + | swap(("Luftballons", 99)) + | + | would give (99, "Luftballons") as a result. + | + | - Pattern Sequences: + | + | def getSecondValue(list: List[Int]): Int = list match + | case List(_, second, x*) => second + | case _ => 0 + | + | Calling: + | + | getSecondValue(List(1, 10, 2)) + | + | would give 10 as a result. + | This pattern is possible because a companion object for the List class has a method + | with the following signature: + | + | def unapplySeq[A](x: List[A]): Some[List[A]] + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a valid pattern - typed pattern def example(x: Any) = x match case _: String => "string" case _ => "other" -``` +``` -```scala sc:compile +```scala sc:compile // Use a variable pattern def example(x: Any) = x match case y => s"value: $y" -``` +``` -```scala sc:compile +```scala sc:compile // Use a constructor pattern case class Person(name: String) diff --git a/docs/_docs/reference/error-codes/E033.md b/docs/_docs/reference/error-codes/E033.md index 33643335f91a..6c3548ddc25b 100644 --- a/docs/_docs/reference/error-codes/E033.md +++ b/docs/_docs/reference/error-codes/E033.md @@ -2,50 +2,62 @@ title: E033: Package Duplicate Symbol kind: Error --- - # E033: Package Duplicate Symbol -This error is emitted when you try to define a package with the same name as an existing symbol (such as an object, class, or trait) in the same scope. +This error is emitted when you try to define a nested package with the same name as an existing type (class or trait) in the same parent package. + +Package names must be unique and cannot conflict with type definitions in the same scope. -Package names must be unique and cannot conflict with other top-level definitions in the same compilation unit. +Note: This error requires package statements which cannot be demonstrated in Scaladoc's snippet compiler. The examples below show the code structure but are not compiled. --- ## Example -```scala sc:fail -object foo +```scala sc:nocompile custom-sc:fail +package foo: + trait id: + def bar: Int package foo: - class Bar + package id: // error: Trying to define package with same name as trait id + class Bar ``` ### Error ```scala sc:nocompile --- [E033] Naming Error: example.scala:3:8 -3 |package foo: - | ^^^ - | Trying to define package with same name as object foo +-- [E033] Naming Error: example.scala:6:10 ------------------------------------- +6 | package id: // error: Trying to define package with same name as trait id + | ^^ + | Trying to define package with same name as trait id ``` -### Solution +### Solution -Use a different package name: +Use a different package name to avoid conflict with the type: -```scala sc:nocompile -package bar: - class Bar +```scala sc:nocompile custom-sc:compile +// Use a different package name +package foo: + trait id: + def bar: Int -object foo -``` +package foo: + package idPkg: + class Bar +``` -Alternative: rename the object to avoid conflict: +Or rename the trait to avoid conflict: -```scala sc:nocompile +```scala sc:nocompile custom-sc:compile +// Or rename the trait to avoid conflict package foo: - class Bar + trait IdTrait: + def bar: Int -object myFoo +package foo: + package id: + class Bar ``` diff --git a/docs/_docs/reference/error-codes/E034.md b/docs/_docs/reference/error-codes/E034.md index 2ba4c287d9fc..c6ab83ab8742 100644 --- a/docs/_docs/reference/error-codes/E034.md +++ b/docs/_docs/reference/error-codes/E034.md @@ -2,7 +2,6 @@ title: E034: Existential Types No Longer Supported kind: Error --- - # E034: Existential Types No Longer Supported This error is emitted when existential types syntax (using `forSome`) is used. Existential types are no longer supported in Scala 3. @@ -19,33 +18,50 @@ Instead of existential types, you should use: ## Example -```scala sc:fail -def example: List[T forSome { type T }] = List() +```scala sc:fail sc-opts:-explain +def example[T]: List[T forSome { type T }] = List() ``` ### Error ```scala sc:nocompile --- [E034] Syntax Error: example.scala:1:17 -1 |def example: List[T forSome { type T }] = List() - | ^ - | Existential types are no longer supported - - | use a wildcard or dependent type instead +-- [E034] Syntax Error: example.scala:1:23 ------------------------------------- +1 |def example[T]: List[T forSome { type T }] = List() + | ^^^^^^^ + | Existential types are no longer supported - + | use a wildcard or dependent type instead + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The use of existential types is no longer supported. + | + | You should use a wildcard or dependent type instead. + | + | For example: + | + | Instead of using forSome to specify a type variable + | + | List[T forSome { type T }] + | + | Try using a wildcard type variable + | + | List[?] + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a wildcard type def example: List[?] = List() -``` +``` -```scala sc:compile +```scala sc:compile // Alternative: use a type parameter def example[T]: List[T] = List() -``` +``` -```scala sc:compile +```scala sc:compile // Alternative: use Any if the type doesn't matter def example: List[Any] = List() ``` diff --git a/docs/_docs/reference/error-codes/E035.md b/docs/_docs/reference/error-codes/E035.md index 84b61ce8be4c..4395abff8299 100644 --- a/docs/_docs/reference/error-codes/E035.md +++ b/docs/_docs/reference/error-codes/E035.md @@ -2,7 +2,6 @@ title: E035: Unbound Wildcard Type kind: Error --- - # E035: Unbound Wildcard Type This error is emitted when the wildcard type syntax (`_` or `?`) is used in a position where it cannot be bound to a concrete type. @@ -20,32 +19,73 @@ This typically happens in: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def example(x: ?) = x ``` ### Error ```scala sc:nocompile --- [E035] Syntax Error: example.scala:1:15 +-- [E035] Syntax Error: example.scala:1:15 ------------------------------------- 1 |def example(x: ?) = x | ^ | Unbound wildcard type + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The wildcard type syntax (_) was used where it could not be bound. + | Replace _ with a non-wildcard type. If the type doesn't matter, + | try replacing _ with Any. + | + | Examples: + | + | - Parameter lists + | + | Instead of: + | def foo(x: _) = ... + | + | Use Any if the type doesn't matter: + | def foo(x: Any) = ... + | + | - Type arguments + | + | Instead of: + | val foo = List[?](1, 2) + | + | Use: + | val foo = List[Int](1, 2) + | + | - Type bounds + | + | Instead of: + | def foo[T <: _](x: T) = ... + | + | Remove the bounds if the type doesn't matter: + | def foo[T](x: T) = ... + | + | - val and def types + | + | Instead of: + | val foo: _ = 3 + | + | Use: + | val foo: Int = 3 + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use Any if the type doesn't matter def example(x: Any) = x -``` +``` -```scala sc:compile +```scala sc:compile // Use a type parameter for generic behavior def example[T](x: T): T = x -``` +``` -```scala sc:compile +```scala sc:compile // Specify a concrete type def example(x: Int) = x ``` diff --git a/docs/_docs/reference/error-codes/E036.md b/docs/_docs/reference/error-codes/E036.md new file mode 100644 index 000000000000..fd1e5b34f020 --- /dev/null +++ b/docs/_docs/reference/error-codes/E036.md @@ -0,0 +1,55 @@ +--- +title: "E036: Dangling This In Path" +kind: Error +until: 3.0.0 +--- + +# E036: Dangling This In Path + +**Note:** This error was removed before Scala 3.0.0 was released and was never emitted by the Scala 3 compiler. + +## What it did + +This error was triggered when using `this` at the end of an import path or type selection without selecting a member. + +### Example + +```scala sc:nocompile +trait Outer { + val member: Int + type Member + trait Inner { + import Outer.this + } +} +``` + +### Error + +```scala sc:nocompile +-- [E036] Syntax Error: example.scala:5:11 ------------------------------------- +5 | import Outer.this + | ^^^^^^^^^^ + | Expected an additional member selection after the keyword `this` +``` + +## Explanation + +Paths of imports and type selections must not end with the keyword `this`. The compiler expected an additional member selection after `this`. + +Valid usages required selecting a member: + +```scala sc:nocompile +trait Outer { + val member: Int + type Member + trait Inner { + // Valid: selecting a member after this + import Outer.this.member + + // Valid: type selection + type T = Outer.this.Member + } +} +``` + diff --git a/docs/_docs/reference/error-codes/E037.md b/docs/_docs/reference/error-codes/E037.md index d04db15c7de8..4c700b8f53ce 100644 --- a/docs/_docs/reference/error-codes/E037.md +++ b/docs/_docs/reference/error-codes/E037.md @@ -2,7 +2,6 @@ title: E037: Overrides Nothing kind: Error --- - # E037: Overrides Nothing This error is emitted when a member is declared with the `override` modifier but there is no corresponding member in a superclass to override. @@ -17,7 +16,7 @@ There must be a field or method with the same name in a super class to override ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Parent: def greet(): String = "Hello" @@ -28,24 +27,31 @@ class Child extends Parent: ### Error ```scala sc:nocompile --- [E037] Declaration Error: example.scala:5:15 +-- [E037] Declaration Error: example.scala:5:15 -------------------------------- 5 | override def greeet(): String = "Hi" - | ^^^^^^ + | ^ | method greeet overrides nothing + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | There must be a field or method with the name greeet in a super + | class of class Child to override it. Did you misspell it? + | Are you extending the right classes? + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Fix the spelling to match the parent method class Parent: def greet(): String = "Hello" class Child extends Parent: override def greet(): String = "Hi" -``` +``` -```scala sc:compile +```scala sc:compile // Or remove the override modifier if not overriding class Parent: def greet(): String = "Hello" @@ -54,4 +60,3 @@ class Child extends Parent: def greeet(): String = "Hi" ``` - diff --git a/docs/_docs/reference/error-codes/E038.md b/docs/_docs/reference/error-codes/E038.md index 2db0208e6a9f..e446ae8bcd4b 100644 --- a/docs/_docs/reference/error-codes/E038.md +++ b/docs/_docs/reference/error-codes/E038.md @@ -2,7 +2,6 @@ title: E038: Overrides Nothing But Name Exists kind: Error --- - # E038: Overrides Nothing But Name Exists This error is emitted when a member is declared with the `override` modifier and a member with the same name exists in the parent class, but the signatures don't match. @@ -13,7 +12,7 @@ There must be a non-final field or method with the same name and the same parame ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Parent: def process(x: Int): String = x.toString @@ -24,24 +23,36 @@ class Child extends Parent: ### Error ```scala sc:nocompile --- [E038] Declaration Error: example.scala:5:15 +-- [E038] Declaration Error: example.scala:5:15 -------------------------------- 5 | override def process(x: String): String = x - | ^^^^^^^ - | method process has a different signature than the overridden declaration + | ^ + | method process has a different signature than the overridden declaration + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | There must be a non-final field or method with the name process and the + | same parameter list in a super class of class Child to override it. + | + | def process(x: String): String + | + | The super classes of class Child contain the following members + | named process: + | def process(x: Int): String + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Match the parameter types of the parent method class Parent: def process(x: Int): String = x.toString class Child extends Parent: override def process(x: Int): String = s"Child: $x" -``` +``` -```scala sc:compile +```scala sc:compile // Or use overloading instead of overriding class Parent: def process(x: Int): String = x.toString @@ -50,4 +61,3 @@ class Child extends Parent: def process(x: String): String = x ``` - diff --git a/docs/_docs/reference/error-codes/E039.md b/docs/_docs/reference/error-codes/E039.md index 38a02debd549..5b17b9d51d50 100644 --- a/docs/_docs/reference/error-codes/E039.md +++ b/docs/_docs/reference/error-codes/E039.md @@ -2,7 +2,6 @@ title: E039: Forward Reference Extends Over Definition kind: Error --- - # E039: Forward Reference Extends Over Definition This error is emitted when a forward reference to a value extends over the definition of another value. @@ -13,7 +12,7 @@ Forward references are allowed only if there are no value definitions between th ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def example = def a: Int = b val b: Int = a @@ -23,24 +22,40 @@ def example = ### Error ```scala sc:nocompile --- [E039] Reference Error: example.scala:2:10 +-- [E039] Reference Error: example.scala:2:17 ---------------------------------- 2 | def a: Int = b | ^ - | b is a forward reference extending over the definition of b + | forward reference to b extends over the definition of b (on line 3) + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | b is used before you define it, and the definition of b + | appears between that use and the definition of b. + | + | Forward references are allowed only if there are no value definitions between + | the reference and the definition that is referred to. + | Specifically, any statement between the reference and the definition + | cannot be a variable definition, and if it's a value definition, it must be lazy. + | + | Define b before it is used, + | or move the definition of b so it does not appear between + | the declaration of b and its use, + | or define b as lazy. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Make the forward dependency lazy // Warning: It still might fail at runtime def example = def a: Int = b lazy val b: Int = a a -``` +``` -```scala sc:compile +```scala sc:compile // Even better ensure to always break the dependecny chain def example = lazy val a: Int = if b == 0 then 1 else b @@ -48,4 +63,3 @@ def example = a ``` - diff --git a/docs/_docs/reference/error-codes/E040.md b/docs/_docs/reference/error-codes/E040.md index 381b6b665892..357c96bd4a27 100644 --- a/docs/_docs/reference/error-codes/E040.md +++ b/docs/_docs/reference/error-codes/E040.md @@ -2,7 +2,6 @@ title: E040: Expected Token But Found kind: Error --- - # E040: Expected Token But Found This error is emitted when the compiler expects a specific token (like a keyword, symbol, or identifier) but finds a different token instead. @@ -13,29 +12,28 @@ This is a general syntax error that indicates the code structure doesn't match w ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def example(x: Int y: Int) = x + y ``` ### Error ```scala sc:nocompile --- [E040] Syntax Error: example.scala:1:19 +-- [E040] Syntax Error: example.scala:1:20 ------------------------------------- 1 |def example(x: Int y: Int) = x + y - | ^ - | ',' expected, but identifier found + | ^ + | an identifier expected, but ':' found ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add the missing comma between parameters def example(x: Int, y: Int) = x + y -``` +``` -```scala sc:compile +```scala sc:compile // Or use separate parameter lists def example(x: Int)(y: Int) = x + y ``` - diff --git a/docs/_docs/reference/error-codes/E041.md b/docs/_docs/reference/error-codes/E041.md index 5c7912588e44..b9122a8e8056 100644 --- a/docs/_docs/reference/error-codes/E041.md +++ b/docs/_docs/reference/error-codes/E041.md @@ -2,7 +2,6 @@ title: E041: Mixed Left And Right Associative Ops kind: Error --- - # E041: Mixed Left And Right Associative Ops This error is emitted when operators with different associativity (left vs right) but the same precedence are used together in an expression without parentheses. @@ -25,7 +24,7 @@ Infix operator precedence is determined by the operator's first character. Chara ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain extension (x: Int) def +: (y: Int): Int = x + y def +* (y: Int): Int = x * y @@ -36,24 +35,52 @@ def example = 1 +: 2 +* 3 ### Error ```scala sc:nocompile --- [E041] Syntax Error: example.scala:5:14 +-- [E041] Syntax Error: example.scala:5:19 ------------------------------------- 5 |def example = 1 +: 2 +* 3 - | ^^^^^^^^^^^ - | +: (which is right-associative) and +* (which is left-associative) have same precedence and may not be mixed + | ^ + |+: (which is right-associative) and +* (which is left-associative) have same precedence and may not be mixed + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The operators +: and +* are used as infix operators in the same expression, + | but they bind to different sides: + | +: is applied to the operand to its right + | +* is applied to the operand to its left + | As both have the same precedence the compiler can't decide which to apply first. + | + | You may use parenthesis to make the application order explicit, + | or use method application syntax operand1.+:(operand2). + | + | Operators ending in a colon : are right-associative. All other operators are left-associative. + | + | Infix operator precedence is determined by the operator's first character. Characters are listed + | below in increasing order of precedence, with characters on the same line having the same precedence. + | (all letters) + | | + | ^ + | & + | = ! + | < > + | : + | + - + | * / % + | (all other special characters) + | Operators starting with a letter have lowest precedence, followed by operators starting with `|`, etc. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use parentheses to make the order explicit extension (x: Int) def +: (y: Int): Int = x + y def +* (y: Int): Int = x * y def example = (1 +: 2) +* 3 -``` +``` -```scala sc:compile +```scala sc:compile // Or use method call syntax extension (x: Int) def +: (y: Int): Int = x + y @@ -62,4 +89,3 @@ extension (x: Int) def example = (1.+:(2)).+*(3) ``` - diff --git a/docs/_docs/reference/error-codes/E042.md b/docs/_docs/reference/error-codes/E042.md index 70db29300053..ad3c77be4b4c 100644 --- a/docs/_docs/reference/error-codes/E042.md +++ b/docs/_docs/reference/error-codes/E042.md @@ -2,7 +2,6 @@ title: E042: Cannot Instantiate Abstract Class Or Trait kind: Error --- - # E042: Cannot Instantiate Abstract Class Or Trait This error is emitted when attempting to directly instantiate an abstract class or a trait using `new`. @@ -13,7 +12,7 @@ Abstract classes and traits need to be extended by a concrete class or object to ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait Animal: def speak(): String @@ -23,24 +22,38 @@ val pet = new Animal ### Error ```scala sc:nocompile --- [E042] Type Error: example.scala:4:14 +-- [E042] Type Error: example.scala:4:14 --------------------------------------- 4 |val pet = new Animal | ^^^^^^ | Animal is a trait; it cannot be instantiated + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Abstract classes and traits need to be extended by a concrete class or object + | to make their functionality accessible. + | + | You may want to create an anonymous class extending Animal with + | class Animal { } + | + | or add a companion object with + | object Animal extends Animal + | + | You need to implement any abstract members in both cases. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Create an anonymous class implementing the trait trait Animal: def speak(): String val pet = new Animal: def speak(): String = "Woof!" -``` +``` -```scala sc:compile +```scala sc:compile // Or create a concrete class that extends the trait trait Animal: def speak(): String @@ -49,9 +62,9 @@ class Dog extends Animal: def speak(): String = "Woof!" val pet = new Dog -``` +``` -```scala sc:compile +```scala sc:compile // For abstract classes, same approach applies abstract class Animal: def speak(): String @@ -62,4 +75,3 @@ class Cat extends Animal: val pet = new Cat ``` - diff --git a/docs/_docs/reference/error-codes/E043.md b/docs/_docs/reference/error-codes/E043.md index c87dc4a1b247..3f0a0d92637e 100644 --- a/docs/_docs/reference/error-codes/E043.md +++ b/docs/_docs/reference/error-codes/E043.md @@ -2,7 +2,6 @@ title: E043: Unreducible Application kind: Error --- - # E043: Unreducible Application This error is emitted when an abstract type constructor (higher-kinded type) is applied to wildcard type arguments. @@ -13,7 +12,7 @@ Such applications are equivalent to existential types, which are not supported i ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait Container[F[_]]: def create: F[?] ``` @@ -21,31 +20,37 @@ trait Container[F[_]]: ### Error ```scala sc:nocompile --- [E043] Type Error: example.scala:2:13 +-- [E043] Type Error: example.scala:2:14 --------------------------------------- 2 | def create: F[?] | ^^^^ - | unreducible application of higher-kinded type F to wildcard arguments + | unreducible application of higher-kinded type F to wildcard arguments + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | An abstract type constructor cannot be applied to wildcard arguments. + | Such applications are equivalent to existential types, which are not + | supported in Scala 3. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a concrete type argument trait Container[F[_]]: def create[A]: F[A] -``` +``` -```scala sc:compile +```scala sc:compile // Or use a type member trait Container[F[_]]: type Element def create: F[Element] -``` +``` -```scala sc:compile +```scala sc:compile // Or make the type concrete in implementations trait Container[F[_]]: def create: F[Int] ``` - diff --git a/docs/_docs/reference/error-codes/E044.md b/docs/_docs/reference/error-codes/E044.md index 9d1855635dc0..03e720f68b37 100644 --- a/docs/_docs/reference/error-codes/E044.md +++ b/docs/_docs/reference/error-codes/E044.md @@ -2,7 +2,6 @@ title: E044: Overloaded Or Recursive Method Needs Result Type kind: Error --- - # E044: Overloaded Or Recursive Method Needs Result Type This error is emitted when an overloaded or recursive method is defined without an explicit return type. @@ -15,7 +14,7 @@ This error is emitted when an overloaded or recursive method is defined without ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain-cyclic def factorial(n: Int) = if n <= 1 then 1 else n * factorial(n - 1) @@ -24,22 +23,39 @@ def factorial(n: Int) = ### Error ```scala sc:nocompile --- [E044] Cyclic Error: example.scala:1:4 -1 |def factorial(n: Int) = - | ^^^^^^^^^ - | Overloaded or recursive method factorial needs return type +-- [E044] Cyclic Error: example.scala:3:11 ------------------------------------- +3 | else n * factorial(n - 1) + | ^ + |Overloaded or recursive method factorial needs return type + | + |The error occurred while trying to compute the signature of method factorial + | which required to type the right hand side of method factorial since no explicit type was given + | which required to compute the signature of method factorial + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Case 1: method factorial is overloaded + | If there are multiple methods named method factorial and at least one definition of + | it calls another, you need to specify the calling method's return type. + | + | Case 2: method factorial is recursive + | If method factorial calls itself on any path (even through mutual recursion), you need to specify the return type + | of method factorial or of a definition it's mutually recursive with. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add an explicit return type def factorial(n: Int): Int = if n <= 1 then 1 else n * factorial(n - 1) -``` +``` -```scala sc:compile +```scala sc:compile // For mutually recursive methods, at least one needs a return type def isEven(n: Int): Boolean = if n == 0 then true else isOdd(n - 1) @@ -48,4 +64,3 @@ def isOdd(n: Int): Boolean = if n == 0 then false else isEven(n - 1) ``` - diff --git a/docs/_docs/reference/error-codes/E045.md b/docs/_docs/reference/error-codes/E045.md index 988421ee9ffa..ef929bb0eb36 100644 --- a/docs/_docs/reference/error-codes/E045.md +++ b/docs/_docs/reference/error-codes/E045.md @@ -2,7 +2,6 @@ title: E045: Recursive Value Needs Result Type kind: Error --- - # E045: Recursive Value Needs Result Type This error is emitted when a recursive value definition doesn't have an explicit type annotation. @@ -13,23 +12,34 @@ When a value references itself in its definition (either directly or through laz ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain-cyclic lazy val ones = 1 #:: ones ``` ### Error ```scala sc:nocompile --- [E045] Cyclic Error: example.scala:2:4 +-- [E045] Cyclic Error: example.scala:1:22 ------------------------------------- 1 |lazy val ones = 1 #:: ones | ^ - | Recursive lazy value ones needs type + |Recursive lazy value ones needs type + | + |The error occurred while trying to compute the signature of lazy value ones + | which required to type the right hand side of lazy value ones since no explicit type was given + | which required to compute the signature of lazy value ones + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The definition of lazy value ones is recursive and you need to specify its type. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add an explicit type annotation lazy val ones: LazyList[Int] = 1 #:: ones -``` +``` diff --git a/docs/_docs/reference/error-codes/E046.md b/docs/_docs/reference/error-codes/E046.md index e2d8e2e320fe..b41e6b3d1aad 100644 --- a/docs/_docs/reference/error-codes/E046.md +++ b/docs/_docs/reference/error-codes/E046.md @@ -2,48 +2,56 @@ title: E046: Cyclic Reference Involving kind: Error --- - # E046: Cyclic Reference Involving This error is emitted when there is a cyclic reference in type definitions that makes it impossible for the compiler to determine the types involved. -A cyclic reference occurs when the definition of a type or value depends on itself, either directly or through a chain of other definitions. To resolve this, try giving the involved definitions explicit types. +A cyclic reference occurs when a type parameter references itself in its own bounds, creating a cycle that the compiler cannot resolve. --- ## Example -```scala sc:fail -class A extends B -class B extends A +```scala sc:fail sc-opts:-explain-cyclic +trait A: + type F[X <: F, Y] ``` ### Error +When compiled with `-explain-cyclic`, the compiler shows the dependency chain: + ```scala sc:nocompile --- [E046] Cyclic Error: example.scala:1:6 -1 |class A extends B - | ^ - | Cyclic reference involving class A +-- [E046] Cyclic Error: example.scala:2:14 ------------------------------------- +2 | type F[X <: F, Y] + | ^ + |Cyclic reference involving type F + | + |The error occurred while trying to compute the signature of type F + | which required to compute the signature of type X + | which required to compute the signature of type F + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | type F is declared as part of a cycle which makes it impossible for the + | compiler to decide upon F's type. + | To avoid this error, try giving F an explicit type. + ----------------------------------------------------------------------------- ``` -### Solution - -```scala sc:compile -// Break the cycle by using a common parent -trait Common +### Solution -class A extends Common -class B extends Common -``` - -```scala sc:compile -// Or use composition instead of inheritance -class A: - var b: B = null - -class B: - var a: A = null +```scala sc:compile +// Use a different bound that doesn't reference itself +trait A: + type F[X, Y] ``` +```scala sc:compile +// Or use an upper bound that is well-defined +trait A: + type F[X <: Any, Y] +``` diff --git a/docs/_docs/reference/error-codes/E047.md b/docs/_docs/reference/error-codes/E047.md index c4f9fcabd3bf..ef2587625487 100644 --- a/docs/_docs/reference/error-codes/E047.md +++ b/docs/_docs/reference/error-codes/E047.md @@ -2,41 +2,18 @@ title: E047: Cyclic Reference Involving Implicit kind: Error --- - # E047: Cyclic Reference Involving Implicit -This error is emitted when there is a cyclic reference involving an implicit (or given) definition. - -This typically happens when the right-hand side of an implicit definition involves an implicit search that depends on the definition being defined. To avoid this error, give the implicit definition an explicit type. - ---- - -## Example - -```scala sc:fail -given a: Int = summon[Int] + 1 -``` - -### Error - -```scala sc:nocompile --- [E047] Cyclic Error: example.scala:1:6 -1 |given a: Int = summon[Int] + 1 - | ^ - | Cyclic reference involving given a -``` +This error is emitted when the compiler detects a cyclic reference involving an implicit value. -### Solution +The compiler message states: **"Cyclic reference involving implicit \"** -```scala sc:compile -// Provide a concrete value instead of relying on implicit search -given a: Int = 42 -``` +The symbol in question is declared as part of a cycle which makes it impossible for the compiler to decide upon its type. This might happen when the right-hand side of the symbol's definition involves an implicit search that depends on the type being inferred. -```scala sc:compile -// Or define separate givens if you need layered implicits -given base: Int = 1 -given derived(using b: Int): Int = b + 1 -``` +To avoid this error, try giving the symbol an explicit type annotation. +This error is related to `CyclicReferenceInvolving` (E046) but specifically targets cases where the cycle involves implicit values. It is triggered in `TypeErrors.scala` when: +- The symbol is a given or implicit val (but not a method) +- The symbol's owner is a term (local scope) +**Note:** This error code is active in the compiler but requires specific implicit resolution cycles that are difficult to reproduce with simple source code examples. The error typically occurs in complex implicit resolution scenarios where type inference creates circular dependencies. diff --git a/docs/_docs/reference/error-codes/E048.md b/docs/_docs/reference/error-codes/E048.md index b40c4b32516d..9ebe960c3c5c 100644 --- a/docs/_docs/reference/error-codes/E048.md +++ b/docs/_docs/reference/error-codes/E048.md @@ -2,7 +2,6 @@ title: E048: Super Qualifier Must Be Parent kind: Error --- - # E048: Super Qualifier Must Be Parent This error is emitted when a qualifier used in a `super` prefix does not name a parent type of the class. @@ -13,7 +12,7 @@ When a qualifier `T` is used in a `super` prefix of the form `C.super[T]`, `T` m ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait A: def greet: String = "A" @@ -27,15 +26,26 @@ class C extends A, B: ### Error ```scala sc:nocompile --- [E048] Reference Error: example.scala:8:37 +-- [E048] Reference Error: example.scala:8:31 ---------------------------------- 8 | override def greet: String = super[String].greet - | ^^^^^^ - | String does not name a parent of class C + | ^^^^^^^^^^^^^ + | String does not name a parent of class C + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | When a qualifier T is used in a super prefix of the form C.super[T], + | T must be a parent type of C. + | + | In this case, the parents of class C are: + | - A + | - B + | - Object + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use an actual parent type in the super qualifier trait A: def greet: String = "A" @@ -45,9 +55,9 @@ trait B: class C extends A, B: override def greet: String = super[A].greet -``` +``` -```scala sc:compile +```scala sc:compile // Or call a specific parent's method trait A: def greet: String = "A" @@ -59,4 +69,3 @@ class C extends A, B: override def greet: String = super[B].greet ``` - diff --git a/docs/_docs/reference/error-codes/E049.md b/docs/_docs/reference/error-codes/E049.md index 9a65dc50ffc8..2c5b9be11c4a 100644 --- a/docs/_docs/reference/error-codes/E049.md +++ b/docs/_docs/reference/error-codes/E049.md @@ -2,7 +2,6 @@ title: E049: Ambiguous Reference kind: Error --- - # E049: Ambiguous Reference This error is emitted when an identifier could refer to multiple different definitions and the compiler cannot determine which one to use. @@ -20,7 +19,7 @@ Note that definitions take precedence over imports, and a binding in an inner sc ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain import scala.collection.immutable.Seq import scala.collection.mutable.Seq @@ -30,37 +29,55 @@ val items = Seq(1, 2, 3) ### Error ```scala sc:nocompile --- [E049] Reference Error: example.scala:4:12 +-- [E049] Reference Error: example.scala:4:12 ---------------------------------- 4 |val items = Seq(1, 2, 3) | ^^^ | Reference to Seq is ambiguous. | It is both imported by name by import scala.collection.immutable.Seq | and imported by name subsequently by import scala.collection.mutable.Seq + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The identifier Seq is ambiguous because two name bindings of equal precedence + | were introduced in the same scope. + | + | The precedence of the different kinds of name bindings, from highest to lowest, is: + | - Definitions in an enclosing scope + | - Inherited definitions and top-level definitions in packages + | - Names introduced by import of a specific name + | - Names introduced by wildcard import + | - Definitions from packages in other files + | Note: + | - As a rule, definitions take precedence over imports. + | - Definitions in an enclosing scope take precedence over inherited definitions, + | which can result in ambiguities in nested classes. + | - When importing, you can avoid naming conflicts by renaming: + | import scala.{Seq => SeqTick} + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a rename to avoid the conflict import scala.collection.immutable.Seq import scala.collection.mutable.{Seq as MutableSeq} val items = Seq(1, 2, 3) val mutableItems = MutableSeq(1, 2, 3) -``` +``` -```scala sc:compile +```scala sc:compile import scala.collection.{immutable, mutable} // Or use qualified names val items = immutable.Seq(1, 2, 3) val mutableItems = mutable.Seq(1, 2, 3) -``` +``` -```scala sc:compile +```scala sc:compile // Or import only what you need import scala.collection.immutable.Seq val items = Seq(1, 2, 3) ``` - diff --git a/docs/_docs/reference/error-codes/E050.md b/docs/_docs/reference/error-codes/E050.md index d9d4c1b8c7a2..692865ceec64 100644 --- a/docs/_docs/reference/error-codes/E050.md +++ b/docs/_docs/reference/error-codes/E050.md @@ -2,7 +2,6 @@ title: E050: Method Does Not Take Parameters kind: Error --- - # E050: Method Does Not Take Parameters This error is emitted when you try to pass arguments to a method or expression that doesn't accept parameters. @@ -16,42 +15,42 @@ This can happen when: ## Example -```scala sc:fail -def greet: String = "Hello" - -val message = greet("World") +```scala sc:fail sc-opts:-explain +object Hello +val message = Hello("World") ``` ### Error ```scala sc:nocompile --- [E050] Type Error: example.scala:3:14 -3 |val message = greet("World") - | ^^^^^^^^^^^^^^ - | method greet does not take parameters +-- [E050] Type Error: example.scala:2:14 --------------------------------------- +2 |val message = Hello("World") + | ^^^^^ + | object Hello does not take parameters + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | You have specified more parameter lists than defined in the method definition(s). + ----------------------------------------------------------------------------- ``` -### Solution - -```scala sc:compile -// Add a parameter to the method definition -def greet(name: String): String = s"Hello, $name" +### Solution -val message = greet("World") -``` - -```scala sc:compile -// Or call the method without arguments -def greet: String = "Hello" +```scala sc:compile +// Enusre that method you want to call exists, especially if it involved Scala syntax desugaring +object Hello: + def apply(value: String) = ??? +val message = Hello("World") +``` -val message = greet -``` +```scala sc:compile +// Enusre that that method actually takes arguments list +class Bag extends scala.reflect.Selectable -```scala sc:compile -// Or use string interpolation if you want to combine -def greet: String = "Hello" +def example = + val bag = new Bag: + val f1 = 23 -val message = s"$greet, World" + val x = bag.f1 // instead of bag.f1() ``` - diff --git a/docs/_docs/reference/error-codes/E051.md b/docs/_docs/reference/error-codes/E051.md index 0a2afa4b43fa..6abb10602f96 100644 --- a/docs/_docs/reference/error-codes/E051.md +++ b/docs/_docs/reference/error-codes/E051.md @@ -2,7 +2,6 @@ title: E051: Ambiguous Overload kind: Error --- - # E051: Ambiguous Overload This error is emitted when there are multiple overloaded methods that match the given arguments and the compiler cannot determine which one to call. @@ -15,42 +14,53 @@ There are multiple methods that could be referenced because the compiler knows t ## Example -```scala sc:fail -def process(x: Int): String = x.toString -def process(x: Long): String = x.toString +```scala sc:fail sc-opts:-explain +object Render: + extension [A](a: A) def render: String = "Hi" + extension [B](b: B) def render(using DummyImplicit): Char = 'x' -val result = process(1: Int | Long) +def example = Render.render(42) ``` ### Error ```scala sc:nocompile --- [E051] Reference Error: example.scala:4:13 -4 |val result = process(1: Int | Long) - | ^^^^^^^ - | Ambiguous overload. The overloaded alternatives of method process with types - | (x: Long): String - | (x: Int): String - | both match arguments ((1 : Int | Long)) +-- [E051] Reference Error: example.scala:5:21 ---------------------------------- +5 |def example = Render.render(42) + | ^^^^^^^^^^^^^ + |Ambiguous overload. The overloaded alternatives of method render in object Render with types + | [B](b: B)(using x$2: DummyImplicit): Char + | [A](a: A): String + |both match arguments ((42 : Int)) + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | There are 2 methods that could be referenced as the compiler knows too little + | about the expected type. + | You may specify the expected type e.g. by + | - assigning it to a value with a specified type, or + | - adding a type ascription as in instance.myMethod: String => Int + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile -// Specify the exact type of the argument -def process(x: Int): String = x.toString -def process(x: Long): String = x.toString +```scala sc:compile +// Hint compiler using explicit argument or result type +object Render: + extension [A](a: A) def render: String = "Hi" + extension [B](b: B) def render(using DummyImplicit): Char = 'x' -val result = process(1: Int) -``` +def example: String = Render.render(42) +``` -```scala sc:compile -// Or assign to a variable with a specific type first -def process(x: Int): String = x.toString -def process(x: Long): String = x.toString +```scala sc:compile +// Or try to remove methods that might lead to amibgious results +import scala.annotation.targetName +object Render: + extension [A](a: A) def render: String = "Hi" + extension [B](b: B) @targetName("render") def renderChar(using DummyImplicit): Char = 'x' -val n: Int = 1 -val result = process(n) +def example = Render.render(42) ``` - diff --git a/docs/_docs/reference/error-codes/E052.md b/docs/_docs/reference/error-codes/E052.md index 58f294709b2c..8ef890cd72d3 100644 --- a/docs/_docs/reference/error-codes/E052.md +++ b/docs/_docs/reference/error-codes/E052.md @@ -2,7 +2,6 @@ title: E052: Reassignment To Val kind: Error --- - # E052: Reassignment To Val This error is emitted when attempting to reassign a value to an immutable variable declared with `val`. @@ -15,38 +14,47 @@ If you're seeing this error in a boolean context, you may have accidentally used ## Example -```scala sc:fail -val x = 1 -x = 2 +```scala sc:fail sc-opts:-explain +def example = + val x = 1 + x = 2 ``` ### Error ```scala sc:nocompile --- [E052] Type Error: example.scala:2:0 -2 |x = 2 - |^^^^^ - |Reassignment to val x +-- [E052] Type Error: example.scala:3:4 ---------------------------------------- +3 | x = 2 + | ^^^^^ + | Reassignment to val x + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | You can not assign a new value to x as values can't be changed. + | Reassigment is only permitted if the variable is declared with `var`. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use var if you need to reassign -var x = 1 -x = 2 -``` +def example = + var x = 1 + x = 2 +``` -```scala sc:compile +```scala sc:compile // Or use a new val with a different name -val x = 1 -val y = 2 -``` +def example = + val x = 1 + val y = 2 +``` -```scala sc:compile +```scala sc:compile // If you meant to compare values, use == -val x = 1 -val isTwo = x == 2 +def example = + val x = 1 + val isTwo = x == 2 ``` - diff --git a/docs/_docs/reference/error-codes/E053.md b/docs/_docs/reference/error-codes/E053.md index 6630df238280..5cfe4e3b4d1d 100644 --- a/docs/_docs/reference/error-codes/E053.md +++ b/docs/_docs/reference/error-codes/E053.md @@ -2,7 +2,6 @@ title: E053: Type Does Not Take Parameters kind: Error --- - # E053: Type Does Not Take Parameters This error is emitted when type parameters are provided to a type that doesn't accept any type parameters. @@ -16,35 +15,40 @@ You specified type parameters for a type that is not declared to take any. This ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val x: Int[String] = 42 ``` ### Error ```scala sc:nocompile --- [E053] Type Error: example.scala:1:7 +-- [E053] Type Error: example.scala:1:7 ---------------------------------------- 1 |val x: Int[String] = 42 | ^^^^^^^^^^^ | Int does not take type parameters + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | You specified a type parameter Ident(String) for Int, which is not + | declared to take any. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove the type parameters from non-generic types val x: Int = 42 -``` +``` -```scala sc:compile +```scala sc:compile // Use a type that does accept parameters val x: List[Int] = List(42) -``` +``` -```scala sc:compile +```scala sc:compile // Or define your own generic type class Box[T](value: T) val x: Box[Int] = Box(42) ``` - diff --git a/docs/_docs/reference/error-codes/E054.md b/docs/_docs/reference/error-codes/E054.md new file mode 100644 index 000000000000..0863046b382b --- /dev/null +++ b/docs/_docs/reference/error-codes/E054.md @@ -0,0 +1,46 @@ +--- +title: "E054: Parameterized Type Lacks Arguments" +kind: Error +until: 3.2.2 +--- +# E054: Parameterized Type Lacks Arguments + +**Note** This error was replaced in Scala 3.2.2 by a more specific error message [E171: Missing Argument](./E171.md). + +Error was triggered when extending a parameterized type without providing the required constructor arguments. + +## Example + +```scala sc:nocompile +trait Foo(x: Int) + +val foo = new Foo {} +``` + +### Error + +```scala sc:nocompile +-- [E054] Type Error: example.scala:3:14 --------------------------------------- +3 |val foo = new Foo {} + | ^^^ + | Parameterized trait Foo lacks argument list + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The trait Foo is declared with non-implicit parameters, you may not leave + | out the parameter list when extending it. + ----------------------------------------------------------------------------- +``` + +## Explanation + +When a class or trait declares constructor parameters, you must provide values for those parameters when extending it. The error occurred because `Foo` requires an `Int` argument but none was provided. + +The fix was to provide the required arguments: + +```scala sc:nocompile +trait Foo(x: Int) + +val foo = new Foo(42) {} +``` + diff --git a/docs/_docs/reference/error-codes/E055.md b/docs/_docs/reference/error-codes/E055.md index d9a99012d476..5c400180e3b5 100644 --- a/docs/_docs/reference/error-codes/E055.md +++ b/docs/_docs/reference/error-codes/E055.md @@ -2,7 +2,6 @@ title: E055: Var Val Parameters May Not Be Call By Name kind: Error --- - # E055: Var Val Parameters May Not Be Call By Name This error is emitted when a `val` or `var` parameter of a class or trait is declared as call-by-name (using `=> T` syntax). @@ -13,36 +12,45 @@ This error is emitted when a `val` or `var` parameter of a class or trait is dec ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class LazyHolder(val value: => Int) ``` ### Error ```scala sc:nocompile --- [E055] Syntax Error: example.scala:1:18 +-- [E055] Syntax Error: example.scala:1:28 ------------------------------------- 1 |class LazyHolder(val value: => Int) - | ^^^^^^^^^^ - | val parameters may not be call-by-name + | ^^ + | val parameters may not be call-by-name + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | var and val parameters of classes and traits may no be call-by-name. In case you + | want the parameter to be evaluated on demand, consider making it just a parameter + | and a def in the class such as + | class MyClass(valueTick: => String) { + | def value() = valueTick + | } + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a regular parameter and a lazy val class LazyHolder(valueInit: => Int): lazy val value: Int = valueInit -``` +``` -```scala sc:compile +```scala sc:compile // Or use a function type class LazyHolder(getValue: () => Int): def value: Int = getValue() -``` +``` -```scala sc:compile +```scala sc:compile // Or simply use a regular val parameter class LazyHolder(val value: Int) ``` - diff --git a/docs/_docs/reference/error-codes/E056.md b/docs/_docs/reference/error-codes/E056.md index 3082f37358c9..98df7b2f8e11 100644 --- a/docs/_docs/reference/error-codes/E056.md +++ b/docs/_docs/reference/error-codes/E056.md @@ -2,7 +2,6 @@ title: E056: Missing Type Parameter For kind: Error --- - # E056: Missing Type Parameter For This error is emitted when a higher-kinded type or type constructor is used where a fully applied type is expected. @@ -13,29 +12,28 @@ A type constructor (like `List` or `Option`) needs to be applied to type argumen ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val items: List = List(1, 2, 3) ``` ### Error ```scala sc:nocompile --- [E056] Syntax Error: example.scala:1:11 +-- [E056] Syntax Error: example.scala:1:11 ------------------------------------- 1 |val items: List = List(1, 2, 3) | ^^^^ | Missing type parameter for List ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Provide the type parameter val items: List[Int] = List(1, 2, 3) -``` +``` -```scala sc:compile +```scala sc:compile // Or let the compiler infer the type val items = List(1, 2, 3) ``` - diff --git a/docs/_docs/reference/error-codes/E057.md b/docs/_docs/reference/error-codes/E057.md index 925734c616da..0b23c007a95b 100644 --- a/docs/_docs/reference/error-codes/E057.md +++ b/docs/_docs/reference/error-codes/E057.md @@ -2,7 +2,6 @@ title: E057: Does Not Conform To Bound kind: Error --- - # E057: Does Not Conform To Bound This error is emitted when a type argument does not conform to the declared type bounds of a type parameter. @@ -13,35 +12,67 @@ Type parameters can have upper bounds (`<:`) and lower bounds (`>:`). When you p ## Example -```scala sc:fail -def process[T <: Number](value: T): T = value +```scala sc:fail sc-opts:-explain +trait A +trait B extends A +trait C extends B +class Contra[-T >: B] -val result = process("hello") +def example = + val a: Contra[A] = ??? + val b: Contra[B] = ??? + val c: Contra[C] = ??? ``` ### Error ```scala sc:nocompile --- [E057] Type Error: example.scala:3:21 -3 |val result = process("hello") - | ^^^^^^^ - | Type argument String does not conform to upper bound Number +-- [E057] Type Mismatch Error: example.scala:9:18 ------------------------------ +9 | val c: Contra[C] = ??? + | ^ + | Type argument C does not conform to lower bound B + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | I tried to show that + | B + | conforms to + | C + | but none of the attempts shown below succeeded: + | + | ==> B <: C = false + | + | The tests were made under the empty constraint + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile -// Use a type that conforms to the bound -def process[T <: Number](value: T): T = value +```scala sc:compile +// Use a types that conforms to the bound +trait A +trait B extends A +trait C extends A -val result = process(Integer.valueOf(42)) -``` +class Contra[-T >: B] -```scala sc:compile -// Or change the type bound if appropriate -def process[T](value: T): T = value +def example = + val a: Contra[A] = ??? + val b: Contra[B] = ??? -val result = process("hello") ``` +```scala sc:compile +// Or change the type bound if appropriate +trait A +trait B extends A +trait C extends B + +class Contra[-T >: C] + +def example = + val a: Contra[A] = ??? + val b: Contra[B] = ??? + val c: Contra[C] = ??? +``` diff --git a/docs/_docs/reference/error-codes/E058.md b/docs/_docs/reference/error-codes/E058.md index edea0848ee3e..6e2f08435f22 100644 --- a/docs/_docs/reference/error-codes/E058.md +++ b/docs/_docs/reference/error-codes/E058.md @@ -2,7 +2,6 @@ title: E058: Does Not Conform To Self Type kind: Error --- - # E058: Does Not Conform To Self Type This error is emitted when a class's self type does not conform to the self type of a trait it extends. @@ -13,7 +12,7 @@ A self type annotation (like `self: SomeType =>`) declares that any concrete cla ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait HasLogger: self: Logger => def log(msg: String): Unit @@ -28,16 +27,29 @@ class MyClass extends HasLogger: ### Error ```scala sc:nocompile --- [E058] Type Error: example.scala:8:6 +-- [E058] Type Mismatch Error: example.scala:8:6 ------------------------------- 8 |class MyClass extends HasLogger: | ^ - | illegal inheritance: self type MyClass of class MyClass does not conform to - | self type Logger of parent trait HasLogger + |illegal inheritance: self type MyClass of class MyClass does not conform to self type Logger + |of parent trait HasLogger + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | I tried to show that + | MyClass + | conforms to + | Logger + | but none of the attempts shown below succeeded: + | + | ==> MyClass <: Logger = false + | + | The tests were made under the empty constraint + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Mix in the required trait trait HasLogger: self: Logger => @@ -49,9 +61,9 @@ trait Logger: class MyClass extends HasLogger with Logger: def log(msg: String): Unit = println(msg) def write(msg: String): Unit = println(msg) -``` +``` -```scala sc:compile +```scala sc:compile // Or add a matching self type to the extending class trait HasLogger: self: Logger => @@ -65,4 +77,3 @@ abstract class MyClass extends HasLogger: def log(msg: String): Unit = println(msg) ``` - diff --git a/docs/_docs/reference/error-codes/E059.md b/docs/_docs/reference/error-codes/E059.md index ccae0ad65136..31827676c847 100644 --- a/docs/_docs/reference/error-codes/E059.md +++ b/docs/_docs/reference/error-codes/E059.md @@ -2,7 +2,6 @@ title: E059: Does Not Conform To Self Type Cannot Be Instantiated kind: Error --- - # E059: Does Not Conform To Self Type Cannot Be Instantiated This error is emitted when attempting to instantiate a class that has a self type which the class itself doesn't satisfy. @@ -13,7 +12,7 @@ When a class declares a self type, it promises that any instance will conform to ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait Database: def query(sql: String): String @@ -27,15 +26,28 @@ val repo = new Repository ### Error ```scala sc:nocompile --- [E059] Type Error: example.scala:8:15 +-- [E059] Type Mismatch Error: example.scala:8:15 ------------------------------ 8 |val repo = new Repository | ^^^^^^^^^^ - | Repository does not conform to its self type Database; cannot be instantiated + |Repository does not conform to its self type Database; cannot be instantiated + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | I tried to show that + | Repository + | conforms to + | Database + | but none of the attempts shown below succeeded: + | + | ==> Repository <: Database = false + | + | The tests were made under the empty constraint + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Implement the required self type when instantiating trait Database: def query(sql: String): String @@ -46,9 +58,9 @@ class Repository: val repo = new Repository with Database: def query(sql: String): String = s"Executed: $sql" -``` +``` -```scala sc:compile +```scala sc:compile // Or create a concrete class that mixes in the required trait trait Database: def query(sql: String): String @@ -63,4 +75,3 @@ class SqlRepository extends Repository with Database: val repo = new SqlRepository ``` - diff --git a/docs/_docs/reference/error-codes/E060.md b/docs/_docs/reference/error-codes/E060.md index 9d570431654a..c2755f31f0bb 100644 --- a/docs/_docs/reference/error-codes/E060.md +++ b/docs/_docs/reference/error-codes/E060.md @@ -2,7 +2,6 @@ title: E060: Abstract Member May Not Have Modifier kind: Error --- - # E060: Abstract Member May Not Have Modifier This error is emitted when an abstract member is declared with a modifier that is incompatible with being abstract, such as `final` or `private`. @@ -13,7 +12,7 @@ Abstract members are meant to be implemented by subclasses, so they cannot be `f ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait Example: final def abstractMethod: Int ``` @@ -21,24 +20,23 @@ trait Example: ### Error ```scala sc:nocompile --- [E060] Syntax Error: example.scala:2:12 +-- [E060] Syntax Error: example.scala:2:12 ------------------------------------- 2 | final def abstractMethod: Int | ^ | abstract method abstractMethod may not have `final` modifier ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove the incompatible modifier trait Example: def abstractMethod: Int -``` +``` -```scala sc:compile +```scala sc:compile // Or provide an implementation if you want final trait Example: final def concreteMethod: Int = 42 ``` - diff --git a/docs/_docs/reference/error-codes/E061.md b/docs/_docs/reference/error-codes/E061.md new file mode 100644 index 000000000000..85236b9860e0 --- /dev/null +++ b/docs/_docs/reference/error-codes/E061.md @@ -0,0 +1,40 @@ +--- +title: "E061: Top Level Can't Be Implicit" +kind: Error +until: 3.0.0 +--- + +This error was made inactive in Scala 3.0.0 because top-level implicits are now allowed. + +This error was triggered when attempting to define an implicit value or method at the top level of a source file. + +## Example + +```scala sc:nocompile +package example +implicit val x: Int = 42 // error in old versions +``` + +### Error + +```scala sc:nocompile +-- [E061] Syntax Error: example.scala:2:0 -------------------------------------- +2 |implicit val x: Int = 42 + |^ + |`implicit` modifier cannot be used for top-level definitions +``` + +## Explanation + +In earlier versions of Scala 3, implicit definitions were required to be inside a class, object, or trait. This restriction was removed. + +Since Scala 3.0.0 (specifically after PR #5754), top-level implicits are allowed and work correctly: + +```scala sc:compile +// This now works in Scala 3 +implicit val x: Int = 42 + +// Or using the modern given syntax +given Int = 42 +``` + diff --git a/docs/_docs/reference/error-codes/E062.md b/docs/_docs/reference/error-codes/E062.md index 75e81b401de9..7163868f0f0e 100644 --- a/docs/_docs/reference/error-codes/E062.md +++ b/docs/_docs/reference/error-codes/E062.md @@ -2,7 +2,6 @@ title: E062: Types And Traits Cannot Be Implicit kind: Error --- - # E062: Types And Traits Cannot Be Implicit This error is emitted when the `implicit` modifier is used on a type alias or trait definition. @@ -13,30 +12,30 @@ The `implicit` modifier can only be used on values, methods, and classes (for im ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain implicit trait MyTrait ``` ### Error ```scala sc:nocompile --- [E062] Syntax Error: example.scala:1:0 +-- [E062] Syntax Error: example.scala:1:15 ------------------------------------- 1 |implicit trait MyTrait - |^^^^^^^^ + |^^^^^^^^^^^^^^^^^^^^^^ |implicit modifier cannot be used for types or traits ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove implicit from trait definitions trait MyTrait // Use given instances instead given myInstance: MyTrait = new MyTrait {} -``` +``` -```scala sc:compile +```scala sc:compile // For implicit conversions, use a given Conversion trait Target class Source @@ -44,4 +43,3 @@ class Source given Conversion[Source, Target] = (s: Source) => new Target {} ``` - diff --git a/docs/_docs/reference/error-codes/E063.md b/docs/_docs/reference/error-codes/E063.md index 3319aecb32f2..1a033c364d77 100644 --- a/docs/_docs/reference/error-codes/E063.md +++ b/docs/_docs/reference/error-codes/E063.md @@ -2,7 +2,6 @@ title: E063: Only Classes Can Be Abstract kind: Error --- - # E063: Only Classes Can Be Abstract This error is emitted when the `abstract` modifier is used on something other than a class, such as a method or value. @@ -13,7 +12,7 @@ The `abstract` modifier can only be used for classes. For abstract members (meth ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait Example: abstract def method: Int ``` @@ -21,25 +20,24 @@ trait Example: ### Error ```scala sc:nocompile --- [E063] Syntax Error: example.scala:2:2 +-- [E063] Syntax Error: example.scala:2:15 ------------------------------------- 2 | abstract def method: Int - | ^^^^^^^^ - | abstract modifier can be used only for classes; it should be omitted for abstract members + | ^ + |abstract modifier can be used only for classes; it should be omitted for abstract members ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Simply omit abstract for member declarations trait Example: def method: Int -``` +``` -```scala sc:compile +```scala sc:compile // Use abstract only for class definitions abstract class Example: def method: Int def concreteMethod: Int = 42 ``` - diff --git a/docs/_docs/reference/error-codes/E064.md b/docs/_docs/reference/error-codes/E064.md index 7591d3806dba..6727f7848db8 100644 --- a/docs/_docs/reference/error-codes/E064.md +++ b/docs/_docs/reference/error-codes/E064.md @@ -2,7 +2,6 @@ title: E064: Abstract Override Only In Traits kind: Error --- - # E064: Abstract Override Only In Traits This error is emitted when `abstract override` is used on a member outside of a trait. @@ -13,7 +12,7 @@ The `abstract override` modifier is only allowed for members of traits. It indic ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Base: def greet: String = "Hello" @@ -24,15 +23,15 @@ class Child extends Base: ### Error ```scala sc:nocompile --- [E064] Syntax Error: example.scala:5:2 +-- [E064] Syntax Error: example.scala:5:24 ------------------------------------- 5 | abstract override def greet: String = super.greet + "!" - | ^^^^^^^^^^^^^^^^^ - | abstract override modifier only allowed for members of traits + | ^ + | abstract override modifier only allowed for members of traits ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use abstract override in a trait class Base: def greet: String = "Hello" @@ -41,9 +40,9 @@ trait Greeter extends Base: abstract override def greet: String = super.greet + "!" class Child extends Base with Greeter -``` +``` -```scala sc:compile +```scala sc:compile // Or use a regular override in a class class Base: def greet: String = "Hello" @@ -52,4 +51,3 @@ class Child extends Base: override def greet: String = super.greet + "!" ``` - diff --git a/docs/_docs/reference/error-codes/E065.md b/docs/_docs/reference/error-codes/E065.md index 51fe9b40d833..8ba07a6e6afc 100644 --- a/docs/_docs/reference/error-codes/E065.md +++ b/docs/_docs/reference/error-codes/E065.md @@ -2,7 +2,6 @@ title: E065: Traits May Not Be Final kind: Error --- - # E065: Traits May Not Be Final This error is emitted when a trait is declared with the `final` modifier. @@ -13,37 +12,41 @@ A trait can never be final since it is abstract by nature and must be extended o ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain final trait MyTrait ``` ### Error ```scala sc:nocompile --- [E065] Syntax Error: example.scala:1:12 +-- [E065] Syntax Error: example.scala:1:12 ------------------------------------- 1 |final trait MyTrait - | ^^^^^^^ + | ^ | trait MyTrait may not be final + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A trait can never be final since it is abstract and must be extended to be useful. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove final from trait definitions trait MyTrait: def method: Int -``` +``` -```scala sc:compile +```scala sc:compile // If you want a final implementation, use a final class final class MyFinalClass: def method: Int = 42 -``` +``` -```scala sc:compile +```scala sc:compile // Or use a sealed trait if you want to restrict implementations sealed trait MyTrait final class Implementation extends MyTrait ``` - diff --git a/docs/_docs/reference/error-codes/E066.md b/docs/_docs/reference/error-codes/E066.md index e23d01dcab66..dd5e0a701b4f 100644 --- a/docs/_docs/reference/error-codes/E066.md +++ b/docs/_docs/reference/error-codes/E066.md @@ -2,7 +2,6 @@ title: E066: Native Members May Not Have Implementation kind: Error --- - # E066: Native Members May Not Have Implementation This error is emitted when a method marked with `@native` annotation has an implementation body. @@ -13,7 +12,7 @@ The `@native` annotation indicates that the method's implementation is provided ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Example: @native def nativeMethod(): Int = 42 ``` @@ -21,24 +20,23 @@ class Example: ### Error ```scala sc:nocompile --- [E066] Syntax Error: example.scala:4:14 -4 | @native def nativeMethod(): Int = 42 - | ^^^^^^^^^^^^ +-- [E066] Syntax Error: example.scala:2:14 ------------------------------------- +2 | @native def nativeMethod(): Int = 42 + | ^ | @native members may not have an implementation ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove the implementation from native methods class Example: @native def nativeMethod(): Int -``` +``` -```scala sc:compile +```scala sc:compile // Or remove @native if you want to provide an implementation class Example: def normalMethod(): Int = 42 ``` - diff --git a/docs/_docs/reference/error-codes/E067.md b/docs/_docs/reference/error-codes/E067.md index 82ea024678b3..b94a535f7c81 100644 --- a/docs/_docs/reference/error-codes/E067.md +++ b/docs/_docs/reference/error-codes/E067.md @@ -2,7 +2,6 @@ title: E067: Only Classes Can Have Declared But Undefined Members kind: Error --- - # E067: Only Classes Can Have Declared But Undefined Members This error is emitted when an abstract member (a declaration without implementation) appears outside of a class or trait context, such as in an object. @@ -13,7 +12,7 @@ Only classes and traits can have abstract members. Objects, being concrete singl ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain object Example: def abstractMethod: Int ``` @@ -21,21 +20,21 @@ object Example: ### Error ```scala sc:nocompile --- [E067] Syntax Error: example.scala:2:6 +-- [E067] Syntax Error: example.scala:2:6 -------------------------------------- 2 | def abstractMethod: Int - | ^^^^^^^^^^^^^^ - | Declaration of method abstractMethod not allowed here: only classes can have declared but undefined members + | ^ + |Declaration of method abstractMethod not allowed here: only classes can have declared but undefined members ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Provide an implementation in objects object Example: def concreteMethod: Int = 42 -``` +``` -```scala sc:compile +```scala sc:compile // Or use a trait or abstract class for abstract members trait Example: def abstractMethod: Int @@ -44,4 +43,3 @@ object ConcreteExample extends Example: def abstractMethod: Int = 42 ``` - diff --git a/docs/_docs/reference/error-codes/E068.md b/docs/_docs/reference/error-codes/E068.md index b9de63f8a13e..51c97fb16747 100644 --- a/docs/_docs/reference/error-codes/E068.md +++ b/docs/_docs/reference/error-codes/E068.md @@ -2,7 +2,6 @@ title: E068: Cannot Extend AnyVal kind: Error --- - # E068: Cannot Extend AnyVal This error is emitted when a trait or object attempts to extend `AnyVal`. @@ -13,27 +12,34 @@ Only classes can extend `AnyVal` to become value classes. Traits may extend `Any ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain trait MyValueTrait extends AnyVal ``` ### Error ```scala sc:nocompile --- [E068] Syntax Error: example.scala:1:6 +-- [E068] Syntax Error: example.scala:1:6 -------------------------------------- 1 |trait MyValueTrait extends AnyVal - | ^^^^^^^^^^^^^^ + | ^ | trait MyValueTrait cannot extend AnyVal + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Only classes (not traits) are allowed to extend AnyVal, but traits may extend + | Any to become "universal traits" which may only have def members. + | Universal traits can be mixed into classes that extend AnyVal. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a class for value classes class MyValueClass(val value: Int) extends AnyVal -``` +``` -```scala sc:compile +```scala sc:compile // For traits, extend Any to create a universal trait trait MyUniversalTrait extends Any: def method: Int @@ -42,4 +48,3 @@ class MyValueClass(val value: Int) extends AnyVal with MyUniversalTrait: def method: Int = value ``` - diff --git a/docs/_docs/reference/error-codes/E069.md b/docs/_docs/reference/error-codes/E069.md index d1397db5a354..f97cb7489c19 100644 --- a/docs/_docs/reference/error-codes/E069.md +++ b/docs/_docs/reference/error-codes/E069.md @@ -2,7 +2,6 @@ title: E069: Cannot Have Same Name As kind: Error --- - # E069: Cannot Have Same Name As This error is emitted when a member has the same name as another definition in a way that creates an illegal conflict. @@ -15,7 +14,7 @@ This typically happens when: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Outer: class Inner @@ -26,15 +25,15 @@ class Child extends Outer: ### Error ```scala sc:nocompile --- [E069] Naming Error: example.scala:5:17 +-- [E069] Naming Error: example.scala:5:17 ------------------------------------- 5 | override class Inner - | ^^^^^ - | class Inner cannot have the same name as class Inner in class Outer -- class definitions cannot be overridden + | ^ + |class Inner cannot have the same name as class Inner in class Outer -- class definitions cannot be overridden ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use an abstract type member with optional interface abstract class Outer: trait Interface @@ -42,4 +41,5 @@ abstract class Outer: class Child extends Outer: class Inner extends Interface -``` +``` + diff --git a/docs/_docs/reference/error-codes/E070.md b/docs/_docs/reference/error-codes/E070.md index 680f1f8a894a..76006965ea4f 100644 --- a/docs/_docs/reference/error-codes/E070.md +++ b/docs/_docs/reference/error-codes/E070.md @@ -2,7 +2,6 @@ title: E070: Value Classes May Not Define Inner Class kind: Error --- - # E070: Value Classes May Not Define Inner Class This error is emitted when a value class (a class extending `AnyVal`) contains an inner class definition. @@ -13,7 +12,7 @@ Value classes have strict limitations to ensure they can be optimized by the com ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Wrapper(val value: Int) extends AnyVal: class Inner ``` @@ -21,26 +20,25 @@ class Wrapper(val value: Int) extends AnyVal: ### Error ```scala sc:nocompile --- [E070] Syntax Error: example.scala:2:8 +-- [E070] Syntax Error: example.scala:2:8 -------------------------------------- 2 | class Inner - | ^^^^^ - | Value classes may not define an inner class + | ^^^^^^^^^^^ + | Value classes may not define an inner class ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Move the inner class outside the value class class Inner class Wrapper(val value: Int) extends AnyVal: def process: Int = value * 2 -``` +``` -```scala sc:compile +```scala sc:compile // Or use a regular class if you need inner classes class Wrapper(val value: Int): class Inner ``` - diff --git a/docs/_docs/reference/error-codes/E071.md b/docs/_docs/reference/error-codes/E071.md index 0a6a76bd319f..8bd9fa3219f1 100644 --- a/docs/_docs/reference/error-codes/E071.md +++ b/docs/_docs/reference/error-codes/E071.md @@ -2,7 +2,6 @@ title: E071: Value Classes May Not Define Non Parameter Field kind: Error --- - # E071: Value Classes May Not Define Non Parameter Field This error is emitted when a value class (a class extending `AnyVal`) defines a `val` or `var` field that is not the primary constructor parameter. @@ -13,7 +12,7 @@ Value classes can only have the single `val` parameter from their primary constr ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Wrapper(val value: Int) extends AnyVal: val doubled = value * 2 ``` @@ -21,24 +20,23 @@ class Wrapper(val value: Int) extends AnyVal: ### Error ```scala sc:nocompile --- [E071] Syntax Error: example.scala:2:6 +-- [E071] Syntax Error: example.scala:2:6 -------------------------------------- 2 | val doubled = value * 2 - | ^^^^^^^ - | Value classes may not define non-parameter field + | ^^^^^^^^^^^^^^^^^^^^^^^ + | Value classes may not define non-parameter field ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a def instead of val class Wrapper(val value: Int) extends AnyVal: def doubled: Int = value * 2 -``` +``` -```scala sc:compile +```scala sc:compile // Or use a regular class if you need fields class Wrapper(val value: Int): val doubled = value * 2 ``` - diff --git a/docs/_docs/reference/error-codes/E072.md b/docs/_docs/reference/error-codes/E072.md index 79207226d1db..1d2d4e715c98 100644 --- a/docs/_docs/reference/error-codes/E072.md +++ b/docs/_docs/reference/error-codes/E072.md @@ -2,7 +2,6 @@ title: E072: Value Classes May Not Define A Secondary Constructor kind: Error --- - # E072: Value Classes May Not Define A Secondary Constructor This error is emitted when a value class (a class extending `AnyVal`) defines a secondary constructor. @@ -13,7 +12,7 @@ Value classes can only have one primary constructor with exactly one `val` param ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Wrapper(val value: Int) extends AnyVal: def this(s: String) = this(s.toInt) ``` @@ -21,26 +20,25 @@ class Wrapper(val value: Int) extends AnyVal: ### Error ```scala sc:nocompile --- [E072] Syntax Error: example.scala:2:6 +-- [E072] Syntax Error: example.scala:2:6 -------------------------------------- 2 | def this(s: String) = this(s.toInt) - | ^^^^ - | Value classes may not define a secondary constructor + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Value classes may not define a secondary constructor ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a companion object factory method instead class Wrapper(val value: Int) extends AnyVal object Wrapper: def fromString(s: String): Wrapper = new Wrapper(s.toInt) -``` +``` -```scala sc:compile +```scala sc:compile // Or use a regular class if you need multiple constructors class Wrapper(val value: Int): def this(s: String) = this(s.toInt) ``` - diff --git a/docs/_docs/reference/error-codes/E073.md b/docs/_docs/reference/error-codes/E073.md index d0439b25cdb6..144bbc303411 100644 --- a/docs/_docs/reference/error-codes/E073.md +++ b/docs/_docs/reference/error-codes/E073.md @@ -2,7 +2,6 @@ title: E073: Value Classes May Not Contain Initialization kind: Error --- - # E073: Value Classes May Not Contain Initialization This error is emitted when a value class (a class extending `AnyVal`) contains initialization statements in its body. @@ -13,7 +12,7 @@ Value classes may not contain initialization statements because they are meant t ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Wrapper(val value: Int) extends AnyVal: println(s"Created wrapper with $value") ``` @@ -21,21 +20,21 @@ class Wrapper(val value: Int) extends AnyVal: ### Error ```scala sc:nocompile --- [E073] Syntax Error: example.scala:2:2 +-- [E073] Syntax Error: example.scala:2:9 -------------------------------------- 2 | println(s"Created wrapper with $value") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | Value classes may not contain initialization statements ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove initialization statements class Wrapper(val value: Int) extends AnyVal: def show: String = s"Wrapper($value)" -``` +``` -```scala sc:compile +```scala sc:compile // Or use a companion object for factory logic class Wrapper(val value: Int) extends AnyVal @@ -43,12 +42,11 @@ object Wrapper: def create(value: Int): Wrapper = println(s"Creating wrapper with $value") new Wrapper(value) -``` +``` -```scala sc:compile +```scala sc:compile // Or use a regular class if you need initialization class Wrapper(val value: Int): println(s"Created wrapper with $value") ``` - diff --git a/docs/_docs/reference/error-codes/E074.md b/docs/_docs/reference/error-codes/E074.md index ff0f0626d428..12bfd1d1479e 100644 --- a/docs/_docs/reference/error-codes/E074.md +++ b/docs/_docs/reference/error-codes/E074.md @@ -2,7 +2,6 @@ title: E074: Value Classes May Not Be Abstract kind: Error --- - # E074: Value Classes May Not Be Abstract This error is emitted when a value class (a class extending `AnyVal`) is declared as abstract. @@ -13,27 +12,27 @@ Value classes must be concrete because they are meant to be inlined by the compi ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain abstract class Wrapper(val value: Int) extends AnyVal ``` ### Error ```scala sc:nocompile --- [E074] Syntax Error: example.scala:1:15 +-- [E074] Syntax Error: example.scala:1:15 ------------------------------------- 1 |abstract class Wrapper(val value: Int) extends AnyVal - | ^^^^^^^ + | ^ | Value classes may not be abstract ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove the abstract modifier class Wrapper(val value: Int) extends AnyVal -``` +``` -```scala sc:compile +```scala sc:compile // For abstraction, use a universal trait trait Numeric extends Any: def value: Int @@ -41,4 +40,3 @@ trait Numeric extends Any: class Wrapper(val value: Int) extends AnyVal with Numeric ``` - diff --git a/docs/_docs/reference/error-codes/E075.md b/docs/_docs/reference/error-codes/E075.md index 5fc3ecc1a238..5aae749844e6 100644 --- a/docs/_docs/reference/error-codes/E075.md +++ b/docs/_docs/reference/error-codes/E075.md @@ -2,7 +2,6 @@ title: E075: Value Classes May Not Be Contained kind: Error --- - # E075: Value Classes May Not Be Contained This error is emitted when a value class (a class extending `AnyVal`) is defined as a local class or as a member of another class. @@ -13,7 +12,7 @@ Value classes must be top-level classes or members of an object. They cannot be ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Outer: class Wrapper(val value: Int) extends AnyVal ``` @@ -21,23 +20,23 @@ class Outer: ### Error ```scala sc:nocompile --- [E075] Syntax Error: example.scala:2:8 +-- [E075] Syntax Error: example.scala:2:8 -------------------------------------- 2 | class Wrapper(val value: Int) extends AnyVal - | ^^^^^^^ + | ^ | Value classes may not be a member of another class ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Define the value class at the top level class Wrapper(val value: Int) extends AnyVal class Outer: def wrap(x: Int): Wrapper = new Wrapper(x) -``` +``` -```scala sc:compile +```scala sc:compile // Or define it inside an object object Types: class Wrapper(val value: Int) extends AnyVal @@ -46,4 +45,3 @@ class Outer: def wrap(x: Int): Types.Wrapper = new Types.Wrapper(x) ``` - diff --git a/docs/_docs/reference/error-codes/E076.md b/docs/_docs/reference/error-codes/E076.md index fdee83eb811b..af49339817d1 100644 --- a/docs/_docs/reference/error-codes/E076.md +++ b/docs/_docs/reference/error-codes/E076.md @@ -2,7 +2,6 @@ title: E076: Value Classes May Not Wrap Another Value Class kind: Error --- - # E076: Value Classes May Not Wrap Another Value Class This error is emitted when a value class (a class extending `AnyVal`) has a parameter whose type is another user-defined value class. @@ -13,7 +12,7 @@ A value class may not wrap another user-defined value class because it would com ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Meters(val value: Double) extends AnyVal class Distance(val meters: Meters) extends AnyVal ``` @@ -21,27 +20,26 @@ class Distance(val meters: Meters) extends AnyVal ### Error ```scala sc:nocompile --- [E076] Syntax Error: example.scala:2:6 +-- [E076] Syntax Error: example.scala:2:6 -------------------------------------- 2 |class Distance(val meters: Meters) extends AnyVal - | ^^^^^^^^ + | ^ | A value class may not wrap another user-defined value class ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Wrap the underlying primitive type directly class Meters(val value: Double) extends AnyVal class Distance(val value: Double) extends AnyVal object Distance: def fromMeters(m: Meters): Distance = new Distance(m.value) -``` +``` -```scala sc:compile +```scala sc:compile // Or use a regular class for the outer wrapper class Meters(val value: Double) extends AnyVal class Distance(val meters: Meters) ``` - diff --git a/docs/_docs/reference/error-codes/E077.md b/docs/_docs/reference/error-codes/E077.md index 16933d35faaa..2a3574e9c82b 100644 --- a/docs/_docs/reference/error-codes/E077.md +++ b/docs/_docs/reference/error-codes/E077.md @@ -2,7 +2,6 @@ title: E077: Value Class Parameter May Not Be A Var kind: Error --- - # E077: Value Class Parameter May Not Be A Var This error is emitted when a value class (a class extending `AnyVal`) has its parameter declared as `var` instead of `val`. @@ -13,29 +12,33 @@ A value class must have exactly one `val` parameter. Using `var` would imply mut ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Wrapper(var value: Int) extends AnyVal ``` ### Error ```scala sc:nocompile --- [E077] Syntax Error: example.scala:1:14 +-- [E077] Syntax Error: example.scala:1:18 ------------------------------------- 1 |class Wrapper(var value: Int) extends AnyVal - | ^^^^^^^^^^^^^ - | A value class parameter may not be a var + | ^ + | A value class parameter may not be a var + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A value class must have exactly one val parameter. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use val instead of var class Wrapper(val value: Int) extends AnyVal -``` +``` -```scala sc:compile +```scala sc:compile // If you need mutability, use a regular class class Wrapper(var value: Int) ``` - diff --git a/docs/_docs/reference/error-codes/E078.md b/docs/_docs/reference/error-codes/E078.md index cdfb0bca82b3..508b14d4cce6 100644 --- a/docs/_docs/reference/error-codes/E078.md +++ b/docs/_docs/reference/error-codes/E078.md @@ -2,7 +2,6 @@ title: E078: Value Class Needs Exactly One Val Parameter kind: Error --- - # E078: Value Class Needs Exactly One Val Parameter This error is emitted when a value class (a class extending `AnyVal`) doesn't have exactly one `val` parameter. @@ -13,29 +12,28 @@ Value classes must have exactly one `val` parameter in their primary constructor ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Wrapper() extends AnyVal ``` ### Error ```scala sc:nocompile --- [E078] Syntax Error: example.scala:1:6 +-- [E078] Syntax Error: example.scala:1:6 -------------------------------------- 1 |class Wrapper() extends AnyVal - | ^^^^^^^ + | ^ | Value class needs one val parameter ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add exactly one val parameter class Wrapper(val value: Int) extends AnyVal -``` +``` -```scala sc:compile +```scala sc:compile // For multiple values, use a regular class or case class case class Wrapper(x: Int, y: Int) ``` - diff --git a/docs/_docs/reference/error-codes/E079.md b/docs/_docs/reference/error-codes/E079.md new file mode 100644 index 000000000000..6078e4c91ebc --- /dev/null +++ b/docs/_docs/reference/error-codes/E079.md @@ -0,0 +1,52 @@ +--- +title: "E079: Only Case Class Or Case Object Allowed" +kind: Error +until: 3.0.0 +--- + +**Note:** This error was removed before Scala 3.0.0 was released and was never emitted by the Scala 3 compiler. + +## What it did + +This error was triggered in early Dotty versions when using `case` keyword outside of a valid context. + +### Example + +```scala sc:nocompile +object Test: + case Foo // error: only case class or case object allowed +``` + +### Error + +```scala sc:nocompile +-- [E079] Syntax Error: example.scala:2:2 -------------------------------------- +2 | case Foo + | ^^^^^^^^ + | Only `case class` or `case object` allowed +``` + +## Explanation + +The `case` keyword can only be used in specific contexts: +- Before `class` to define a case class +- Before `object` to define a case object +- Inside `match` expressions for pattern matching +- Inside `enum` definitions for enum cases + +This error was removed in commit 2e5df79218 (May 2021) as part of "Refactor remaining statement and declaration loops". The parser was refactored to handle invalid syntax differently. + +The correct usages are: + +```scala sc:nocompile +// Case class +case class Foo(x: Int) + +// Case object +case object Bar + +// Enum cases +enum Color: + case Red, Green, Blue +``` + diff --git a/docs/_docs/reference/error-codes/E080.md b/docs/_docs/reference/error-codes/E080.md new file mode 100644 index 000000000000..9f9f64766a70 --- /dev/null +++ b/docs/_docs/reference/error-codes/E080.md @@ -0,0 +1,56 @@ +--- +title: "E080: Expected Top Level Def" +kind: Error +until: 3.0.0 +--- + +**Note:** This error was removed before Scala 3.0.0 was released and was never emitted by the Scala 3 compiler. + +## What it did + +This error was triggered in early Dotty versions when the parser expected a top-level definition but found something else. + +## Example + +```scala sc:nocompile +// Invalid top-level statement +42 +``` + +### Error + +```scala sc:nocompile +-- [E080] Syntax Error: example.scala:1:0 -------------------------------------- +1 |42 + |^^ + |Expected a toplevel definition +``` + +## Explanation + +At the top level of a Scala source file, only definitions are allowed: +- `package` declarations +- `import` statements +- `class`, `trait`, `object`, `enum` definitions +- `type` aliases +- `val`, `var`, `def` definitions +- `extension` definitions +- `given` definitions +- `export` clauses + +Standalone expressions like `42` or `println("hello")` are not valid at the top level (outside of a definition). + +This error was removed in commit 2e5df79218 (May 2021) as part of "Refactor remaining statement and declaration loops". The parser was refactored to provide different error handling for invalid top-level syntax. + +To execute code at the top level, wrap it in a main method or object: + +```scala sc:compile +@main def run(): Unit = + println("hello") + +// Or +object Main: + def main(args: Array[String]): Unit = + println("hello") +``` + diff --git a/docs/_docs/reference/error-codes/E081.md b/docs/_docs/reference/error-codes/E081.md index de8feda211f0..e9f8a86c6bde 100644 --- a/docs/_docs/reference/error-codes/E081.md +++ b/docs/_docs/reference/error-codes/E081.md @@ -2,7 +2,6 @@ title: E081: Anonymous Function Missing Parameter Type kind: Error --- - # E081: Anonymous Function Missing Parameter Type This error is emitted when the compiler cannot infer the type of a parameter in an anonymous function (lambda) and no explicit type is provided. @@ -13,36 +12,35 @@ The compiler needs to know the types of function parameters to properly type-che ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val f = (x) => x + 1 ``` ### Error ```scala sc:nocompile --- [E081] Type Error: example.scala:1:10 +-- [E081] Type Error: example.scala:1:9 ---------------------------------------- 1 |val f = (x) => x + 1 - | ^ - | Missing parameter type + | ^ + | Missing parameter type | - | I could not infer the type of the parameter x. + | I could not infer the type of the parameter x ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add an explicit type annotation to the parameter val f = (x: Int) => x + 1 -``` +``` -```scala sc:compile +```scala sc:compile // Or provide type context through the variable declaration val f: Int => Int = x => x + 1 -``` +``` -```scala sc:compile +```scala sc:compile // Or use the function in a context that provides type information -List(1, 2, 3).map(x => x + 1) +val result = List(1, 2, 3).map(x => x + 1) ``` - diff --git a/docs/_docs/reference/error-codes/E082.md b/docs/_docs/reference/error-codes/E082.md index fe515c58f8eb..e8180a98f5fa 100644 --- a/docs/_docs/reference/error-codes/E082.md +++ b/docs/_docs/reference/error-codes/E082.md @@ -2,7 +2,6 @@ title: E082: Super Calls Not Allowed In Inlineable kind: Error --- - # E082: Super Calls Not Allowed In Inlineable This error is emitted when an `inline` method contains a call to `super`. @@ -13,7 +12,7 @@ Method inlining prohibits calling superclass methods because when the method is ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Parent: def greet: String = "Hello" @@ -24,24 +23,29 @@ class Child extends Parent: ### Error ```scala sc:nocompile --- [E082] Syntax Error: example.scala:5:33 +-- [E082] Syntax Error: example.scala:5:33 ------------------------------------- 5 | inline def greetLoud: String = super.greet + "!" - | ^^^^^^^^^^^ - | Super call not allowed in inlineable method greetLoud + | ^^^^^ + | Super call not allowed in inlineable method greetLoud + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Method inlining prohibits calling superclass methods, as it may lead to confusion about which super is being called. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove the inline modifier class Parent: def greet: String = "Hello" class Child extends Parent: def greetLoud: String = super.greet + "!" -``` +``` -```scala sc:compile +```scala sc:compile // Or use a helper method for the super call class Parent: def greet: String = "Hello" @@ -51,4 +55,3 @@ class Child extends Parent: inline def greetLoud: String = parentGreet + "!" ``` - diff --git a/docs/_docs/reference/error-codes/E083.md b/docs/_docs/reference/error-codes/E083.md index 7f389f2e36d4..ae33e2575a4c 100644 --- a/docs/_docs/reference/error-codes/E083.md +++ b/docs/_docs/reference/error-codes/E083.md @@ -2,7 +2,6 @@ title: E083: Not A Path kind: Error --- - # E083: Not A Path This error is emitted when an expression is used where a stable path is required, but the expression is not an immutable path. @@ -18,7 +17,7 @@ Paths are required in certain contexts like singleton types, type projections, a ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain var x = 1 def example: x.type = x ``` @@ -26,24 +25,31 @@ def example: x.type = x ### Error ```scala sc:nocompile --- [E083] Type Error: example.scala:2:13 +-- [E083] Type Error: example.scala:2:13 --------------------------------------- 2 |def example: x.type = x | ^^^^^^ - | x.type is not a valid type, since it is not an immutable path + |(x : Int) is not a valid singleton type, since it is not an immutable path + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | An immutable path is + | - a reference to an immutable value, or + | - a reference to `this`, or + | - a selection of an immutable path with an immutable value. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use val instead of var for stable paths val x = 1 def example: x.type = x -``` +``` -```scala sc:compile +```scala sc:compile // Or don't use singleton types for mutable values var x = 1 def example: Int = x ``` - diff --git a/docs/_docs/reference/error-codes/E084.md b/docs/_docs/reference/error-codes/E084.md index edc19d4e0b1a..0877358303b6 100644 --- a/docs/_docs/reference/error-codes/E084.md +++ b/docs/_docs/reference/error-codes/E084.md @@ -2,7 +2,6 @@ title: E084: Wildcard On Type Argument Not Allowed On New kind: Error --- - # E084: Wildcard On Type Argument Not Allowed On New This error is emitted when a wildcard type argument (`?` or `_`) is used in a `new` expression. @@ -13,45 +12,57 @@ When creating a new instance, the compiler needs to know the exact types to allo ## Example -```scala sc:fail -class Box[T](value: T) +```scala sc:fail sc-opts:-explain +class Team[A] -val box = new Box[?](42) +val team = new Team[?] ``` ### Error ```scala sc:nocompile --- [E084] Syntax Error: example.scala:3:18 -3 |val box = new Box[?](42) - | ^ - | Type argument must be fully defined +-- [E084] Syntax Error: example.scala:3:20 ------------------------------------- +3 |val team = new Team[?] + | ^ + | Type argument must be fully defined + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Wildcard on arguments is not allowed when declaring a new type. + | + | Given the following example: + | + | + | object TyperDemo { + | class Team[A] + | val team = new Team[?] + | } + | + | + | You must complete all the type parameters, for instance: + | + | + | object TyperDemo { + | class Team[A] + | val team = new Team[Int] + | } + | + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a concrete type argument -class Box[T](value: T) - -val box = new Box[Int](42) -``` - -```scala sc:compile -// Or let the compiler infer the type -class Box[T](value: T) +class Team[A] -val box = new Box(42) -``` - -```scala sc:compile -// Or use a factory method if you need more flexibility -class Box[T](value: T) +val team = new Team[Int] +``` -object Box: - def apply[T](value: T): Box[T] = new Box(value) +```scala sc:compile +// Or let the compiler infer the type from usage context +class Team[A](member: A) -val box = Box(42) +val team = new Team("Alice") ``` - diff --git a/docs/_docs/reference/error-codes/E085.md b/docs/_docs/reference/error-codes/E085.md index e4e87994ac38..629959663e3f 100644 --- a/docs/_docs/reference/error-codes/E085.md +++ b/docs/_docs/reference/error-codes/E085.md @@ -1,41 +1,39 @@ --- -title: E085: Function Type Needs Non Empty Parameter List +title: "E085: Function Type Needs Non-Empty Parameter List" kind: Error +until: 3.0.0 --- -# E085: Function Type Needs Non Empty Parameter List +This error was removed before Scala 3.0.0 was released and was never emitted by the Scala 3 compiler. +This error was triggered when attempting to define implicit or erased function types with empty parameter lists. -This error is emitted when a function type syntax is used incorrectly, typically when trying to create a function type with improper syntax. +### Example (would have failed in early Dotty versions) -Function types in Scala follow the form `(A, B) => C` for multi-parameter functions, `A => B` for single-parameter functions, and `() => A` for nullary functions. - ---- - -## Example - -```scala sc:fail -type Invalid = => Int +```scala sc:nocompile +type Contextual[T] = implicit () => T +val x: implicit () => Int +val y: erased () => Int +val z: erased implicit () => Int ``` ### Error ```scala sc:nocompile --- [E085] Syntax Error: example.scala:1:15 -1 |type Invalid = => Int - | ^^ - | Function type needs non-empty parameter list +-- Error: example.scala:1:26 --------------------------------------------------- +1 |type Contextual[T] = implicit () => T + | ^^ + |implicit function type needs non-empty parameter list ``` -### Solution +## Explanation -```scala sc:compile -// Use () for nullary functions -type Valid = () => Int -``` +In early versions of Dotty (before Scala 3.0.0), it was not allowed to leave implicit or erased function parameter lists empty. This restriction was removed in commit d34b677d88 (May 2018) as it was considered an unnecessary limitation. -```scala sc:compile -// Or use a by-name parameter type in method signatures -def delayed(x: => Int): Int = x -``` +The error message suggested defining the function types with explicit parameters: +```scala sc:nocompile +type Transactional[T] = implicit Transaction => T +val cl: implicit A => B +``` +Since Scala 3.0.0, empty parameter lists are allowed for implicit and erased function types, making this error obsolete. diff --git a/docs/_docs/reference/error-codes/E086.md b/docs/_docs/reference/error-codes/E086.md index 156d4386f4a8..aaeaee2bb6e6 100644 --- a/docs/_docs/reference/error-codes/E086.md +++ b/docs/_docs/reference/error-codes/E086.md @@ -2,7 +2,6 @@ title: E086: Wrong Number Of Parameters kind: Error --- - # E086: Wrong Number Of Parameters This error is emitted when a function literal has a different number of parameters than what is expected by the context. @@ -13,29 +12,41 @@ When you provide a function literal where a specific function type is expected, ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val f: (Int, Int) => Int = x => x + 1 ``` ### Error ```scala sc:nocompile --- [E086] Syntax Error: example.scala:1:27 +-- [E086] Syntax Error: example.scala:1:29 ------------------------------------- 1 |val f: (Int, Int) => Int = x => x + 1 | ^^^^^^^^^^ | Wrong number of parameters, expected: 2 + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The function literal + | + | x => x + 1 + | + | has 1 parameter. But the expected type + | + | (Int, Int) => Int + | + | requires a function with 2 parameters. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Provide the correct number of parameters val f: (Int, Int) => Int = (x, y) => x + y -``` +``` -```scala sc:compile +```scala sc:compile // Or change the expected type val f: Int => Int = x => x + 1 ``` - diff --git a/docs/_docs/reference/error-codes/E087.md b/docs/_docs/reference/error-codes/E087.md index bd97d175702e..2cf8dc7e3acf 100644 --- a/docs/_docs/reference/error-codes/E087.md +++ b/docs/_docs/reference/error-codes/E087.md @@ -2,10 +2,9 @@ title: E087: Duplicate Private Protected Qualifier kind: Error --- - # E087: Duplicate Private Protected Qualifier -This error is emitted when both `private` and `protected` modifiers are used on the same definition. +This error is emitted when both `private` and `protected` modifiers with scope qualifiers (like `[ClassName]`) are used on the same definition. It is not allowed to combine `private` and `protected` modifiers even if they are qualified to different scopes. A member can only have one visibility modifier. @@ -13,32 +12,29 @@ It is not allowed to combine `private` and `protected` modifiers even if they ar ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Example: - private protected def method: Int = 42 + private[Example] protected[Example] def method: Int = 42 ``` ### Error ```scala sc:nocompile --- [E087] Syntax Error: example.scala:2:10 -2 | private protected def method: Int = 42 - | ^^^^^^^^^ - | Duplicate private/protected modifier +-- [E087] Syntax Error: example.scala:2:28 ------------------------------------- +2 | private[Example] protected[Example] def method: Int = 42 + | ^ + | Duplicate private/protected modifier + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | It is not allowed to combine `private` and `protected` modifiers even if they are qualified to different scopes + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use only one access modifier -class Example: - private def method: Int = 42 -``` - -```scala sc:compile -// Or use protected with a qualifier if needed class Example: protected[Example] def method: Int = 42 ``` - - diff --git a/docs/_docs/reference/error-codes/E088.md b/docs/_docs/reference/error-codes/E088.md index 2b56a3b70848..346bc9b45fd2 100644 --- a/docs/_docs/reference/error-codes/E088.md +++ b/docs/_docs/reference/error-codes/E088.md @@ -2,7 +2,6 @@ title: E088: Expected Start Of Top Level Definition kind: Error --- - # E088: Expected Start Of Top Level Definition This error is emitted when modifiers are provided but no valid definition follows them. @@ -13,29 +12,33 @@ After using modifiers like `private`, `protected`, `final`, `abstract`, etc., yo ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain final ``` ### Error ```scala sc:nocompile --- [E088] Syntax Error: example.scala:1:0 +-- [E088] Syntax Error: example.scala:1:5 -------------------------------------- 1 |final - |^^^^^ - |Expected start of definition + | ^ + | Expected start of definition + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | You have to provide either class, trait, object, or enum definitions after modifiers + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add a definition after the modifier final class Example -``` +``` -```scala sc:compile +```scala sc:compile // Or for methods/values final val x = 42 ``` - diff --git a/docs/_docs/reference/error-codes/E089.md b/docs/_docs/reference/error-codes/E089.md index 625354932dfb..85d38805cb9b 100644 --- a/docs/_docs/reference/error-codes/E089.md +++ b/docs/_docs/reference/error-codes/E089.md @@ -2,7 +2,6 @@ title: E089: Missing Return Type With Return Statement kind: Error --- - # E089: Missing Return Type With Return Statement This error is emitted when a method contains a `return` statement but doesn't have an explicit return type. @@ -13,7 +12,7 @@ If a method contains a `return` statement, it must have an explicit return type. ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def example(x: Int) = if x > 0 then return x 0 @@ -22,26 +21,33 @@ def example(x: Int) = ### Error ```scala sc:nocompile --- [E089] Syntax Error: example.scala:1:4 -1 |def example(x: Int) = - | ^^^^^^^ - | method example has a return statement; it needs a result type +-- [E089] Syntax Error: example.scala:2:16 ------------------------------------- +2 | if x > 0 then return x + | ^^^^^^^^ + | method example has a return statement; it needs a result type + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | If a method contains a return statement, it must have an + | explicit return type. For example: + | + | def good: Int /* explicit return type */ = return 1 + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Add an explicit return type def example(x: Int): Int = if x > 0 then return x 0 -``` +``` -```scala sc:compile +```scala sc:compile // Or avoid using return (preferred in Scala) def example(x: Int): Int = if x > 0 then x else 0 ``` - diff --git a/docs/_docs/reference/error-codes/E090.md b/docs/_docs/reference/error-codes/E090.md index 9d3e25afcf2f..bed6bc3c7154 100644 --- a/docs/_docs/reference/error-codes/E090.md +++ b/docs/_docs/reference/error-codes/E090.md @@ -2,7 +2,6 @@ title: E090: No Return From Inlineable kind: Error --- - # E090: No Return From Inlineable This error is emitted when an `inline` method contains an explicit `return` statement. @@ -13,7 +12,7 @@ Methods marked with `inline` modifier may not use `return` statements because wh ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain inline def example(x: Int): Int = if x < 0 then return 0 x * 2 @@ -22,26 +21,32 @@ inline def example(x: Int): Int = ### Error ```scala sc:nocompile --- [E090] Syntax Error: example.scala:2:16 +-- [E090] Syntax Error: example.scala:2:16 ------------------------------------- 2 | if x < 0 then return 0 | ^^^^^^^^ | No explicit return allowed from inlineable method example + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Methods marked with inline modifier may not use return statements. + | Instead, you should rely on the last expression's value being + | returned from a method. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use if-else expression instead of return inline def example(x: Int): Int = if x < 0 then 0 else x * 2 -``` +``` -```scala sc:compile +```scala sc:compile // Or remove inline if you need return def example(x: Int): Int = if x < 0 then return 0 x * 2 ``` - diff --git a/docs/_docs/reference/error-codes/E091.md b/docs/_docs/reference/error-codes/E091.md index 6c443d88d501..680be342e38c 100644 --- a/docs/_docs/reference/error-codes/E091.md +++ b/docs/_docs/reference/error-codes/E091.md @@ -2,7 +2,6 @@ title: E091: Return Outside Method Definition kind: Error --- - # E091: Return Outside Method Definition This error is emitted when a `return` statement is used outside of a method definition. @@ -13,30 +12,35 @@ The `return` keyword may only be used within method definitions. It cannot be us ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val x = return 42 ``` ### Error ```scala sc:nocompile --- [E091] Syntax Error: example.scala:1:8 +-- [E091] Syntax Error: example.scala:1:8 -------------------------------------- 1 |val x = return 42 | ^^^^^^^^^ | return outside method definition + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | You used return in the top-level definitions in package . + | return is a keyword and may only be used within method declarations. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Simply use the value directly val x = 42 -``` +``` -```scala sc:compile +```scala sc:compile // Use return only inside methods def getValue: Int = return 42 // but even here, avoid return def getBetterValue: Int = 42 // preferred style ``` - diff --git a/docs/_docs/reference/error-codes/E092.md b/docs/_docs/reference/error-codes/E092.md index 1b29bd90b73d..b3e5391e2a06 100644 --- a/docs/_docs/reference/error-codes/E092.md +++ b/docs/_docs/reference/error-codes/E092.md @@ -2,7 +2,6 @@ title: E092: Unchecked Type Pattern kind: Warning --- - # E092: Unchecked Type Pattern This warning is emitted when a type pattern cannot be fully checked at runtime due to type erasure. @@ -13,7 +12,7 @@ Type arguments and type refinements are erased during compile time, making it im ## Example -```scala sc:fail sc-opts:-Werror +```scala sc:fail sc-opts:-explain,-Werror def example(x: Any): Unit = x match case list: List[String] => println("strings") case _ => println("other") @@ -22,30 +21,38 @@ def example(x: Any): Unit = x match ### Error ```scala sc:nocompile --- [E092] Pattern Match Unchecked Warning: example.scala:2:8 +-- [E092] Pattern Match Unchecked Warning: example.scala:2:7 ------------------- 2 | case list: List[String] => println("strings") - | ^^^^^^^^^^^^ - | the type test for List[String] cannot be checked at runtime because its type arguments can't be determined from Any + | ^ + |the type test for List[String] cannot be checked at runtime because its type arguments can't be determined from Any + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Type arguments and type refinements are erased during compile time, thus it's + | impossible to check them at run-time. + | + | You can either replace the type arguments by _ or use `@unchecked`. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use a wildcard for the type argument def example(x: Any): Unit = x match case list: List[?] => println("some list") case _ => println("other") -``` +``` -```scala sc:compile +```scala sc:compile // Or use @unchecked if you're certain about the type import scala.unchecked def example(x: Any): Unit = x match case list: List[String @unchecked] => println("strings") case _ => println("other") -``` +``` -```scala sc:compile +```scala sc:compile // Or check the element types explicitly def example(x: Any): Unit = x match case list: List[?] if list.forall(_.isInstanceOf[String]) => @@ -53,4 +60,3 @@ def example(x: Any): Unit = x match case _ => println("other") ``` - diff --git a/docs/_docs/reference/error-codes/E093.md b/docs/_docs/reference/error-codes/E093.md index b51d45263e7f..3034759a5979 100644 --- a/docs/_docs/reference/error-codes/E093.md +++ b/docs/_docs/reference/error-codes/E093.md @@ -2,7 +2,6 @@ title: E093: Extend Final Class kind: Error --- - # E093: Extend Final Class This error is emitted when attempting to extend a class that is marked as `final`. @@ -13,7 +12,7 @@ A class marked with the `final` keyword cannot be extended by any other class. T ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain final class Parent class Child extends Parent @@ -22,22 +21,27 @@ class Child extends Parent ### Error ```scala sc:nocompile --- [E093] Syntax Error: example.scala:3:6 +-- [E093] Syntax Error: example.scala:3:6 -------------------------------------- 3 |class Child extends Parent - | ^^^^^ + | ^ | class Child cannot extend final class Parent + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A class marked with the final keyword cannot be extended + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Remove final from the parent if inheritance is intended class Parent class Child extends Parent -``` +``` -```scala sc:compile +```scala sc:compile // Or use composition instead of inheritance final class Parent: def greet: String = "Hello" @@ -47,4 +51,3 @@ class Child: def greet: String = parent.greet ``` - diff --git a/docs/_docs/reference/error-codes/E094.md b/docs/_docs/reference/error-codes/E094.md index 3376339dfa6a..484fbdaa29d6 100644 --- a/docs/_docs/reference/error-codes/E094.md +++ b/docs/_docs/reference/error-codes/E094.md @@ -1,47 +1,31 @@ --- -title: E094: Enum Case Definition In Non Enum Owner +title: "E094: Enum Case Definition In Non-Enum Owner" kind: Error +until: 3.0.0 --- -# E094: Enum Case Definition In Non Enum Owner +This error was removed before Scala 3.0.0 was released and was never emitted by the Scala 3 compiler. +This error was triggered when trying to define enum cases outside of an enum class companion object in early enum implementations. -This error is emitted when a `case` is defined outside of an `enum` definition. +### Example -Enum cases can only be defined inside an `enum` body. They represent the possible values of that enumeration type. - ---- - -## Example - -```scala sc:fail -object Colors: - case Red +```scala sc:nocompile +object Qux { + case Foo +} ``` ### Error ```scala sc:nocompile --- [E094] Syntax Error: example.scala:2:2 -2 | case Red - | ^^^^ - | Enum case not allowed here; case may only appear inside an enum definition -``` - -### Solution - -```scala sc:compile -// Define cases inside an enum -enum Colors: - case Red, Green, Blue -``` - -```scala sc:compile -// Or use case objects for similar functionality outside enums -object Colors: - sealed trait Color - case object Red extends Color - case object Green extends Color - case object Blue extends Color +-- Error: example.scala:2:2 ---------------------------------------------------- +2 | case Foo + | ^^^^^^^^ + |case not allowed here, since owner object Qux is not an enum object ``` +## Explanation +In early versions of Dotty (before Scala 3.0.0), enum cases were only allowed within the companion object of an enum class. The compiler would check that the owner of a case definition was a module class and that its linked class derived from `scala.runtime.EnumClass`. +This restriction was part of an earlier enum implementation scheme that was replaced with a new enum design in commit e1470f488b (February 2018). The new design changed how enum cases are validated and desugared, making this error obsolete. +Since Scala 3.0.0, enums use a different validation mechanism that doesn't rely on this specific error. diff --git a/docs/_docs/reference/error-codes/E095.md b/docs/_docs/reference/error-codes/E095.md index 0a607fd26cb1..2307eeb47b3a 100644 --- a/docs/_docs/reference/error-codes/E095.md +++ b/docs/_docs/reference/error-codes/E095.md @@ -2,7 +2,6 @@ title: E095: Expected Type Bound Or Equals kind: Error --- - # E095: Expected Type Bound Or Equals This error is emitted when a type parameter or type member definition has invalid syntax - expecting `=`, `>:`, or `<:` but finding something else. @@ -16,39 +15,50 @@ Type parameters and abstract types may be constrained by type bounds: ## Example -```scala sc:fail -type MyType : Int +```scala sc:fail sc-opts:-explain +class Container: + type MyType @ ``` ### Error ```scala sc:nocompile --- [E095] Syntax Error: example.scala:1:12 -1 |type MyType : Int - | ^ - | '=', '>:', or '<:' expected, but ':' found +-- [E095] Syntax Error: example.scala:2:14 ------------------------------------- +2 | type MyType @ + | ^ + | =, >:, or <: expected, but '@' found + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Type parameters and abstract types may be constrained by a type bound. + | Such type bounds limit the concrete values of the type variables and possibly + | reveal more information about the members of such types. + | + | A lower type bound B >: A expresses that the type variable B + | refers to a supertype of type A. + | + | An upper type bound T <: A declares that type variable T + | refers to a subtype of type A. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use = for type alias -type MyType = Int -``` +class Container: + type MyType = Int +``` -```scala sc:compile +```scala sc:compile // Use <: for upper bound -type MyType <: AnyVal -``` +class Container: + type MyType <: AnyVal +``` -```scala sc:compile +```scala sc:compile // Use >: for lower bound -type MyType >: Nothing -``` - -```scala sc:compile -// Combine bounds -type MyType >: Nothing <: AnyVal +class Container: + type MyType >: Nothing ``` - diff --git a/docs/_docs/reference/error-codes/E096.md b/docs/_docs/reference/error-codes/E096.md index 8c24b82b57c7..00d82e95ca12 100644 --- a/docs/_docs/reference/error-codes/E096.md +++ b/docs/_docs/reference/error-codes/E096.md @@ -2,7 +2,6 @@ title: E096: Class And Companion Name Clash kind: Error --- - # E096: Class And Companion Name Clash This error is emitted when both a class/trait and its companion object define a class, trait, or object with the same name. @@ -13,7 +12,7 @@ A class and its companion object share the same namespace for nested types, so t ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain class Outer: class Inner @@ -24,24 +23,31 @@ object Outer: ### Error ```scala sc:nocompile --- [E096] Naming Error: example.scala:5:8 -5 | class Inner - | ^^^^^ - | Name clash: both class Outer and its companion object defines Inner +-- [E096] Naming Error: example.scala:2:8 -------------------------------------- +2 | class Inner + | ^ + | Name clash: both class Outer and its companion object defines Inner + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A class and its companion object cannot both define a class, trait or object with the same name: + | - class Outer defines class Inner + | - object Outer defines class Inner + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use different names for the nested types class Outer: class InnerClass object Outer: class InnerObject -``` +``` -```scala sc:compile +```scala sc:compile // Or define the type in only one place class Outer: class Inner @@ -53,4 +59,3 @@ object Outer: new out.Inner() ``` - diff --git a/docs/_docs/reference/error-codes/E097.md b/docs/_docs/reference/error-codes/E097.md index f8a15e57ce22..c4df3c2f0d0e 100644 --- a/docs/_docs/reference/error-codes/E097.md +++ b/docs/_docs/reference/error-codes/E097.md @@ -2,7 +2,6 @@ title: E097: Tailrec Not Applicable kind: Error --- - # E097: Tailrec Not Applicable This error is emitted when the `@tailrec` annotation is used on a method that cannot be optimized for tail recursion. @@ -17,7 +16,7 @@ Tail recursion optimization requires that: ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain import scala.annotation.tailrec class Example: @@ -29,15 +28,15 @@ class Example: ### Error ```scala sc:nocompile --- [E097] Syntax Error: example.scala:4:14 +-- [E097] Syntax Error: example.scala:4:15 ------------------------------------- 4 | @tailrec def factorial(n: Int, acc: Int = 1): Int = - | ^^^^^^^^^ - | TailRec optimisation not applicable, method factorial is neither private nor final so can be overridden + | ^ + |TailRec optimisation not applicable, method factorial is neither private nor final so can be overridden ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Make the method final or private import scala.annotation.tailrec @@ -45,9 +44,9 @@ class Example: @tailrec final def factorial(n: Int, acc: Int = 1): Int = if n <= 1 then acc else factorial(n - 1, n * acc) -``` +``` -```scala sc:compile +```scala sc:compile // Or use private import scala.annotation.tailrec @@ -57,4 +56,3 @@ class Example: else factorial(n - 1, n * acc) ``` - diff --git a/docs/_docs/reference/error-codes/E098.md b/docs/_docs/reference/error-codes/E098.md index 6e80f4cc83a3..8a495a16dad3 100644 --- a/docs/_docs/reference/error-codes/E098.md +++ b/docs/_docs/reference/error-codes/E098.md @@ -2,54 +2,54 @@ title: E098: Failure To Eliminate Existential kind: Warning --- - # E098: Failure To Eliminate Existential -This warning is emitted when an existential type from a Scala 2 classfile cannot be accurately mapped to a Scala 3 equivalent. +This warning is emitted when a **complex** existential type from a Scala 2 classfile cannot be accurately mapped to a Scala 3 equivalent. + +Existential types in their full generality are no longer supported in Scala 3. When reading Scala 2 classfiles that contain existential types, Scala 3 attempts to approximate them. Simple existentials (like `List[T] forSome { type T }`) are handled cleanly, but complex existential types where bound variables cannot be fully eliminated may trigger this warning. -Existential types in their full generality are no longer supported in Scala 3. When reading Scala 2 classfiles that contain existential types, Scala 3 attempts to approximate them, but sometimes this approximation may not be accurate. +This is a rare compatibility warning that most users will never encounter. --- ## Example -This error typically occurs when loading classes compiled with Scala 2 that use existential types: +This warning can only occur when loading classes compiled with Scala 2 that use complex existential types where the bound type variable appears in a position that prevents clean elimination: -```scala sc:nocompile -// From a Scala 2 library +```scala sc-name:scala2-existential sc:nocompile +// Scala 2 library code (compiled with Scala 2) +// Complex existential where T appears in multiple positions class Container { - def get: List[T] forSome { type T } = ??? + def get: (T, List[T]) forSome { type T } = ??? } ``` +```scala sc:nocompile +// Scala 3 code trying to use the Scala 2 library +val container = new Container() +val items = container.get // Warning E098 may be emitted when loading Container.class +``` + ### Error ```scala sc:nocompile --- [E098] Compatibility Warning: - An existential type that came from a Scala-2 classfile for Container - cannot be mapped accurately to a Scala-3 equivalent. - original type : List[T] forSome { type T } - reduces to : List[?] - type used instead: List[Any] - This choice can cause follow-on type errors or hide type errors. - Proceed at own risk. +-- [E098] Compatibility Warning: ----------------------------------------------- + |An existential type that came from a Scala-2 classfile for Container + |cannot be mapped accurately to a Scala-3 equivalent. + |original type : List[T] forSome { type T } + |reduces to : List[?] + |type used instead: List[Any] + |This choice can cause follow-on type errors or hide type errors. + |Proceed at own risk. ``` -### Solution +### Solution -```scala sc:nocompile -// If you control the library, recompile it with Scala 3 -// Replace existential types with wildcards or type parameters: +If you control the library, recompile it with Scala 3. Replace existential types with wildcards or type parameters +If you don't control the library, be aware of potential type mismatches and use explicit type annotations where needed -// Instead of: List[T] forSome { type T } -// Use: List[?] or List[_] or add type parameter +```scala sc:nocompile +// Instead of: List[T] forSome { type T } use wildcards or add type parameter def get[T]: List[T] = ??? def getAny: List[?] = ??? -``` - -```scala sc:nocompile -// If you don't control the library, be aware of potential -// type mismatches and use explicit type annotations where needed ``` - - diff --git a/docs/_docs/reference/error-codes/E099.md b/docs/_docs/reference/error-codes/E099.md index 22d0d47232da..bceb81558ccc 100644 --- a/docs/_docs/reference/error-codes/E099.md +++ b/docs/_docs/reference/error-codes/E099.md @@ -2,7 +2,6 @@ title: E099: Only Functions Can Be Followed By Underscore kind: Error --- - # E099: Only Functions Can Be Followed By Underscore This error is emitted when the eta-expansion syntax `x _` is used on an expression that is not a method. @@ -13,7 +12,7 @@ The syntax `x _` for converting a method to a function value is deprecated and o ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain val x = 42 val f = x _ ``` @@ -21,16 +20,23 @@ val f = x _ ### Error ```scala sc:nocompile --- [E099] Syntax Error: example.scala:2:8 +-- [E099] Syntax Error: example.scala:2:10 ------------------------------------- 2 |val f = x _ | ^^^ - | Only function types can be followed by _ but the current expression has type Int + |Only function types can be followed by _ but the current expression has type Int + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The syntax x _ is no longer supported if x is not a function. + | To convert to a function value, you need to explicitly write () => x + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Use explicit function syntax val x = 42 val f = () => x -``` +``` + diff --git a/docs/_docs/reference/error-codes/E100.md b/docs/_docs/reference/error-codes/E100.md index db1fb55c1fb2..1245955ea601 100644 --- a/docs/_docs/reference/error-codes/E100.md +++ b/docs/_docs/reference/error-codes/E100.md @@ -2,7 +2,6 @@ title: E100: Missing Empty Argument List kind: Error --- - # E100: Missing Empty Argument List This error is emitted when a nullary method (a method with an empty parameter list `()`) is called without the empty argument list. @@ -13,7 +12,7 @@ In Scala 3, the application syntax must follow exactly the parameter syntax. If ## Example -```scala sc:fail +```scala sc:fail sc-opts:-explain def next(): Int = 42 val n = next @@ -22,26 +21,36 @@ val n = next ### Error ```scala sc:nocompile --- [E100] Type Error: example.scala:3:8 +-- [E100] Syntax Error: example.scala:3:8 -------------------------------------- 3 |val n = next | ^^^^ | method next must be called with () argument + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Previously an empty argument list () was implicitly inserted when calling a nullary method without arguments. E.g. + | + | def next(): T = ... + | |next // is expanded to next() + | + | In Dotty, this idiom is an error. The application syntax has to follow exactly the parameter syntax. + | Excluded from this rule are methods that are defined in Java or that override methods defined in Java. + ----------------------------------------------------------------------------- ``` -### Solution +### Solution -```scala sc:compile +```scala sc:compile // Include the empty argument list def next(): Int = 42 val n = next() -``` +``` -```scala sc:compile +```scala sc:compile // Or define without () if no arguments are needed def next: Int = 42 val n = next ``` - diff --git a/docs/_docs/reference/error-codes/E101.md b/docs/_docs/reference/error-codes/E101.md new file mode 100644 index 000000000000..9676a625ff7e --- /dev/null +++ b/docs/_docs/reference/error-codes/E101.md @@ -0,0 +1,42 @@ +--- +title: E101: Duplicate Named Type Parameter +kind: Error +--- +# E101: Duplicate Named Type Parameter + +This error is emitted when a type parameter is defined multiple times in a named type argument list. + +When using named type arguments (type parameter names followed by `=` and a type), each type parameter can only be specified once. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +import scala.language.experimental.namedTypeArguments + +def example[A, B](a: A, b: B): (A, B) = (a, b) + +val result = example[A = Int, A = String](1, "hello") +``` + +### Error + +```scala sc:nocompile +-- [E101] Syntax Error: example.scala:5:34 ------------------------------------- +5 |val result = example[A = Int, A = String](1, "hello") + | ^^^^^^ + | Type parameter A was defined multiple times. +``` + +### Solution + +```scala sc:compile +// Use each type parameter name only once +import scala.language.experimental.namedTypeArguments + +def example[A, B](a: A, b: B): (A, B) = (a, b) + +val result = example[A = Int, B = String](1, "hello") +``` + diff --git a/docs/_docs/reference/error-codes/E102.md b/docs/_docs/reference/error-codes/E102.md new file mode 100644 index 000000000000..bc0a70356615 --- /dev/null +++ b/docs/_docs/reference/error-codes/E102.md @@ -0,0 +1,42 @@ +--- +title: E102: Undefined Named Type Parameter +kind: Error +--- +# E102: Undefined Named Type Parameter + +This error is emitted when a named type argument refers to a type parameter that does not exist in the definition. + +When using named type arguments, you must use the exact names of the type parameters as declared in the method or class definition. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +import scala.language.experimental.namedTypeArguments + +def example[A, B](a: A, b: B): (A, B) = (a, b) + +val result = example[A = Int, C = String](1, "hello") +``` + +### Error + +```scala sc:nocompile +-- [E102] Syntax Error: example.scala:5:34 ------------------------------------- +5 |val result = example[A = Int, C = String](1, "hello") + | ^^^^^^ + | Type parameter C is undefined. Expected one of A, B. +``` + +### Solution + +```scala sc:compile +// Use the correct, existing, type parameter name +import scala.language.experimental.namedTypeArguments + +def example[A, B](a: A, b: B): (A, B) = (a, b) + +val result = example[A = Int, B = String](1, "hello") +``` + diff --git a/docs/_docs/reference/error-codes/E103.md b/docs/_docs/reference/error-codes/E103.md new file mode 100644 index 000000000000..22994c71cf89 --- /dev/null +++ b/docs/_docs/reference/error-codes/E103.md @@ -0,0 +1,50 @@ +--- +title: E103: Illegal Start of Statement +kind: Error +--- +# E103: Illegal Start of Statement + +This error is emitted when the compiler encounters a token or expression that cannot legally begin a statement in that context. + +A statement is an import, export, a definition, or an expression. Some statements are only allowed in certain contexts. This error often occurs when the parser encounters something that looks like it could start a definition but is actually invalid syntax at the top level. + +One of the most common cases of this error is using an expression (e.g., method invocation) outside of a class or top-level member definition. + +--- + +## Example + +```scala sc:nocompile custom-sc:fail +package example + +def fa(f: String ?=> Unit): Unit = ??? +fa(42) +``` + +### Error + +```scala sc:nocompile +-- [E103] Syntax Error: example.scala:4:0 -------------------------------------- +4 |fa(42) + |^^ + |Illegal start of toplevel definition + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A statement is an import or export, a definition or an expression. + | Some statements are only allowed in certain contexts + ----------------------------------------------------------------------------- +``` + +### Solution + +Wrap the expression in a method definition: + +```scala sc:nocompile custom-sc:compile +// Wrap the call in a method definition +package example + +def fa(f: String ?=> Unit): Unit = ??? +def test: Unit = fa(()) +``` + diff --git a/docs/_docs/reference/error-codes/E104.md b/docs/_docs/reference/error-codes/E104.md new file mode 100644 index 000000000000..240d33aa1ecb --- /dev/null +++ b/docs/_docs/reference/error-codes/E104.md @@ -0,0 +1,67 @@ +--- +title: E104: Trait Is Expected +kind: Error +--- +# E104: Trait Is Expected + +This error is emitted when a class is used in a position where only a trait is allowed. + +In Scala, only traits can be mixed into classes using the `with` keyword. Classes cannot be mixed in this way. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +class A +class B + +val example = new A with B +``` + +### Error + +```scala sc:nocompile +-- [E104] Syntax Error: example.scala:4:25 ------------------------------------- +4 |val example = new A with B + | ^ + | class B is not a trait + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Only traits can be mixed into classes using a with keyword. + | Consider the following example: + | + | class A + | class B + | + | val a = new A with B // will fail with a compile error - class B is not a trait + | + | The example mentioned above would fail because B is not a trait. + | But if you make B a trait it will be compiled without any errors: + | + | class A + | trait B + | + | val a = new A with B // compiles normally + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Change the class to a trait +class A +trait B + +val example = new A with B +``` + +```scala sc:compile +// Or use extends instead of with +class A +class B extends A + +val example = new B() +``` + diff --git a/docs/_docs/reference/error-codes/E105.md b/docs/_docs/reference/error-codes/E105.md new file mode 100644 index 000000000000..e092a5f3b9e1 --- /dev/null +++ b/docs/_docs/reference/error-codes/E105.md @@ -0,0 +1,17 @@ +--- +title: E105: Trait Redefined Final Method From AnyRef +kind: Error +until: 3.0.0 +--- + +# E105: Trait Redefined Final Method From AnyRef + +This error is intended to be emitted when a trait attempts to redefine a final method from `AnyRef` (also known as `java.lang.Object`). + +The compiler message indicates: +- Traits cannot redefine final methods from `class AnyRef` +- Methods like `getClass`, `notify`, `notifyAll`, and `wait` are final in `AnyRef` + +Note: While this error message class exists in the compiler, it is not currently instantiated by any code path. Attempting to redefine these methods produces different errors (such as E120 DoubleDefinitionID). + + diff --git a/docs/_docs/reference/error-codes/E106.md b/docs/_docs/reference/error-codes/E106.md new file mode 100644 index 000000000000..82004a0d0ed0 --- /dev/null +++ b/docs/_docs/reference/error-codes/E106.md @@ -0,0 +1,25 @@ +--- +title: E106: Package Name Already Defined +kind: Error +--- + +# E106: Package Name Already Defined + +This error is emitted when a top-level definition (such as an object or class) has the same name as an existing package symbol. + +The compiler message indicates: +- The name is already used by a package +- The definition cannot coexist with a package of the same name + +This error typically occurs in incremental compilation scenarios where: +- A classfile exists defining a symbol with a certain name +- Source code attempts to define a package with the same name +- The conflict between the classfile and the package definition triggers this error + +Reproducing this error with simple source code is difficult as it requires specific classpath and compilation order conditions. + +To resolve this error, either: +- Rename the top-level definition to avoid the conflict +- Delete the conflicting classfile +- Reorganize your package structure + diff --git a/docs/_docs/reference/error-codes/E107.md b/docs/_docs/reference/error-codes/E107.md new file mode 100644 index 000000000000..6fea9c9286f8 --- /dev/null +++ b/docs/_docs/reference/error-codes/E107.md @@ -0,0 +1,64 @@ +--- +title: E107: Unapply Invalid Number of Arguments +kind: Error +--- +# E107: Unapply Invalid Number of Arguments + +This error is emitted when a pattern match uses an extractor with the wrong number of argument patterns. + +The number of argument patterns in a case clause must match the number of values returned by the extractor's `unapply` method. When `unapply` returns a `Boolean` (indicating match/no-match without extracting values), no argument patterns should be used. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +object IsEven: + def unapply(x: Int): Boolean = x % 2 == 0 + +def example(n: Int) = n match + case IsEven(x) => "even" + case _ => "odd" +``` + +### Error + +```scala sc:nocompile +-- [E107] Syntax Error: example.scala:5:13 ------------------------------------- +5 | case IsEven(x) => "even" + | ^^^^^^^^^ + | Wrong number of argument patterns for IsEven; expected: () + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The Unapply method of IsEven was used with incorrect number of arguments. + | Expected usage would be something like: + | case IsEven() => ... + | + | where subsequent arguments would have following types: (). + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Use empty argument list for Boolean-returning unapply +object IsEven: + def unapply(x: Int): Boolean = x % 2 == 0 + +def example(n: Int) = n match + case IsEven() => "even" + case _ => "odd" +``` + +```scala sc:compile +// Or use Option-returning unapply to extract values +object IsEven: + def unapply(x: Int): Option[Int] = + if x % 2 == 0 then Some(x) else None + +def example(n: Int) = n match + case IsEven(x) => s"even: $x" + case _ => "odd" +``` + diff --git a/docs/_docs/reference/error-codes/E108.md b/docs/_docs/reference/error-codes/E108.md new file mode 100644 index 000000000000..2e64cff80411 --- /dev/null +++ b/docs/_docs/reference/error-codes/E108.md @@ -0,0 +1,105 @@ +--- +title: E108: Unapply Invalid Return Type +kind: Error +--- +# E108: Unapply Invalid Return Type + +This error is emitted when an extractor's `unapply` or `unapplySeq` method has an invalid return type. + +To be used as an extractor, an `unapply` method must return a type that either: +- Has members `isEmpty: Boolean` and `get: S` (usually an `Option[S]`) +- Is a `Boolean` +- Is a `Product` (like a `Tuple2[T1, T2]`) + +--- + +## Example + +```scala sc:fail sc-opts:-explain +object MyExtractor: + def unapply(s: String): String = s + +def example(s: String) = s match + case MyExtractor(_) => "ok" + case _ => "no match" +``` + +### Error + +```scala sc:nocompile +-- [E108] Declaration Error: example.scala:5:18 -------------------------------- +5 | case MyExtractor(_) => "ok" + | ^^^^^^^^^^^^^^ + | String is not a valid result type of an unapply method of an extractor. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | + | To be used as an extractor, an unapply method has to return a type that either: + | - has members isEmpty: Boolean and get: S (usually an Option[S]) + | - is a Boolean + | - is a Product (like a Tuple2[T1, T2]) of arity i with i >= 1, and has members _1 to _i + | + | See: https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html#fixed-arity-extractors + | + | Examples: + | + | class A(val i: Int) + | + | object B { + | def unapply(a: A): Option[Int] = Some(a.i) + | } + | + | object C { + | def unapply(a: A): Boolean = a.i == 2 + | } + | + | object D { + | def unapply(a: A): (Int, Int) = (a.i, a.i) + | } + | + | object Test { + | def test(a: A) = a match { + | case B(1) => 1 + | case a @ C() => 2 + | case D(3, 3) => 3 + | } + | } + | + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Return Option[T] for single value extraction +object MyExtractor: + def unapply(s: String): Option[String] = Some(s) + +def example(s: String) = s match + case MyExtractor(x) => x + case _ => "no match" +``` + +```scala sc:compile +// Or return Boolean for test-only extraction +object IsEmpty: + def unapply(s: String): Boolean = s.isEmpty + +def example(s: String) = s match + case IsEmpty() => "empty" + case _ => "not empty" +``` + +```scala sc:compile +// Or return a tuple for multiple values +object Split: + def unapply(s: String): Option[(String, String)] = + val mid = s.length / 2 + Some((s.take(mid), s.drop(mid))) + +def example(s: String) = s match + case Split(a, b) => s"$a | $b" + case _ => "no match" +``` + diff --git a/docs/_docs/reference/error-codes/E109.md b/docs/_docs/reference/error-codes/E109.md new file mode 100644 index 000000000000..49bce6db3ea1 --- /dev/null +++ b/docs/_docs/reference/error-codes/E109.md @@ -0,0 +1,53 @@ +--- +title: E109: Static Fields Only Allowed in Objects +kind: Error +--- +# E109: Static Fields Only Allowed in Objects + +This error is emitted when the `@static` annotation is used on a member that is not inside an `object`. + +The `@static` annotation can only be applied to members defined within a Scala `object`, not in classes or traits. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +import scala.annotation.static + +class Example: + @static val count = 0 +``` + +### Error + +```scala sc:nocompile +-- [E109] Syntax Error: example.scala:4:14 ------------------------------------- +4 | @static val count = 0 + | ^^^^^^^^^^^^^^^^^^^^^ + |@static value count in class Example must be defined inside a static object. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | @static members are only allowed inside objects. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Move the @static member to an object +import scala.annotation.static + +class Example + +object Example: + @static val count = 0 +``` + +```scala sc:compile +// Or remove @static if you don't need static behavior +class Example: + val count = 0 +``` + diff --git a/docs/_docs/reference/error-codes/E110.md b/docs/_docs/reference/error-codes/E110.md new file mode 100644 index 000000000000..b3dbe5d78a67 --- /dev/null +++ b/docs/_docs/reference/error-codes/E110.md @@ -0,0 +1,52 @@ +--- +title: E110: Cyclic Inheritance +kind: Error +--- +# E110: Cyclic Inheritance + +This error is emitted when a class or trait extends itself, directly or indirectly. + +Cyclic inheritance is prohibited in Scala because it would create an impossible situation where a class needs to be fully defined before it can extend itself. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +class A extends A +``` + +### Error + +```scala sc:nocompile +-- [E110] Syntax Error: example.scala:1:16 ------------------------------------- +1 |class A extends A + | ^ + | Cyclic inheritance: class A extends itself + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Cyclic inheritance is prohibited in Dotty. + | Consider the following example: + | + | class A extends A + | + | The example mentioned above would fail because this type of inheritance hierarchy + | creates a "cycle" where a not yet defined class A extends itself which makes + | impossible to instantiate an object of this class + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Remove the cyclic inheritance +class A +``` + +```scala sc:compile +// Or create a proper inheritance hierarchy +class Base +class A extends Base +``` + diff --git a/docs/_docs/reference/error-codes/E111.md b/docs/_docs/reference/error-codes/E111.md new file mode 100644 index 000000000000..e19d9ee6b877 --- /dev/null +++ b/docs/_docs/reference/error-codes/E111.md @@ -0,0 +1,28 @@ +--- +title: E111: Bad Symbolic Reference +kind: Error +--- + +# E111: Bad Symbolic Reference + +This error is emitted when a compiled classfile refers to a symbol that cannot be found on the current classpath. + +The compiler message indicates: +- A signature in a classfile refers to a symbol that is not available +- The symbol may be completely missing from the classpath +- The classpath version might be incompatible with the version used when compiling the classfile + +This error typically occurs when: +- A dependency is missing from the classpath +- A dependency version is incompatible with other compiled code +- A required classfile has been deleted or corrupted +- Binary compatibility has been broken between library versions + +Reproducing this error with simple source code is difficult as it requires specific classpath conditions with missing or incompatible classfiles. + +To resolve this error: +- Add the missing dependency to your classpath +- Ensure all dependency versions are compatible +- Clean and rebuild your project +- Check that all required JAR files are present and not corrupted + diff --git a/docs/_docs/reference/error-codes/E112.md b/docs/_docs/reference/error-codes/E112.md new file mode 100644 index 000000000000..f1c2c4ad6ef9 --- /dev/null +++ b/docs/_docs/reference/error-codes/E112.md @@ -0,0 +1,50 @@ +--- +title: E112: Unable to Extend Sealed Class +kind: Error +--- + +# E112: Unable to Extend Sealed Class + +This error is emitted when attempting to extend a `sealed` class or trait from a different source file. + +Sealed classes and traits can only be extended in the same source file where they are declared. This restriction enables exhaustive pattern matching. + +--- + +## Example + +```scala sc:nocompile +sealed trait Animal +case class Dog(name: String) extends Animal +``` + +```scala sc:nocompile +case class Cat(name: String) extends Animal +``` + +### Error + +```scala sc:nocompile +-- [E112] Syntax Error: example.scala:1:32 +1 |case class Cat(name: String) extends Animal + | ^^^^^^ + | Cannot extend sealed trait Animal in a different source file +``` + +### Solution + +```scala sc:compile +// Define all subclasses in the same file as the sealed trait +sealed trait Animal +case class Dog(name: String) extends Animal +case class Cat(name: String) extends Animal +``` + +```scala sc:compile +// Or use an open or abstract class instead of sealed +abstract class Animal +case class Dog(name: String) extends Animal +// Cat can now be defined in another file +``` + + diff --git a/docs/_docs/reference/error-codes/E113.md b/docs/_docs/reference/error-codes/E113.md new file mode 100644 index 000000000000..de700d7398ce --- /dev/null +++ b/docs/_docs/reference/error-codes/E113.md @@ -0,0 +1,21 @@ +--- +title: E113: Symbol Has Unparsable Version Number +kind: Error +--- + +# E113: Symbol Has Unparsable Version Number + +This error is emitted when a symbol marked with the `@migration` annotation has a version number that cannot be parsed. + +The compiler message indicates: +- The symbol is marked with `@migration` indicating changed semantics between versions +- The `-Xmigration` setting is used to warn about constructs whose behavior may have changed +- The version number in the annotation is malformed + +The `@migration` annotation is used internally by the Scala standard library to mark methods whose behavior has changed between Scala versions. When the `-Xmigration` compiler flag is used, it warns about uses of these methods. + +Reproducing this error with simple user code is difficult as `@migration` is primarily used in the standard library. + +To resolve this error, ensure the version number in the `@migration` annotation follows a valid format (e.g., "2.13.0"). + +**Note** `-Xmigration` was never implemented in stable Scala 3, but `@migration` annotations be found by compiler when using Scala 2.13 libraries \ No newline at end of file diff --git a/docs/_docs/reference/error-codes/E114.md b/docs/_docs/reference/error-codes/E114.md new file mode 100644 index 000000000000..c4a630d0cc63 --- /dev/null +++ b/docs/_docs/reference/error-codes/E114.md @@ -0,0 +1,21 @@ +--- +title: E114: Symbol Changed Semantics In Version +kind: Warning +--- + +# E114: Symbol Changed Semantics In Version + +This warning is emitted when code uses a symbol that has been marked with the `@migration` annotation, indicating its semantics have changed in a specific Scala version. + +The compiler message indicates: +- The symbol has changed semantics in a particular version +- The `-Xmigration` setting is used to warn about such constructs +- A migration message describes what changed + +The `@migration` annotation is used internally by the Scala standard library to mark methods whose behavior has changed between Scala versions. When the `-Xmigration` compiler flag is used, it warns about uses of these methods to help with code migration. + +Reproducing this warning with simple user code is difficult as `@migration` is primarily used in the standard library and requires specific `-Xmigration` flag settings. + +To address this warning, review the migration message and update your code to account for the changed semantics if necessary. + +**Note** `-Xmigration` was never implemented in stable Scala 3, but `@migration` annotations be found by compiler when using Scala 2.13 libraries \ No newline at end of file diff --git a/docs/_docs/reference/error-codes/E115.md b/docs/_docs/reference/error-codes/E115.md new file mode 100644 index 000000000000..4f89f8b7b3e3 --- /dev/null +++ b/docs/_docs/reference/error-codes/E115.md @@ -0,0 +1,113 @@ +--- +title: E115: Unable to Emit Switch +kind: Warning +--- +# E115: Unable to Emit Switch + +This warning is emitted when the `@switch` annotation is used on a match expression that cannot be compiled to a JVM tableswitch or lookupswitch instruction. + +If annotated with `@switch`, the compiler will verify that the match has been compiled to a tableswitch or lookupswitch and issue an error if it instead compiles into a series of conditional expressions. + +The compiler will not apply the optimisation if: +- the matched value is not of type `Int`, `Byte`, `Short` or `Char` +- the matched value is not a constant literal +- there are less than three cases + +--- + +## Example + +```scala sc:fail sc-opts:-explain,-Werror +import scala.annotation.switch + +val ConstantB = 'B' +final val ConstantC = 'C' +def tokenMe(ch: Char) = (ch: @switch) match { + case '\t' | '\n' => 1 + case 'A' => 2 + case ConstantB => 3 // a non-literal may prevent switch generation: this would not compile + case ConstantC => 4 // a constant value is allowed + case _ => 5 +} +``` + +### Error + +```scala sc:nocompile +-- [E115] Syntax Warning: example.scala:5:38 ----------------------------------- + 5 |def tokenMe(ch: Char) = (ch: @switch) match { + | ^ + | Could not emit switch for @switch annotated match + 6 | case '\t' | '\n' => 1 + 7 | case 'A' => 2 + 8 | case ConstantB => 3 // a non-literal may prevent switch generation: this would not compile + 9 | case ConstantC => 4 // a constant value is allowed +10 | case _ => 5 +11 |} + |---------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | If annotated with @switch, the compiler will verify that the match has been compiled to a + | tableswitch or lookupswitch and issue an error if it instead compiles into a series of conditional + | expressions. Example usage: + | + | val ConstantB = 'B' + | final val ConstantC = 'C' + | def tokenMe(ch: Char) = (ch: @switch) match { + | case '\t' | '\n' => 1 + | case 'A' => 2 + | case ConstantB => 3 // a non-literal may prevent switch generation: this would not compile + | case ConstantC => 4 // a constant value is allowed + | case _ => 5 + | } + | + | The compiler will not apply the optimisation if: + | - the matched value is not of type Int, Byte, Short or Char + | - the matched value is not a constant literal + | - there are less than three cases + ---------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Make all constants final so they can be inlined +import scala.annotation.switch + +final val ConstantB = 'B' +final val ConstantC = 'C' +def tokenMe(ch: Char) = (ch: @switch) match { + case '\t' | '\n' => 1 + case 'A' => 2 + case ConstantB => 3 + case ConstantC => 4 + case _ => 5 +} +``` + +```scala sc:compile +// Or use literal values directly +import scala.annotation.switch + +def tokenMe(ch: Char) = (ch: @switch) match { + case '\t' | '\n' => 1 + case 'A' => 2 + case 'B' => 3 + case 'C' => 4 + case _ => 5 +} +``` + +```scala sc:compile +// Or remove @switch if optimization is not required +val ConstantB = 'B' +final val ConstantC = 'C' +def tokenMe(ch: Char) = ch match { + case '\t' | '\n' => 1 + case 'A' => 2 + case ConstantB => 3 + case ConstantC => 4 + case _ => 5 +} +``` + diff --git a/docs/_docs/reference/error-codes/E116.md b/docs/_docs/reference/error-codes/E116.md new file mode 100644 index 000000000000..424614766bff --- /dev/null +++ b/docs/_docs/reference/error-codes/E116.md @@ -0,0 +1,53 @@ +--- +title: E116: Missing Companion for Static +kind: Error +--- +# E116: Missing Companion for Static + +This error is emitted when an object contains `@static` members but does not have a companion class. + +Objects with `@static` members must have a companion class because the static members are placed in the companion class's bytecode. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +import scala.annotation.static + +object Example: + @static val count = 0 +``` + +### Error + +```scala sc:nocompile +-- [E116] Syntax Error: example.scala:4:14 ------------------------------------- +4 | @static val count = 0 + | ^^^^^^^^^^^^^^^^^^^^^ + | object Example does not have a companion class + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | An object that contains @static members must have a companion class. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Add a companion class +import scala.annotation.static + +class Example + +object Example: + @static val count = 0 +``` + +```scala sc:compile +// Or remove @static if you don't need static behavior +object Example: + val count = 0 +``` + diff --git a/docs/_docs/reference/error-codes/E117.md b/docs/_docs/reference/error-codes/E117.md new file mode 100644 index 000000000000..edbbc24e96ec --- /dev/null +++ b/docs/_docs/reference/error-codes/E117.md @@ -0,0 +1,49 @@ +--- +title: E117: Polymorphic Method Missing Type in Parent +kind: Error +--- +# E117: Polymorphic Method Missing Type in Parent + +This error is emitted when a structural refinement includes a polymorphic (generic) method that does not override a method in the parent type. + +Structural refinement in Scala does not allow for polymorphic methods that are not already defined in the parent type. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +type Example = AnyRef { def foo[T](x: T): T } +``` + +### Error + +```scala sc:nocompile +-- [E117] Syntax Error: example.scala:1:28 ------------------------------------- +1 |type Example = AnyRef { def foo[T](x: T): T } + | ^^^^^^^^^^^^^^^^^^^ + |Polymorphic refinement method foo without matching type in parent type AnyRef is no longer allowed + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Polymorphic method foo is not allowed in the structural refinement of type AnyRef because + | method foo does not override any method in type AnyRef. Structural refinement does not allow for + | polymorphic methods. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Define the polymorphic method in a trait +trait HasFoo: + def foo[T](x: T): T + +type Example = HasFoo +``` + +```scala sc:compile +// Or use a non-polymorphic method in the refinement +type Example = AnyRef { def foo(x: Int): Int } +``` + diff --git a/docs/_docs/reference/error-codes/E118.md b/docs/_docs/reference/error-codes/E118.md new file mode 100644 index 000000000000..8b89a255d239 --- /dev/null +++ b/docs/_docs/reference/error-codes/E118.md @@ -0,0 +1,39 @@ +--- +title: E118: Params No Inline +kind: Error +--- +# E118: Params No Inline + +This error is emitted when the `inline` modifier is used on parameters of a non-inline method. + +The `inline` modifier on parameters is only allowed for parameters of `inline` methods, where it enables the parameter to be inlined at the call site. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +def example(inline x: Int): Int = x + 1 +``` + +### Error + +```scala sc:nocompile +-- [E118] Syntax Error: example.scala:1:19 ------------------------------------- +1 |def example(inline x: Int): Int = x + 1 + | ^ + | inline modifier can only be used for parameters of inline methods +``` + +### Solution + +```scala sc:compile +// Make the method inline as well +inline def example(inline x: Int): Int = x + 1 +``` + +```scala sc:compile +// Or remove inline from the parameter +def example(x: Int): Int = x + 1 +``` + diff --git a/docs/_docs/reference/error-codes/E119.md b/docs/_docs/reference/error-codes/E119.md new file mode 100644 index 000000000000..a31b64262127 --- /dev/null +++ b/docs/_docs/reference/error-codes/E119.md @@ -0,0 +1,40 @@ +--- +title: E119: Symbol Is Not a Value +kind: Error +--- +# E119: Symbol Is Not a Value + +This error is emitted when a package or Java-defined class is used in a position where a value is expected. + +Packages and Java classes (without companion objects) cannot be used as values in Scala. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +val x = scala.collection +``` + +### Error + +```scala sc:nocompile +-- [E119] Type Error: example.scala:1:14 --------------------------------------- +1 |val x = scala.collection + | ^^^^^^^^^^^^^^^^ + | package scala.collection is not a value +``` + +### Solution + +```scala sc:compile +// Use a specific value from the package +val x = scala.collection.immutable.List +``` + +```scala sc:compile +// Or import and use a specific type +import scala.collection.mutable.ArrayBuffer +val x = ArrayBuffer[Int]() +``` + diff --git a/docs/_docs/reference/error-codes/E120.md b/docs/_docs/reference/error-codes/E120.md new file mode 100644 index 000000000000..d85a4a6a9705 --- /dev/null +++ b/docs/_docs/reference/error-codes/E120.md @@ -0,0 +1,96 @@ +--- +title: E120: Double Definition +kind: Error +--- +# E120: Double Definition + +This error is emitted when two definitions conflict because they have the same name and type after erasure. + +Due to JVM type erasure, generic parameters are removed at runtime. This can cause methods with different generic signatures to have identical runtime signatures, creating a conflict. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +class Example: + def process(list: List[Int]): Unit = () + def process(list: List[String]): Unit = () +``` + +### Error + +```scala sc:nocompile +-- [E120] Naming Error: example.scala:3:6 -------------------------------------- +3 | def process(list: List[String]): Unit = () + | ^ + |Conflicting definitions: + |def process(list: List[Int]): Unit in class Example at line 2 and + |def process(list: List[String]): Unit in class Example at line 3 + |have the same type (list: List): Unit after erasure. + | + |Consider adding a @targetName annotation to one of the conflicting definitions + |for disambiguation. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | + | As part of the Scala compilation pipeline every type is reduced to its erased + | (runtime) form. In this phase, among other transformations, generic parameters + | disappear and separate parameter-list boundaries are flattened. + | + | For example, both `f[T](x: T)(y: String): Unit` and `f(x: Any, z: String): Unit` + | erase to the same runtime signature `f(x: Object, y: String): Unit`. Note that + | parameter names are irrelevant. + | + | In your code the two declarations + | + | def process(list: List[Int]): Unit + | def process(list: List[String]): Unit + | + | erase to the identical signature + | + | (list: List): Unit + | + | so the compiler cannot keep both: the generated bytecode symbols would collide. + | + | To fix this error, you must disambiguate the two definitions by doing one of the following: + | + | 1. Rename one of the definitions. + | 2. Keep the same names in source but give one definition a distinct + | bytecode-level name via `@targetName`; for example: + | + | @targetName("process_2") + | def process(list: List[String]): Unit + | + | Choose the `@targetName` argument carefully: it is the name that will be used + | when calling the method externally, so it should be unique and descriptive. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Use different method names +class Example: + def processInts(list: List[Int]): Unit = () + def processStrings(list: List[String]): Unit = () +``` + +```scala sc:compile +// Or use @targetName to give them different bytecode names +import scala.annotation.targetName + +class Example: + def process(list: List[Int]): Unit = () + + @targetName("processStrings") + def process(list: List[String]): Unit = () +``` + +```scala sc:compile +// Or combine into a single generic method +class Example: + def process[T](list: List[T]): Unit = () +``` + diff --git a/docs/_docs/reference/error-codes/E121.md b/docs/_docs/reference/error-codes/E121.md new file mode 100644 index 000000000000..eb3530ccbef5 --- /dev/null +++ b/docs/_docs/reference/error-codes/E121.md @@ -0,0 +1,47 @@ +--- +title: E121: Match Case Only Null Warning +kind: Warning +--- +# E121: Match Case Only Null Warning + +This warning is emitted when a pattern match case can only match `null` and nothing else. + +This typically indicates a case that is effectively unreachable for non-null values because all non-null cases have already been covered by previous patterns. If matching `null` is intentional, it should be written explicitly as `case null =>`. + +--- + +## Example + +```scala sc:fail sc-opts:-explain,-Werror +def example(s: String | Int): Int = s match + case _: Int => 1 + case _: String => 2 + case _ => 3 +``` + +### Error + +```scala sc:nocompile +-- [E121] Pattern Match Warning: example.scala:4:7 ----------------------------- +4 | case _ => 3 + | ^ + |Unreachable case except for null (if this is intentional, consider writing case null => instead). +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use explicit null pattern if matching null is intentional +def example(s: String | Int): Int = s match + case _: Int => 1 + case _: String => 2 + case null => 3 +``` + +```scala sc:compile sc-opts:-Werror +// Or remove the unreachable case if null matching is not needed +def example(s: String | Int): Int = s match + case _: Int => 1 + case _: String => 2 +``` + diff --git a/docs/_docs/reference/error-codes/E122.md b/docs/_docs/reference/error-codes/E122.md new file mode 100644 index 000000000000..b258e9fc0db5 --- /dev/null +++ b/docs/_docs/reference/error-codes/E122.md @@ -0,0 +1,39 @@ +--- +title: E122: Imported Twice +kind: Error +--- +# E122: Imported Twice + +This error is emitted when the same name is imported twice on the same import line. + +Each import line should only import a name once. Duplicate imports on the same line are redundant and indicate a likely mistake. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +import scala.collection.mutable.{ArrayBuffer, ArrayBuffer} +``` + +### Error + +```scala sc:nocompile +-- [E122] Syntax Error: example.scala:1:46 ------------------------------------- +1 |import scala.collection.mutable.{ArrayBuffer, ArrayBuffer} + | ^^^^^^^^^^^ + | ArrayBuffer is imported twice on the same import line. +``` + +### Solution + +```scala sc:compile +// Import each name only once +import scala.collection.mutable.ArrayBuffer +``` + +```scala sc:compile +// Or if you need aliases, use different names +import scala.collection.mutable.{ArrayBuffer, ArrayBuffer as MutableBuffer} +``` + diff --git a/docs/_docs/reference/error-codes/E123.md b/docs/_docs/reference/error-codes/E123.md new file mode 100644 index 000000000000..3d8ce630357b --- /dev/null +++ b/docs/_docs/reference/error-codes/E123.md @@ -0,0 +1,39 @@ +--- +title: E123: Type Test Always Diverges +kind: Warning +--- +# E123: Type Test Always Diverges + +This warning is emitted when a type test (via `isInstanceOf` or pattern matching) is performed on a scrutinee whose type cannot contain any value, meaning the test can never return a result. + +This typically occurs when the scrutinee has type `Nothing`, such as expressions like `???`, `throw`, or values explicitly typed as `Nothing`. Since `Nothing` has no instances, the type test will never complete - evaluating the scrutinee will always diverge before the test can be performed. + +--- + +## Example + +```scala sc:fail sc-opts:-explain,-Werror +def example: Boolean = ???.isInstanceOf[String] +``` + +### Error + +```scala sc:nocompile +-- [E123] Syntax Warning: example.scala:1:39 ----------------------------------- +1 |def example: Boolean = ???.isInstanceOf[String] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + |This type test will never return a result since the scrutinee type (??? : => Nothing) does not contain any value. +``` + +### Solution + +```scala sc:compile +// Use a type that can contain values +def example(x: Any): Boolean = x.isInstanceOf[String] +``` + +```scala sc:compile +// Or acknowledge that the code path is unreachable +def example: Boolean = ??? // Returns Nothing, no type test needed +``` + diff --git a/docs/_docs/reference/error-codes/E124.md b/docs/_docs/reference/error-codes/E124.md new file mode 100644 index 000000000000..5e43943b1eae --- /dev/null +++ b/docs/_docs/reference/error-codes/E124.md @@ -0,0 +1,55 @@ +--- +title: E124: Term Member Needs Result Type for Implicit Search +kind: Error +--- +# E124: Term Member Needs Result Type for Implicit Search + +This error is emitted when a term member's definition requires an implicit search, but the implicit search cannot proceed without knowing the result type of the member first. + +The right-hand side of the definition requires an implicit search at the highlighted position. To avoid this error, give the member an explicit type. + +--- + +## Example + +```scala sc:fail sc-opts:-explain-cyclic +def example = + implicit val i = implicitly[Int] +``` + +### Error + +```scala sc:nocompile +-- [E124] Cyclic Error: example.scala:2:29 ------------------------------------- +2 | implicit val i = implicitly[Int] + | ^ + |value i needs result type because its right-hand side attempts implicit search + | + |The error occurred while trying to compute the signature of method example + | which required to type the right hand side of method example since no explicit type was given + | which required to compute the signature of value i + | which required to type the right hand side of value i since no explicit type was given + | which required to searching for an implicit argument of type Int + | which required to compute the signature of value i + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The right hand-side of value i's definition requires an implicit search at the highlighted position. + | To avoid this error, give `value i` an explicit type. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile +// Add an explicit result type to avoid the cyclic dependency +// and ensure the implicit is available from an outer scope +given Int = 42 + +def example = + val i: Int = summon[Int] + i +``` + diff --git a/docs/_docs/reference/error-codes/E125.md b/docs/_docs/reference/error-codes/E125.md new file mode 100644 index 000000000000..51d8c2459175 --- /dev/null +++ b/docs/_docs/reference/error-codes/E125.md @@ -0,0 +1,50 @@ +--- +title: E125: Class Cannot Extend Enum +kind: Error +--- +# E125: Class Cannot Extend Enum + +This error is emitted when a class attempts to extend an enum. + +In Scala 3, enums are sealed by design and can only be extended by their defined cases within the same enum declaration. External classes cannot extend enums. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +enum Color: + case Red, Green, Blue + +class CustomColor extends Color +``` + +### Error + +```scala sc:nocompile +-- [E125] Syntax Error: example.scala:4:6 -------------------------------------- +4 |class CustomColor extends Color + |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |class CustomColor in package extends enum Color, but extending enums is prohibited. +``` + +### Solution + +```scala sc:compile +// Add new cases within the enum definition +enum Color: + case Red, Green, Blue + case Custom(rgb: Int) +``` + +```scala sc:compile +// Or use a sealed trait if you need external extensibility +sealed trait Color +object Color: + case object Red extends Color + case object Green extends Color + case object Blue extends Color + +case class CustomColor(rgb: Int) extends Color +``` + diff --git a/docs/_docs/reference/error-codes/E126.md b/docs/_docs/reference/error-codes/E126.md new file mode 100644 index 000000000000..26c16e739753 --- /dev/null +++ b/docs/_docs/reference/error-codes/E126.md @@ -0,0 +1,40 @@ +--- +title: E126: Value Class Parameter May Not Be Call-By-Name +kind: Error +--- +# E126: Value Class Parameter May Not Be Call-By-Name + +This error occurs when a value class (a class that extends `AnyVal`) has a call-by-name parameter (using `=> T` syntax). + +Value classes are a special mechanism in Scala that allows defining wrapper classes that avoid runtime allocation overhead. The JVM represents value class instances as their underlying value at runtime. Call-by-name parameters, which are evaluated lazily each time they are accessed, are incompatible with this optimization because they cannot be unboxed to a primitive value. + +--- + +## Example + +```scala sc:fail +class Wrapper(x: => Int) extends AnyVal +``` + +### Error + +```scala sc:nocompile +-- [E126] Syntax Error: example.scala:1:14 ------------------------------------- +1 |class Wrapper(x: => Int) extends AnyVal + | ^ + | Value class parameter `x` may not be call-by-name +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use a regular (by-value) parameter +class Wrapper(val x: Int) extends AnyVal +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: If lazy evaluation is needed, consider using a regular class +class Wrapper(x: => Int): + def value: Int = x +``` + diff --git a/docs/_docs/reference/error-codes/E127.md b/docs/_docs/reference/error-codes/E127.md new file mode 100644 index 000000000000..99054d4b11c5 --- /dev/null +++ b/docs/_docs/reference/error-codes/E127.md @@ -0,0 +1,78 @@ +--- +title: E127: Not An Extractor +kind: Error +--- +# E127: Not An Extractor + +This error occurs when attempting to use a type as an extractor in a pattern match, but the type lacks an appropriate `unapply` or `unapplySeq` method. + +In Scala, pattern matching with extractor syntax (like `case Foo(x)`) requires the type to have an `unapply` or `unapplySeq` method. Case classes automatically get these methods, but regular classes do not. + +An `unapply` method should be in an `object`, take a single explicit term parameter, and: +- If it is just a test, return a `Boolean`. For example `case even()` +- If it returns a single sub-value of type T, return an `Option[T]` +- If it returns several sub-values T1,...,Tn, group them in an optional tuple `Option[(T1,...,Tn)]` + +Additionally, `unapply` or `unapplySeq` methods cannot take type parameters after their explicit term parameter. + +Sometimes, the number of sub-values isn't fixed and we would like to return a sequence. +For this reason, you can also define patterns through `unapplySeq` which returns `Option[Seq[T]]`. +This mechanism is used for instance in pattern `case List(x1, ..., xn)`. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +class Box(val x: Int) + +def example(a: Any) = a match + case Box(x) => () +``` + +### Error + +```scala sc:nocompile +-- [E127] Pattern Match Error: example.scala:4:7 ------------------------------- +4 | case Box(x) => () + | ^^^ + |Box cannot be used as an extractor in a pattern because it lacks an unapply or unapplySeq method with the appropriate signature + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | An unapply method should be in an object, take a single explicit term parameter, and: + | - If it is just a test, return a Boolean. For example case even() + | - If it returns a single sub-value of type T, return an Option[T] + | - If it returns several sub-values T1,...,Tn, group them in an optional tuple Option[(T1,...,Tn)] + | + | Additionaly, unapply or unapplySeq methods cannot take type parameters after their explicit term parameter. + | + | Sometimes, the number of sub-values isn't fixed and we would like to return a sequence. + | For this reason, you can also define patterns through unapplySeq which returns Option[Seq[T]]. + | This mechanism is used for instance in pattern case List(x1, ..., xn) + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use a case class which automatically provides an unapply method +case class Box(x: Int) + +def example(a: Any) = a match + case Box(x) => x + case _ => 0 +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Define an explicit companion object with an unapply method +class Box(val x: Int) + +object Box: + def unapply(box: Box): Option[Int] = Some(box.x) + +def example(a: Any) = a match + case Box(x) => x + case _ => 0 +``` + diff --git a/docs/_docs/reference/error-codes/E128.md b/docs/_docs/reference/error-codes/E128.md new file mode 100644 index 000000000000..5642cadfb217 --- /dev/null +++ b/docs/_docs/reference/error-codes/E128.md @@ -0,0 +1,57 @@ +--- +title: E128: Member With Same Name As Static +kind: Error +--- +# E128: Member With Same Name As Static + +This error occurs when a companion class defines a member with the same name as a `@static` member in the companion object. + +The `@static` annotation in Scala allows members to be exposed as static members at the JVM level. When a companion object has a `@static` member, the companion class cannot have a member with the same name because this would create a naming conflict in the generated bytecode. + +--- + +## Example + +```scala sc:fail +import scala.annotation.static + +class Example: + val count: Int = 1 + +object Example: + @static val count: Int = 0 +``` + +### Error + +```scala sc:nocompile +-- [E128] Syntax Error: example.scala:7:14 ------------------------------------- +7 | @static val count: Int = 0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + |Companion classes cannot define members with same name as a @static member +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Rename the @static member in the companion object to avoid conflict +import scala.annotation.static + +class Example: + val count: Int = 1 + +object Example: + @static val defaultCount: Int = 0 +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Rename the member in the companion class +import scala.annotation.static + +class Example: + val instanceCount: Int = 1 + +object Example: + @static val count: Int = 0 +``` + diff --git a/docs/_docs/reference/error-codes/E129.md b/docs/_docs/reference/error-codes/E129.md new file mode 100644 index 000000000000..ef51c5f01ad5 --- /dev/null +++ b/docs/_docs/reference/error-codes/E129.md @@ -0,0 +1,56 @@ +--- +title: E129: Pure Expression In Statement Position +kind: Warning +--- +# E129: Pure Expression In Statement Position + +This warning is emitted when a pure expression (one without side effects) is used in statement position where its result is not used. + +A pure expression does nothing in statement position because it has no side effect and its result is not assigned to a variable or returned. Such expressions can be safely removed without changing the program's semantics, which often indicates a programming error such as a missing assignment or function call. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +def example(): Unit = + 1 + () +``` + +### Warning + +```scala sc:nocompile +-- [E129] Potential Issue Warning: example.scala:2:2 --------------------------- +2 | 1 + | ^ + | A pure expression does nothing in statement position + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The pure expression 1 doesn't have any side effect and its result is not assigned elsewhere. + | It can be removed without changing the semantics of the program. This may indicate an error. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Remove the unused pure expression +def example(): Unit = + () +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Assign the value to a variable if it was intended to be used +def example(): Int = + val x = 1 + x + 1 +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: If the expression was meant to be returned, remove trailing statements +def example(): Int = + 1 +``` + diff --git a/docs/_docs/reference/error-codes/E130.md b/docs/_docs/reference/error-codes/E130.md new file mode 100644 index 000000000000..783ca22ce779 --- /dev/null +++ b/docs/_docs/reference/error-codes/E130.md @@ -0,0 +1,64 @@ +--- +title: E130: Trait Companion With Mutable Static +kind: Error +--- +# E130: Trait Companion With Mutable Static + +This error occurs when a companion object of a trait defines a mutable field with the `@static` annotation. + +The `@static` annotation in Scala allows members to be exposed as static members at the JVM level. However, mutable `@static` fields (declared with `var`) are not allowed in companion objects of traits due to initialization order complexities and thread-safety concerns in the JVM. + +--- + +## Example + +```scala sc:fail +import scala.annotation.static + +trait Example + +object Example: + @static var count: Int = 0 +``` + +### Error + +```scala sc:nocompile +-- [E130] Syntax Error: example.scala:6:14 ------------------------------------- +6 | @static var count: Int = 0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Companion of traits cannot define mutable @static fields +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use an immutable @static val instead +import scala.annotation.static + +trait Example + +object Example: + @static val count: Int = 0 +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Use a class companion instead of a trait companion +import scala.annotation.static + +class Example + +object Example: + @static var count: Int = 0 +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Use a non-static mutable field +import scala.annotation.static + +trait Example + +object Example: + var count: Int = 0 +``` + diff --git a/docs/_docs/reference/error-codes/E131.md b/docs/_docs/reference/error-codes/E131.md new file mode 100644 index 000000000000..4391f4f9757b --- /dev/null +++ b/docs/_docs/reference/error-codes/E131.md @@ -0,0 +1,54 @@ +--- +title: E131: Lazy Static Field +kind: Error +--- +# E131: Lazy Static Field + +This error occurs when a `lazy val` is annotated with `@static`. + +The `@static` annotation in Scala allows members to be exposed as static fields at the JVM level. However, lazy values cannot be marked as `@static` because the JVM's static field initialization mechanism is incompatible with Scala's lazy initialization semantics. Lazy vals require wrapper code for thread-safe initialization, which cannot be represented as a simple static field. + +--- + +## Example + +```scala sc:fail +import scala.annotation.static + +class Example + +object Example: + @static lazy val count: Int = 0 +``` + +### Error + +```scala sc:nocompile +-- [E131] Syntax Error: example.scala:6:19 ------------------------------------- +6 | @static lazy val count: Int = 0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Lazy @static fields are not supported +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use a non-lazy @static val +import scala.annotation.static + +class Example + +object Example: + @static val count: Int = 0 +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Keep it lazy but remove @static +import scala.annotation.static + +class Example + +object Example: + lazy val count: Int = 0 +``` + diff --git a/docs/_docs/reference/error-codes/E132.md b/docs/_docs/reference/error-codes/E132.md new file mode 100644 index 000000000000..f07dedccb890 --- /dev/null +++ b/docs/_docs/reference/error-codes/E132.md @@ -0,0 +1,63 @@ +--- +title: E132: Static Overriding Non-Static Members +kind: Error +--- +# E132: Static Overriding Non-Static Members + +This error occurs when a `@static` member in a companion object tries to override or implement a non-static member from a parent trait or class. + +The `@static` annotation causes a member to be compiled as a JVM static member. Static members cannot participate in inheritance hierarchies because they are not part of instances and cannot be dynamically dispatched. Therefore, a `@static` member cannot override or implement abstract members from parent types. + +--- + +## Example + +```scala sc:fail +import scala.annotation.static + +trait Parent: + def value: Int + +class Child + +object Child extends Parent: + @static def value: Int = 42 +``` + +### Error + +```scala sc:nocompile +-- [E132] Syntax Error: example.scala:9:14 ------------------------------------- +9 | @static def value: Int = 42 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | @static members cannot override or implement non-static ones +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Remove the @static annotation to allow proper implementation +import scala.annotation.static + +trait Parent: + def value: Int + +class Child + +object Child extends Parent: + def value: Int = 42 +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Don't extend the trait and use a different method name +import scala.annotation.static + +trait Parent: + def value: Int + +class Child + +object Child: + @static def staticValue: Int = 42 +``` + diff --git a/docs/_docs/reference/error-codes/E133.md b/docs/_docs/reference/error-codes/E133.md new file mode 100644 index 000000000000..de3b9e45fb48 --- /dev/null +++ b/docs/_docs/reference/error-codes/E133.md @@ -0,0 +1,55 @@ +--- +title: E133: Overload In Refinement +kind: Error +--- +# E133: Overload In Refinement + +This error occurs when a refinement type introduces an overloaded definition. + +In Scala, refinement types (structural types) can add or refine members of a base type. However, they cannot introduce overloaded methods because refinements are meant to describe structural constraints, not create new method signatures that would conflict with existing ones. Adding an overload would change the semantics of method resolution in ways that are not supported by refinement types. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +trait Base: + def foo(x: Int): Int + +type Refined = Base { def foo(x: String): String } +``` + +### Error + +```scala sc:nocompile +-- [E133] Declaration Error: example.scala:4:26 -------------------------------- +4 |type Refined = Base { def foo(x: String): String } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Refinements cannot introduce overloaded definitions + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The refinement `method foo` introduces an overloaded definition. + | Refinements cannot contain overloaded definitions. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use a different method name in the refinement +trait Base: + def foo(x: Int): Int + +type Refined = Base { def bar(x: String): String } +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Define a trait with both methods instead of using refinement +trait Base: + def foo(x: Int): Int + +trait Refined extends Base: + def foo(x: String): String +``` + diff --git a/docs/_docs/reference/error-codes/E134.md b/docs/_docs/reference/error-codes/E134.md new file mode 100644 index 000000000000..f7a0384b0123 --- /dev/null +++ b/docs/_docs/reference/error-codes/E134.md @@ -0,0 +1,58 @@ +--- +title: E134: No Matching Overload +kind: Error +--- +# E134: No Matching Overload + +This error occurs when none of the overloaded alternatives of a method match the expected type. + +When a method is overloaded (has multiple definitions with different parameter types), Scala needs to select which overload to use based on the expected type. This error appears when the expected type doesn't match any of the available overloaded signatures. + +--- + +## Example + +```scala sc:fail +object Example: + def foo(x: Int): Int = x + def foo(x: String): String = x + +def example(): Unit = + val f: Boolean => Boolean = Example.foo +``` + +### Error + +```scala sc:nocompile +-- [E134] Type Error: example.scala:6:38 --------------------------------------- +6 | val f: Boolean => Boolean = Example.foo + | ^^^^^^^^^^^ + |None of the overloaded alternatives of method foo in object Example with types + | (x: String): String + | (x: Int): Int + |match expected type Boolean => Boolean +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use a type that matches one of the overloaded alternatives +object Example: + def foo(x: Int): Int = x + def foo(x: String): String = x + +def example(): Unit = + val f: Int => Int = Example.foo +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Add an overload that matches the expected type +object Example: + def foo(x: Int): Int = x + def foo(x: String): String = x + def foo(x: Boolean): Boolean = x + +def example(): Unit = + val f: Boolean => Boolean = Example.foo +``` + diff --git a/docs/_docs/reference/error-codes/E135.md b/docs/_docs/reference/error-codes/E135.md new file mode 100644 index 000000000000..cde2aeca7389 --- /dev/null +++ b/docs/_docs/reference/error-codes/E135.md @@ -0,0 +1,53 @@ +--- +title: E135: Stable Identifier Pattern +kind: Error +--- +# E135: Stable Identifier Pattern + +This error occurs when using a non-stable identifier in a pattern match where a stable identifier is required. + +In Scala pattern matching, when you use backticks to match against an existing value (e.g., `` `x` ``), the referenced identifier must be stable. A stable identifier is one whose value cannot change, such as a `val`, an `object`, or a stable path. Mutable variables (`var`) are not stable identifiers because their values can change. + +Using a mutable variable in a pattern would be problematic because the value being matched against could change during or after the match, leading to inconsistent behavior. + +--- + +## Example + +```scala sc:fail +def example(a: Any) = + var x = 1 + a match + case `x` => "matched x" + case _ => "other" +``` + +### Error + +```scala sc:nocompile +-- [E135] Type Error: example.scala:4:9 ---------------------------------------- +4 | case `x` => "matched x" + | ^^^ + | Stable identifier required, but `x` found +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use a val instead of a var for the stable identifier +def example(a: Any) = + val x = 1 + a match + case `x` => "matched x" + case _ => "other" +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Use a guard condition instead of stable identifier +def example(a: Any) = + var x = 1 + a match + case y if y == x => "matched x" + case _ => "other" +``` + diff --git a/docs/_docs/reference/error-codes/E136.md b/docs/_docs/reference/error-codes/E136.md new file mode 100644 index 000000000000..8fe2b5ec6948 --- /dev/null +++ b/docs/_docs/reference/error-codes/E136.md @@ -0,0 +1,61 @@ +--- +title: E136: Static Fields Should Precede Non-Static +kind: Error +--- +# E136: Static Fields Should Precede Non-Static + +This error occurs when a `@static` field is defined after non-static fields in a companion object. + +The `@static` annotation causes fields to be initialized during class loading, while non-static fields are initialized only when the object is first accessed. To avoid surprises in initialization order, Scala requires all `@static` fields to be declared before any non-static fields in the same object. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +import scala.annotation.static + +class Example + +object Example: + val nonStatic: Int = 1 + @static val staticField: Int = 2 +``` + +### Error + +```scala sc:nocompile +-- [E136] Syntax Error: example.scala:7:14 ------------------------------------- +7 | @static val staticField: Int = 2 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |@static value staticField in object Example must be defined before non-static fields. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The fields annotated with @static should precede any non @static fields. + | This ensures that we do not introduce surprises for users in initialization order of this class. + | Static field are initialized when class loading the code of Foo. + | Non static fields are only initialized the first time that Foo is accessed. + | + | The definition of staticField should have been before the non @static vals: + | object Example { + | | @static val staticField = ... + | | val nonStatic = ... + | | ... + | |} + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Move @static fields before non-static fields +import scala.annotation.static + +class Example + +object Example: + @static val staticField: Int = 2 + val nonStatic: Int = 1 +``` + diff --git a/docs/_docs/reference/error-codes/E137.md b/docs/_docs/reference/error-codes/E137.md new file mode 100644 index 000000000000..974d0d903558 --- /dev/null +++ b/docs/_docs/reference/error-codes/E137.md @@ -0,0 +1,89 @@ +--- +title: E137: Illegal Super Accessor +kind: Error +--- +# E137: Illegal Super Accessor + +This error occurs when a class cannot be defined due to a conflict between its parent traits when implementing a super-accessor. + +When a trait calls `super.method` without explicitly naming a parent (like `super[Parent].method`), Scala generates a super-accessor in the extending class based on the linearization order. If the resolved super-call has an incompatible return type with what the trait expects, this error is raised. + +This typically happens when: +1. A trait contains a `super.method` call +2. Another trait in the hierarchy overrides the same method with a different return type +3. Due to linearization order, the super-accessor would bind to the wrong implementation + +--- + +## Example + +```scala sc:fail +class X +class Y extends X + +trait A[+T]: + def foo: T = null.asInstanceOf[T] + +trait B extends A[X]: + override def foo: X = new X + +trait C extends A[Y]: + override def foo: Y = new Y + def superFoo: Y = super.foo + +class Fail extends B with C +``` + +### Error + +```scala sc:nocompile +-- [E137] Declaration Error: example.scala:14:6 -------------------------------- +14 |class Fail extends B with C + | ^ + |class Fail cannot be defined due to a conflict between its parents when + |implementing a super-accessor for foo in trait C: + | + |1. One of its parent (C) contains a call super.foo in its body, + | and when a super-call in a trait is written without an explicit parent + | listed in brackets, it is implemented by a generated super-accessor in + | the class that extends this trait based on the linearization order of + | the class. + |2. Because B comes before C in the linearization + | order of Fail, and because B overrides foo, + | the super-accessor in Fail is implemented as a call to + | super[B].foo. + |3. However, + | X (the type of super[B].foo in Fail) + | is not a subtype of + | Y (the type of foo in trait C). + | Hence, the super-accessor that needs to be generated in Fail + | is illegal. + | + |Here are two possible ways to resolve this: + | + |1. Change the linearization order of Fail such that + | C comes before B. + |2. Alternatively, replace super.foo in the body of trait C by a + | super-call to a specific parent, e.g. super[A].foo +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use explicit super-call in the trait +class X +class Y extends X + +trait A[+T]: + def foo: T = null.asInstanceOf[T] + +trait B extends A[X]: + override def foo: X = new X + +trait C extends A[Y]: + override def foo: Y = new Y + def superFoo: Y = super[A].foo + +class Fixed extends B with C +``` + diff --git a/docs/_docs/reference/error-codes/E138.md b/docs/_docs/reference/error-codes/E138.md new file mode 100644 index 000000000000..d41403504be9 --- /dev/null +++ b/docs/_docs/reference/error-codes/E138.md @@ -0,0 +1,11 @@ +--- +title: E138: Trait Parameter Used As Parent Prefix +kind: Error +--- +# E138: Trait Parameter Used As Parent Prefix + +This error occurs when a trait tries to extend a parent type that is derived from the trait's own parameters. + +Using a trait parameter as the prefix for a parent type is disallowed to prevent outer-related `NullPointerException` errors at runtime. The parent class initialization happens before trait parameters are available, which would cause runtime failures. + +**Note:** This error code is typically caught by an earlier compiler phase with a different error message. The `TraitParameterUsedAsParentPrefix` check in RefChecks serves as a safety net but is rarely triggered in practice because PostTyper catches the same scenarios first. diff --git a/docs/_docs/reference/error-codes/E139.md b/docs/_docs/reference/error-codes/E139.md new file mode 100644 index 000000000000..28f7db310bd2 --- /dev/null +++ b/docs/_docs/reference/error-codes/E139.md @@ -0,0 +1,54 @@ +--- +title: E139: Unknown Named Enclosing Class Or Object +kind: Error +--- +# E139: Unknown Named Enclosing Class Or Object + +This error occurs when a visibility modifier references a class or object name that cannot be found in the enclosing scope. + +In Scala, you can use qualified private or protected modifiers like `private[ClassName]` or `protected[PackageName]` to restrict visibility to a specific enclosing class, object, or package. This error is raised when the specified name does not match any enclosing scope. + +The class or object named in the visibility modifier was used but could not be resolved. Make sure that the name is not misspelled and refers to an actual enclosing class, object, or package. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +class Example: + private[NonExistent] val x: Int = 42 +``` + +### Error + +```scala sc:nocompile +-- [E139] Reference Error: example.scala:2:27 ---------------------------------- +2 | private[NonExistent] val x: Int = 42 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | no enclosing class or object is named 'NonExistent' + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | + | The class or object named 'NonExistent' was used as a visibility + | modifier, but could not be resolved. Make sure that + | 'NonExistent' is not misspelled and has been imported into the + | current scope. + | + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use the correct enclosing class name +class Example: + private[Example] val x: Int = 42 +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: Use a simple private modifier +class Example: + private val x: Int = 42 +``` + diff --git a/docs/_docs/reference/error-codes/E140.md b/docs/_docs/reference/error-codes/E140.md new file mode 100644 index 000000000000..19d09aa7e06e --- /dev/null +++ b/docs/_docs/reference/error-codes/E140.md @@ -0,0 +1,50 @@ +--- +title: E140: Illegal Cyclic Type Reference +kind: Error +--- +# E140: Illegal Cyclic Type Reference + +This error occurs when a type alias or type definition references itself, either directly or through a chain of other type aliases, creating a cycle. + +Type aliases must eventually resolve to a concrete type. When a type refers back to itself without eventually resolving to a non-circular definition, the compiler cannot determine what the type actually represents. + +Use the `-explain-cyclic` flag to get a detailed trace of how the cyclic reference was discovered. + +--- + +## Example + +```scala sc:fail sc-opts:-explain-cyclic +type A = B +type B = A +``` + +### Error + +```scala sc:nocompile +-- [E140] Cyclic Error: example.scala:1:5 -------------------------------------- +1 |type A = B + | ^ + |illegal cyclic type reference: alias B of type A refers back to the type itself + | + |The error occurred while trying to compute the signature of type A + | which required to explore type B for cyclic references + | which required to explore type A for cyclic references + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Break the cycle by using a concrete type +type A = Int +type B = A +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: If recursion is needed, use a class or trait +trait A: + def next: A +``` + diff --git a/docs/_docs/reference/error-codes/E141.md b/docs/_docs/reference/error-codes/E141.md new file mode 100644 index 000000000000..c9c70b37bdbf --- /dev/null +++ b/docs/_docs/reference/error-codes/E141.md @@ -0,0 +1,62 @@ +--- +title: E141: Missing Type Parameter In Type App +kind: Error +--- +# E141: Missing Type Parameter In Type App + +This error occurs when a type constructor that takes type parameters is used without providing all required type arguments in a context where a fully applied type is expected. + +This typically happens when a parameterized type like `Container[T]` is passed to a method expecting a simple type `T`, but `Container` is passed without its type argument. The type constructor needs to be fully applied with concrete types to match the expected kind. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +object Example: + class Container[T] + + def process[T] = ??? + + def test(): Unit = + process[Container] +``` + +### Error + +```scala sc:nocompile +-- [E141] Type Error: example.scala:7:12 --------------------------------------- +7 | process[Container] + | ^^^^^^^^^ + | Missing type parameter for Example.Container + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A fully applied type is expected but Example.Container takes 1 parameter + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Provide the missing type parameter +object Example: + class Container[T] + + def process[T] = ??? + + def test(): Unit = + process[Container[Int]] +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: If higher-kinded type is intended, change the method signature +object Example: + class Container[T] + + def process[F[_]] = ??? + + def test(): Unit = + process[Container] +``` + diff --git a/docs/_docs/reference/error-codes/E142.md b/docs/_docs/reference/error-codes/E142.md new file mode 100644 index 000000000000..bf128ecb4bbc --- /dev/null +++ b/docs/_docs/reference/error-codes/E142.md @@ -0,0 +1,108 @@ +--- +title: "E142: Skolem in Inferred" +kind: Error +until: 3.8.1 +--- +# E142: Skolem in Inferred + +**Note:** This error code was made inactive in Scala 3.8.1. The behavior was changed to throw a TypeError earlier in the compilation process, preventing the generation of invalid trees. + +This error occurred when the compiler attempted to generate a given instance that contained a reference to a skolem type. Skolem types are placeholder types used internally by the compiler during type inference that cannot be directly referenced in generated code. + +According to the [commit that changed this behavior](https://github.com/scala/scala3/commit/6e4b0a0bb5659bf82b1cf00dac9c48da2913ceaf): "Previously, the valueOf inline call succeeded (because the ValueOf synthesizer calls `tpd.ref` which calls `tpd.singleton`), leading to an invalid tree which crashed in the backend with: 'assertion failed: Cannot create ClassBType from NoSymbol'. Fixed by throwing a TypeError from `tpd.singleton`." + +The error message indicated that implicit search found a solution, but the solution contained a part that referred to a skolem type which could not be materialized into actual code. + +--- + +## Example + +```scala sc:nocompile custom-sc:fail +trait QC: + object tasty: + type Tree + extension (tree: Tree) + def pos: Tree = ??? + +def test = + given [T]: QC = ??? + def unseal(using qctx: QC): qctx.tasty.Tree = ??? + unseal.pos +``` + +### Error + +```scala sc:nocompile +-- [E142] Type Error: example.scala:10:2 --------------------------------------- +10 | unseal.pos + | ^^^^^^ + |Failure to generate given instance for type ?{ pos: ? } from argument of type ?1.tasty.Tree) + | + |I found: .tasty.pos(unseal(given_QC[Any])) + |But the part corresponding to `` is not a reference that can be generated. + |This might be because resolution yielded as given instance a function that is not + |known to be total and side-effect free. + | + |where: ?1 is an unknown value of type QC + |---------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The part of given resolution that corresponds to `` produced a term that + | is not a stable reference. Therefore a given instance could not be generated. + | + | To trouble-shoot the problem, try to supply an explicit expression instead of + | relying on implicit search at this point. + ---------------------------------------------------------------------------- +``` + +**Note**: In Scala 3.8.1+, this error was changed to throw a TypeError earlier in compilation, resulting in error E008 instead. + +### Solution + +The key to solving this error is to avoid creating skolem types by making the context parameter explicit and stable. + +```scala sc:compile +trait QC: + object tasty: + type Tree + extension (tree: Tree) + def pos: Tree = ??? + +// Solution 1: Use an explicit named given instead of polymorphic given +def test = + given qc: QC = ??? // Named given, not [T]: QC + def unseal(using qctx: QC): qctx.tasty.Tree = ??? + val tree = unseal(using qc) + qc.tasty.pos(tree) // Call extension method explicitly with stable context +``` + +```scala sc:compile +trait QC: + object tasty: + type Tree + extension (tree: Tree) + def pos: Tree = ??? + +// Solution 2: Store result with explicit type annotation +def test = + given qc: QC = ??? + val tree: qc.tasty.Tree = { + def unseal(using qctx: QC): qctx.tasty.Tree = ??? + unseal + } + tree.pos // Now the type is stable +``` + +```scala sc:compile +trait QC: + object tasty: + type Tree + extension (tree: Tree) + def pos: Tree = ??? + +// Solution 3: Make the context parameter explicit in the function signature +def test(using qc: QC) = // Explicit context parameter + def unseal(using qctx: QC): qctx.tasty.Tree = ??? + unseal.pos // Works because qc is stable +``` + diff --git a/docs/_docs/reference/error-codes/E143.md b/docs/_docs/reference/error-codes/E143.md new file mode 100644 index 000000000000..c655d122bb45 --- /dev/null +++ b/docs/_docs/reference/error-codes/E143.md @@ -0,0 +1,12 @@ +--- +title: E143: Erased Types Can Only Be Function Types +kind: Error +--- +# E143: Erased Types Can Only Be Function Types + +This error occurs when the `erased` keyword is used in a type context that is not a function type. + +The `erased` keyword is an experimental feature that marks function parameters as erased at runtime. When used in type annotations, `erased` can only appear in function types of the form `(erased ...) => ...`. + +**Note:** This error code is difficult to reproduce in practice because the parser typically reports E040 ("=> expected") before reaching this specific error. The E143 error may only be triggered in specific internal parsing paths. + diff --git a/docs/_docs/reference/error-codes/E144.md b/docs/_docs/reference/error-codes/E144.md new file mode 100644 index 000000000000..0f56f648ac1b --- /dev/null +++ b/docs/_docs/reference/error-codes/E144.md @@ -0,0 +1,51 @@ +--- +title: E144: Case Class Missing Non-Implicit Parameter List +kind: Error +--- +# E144: Case Class Missing Non-Implicit Parameter List + +This error occurs when a case class is defined with only implicit or using parameter lists, without any leading non-implicit parameter list. + +Case classes in Scala require at least one leading non-implicit parameter list. This is because case classes automatically generate methods like `equals`, `hashCode`, `toString`, and `copy` based on their primary constructor parameters, and these generated methods expect regular (non-implicit) parameters. + +--- + +## Example + +```scala sc:fail +case class Example(using x: Int) +``` + +### Error + +```scala sc:nocompile +-- [E144] Syntax Error: example.scala:1:11 ------------------------------------- +1 |case class Example(using x: Int) + | ^^^^^^^ + | A case class must have at least one leading non-implicit parameter list + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Example must have at least one leading non-implicit parameter list, + | if you're aiming to have a case class parametrized only by implicit ones, you should + | add an explicit () as the first parameter list to Example. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Add an explicit empty parameter list before the using clause +case class Example()(using x: Int) +``` + +```scala sc:compile sc-opts:-Werror +// Or add a regular parameter +case class Example(value: String)(using x: Int) +``` + +```scala sc:compile sc-opts:-Werror +// If no parameters are needed, consider using a regular class or object +class Example(using x: Int) +``` + diff --git a/docs/_docs/reference/error-codes/E145.md b/docs/_docs/reference/error-codes/E145.md new file mode 100644 index 000000000000..2dec617951fd --- /dev/null +++ b/docs/_docs/reference/error-codes/E145.md @@ -0,0 +1,50 @@ +--- +title: E145: Enumerations Should Not Be Empty +kind: Error +--- +# E145: Enumerations Should Not Be Empty + +This error occurs when an enum is defined without any cases. + +In Scala 3, enums must contain at least one case. An empty enum has no values and cannot be meaningfully used. If you need an empty sealed hierarchy, consider using a sealed trait instead. + +--- + +## Example + +```scala sc:fail +enum Empty {} +``` + +### Error + +```scala sc:nocompile +-- [E145] Syntax Error: example.scala:1:5 -------------------------------------- +1 |enum Empty {} + | ^^^^^ + | Enumerations must contain at least one case + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Enumeration Empty must contain at least one case + | Example Usage: + | enum Empty { + | case Option1, Option2 + | } + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Add at least one case to the enum +enum Status { + case Active, Inactive +} +``` + +```scala sc:compile sc-opts:-Werror +// Or use a sealed trait if no cases are needed yet +sealed trait Empty +``` + diff --git a/docs/_docs/reference/error-codes/E146.md b/docs/_docs/reference/error-codes/E146.md new file mode 100644 index 000000000000..d6271dc5ff20 --- /dev/null +++ b/docs/_docs/reference/error-codes/E146.md @@ -0,0 +1,66 @@ +--- +title: E146: Illegal Parameter Initialization +kind: Error +--- +# E146: Illegal Parameter Initialization + +This error occurs when a class extends multiple traits that define the same parameterized trait, but the argument passed to the trait parameter doesn't conform to the required intersection type. + +When a class inherits from multiple traits that share a common parameterized base trait with different type arguments, the parameter type becomes an intersection of all the required types. The value passed to initialize the parameter must conform to this intersection type. + +--- + +## Example + +```scala sc:fail +trait Base[+A](val value: A) +trait Derived[+B] extends Base[B] + +class Example extends Derived[String] with Base[Int](42) +``` + +### Error + +```scala sc:nocompile +-- [E146] Type Mismatch Error: example.scala:4:53 ------------------------------ +4 |class Example extends Derived[String] with Base[Int](42) + | ^^ + | illegal parameter initialization of value value. + | + | The argument passed for value value has type: (42 : Int) + | but class Example expects value value to have type: String & Int + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | I tried to show that + | (42 : Int) + | conforms to + | String & Int + | but none of the attempts shown below succeeded: + | + | ==> (42 : Int) <: String & Int + | ==> (42 : Int) <: String + | ==> Int <: String = false + | + | The tests were made under the empty constraint + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +trait Base[+A](val value: A) +trait Derived[+B] extends Base[B] + +// Provide a value that satisfies both type constraints +class Example extends Derived[Any] with Base[Any]("hello") +``` + +```scala sc:compile sc-opts:-Werror +trait Base[+A](val value: A) +trait Derived[+B] extends Base[B] + +// Or use consistent types across the inheritance hierarchy +class Example extends Derived[String] with Base[String]("hello") +``` + diff --git a/docs/_docs/reference/error-codes/E147.md b/docs/_docs/reference/error-codes/E147.md new file mode 100644 index 000000000000..e8911a97976c --- /dev/null +++ b/docs/_docs/reference/error-codes/E147.md @@ -0,0 +1,41 @@ +--- +title: E147: Redundant Modifier +kind: Warning +--- +# E147: Redundant Modifier + +This warning occurs when a modifier is applied to a definition where it has no effect because the definition is already implicitly given that property. + +Common cases include: +- Using `final` on a given definition (givens are already final) +- Using `final` on an object member in a final class +- Using modifiers that are implied by the definition context + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +object Example { + final given g: Object() +} +``` + +### Error + +```scala sc:nocompile +-- [E147] Syntax Warning: example.scala:2:2 ------------------------------------ +2 | final given g: Object() + | ^^^^^ + | Modifier final is redundant for this definition +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +object Example { + // Remove the redundant `final` modifier - givens are implicitly final + given g: Object() +} +``` + diff --git a/docs/_docs/reference/error-codes/E148.md b/docs/_docs/reference/error-codes/E148.md new file mode 100644 index 000000000000..0c834de902b4 --- /dev/null +++ b/docs/_docs/reference/error-codes/E148.md @@ -0,0 +1,56 @@ +--- +title: E148: Typed Case Does Not Explicitly Extend Typed Enum +kind: Error +--- +# E148: Typed Case Does Not Explicitly Extend Typed Enum + +This error occurs when both an enum class and an enum case have type parameters, but the enum case does not include an explicit `extends` clause. + +When both the enum and its case have type parameters, the compiler cannot automatically infer how the case's type parameters relate to the enum's type parameters. An explicit `extends` clause is required to specify this relationship. + +--- + +## Example + +```scala sc:fail +enum Container[T] { + case Item[U](value: U) +} +``` + +### Error + +```scala sc:nocompile +-- [E148] Syntax Error: example.scala:2:2 -------------------------------------- +2 | case Item[U](value: U) + | ^ + |explicit extends clause needed because both enum case and enum class have type parameters + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Enumerations where the enum class as well as the enum case have type parameters need + | an explicit extends. + | for example: + | enum Container[T] { + | case Item[U](u: U) extends Container[U] + | } + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +enum Container[T] { + // Add explicit extends clause to show how type parameters relate + case Item[U](value: U) extends Container[U] +} +``` + +```scala sc:compile sc-opts:-Werror +// Alternative: If the case doesn't need its own type parameters, +// use the enum's type parameter directly +enum Container[T] { + case Item(value: T) +} +``` + diff --git a/docs/_docs/reference/error-codes/E149.md b/docs/_docs/reference/error-codes/E149.md new file mode 100644 index 000000000000..e0d23d356991 --- /dev/null +++ b/docs/_docs/reference/error-codes/E149.md @@ -0,0 +1,48 @@ +--- +title: E149: Illegal Redefinition Of Standard Kind +kind: Error +--- +# E149: Illegal Redefinition Of Standard Kind + +This error occurs when code in the `scala` package attempts to define a class or object with a name that is reserved for core Scala types. + +Reserved names include fundamental types like `Any`, `Nothing`, `AnyRef`, `AnyVal`, `Null`, `Unit`, and other core Scala classes. These names are reserved because they are synthesized by the compiler and have special semantics that cannot be replicated by user-defined classes. + +--- + +## Example + +```scala sc:nocompile custom-sc:fail +package scala + +class Any +``` + +### Error + +```scala sc:nocompile +-- [E149] Syntax Error: example.scala:3:6 -------------------------------------- +3 |class Any + | ^^^ + | illegal redefinition of standard class Any + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | "Any" is a standard Scala core `class` + | Please choose a different name to avoid conflicts + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:nocompile custom-sc:compile +package scala + +// Choose a different name that doesn't conflict with reserved names +class MyAny +``` + +--- + +**Note:** This error can only occur when defining classes in the `scala` package. Regular user code in other packages can freely use names like `Any` without conflict, though this is generally not recommended for clarity. + diff --git a/docs/_docs/reference/error-codes/E150.md b/docs/_docs/reference/error-codes/E150.md new file mode 100644 index 000000000000..e0e2354b0d2c --- /dev/null +++ b/docs/_docs/reference/error-codes/E150.md @@ -0,0 +1,11 @@ +--- +title: E150: No Extension Method Allowed +kind: Error +until: 3.0.0 +--- +# E150: No Extension Method Allowed + +This error is defined for cases where an extension method is incorrectly nested within another extension clause that already has collective parameters. +When an extension clause defines collective type or value parameters, the methods inside it share those parameters. Attempting to define another nested extension within such a clause is not allowed. + +**Note** This error was never emitted by stable Scala 3 compiler. diff --git a/docs/_docs/reference/error-codes/E151.md b/docs/_docs/reference/error-codes/E151.md new file mode 100644 index 000000000000..004171cd6dc0 --- /dev/null +++ b/docs/_docs/reference/error-codes/E151.md @@ -0,0 +1,11 @@ +--- +title: E151: Extension Method Cannot Have Type Parameters +kind: Error +until: 3.0.0 +--- +# E151: Extension Method Cannot Have Type Parameters + +This error occurs when an extension method defines its own type parameters while the enclosing extension clause already has type parameters. +When an extension clause has collective type parameters, all methods within it share those parameters. If a method needs additional type parameters, they should be moved to the extension clause's type parameter list instead. + +**Note** This error was never emitted by stable Scala 3 compiler. diff --git a/docs/_docs/reference/error-codes/E152.md b/docs/_docs/reference/error-codes/E152.md new file mode 100644 index 000000000000..898627a4ba77 --- /dev/null +++ b/docs/_docs/reference/error-codes/E152.md @@ -0,0 +1,11 @@ +--- +title: E152: Extension Can Only Have Defs +kind: Error +until: 3.0.0 +--- +# E152: Extension Can Only Have Defs + +This error occurs when an extension clause with collective parameters contains something other than method definitions (`def`). +Extension clauses that have collective type or value parameters can only contain method definitions. Other declarations like `val`, `var`, `type`, or nested classes are not allowed in this context. + +**Note** This error was never emitted by stable Scala 3 compiler. diff --git a/docs/_docs/reference/error-codes/E153.md b/docs/_docs/reference/error-codes/E153.md new file mode 100644 index 000000000000..ee6e5d5adf13 --- /dev/null +++ b/docs/_docs/reference/error-codes/E153.md @@ -0,0 +1,69 @@ +--- +title: E153: Unexpected Pattern For SummonFrom +kind: Error +--- +# E153: Unexpected Pattern For SummonFrom + +This error occurs when `summonFrom` is used with an invalid pattern in a `case` clause. The `summonFrom` macro only accepts typed patterns (`x: T`) or wildcard patterns (`_`). + +`summonFrom` is a compile-time construct that tries to summon an implicit value. It requires patterns that check for the presence of an implicit, not arbitrary value patterns. + +--- + +## Example + +```scala sc:fail +import scala.compiletime.summonFrom + +inline def example = summonFrom { + case 42 => "found" +} +``` + +### Error + +```scala sc:nocompile +-- [E153] Syntax Error: example.scala:4:7 -------------------------------------- +4 | case 42 => "found" + | ^^ + | Unexpected pattern for summonFrom. Expected `x: T` or `_` + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The pattern "42" provided in the case expression of the summonFrom, + | needs to be of the form `x: T` or `_`. + | + | Example usage: + | inline def a = summonFrom { + | case x: T => ??? + | } + | + | or + | inline def a = summonFrom { + | case _ => ??? + | } + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +import scala.compiletime.summonFrom + +// Use typed pattern to check for implicit presence +inline def example = summonFrom { + case given String => "found a String" + case _ => "not found" +} +``` + +```scala sc:compile sc-opts:-Werror +import scala.compiletime.summonFrom + +// Use binding with type pattern +inline def example2 = summonFrom { + case s: String => s"found: $s" + case _ => "not found" +} +``` + diff --git a/docs/_docs/reference/error-codes/E154.md b/docs/_docs/reference/error-codes/E154.md new file mode 100644 index 000000000000..e9096b3b6782 --- /dev/null +++ b/docs/_docs/reference/error-codes/E154.md @@ -0,0 +1,43 @@ +--- +title: E154: Anonymous Instance Cannot Be Empty +kind: Error +--- +# E154: Anonymous Instance Cannot Be Empty + +This error occurs when an anonymous given instance is defined without implementing a type or providing at least one extension method. +Anonymous givens must either implement a specific type or contain extension methods. An empty anonymous given has no practical use and is not allowed. + +--- + +## Example + +```scala sc:nocompile +given {} +``` + +### Error + +```scala sc:nocompile +-- [E154] Syntax Error: example.scala:1:6 -------------------------------------- +1 |given { + | ^ + | anonymous instance must implement a type or have at least one extension method +``` + +### Solution + +```scala sc:nocompile +trait Printable { + def print(): Unit +} + +// Implement a type +given Printable { + def print(): Unit = println("hello") +} +``` + +--- + +**Note:** This error code is difficult to reproduce with current parser syntax, as the parser typically reports syntax errors before reaching this validation. The behavior described here reflects the intended semantics of the error message. + diff --git a/docs/_docs/reference/error-codes/E155.md b/docs/_docs/reference/error-codes/E155.md new file mode 100644 index 000000000000..e16eaafa8953 --- /dev/null +++ b/docs/_docs/reference/error-codes/E155.md @@ -0,0 +1,76 @@ +--- +title: "E155: Type Splice in Val Pattern" +kind: Error +until: 3.2.0 +--- +# E155: Type Splice in Val Pattern + +**Note:** This error code was made inactive in Scala 3.2.0. The old syntax for type splicing in quoted patterns is no longer supported, making this error impossible to trigger. + +This error occurred in early versions of Scala 3 when attempting to use type splices (`$t` syntax) in val patterns within quoted code (macros). Type splices allow capturing and manipulating types in quoted expressions, but they were not allowed in val pattern destructuring. + +According to the [commit that removed this error](https://github.com/scala/scala3/commit/a72309cecbbc16049a7d5c51edfb9423f33e8055), "Now that we do not support the old syntax for splicing types it is not possible to get this error." + +--- + +## Example + +```scala sc:nocompile +import scala.quoted.* + +object Foo { + def f(using q: Quotes) = { + val t: Type[Int] = ??? + val '[ *:[$t] ] = ??? + } +} +``` + +### Error + +```scala sc:nocompile +-- [E155] Syntax Error: example.scala:5:20 ----------------------------------- +5 | val '[ *:[$t] ] = ??? + | ^ + |Type splices cannot be used in val patterns. Consider using `match` instead. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Type splice: `$t` cannot be used in a `val` pattern. Consider rewriting + | the `val` pattern as a `match` with a corresponding `case` to replace + | the `val`. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:nocompile +import scala.quoted.* + +object Foo { + def f(using q: Quotes) = { + val t: Type[Int] = ??? + ??? match { + case '[ *:[$t] ] => // Use match/case instead of val + // Handle the pattern here + } + } +} +``` + +Modern approach: +```scala sc:nocompile +import scala.quoted.* + +object Foo { + def f(using Quotes): Unit = { + // Use the modern quoted pattern matching syntax + // The old $t syntax is no longer supported + Type.of[Int] match { + case '[List[t]] => + // Work with the captured type 't' + () + } + } +} +``` diff --git a/docs/_docs/reference/error-codes/E156.md b/docs/_docs/reference/error-codes/E156.md new file mode 100644 index 000000000000..9f29310cbb9f --- /dev/null +++ b/docs/_docs/reference/error-codes/E156.md @@ -0,0 +1,51 @@ +--- +title: E156: Modifier Not Allowed For Definition +kind: Error +--- +# E156: Modifier Not Allowed For Definition + +This error occurs when a modifier is used on a definition where it is not applicable. Different kinds of definitions (classes, objects, methods, etc.) support different sets of modifiers. + +Common invalid combinations include: +- `opaque` on a method definition (only valid for type aliases) +- `abstract` on an object definition +- `sealed` on an object definition + +--- + +## Example + +```scala sc:fail +object Test { + opaque def example: Int = 42 +} +``` + +### Error + +```scala sc:nocompile +-- [E156] Syntax Error: example.scala:2:13 ------------------------------------- +2 | opaque def example: Int = 42 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Modifier opaque is not allowed for this definition +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +object Test { + // opaque is only valid for type aliases + opaque type PositiveInt = Int + + // Regular method definition + def example: Int = 42 +} +``` + +```scala sc:compile sc-opts:-Werror +// abstract is not allowed on object - use trait or abstract class instead +abstract class Base { + def example: Int +} +``` + diff --git a/docs/_docs/reference/error-codes/E157.md b/docs/_docs/reference/error-codes/E157.md new file mode 100644 index 000000000000..28a4f3444d8b --- /dev/null +++ b/docs/_docs/reference/error-codes/E157.md @@ -0,0 +1,45 @@ +--- +title: E157: Cannot Extend Java Enum +kind: Error +--- +# E157: Cannot Extend Java Enum + +This error occurs when a class tries to extend `java.lang.Enum` directly. In Scala 3, only enums defined with the `enum` syntax are allowed to extend Java's Enum class. + +This restriction ensures that Scala enums follow proper semantics and benefit from compiler support for exhaustiveness checking and other enum-specific features. + +--- + +## Example + +```scala sc:fail +class MyEnum extends java.lang.Enum[MyEnum] +``` + +### Error + +```scala sc:nocompile +-- [E157] Syntax Error: example.scala:1:6 -------------------------------------- +1 |class MyEnum extends java.lang.Enum[MyEnum] + | ^ + |class MyEnum cannot extend java.lang.Enum: only enums defined with the enum syntax can +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use Scala 3 enum syntax instead +enum MyEnum { + case Value1, Value2, Value3 +} +``` + +```scala sc:compile sc-opts:-Werror +// For Java interop, Scala 3 enums automatically extend java.lang.Enum +enum Color { + case Red, Green, Blue +} + +// Color cases are instances of java.lang.Enum[Color] +``` + diff --git a/docs/_docs/reference/error-codes/E158.md b/docs/_docs/reference/error-codes/E158.md new file mode 100644 index 000000000000..3c7eabebe397 --- /dev/null +++ b/docs/_docs/reference/error-codes/E158.md @@ -0,0 +1,37 @@ +--- +title: E158: Invalid Reference In ImplicitNotFound Annotation +kind: Warning +--- +# E158: Invalid Reference In ImplicitNotFound Annotation + +This warning occurs when an `@implicitNotFound` annotation references a type variable that doesn't exist in the scope of the annotated type. + +The `@implicitNotFound` annotation allows customizing the error message when an implicit value cannot be found. It can interpolate type parameters using `${TypeParam}` syntax, but the referenced type parameter must be defined by the annotated trait, class, or method. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +@annotation.implicitNotFound("Missing ${X}") +trait Show[T] +``` + +### Error + +```scala sc:nocompile +-- [E158] Reference Warning: example.scala:1:40 -------------------------------- +1 |@annotation.implicitNotFound("Missing ${X}") + | ^ + |Invalid reference to a type variable `X` found in the annotation argument. + |The variable does not occur as a parameter in the scope of type `Show`. +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Reference the actual type parameter T +@annotation.implicitNotFound("No Show instance found for ${T}") +trait Show[T] +``` + diff --git a/docs/_docs/reference/error-codes/E159.md b/docs/_docs/reference/error-codes/E159.md new file mode 100644 index 000000000000..4ed2ac8f951d --- /dev/null +++ b/docs/_docs/reference/error-codes/E159.md @@ -0,0 +1,49 @@ +--- +title: E159: Trait May Not Define Native Method +kind: Error +--- +# E159: Trait May Not Define Native Method + +This error occurs when a trait attempts to define a method with the `@native` annotation. + +Native methods are implemented in platform-specific code (like C or assembly through JNI) and require a concrete class implementation. Since traits can be mixed into multiple classes and don't have a direct JVM implementation path for native code, they cannot define native methods. + +--- + +## Example + +```scala sc:fail +trait NativeOperations { + @native def performNativeOp(): Unit +} +``` + +### Error + +```scala sc:nocompile +-- [E159] Syntax Error: example.scala:2:14 ------------------------------------- +2 | @native def performNativeOp(): Unit + | ^ + | A trait cannot define a @native method. +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Define native methods in a class or object instead +class NativeOperations { + @native def performNativeOp(): Unit +} +``` + +```scala sc:compile sc-opts:-Werror +// Or use an abstract method in the trait and implement it in a class +trait NativeOperations { + def performNativeOp(): Unit +} + +class NativeImpl extends NativeOperations { + @native def performNativeOp(): Unit +} +``` + diff --git a/docs/_docs/reference/error-codes/E160.md b/docs/_docs/reference/error-codes/E160.md new file mode 100644 index 000000000000..5834a192287d --- /dev/null +++ b/docs/_docs/reference/error-codes/E160.md @@ -0,0 +1,38 @@ +--- +title: E160: Java Enum Parent Args +kind: Error +--- +# E160: Java Enum Parent Args + +This error occurs when a class extends `java.lang.Enum` without providing the required constructor arguments (`name` and `ordinal`). + +The `java.lang.Enum` constructor requires two arguments: a `String` name and an `Int` ordinal. When manually extending `java.lang.Enum` (which is only allowed with `-source:3.0-migration`), these arguments must be provided. + +Note: In modern Scala 3, you should use the `enum` keyword instead of manually extending `java.lang.Enum`. + +--- + +## Example + +```scala sc:fail sc-opts:-source:3.0-migration +final class MyEnum extends java.lang.Enum[MyEnum] +``` + +### Error + +```scala sc:nocompile +-- [E160] Type Error: example.scala:1:12 --------------------------------------- +1 |final class MyEnum extends java.lang.Enum[MyEnum] + | ^ + |not enough arguments for constructor Enum: (name: String, ordinal: Int): Enum[MyEnum] +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use Scala 3 enum syntax instead (recommended) +enum MyEnum { + case Value1, Value2 +} +``` + diff --git a/docs/_docs/reference/error-codes/E161.md b/docs/_docs/reference/error-codes/E161.md new file mode 100644 index 000000000000..e0f19a777bf1 --- /dev/null +++ b/docs/_docs/reference/error-codes/E161.md @@ -0,0 +1,48 @@ +--- +title: E161: Already Defined +kind: Error +--- +# E161: Already Defined + +This error occurs when multiple definitions with the same synthesized name exist in the same scope. This commonly happens with anonymous givens that have the same type, as the compiler generates identical names for them. + +When defining multiple anonymous givens of the same type, the compiler synthesizes names based on the type (e.g., `given_Option_String`). If two givens would have the same synthesized name, this error is reported. + +--- + +## Example + +```scala sc:fail +def example = { + given Option[String] = Some("a") + given Option[String] = Some("b") + () +} +``` + +### Error + +```scala sc:nocompile +-- [E161] Naming Error: example.scala:3:8 -------------------------------------- +3 | given Option[String] = Some("b") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |given_Option_String is already defined as given instance given_Option_String + | + |Provide an explicit, unique name to given definitions, + |since the names assigned to anonymous givens may clash. For example: + | + | given myGiven: Option[String] // define an instance + | given myGiven @ Option[String] // as a pattern variable +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +def example = { + // Provide explicit unique names for givens + given first: Option[String] = Some("a") + given second: Option[String] = Some("b") + () +} +``` + diff --git a/docs/_docs/reference/error-codes/E162.md b/docs/_docs/reference/error-codes/E162.md new file mode 100644 index 000000000000..a0504667b32e --- /dev/null +++ b/docs/_docs/reference/error-codes/E162.md @@ -0,0 +1,53 @@ +--- +title: E162: Case Class In Inlined Code +kind: Error +--- +# E162: Case Class In Inlined Code + +This error occurs when a case class or case object is defined inside an inline method or quoted code block. + +Case class definitions generate a significant amount of bytecode (including `apply`, `unapply`, `copy`, `equals`, `hashCode`, `toString`, and other methods). Inlining such definitions would multiply this bytecode footprint at every call site, leading to excessive code bloat. + +--- + +## Example + +```scala sc:fail +inline def example = { + case class Data(x: Int) + Data(42) +} +``` + +### Error + +```scala sc:nocompile +-- [E162] Syntax Error: example.scala:2:13 ------------------------------------- +2 | case class Data(x: Int) + | ^^^^^^^^^^^^^^^^^^^^^^^ + |Case class definitions are not allowed in inline methods or quoted code. Use a normal class instead. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Case class/object definitions generate a considerable footprint in code size. + | Inlining such definition would multiply this footprint for each call site. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Define case class outside the inline method +case class Data(x: Int) + +inline def example = Data(42) +``` + +```scala sc:compile sc-opts:-Werror +// Or use a regular class inside the inline method +inline def example = { + class Data(val x: Int) + new Data(42) +} +``` + diff --git a/docs/_docs/reference/error-codes/E163.md b/docs/_docs/reference/error-codes/E163.md new file mode 100644 index 000000000000..6928eb25596a --- /dev/null +++ b/docs/_docs/reference/error-codes/E163.md @@ -0,0 +1,77 @@ +--- +title: "E163: Override Type Mismatch Error" +kind: Error +until: 3.3.0 +--- +# E163: Override Type Mismatch Error + +**Note:** This error code was made inactive in Scala 3.3.0. Override type mismatch errors are now reported as [E164 (Override Error)](E164.md). + +This error occurred until Scala 3.2.x when a method override had an incompatible type signature compared to the method it was overriding. The overriding method's return type must be a subtype of the overridden method's return type (covariance). + +In Scala 3.3.0, the implementation of override errors was unified, and this error code was merged into E164, which provides more comprehensive override validation and better error messages. + +--- + +## Example + +```scala sc:nocompile +class Base: + def foo: Int = 42 + +class Derived extends Base: + override def foo: String = "hello" +``` + +### Error + +```scala sc:nocompile +-- [E163] Declaration Error: example.scala:5:15 -------------------------------- +5 | override def foo: String = "hello" + | ^ + | error overriding method foo in class Base of type => Int; + | method foo of type => String has incompatible type + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | I tried to show that + | => String + | conforms to + | => Int + | but the comparison trace ended with `false`: + | + | ==> => String <: => Int + | ==> String <: Int + | ==> String <: Int + | <== String <: Int = false + | <== String <: Int = false + | <== => String <: => Int = false + | + | The tests were made under the empty constraint + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:nocompile +class Base: + def foo: Int = 42 + +class Derived extends Base: + // Return type must be Int or a subtype + override def foo: Int = 100 +``` + +```scala sc:compile +// If different behavior is needed, use a different method name +class Base: + def foo: Int = 42 + +class Derived extends Base: + def fooString: String = "hello" +``` + +## See Also + +- [E164: Override Error](E164.md) - The current error code for override type mismatches (Scala 3.3.0+) + diff --git a/docs/_docs/reference/error-codes/E164.md b/docs/_docs/reference/error-codes/E164.md new file mode 100644 index 000000000000..9e77559404c3 --- /dev/null +++ b/docs/_docs/reference/error-codes/E164.md @@ -0,0 +1,72 @@ +--- +title: E164: Override Error +kind: Error +--- +# E164: Override Error + +This error occurs when a method override violates override rules, typically when the overriding method has an incompatible return type or doesn't properly match the signature of the method it's overriding. + +For a method override to be valid, the overriding method's return type must be a subtype of the overridden method's return type (covariance), and parameter types must be supertypes (contravariance). + +--- + +## Example + +```scala sc:fail +class Base { + def foo: String = "hello" +} + +class Derived extends Base { + override def foo: Int = 42 +} +``` + +### Error + +```scala sc:nocompile +-- [E164] Declaration Error: example.scala:6:15 -------------------------------- +6 | override def foo: Int = 42 + | ^ + | error overriding method foo in class Base of type => String; + | method foo of type => Int has incompatible type + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | I tried to show that + | => Int + | conforms to + | => String + | but none of the attempts shown below succeeded: + | + | ==> => Int <: => String + | ==> Int <: String = false + | + | The tests were made under the empty constraint + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +class Base { + def foo: String = "hello" +} + +class Derived extends Base { + // Return type must be String or a subtype + override def foo: String = "world" +} +``` + +```scala sc:compile sc-opts:-Werror +// If different behavior is needed, use a different method name +class Base { + def foo: String = "hello" +} + +class Derived extends Base { + def fooInt: Int = 42 +} +``` + diff --git a/docs/_docs/reference/error-codes/E165.md b/docs/_docs/reference/error-codes/E165.md new file mode 100644 index 000000000000..df3852a41d4a --- /dev/null +++ b/docs/_docs/reference/error-codes/E165.md @@ -0,0 +1,71 @@ +--- +title: E165: Matchable Warning +kind: Warning +--- +# E165: Matchable Warning + +This warning occurs when pattern matching is performed on a value whose type doesn't extend `Matchable`. In future Scala versions, pattern matching will require the scrutinee to be an instance of `Matchable`. + +The `Matchable` trait marks types that can be safely pattern matched. This restriction helps catch potential issues with pattern matching on abstract types that might be instantiated with types that don't support pattern matching (like opaque types or certain intersection types). + +This warning is enabled with `-source:future` or `-source:future-migration` + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-source:future-migration +//> using options -source:future + +def example[T](x: T) = x match { + case s: String => s + case _ => "" +} +``` + +### Error + +```scala sc:nocompile +-- [E165] Type Warning: example.scala:4:10 ------------------------------------- +4 | case s: String => s + | ^^^^^^ + | pattern selector should be an instance of Matchable, + | but it has unmatchable type T instead + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A value of type T cannot be the selector of a match expression + | since it is not constrained to be `Matchable`. Matching on unconstrained + | values is disallowed since it can uncover implementation details that + | were intended to be hidden and thereby can violate paramtetricity laws + | for reasoning about programs. + | + | The restriction can be overridden by appending `.asMatchable` to + | the selector value. `asMatchable` needs to be imported from + | scala.compiletime. Example: + | + | import compiletime.asMatchable + | def f[X](x: X) = x.asMatchable match { ... } + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror,-source:future-migration +// Constrain the type parameter to Matchable +def example[T <: Matchable](x: T) = x match { + case s: String => s + case _ => "" +} +``` + +```scala sc:compile sc-opts:-Werror,-source:future-migration +//> using options -source:future + +// Or use a more specific type bound +def example[T <: AnyRef](x: T) = x match { + case s: String => s + case _ => "" +} +``` + diff --git a/docs/_docs/reference/error-codes/E166.md b/docs/_docs/reference/error-codes/E166.md new file mode 100644 index 000000000000..887005a1dc12 --- /dev/null +++ b/docs/_docs/reference/error-codes/E166.md @@ -0,0 +1,43 @@ +--- +title: E166: Cannot Extend Function +kind: Error +--- +# E166: Cannot Extend Function + +This error occurs when a class attempts to extend a context function type (a function type using `?=>`). + +Context function types are special types that represent functions with implicit parameters. Classes cannot directly extend these types because they have special semantics related to implicit resolution. + +--- + +## Example + +```scala sc:fail +class MyContextFunction extends (Int ?=> String) +``` + +### Error + +```scala sc:nocompile +-- [E166] Syntax Error: example.scala:1:6 -------------------------------------- +1 |class MyContextFunction extends (Int ?=> String) + | ^ + | class MyContextFunction cannot extend a context function class +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Define a regular class with a method that returns the context function +class MyContextFunction { + def apply: Int ?=> String = summon[Int].toString +} +``` + +```scala sc:compile sc-opts:-Werror +// Or implement a regular function type +class MyFunction extends (Int => String) { + def apply(x: Int): String = x.toString +} +``` + diff --git a/docs/_docs/reference/error-codes/E167.md b/docs/_docs/reference/error-codes/E167.md new file mode 100644 index 000000000000..b8d974106e1d --- /dev/null +++ b/docs/_docs/reference/error-codes/E167.md @@ -0,0 +1,41 @@ +--- +title: E167: Lossy Widening Constant Conversion +kind: Warning +since: 3.1.2 +--- +# E167: Lossy Widening Constant Conversion + +This warning occurs when a numeric literal is automatically widened to a type that cannot represent it precisely. This typically happens when assigning large integer literals to floating-point types. + +Floating-point types (`Float` and `Double`) have limited precision and cannot exactly represent all integer values. When a conversion would lose precision, the compiler warns you to make the conversion explicit using `.toFloat` or `.toDouble`. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +def example: Float = 16777217 +``` + +### Error + +```scala sc:nocompile +-- [E167] Lossy Conversion Warning: example.scala:1:21 ------------------------- +1 |def example: Float = 16777217 + | ^^^^^^^^ + | Widening conversion from Int to Float loses precision. + | Write `.toFloat` instead. +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Make the lossy conversion explicit +def example: Float = 16777217.toFloat +``` + +```scala sc:compile sc-opts:-Werror +// Or use Double which has more precision +def example: Double = 16777217 +``` + diff --git a/docs/_docs/reference/error-codes/E168.md b/docs/_docs/reference/error-codes/E168.md new file mode 100644 index 000000000000..7812d8540c5f --- /dev/null +++ b/docs/_docs/reference/error-codes/E168.md @@ -0,0 +1,58 @@ +--- +title: E168: Implicit Search Too Large +kind: Warning +since: 3.1.2 +--- +# E168: Implicit Search Too Large + +This warning occurs when the implicit search exceeds a complexity threshold. This typically indicates a recursive or highly complex implicit derivation that may cause slow compilation or stack overflows. + +The compiler limits implicit search depth to prevent infinite recursion and excessive compilation times. When this limit is reached, the warning helps identify problematic implicit definitions. + +--- + +## Example + +```scala sc:nocompile +// Complex recursive type class derivation can trigger this warning +trait Codec[T] + +object Codec { + given Codec[Int] = ??? + given [T: Codec]: Codec[List[T]] = ??? + given [A: Codec, B: Codec]: Codec[(A, B)] = ??? +} + +// Deeply nested types can cause search to exceed limits +val codec = summon[Codec[List[List[List[(Int, Int)]]]]] +``` + +### Error + +```scala sc:nocompile +-- [E168] Type Warning: example.scala:10:14 ------------------------------------ +10 |val codec = summon[Codec[List[List[List[(Int, Int)]]]]] + | ^ + | Implicit search problem too large. +``` + +### Solution + +```scala sc:nocompile +// Break up derivation into smaller explicit steps +trait Codec[T] + +object Codec { + given intCodec: Codec[Int] = ??? + given [T: Codec]: Codec[List[T]] = ??? +} + +// Use explicit type annotation to cache intermediate results +given pairCodec: Codec[(Int, Int)] = ??? +given listPairCodec: Codec[List[(Int, Int)]] = ??? +``` + +--- + +**Note:** This warning is difficult to reproduce with simple examples as it requires complex implicit resolution graphs that exceed the compiler's search limit. + diff --git a/docs/_docs/reference/error-codes/E169.md b/docs/_docs/reference/error-codes/E169.md new file mode 100644 index 000000000000..245bde144fed --- /dev/null +++ b/docs/_docs/reference/error-codes/E169.md @@ -0,0 +1,69 @@ +--- +title: E169: TargetName On Top-Level Class +kind: Error +since: 3.2.0 +--- +# E169: TargetName On Top-Level Class + +This error occurs when the `@targetName` annotation is applied to a top-level class, trait, or object. + +The `@targetName` annotation is used to specify an alternative name for a definition in the generated bytecode, primarily for interoperability purposes. However, it cannot be applied to top-level type definitions because the class name in the bytecode must match the filename and package structure. + +--- + +## Example + +```scala sc:nocompile custom-sc:fail +import scala.annotation.targetName + +@targetName("Foo") class MyClass +``` + +### Error + +```scala sc:nocompile +-- [E169] Syntax Error: example.scala:3:25 ------------------------------------- +3 |@targetName("Foo") class MyClass + | ^ + | @targetName annotation not allowed on top-level class MyClass + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The @targetName annotation may be applied to a top-level val or def, but not + | a top-level class, trait, or object. + | + | This restriction is due to the naming convention of Java classfiles, whose filenames + | are based on the name of the class defined within. If @targetName were permitted + | here, the name of the classfile would be based on the target name, and the compiler + | could not associate that classfile with the Scala-visible defined name of the class. + | + | If your use case requires @targetName, consider wrapping class MyClass in an object + | (and possibly exporting it), as in the following example: + | + | object Wrapper: + | @targetName("Foo") class MyClass { ... } + | + | export Wrapper.MyClass // optional + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +import scala.annotation.targetName + +// @targetName can be used on methods and vals +class MyClass { + @targetName("addOne") def ++(x: Int): Int = x + 1 +} +``` + +```scala sc:compile sc-opts:-Werror +import scala.annotation.targetName + +// Wrap in an object if you need targetName on a class +object Wrapper { + @targetName("FooClass") class MyClass +} +``` + diff --git a/docs/_docs/reference/error-codes/E170.md b/docs/_docs/reference/error-codes/E170.md new file mode 100644 index 000000000000..1e397dfbb88e --- /dev/null +++ b/docs/_docs/reference/error-codes/E170.md @@ -0,0 +1,50 @@ +--- +title: E170: Not Class Type +kind: Error +since: 3.2.0 +--- +# E170: Not Class Type + +This error occurs when a class type is expected but something that isn't a concrete class type is provided. This commonly happens with `classOf[T]` when `T` is a type parameter or a refined type. + +The `classOf` operator requires a concrete class type known at compile time. Abstract types, type parameters, and refined types cannot be used because their actual class is not statically known. + +--- + +## Example + +```scala sc:fail +def f[T] = classOf[T] +``` + +### Error + +```scala sc:nocompile +-- [E170] Type Error: example.scala:1:19 --------------------------------------- +1 |def f[T] = classOf[T] + | ^ + | T is not a class type + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A class type includes classes and traits in a specific order. Defining a class, even an anonymous class, + | requires specifying a linearization order for the traits it extends. For example, `A & B` is not a class type + | because it doesn't specify which trait takes precedence, A or B. For more information about class types, please see the Scala Language Specification. + | Class types also can't have refinements. + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Use a concrete class type +def f = classOf[String] +``` + +```scala sc:compile sc-opts:-Werror +// Use ClassTag for runtime type information with type parameters +import scala.reflect.ClassTag + +def f[T: ClassTag]: Class[?] = summon[ClassTag[T]].runtimeClass +``` + diff --git a/docs/_docs/reference/error-codes/E171.md b/docs/_docs/reference/error-codes/E171.md new file mode 100644 index 000000000000..84b76176a138 --- /dev/null +++ b/docs/_docs/reference/error-codes/E171.md @@ -0,0 +1,46 @@ +--- +title: E171: Missing Argument +kind: Error +since: 3.2.2 +--- +# E171: Missing Argument + +This error occurs when a method is called without providing all required arguments. + +When calling a method, you must provide values for all parameters that don't have default values. This error identifies which parameter is missing from the call. + +--- + +## Example + +```scala sc:fail +def greet(name: String, greeting: String) = s"$greeting, $name!" + +def test = greet("World") +``` + +### Error + +```scala sc:nocompile +-- [E171] Type Error: example.scala:3:16 --------------------------------------- +3 |def test = greet("World") + | ^^^^^^^^^^^^^^ + |missing argument for parameter greeting of method greet: (name: String, greeting: String): String +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +def greet(name: String, greeting: String) = s"$greeting, $name!" + +// Provide all required arguments +def test = greet("World", "Hello") +``` + +```scala sc:compile sc-opts:-Werror +// Or use default parameter values +def greet(name: String, greeting: String = "Hello") = s"$greeting, $name!" + +def test = greet("World") +``` + diff --git a/docs/_docs/reference/error-codes/E172.md b/docs/_docs/reference/error-codes/E172.md new file mode 100644 index 000000000000..909d47a5cb21 --- /dev/null +++ b/docs/_docs/reference/error-codes/E172.md @@ -0,0 +1,51 @@ +--- +title: E172: Missing Implicit Argument +kind: Error +since: 3.3.0 +--- +# E172: Missing Implicit Argument + +This error occurs when a method requires an implicit (context) parameter but no matching given instance is in scope. + +Context parameters (using `using` or the older `implicit` syntax) are automatically provided by the compiler when a matching given instance is available. If none is found, this error is reported. + +--- + +## Example + +```scala sc:fail +trait Show[T] { + def show(t: T): String +} + +def printIt[T: Show](t: T) = println(summon[Show[T]].show(t)) + +def test = printIt(42) +``` + +### Error + +```scala sc:nocompile +-- [E172] Type Error: example.scala:7:22 --------------------------------------- +7 |def test = printIt(42) + | ^ + |No given instance of type Show[Int] was found for a context parameter of method printIt +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +trait Show[T] { + def show(t: T): String +} + +def printIt[T: Show](t: T) = println(summon[Show[T]].show(t)) + +// Provide a given instance for the required type +given Show[Int] with { + def show(t: Int) = t.toString +} + +def test = printIt(42) +``` + diff --git a/docs/_docs/reference/error-codes/E173.md b/docs/_docs/reference/error-codes/E173.md new file mode 100644 index 000000000000..42c80fd3bff1 --- /dev/null +++ b/docs/_docs/reference/error-codes/E173.md @@ -0,0 +1,64 @@ +--- +title: E173: Cannot Be Accessed +kind: Error +since: 3.3.0 +--- +# E173: Cannot Be Accessed + +This error occurs when trying to access a member that is not visible due to access modifiers (private, protected, etc.) from the current scope. + +Scala's access modifiers control which code can access which members. Private members can only be accessed from within the defining class, while protected members can be accessed from subclasses. + +--- + +## Example + +```scala sc:fail +class Secret { + private def hidden = 42 +} + +def test = { + val s = new Secret + s.hidden +} +``` + +### Error + +```scala sc:nocompile +-- [E173] Reference Error: example.scala:7:4 ----------------------------------- +7 | s.hidden + | ^^^^^^^^ + |method hidden cannot be accessed as a member of (s : Secret) from the top-level definitions in package . + | private method hidden can only be accessed from class Secret. +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +class Secret { + private def hidden = 42 + + // Expose via a public method + def revealed: Int = hidden +} + +def test = { + val s = new Secret + s.revealed +} +``` + +```scala sc:compile sc-opts:-Werror +// Or change the access modifier +class Secret { + def visible = 42 +} + +def test = { + val s = new Secret + s.visible +} +``` + diff --git a/docs/_docs/reference/error-codes/E174.md b/docs/_docs/reference/error-codes/E174.md new file mode 100644 index 000000000000..96ac18544b88 --- /dev/null +++ b/docs/_docs/reference/error-codes/E174.md @@ -0,0 +1,61 @@ +--- +title: E174: Inline Given Should Not Be Function +kind: Warning +since: 3.3.0 +--- +# E174: Inline Given Should Not Be Function + +This warning occurs when an `inline given` alias has a function value as its right-hand side. This pattern can significantly increase generated code size because the function is inlined at every use site. + +When you combine `inline` with a given that returns a function, the function literal is duplicated everywhere the given is summoned, leading to code bloat. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +inline given toStringFunc: (Int => String) = (x: Int) => x.toString +``` + +### Error + +```scala sc:nocompile +-- [E174] Syntax Warning: example.scala:1:54 ----------------------------------- +1 |inline given toStringFunc: (Int => String) = (x: Int) => x.toString + | ^^^^^^^^^^^^^^^^^^^^^^ + |An inline given alias with a function value as right-hand side can significantly increase + |generated code size. You should either drop the `inline` or rewrite the given with an + |explicit `apply` method. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A function value on the right-hand side of an inline given alias expands to + | an anonymous class. Each application of the inline given will then create a + | fresh copy of that class, which can increase code size in surprising ways. + | For that reason, functions are discouraged as right hand sides of inline given aliases. + | You should either drop `inline` or rewrite to an explicit `apply` method. E.g. + | + | inline given Conversion[A, B] = x => x.toB + | + | should be re-formulated as + | + | given Conversion[A, B] with + | inline def apply(x: A) = x.toB + | + ----------------------------------------------------------------------------- +``` + +### Solution + +```scala sc:compile sc-opts:-Werror +// Option 1: Remove the inline modifier +given toStringFunc: (Int => String) = (x: Int) => x.toString +``` + +```scala sc:compile sc-opts:-Werror +// Option 2: Use an explicit apply method +inline given toStringFunc: (Int => String) with { + def apply(x: Int): String = x.toString +} +``` + diff --git a/docs/_docs/reference/error-codes/E175.md b/docs/_docs/reference/error-codes/E175.md new file mode 100644 index 000000000000..506fec65f7fe --- /dev/null +++ b/docs/_docs/reference/error-codes/E175.md @@ -0,0 +1,60 @@ +--- +title: E175: Value Discarding +kind: Warning +since: 3.3.0 +--- +# E175: Value Discarding + +This warning occurs when a non-Unit expression's value is discarded (not used). This often indicates a programming error where a return value is accidentally ignored. + +This warning is enabled with the `-Wvalue-discard` compiler flag and helps catch bugs where important values like error results or updated collections are not handled. + +--- + +## Example + +```scala sc:fail sc-opts:-Wvalue-discard,-Werror +//> using options -Wvalue-discard + +import scala.collection.mutable + +def example: Unit = { + mutable.Set.empty[String].remove("") +} +``` + +### Error + +```scala sc:nocompile +-- [E175] Potential Issue Warning: example.scala:6:34 -------------------------- +6 | mutable.Set.empty[String].remove("") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |discarded non-Unit value of type Boolean. Add `: Unit` to discard silently. +``` + +### Solution + +```scala sc:compile sc-opts:-Wvalue-discard,-Werror +//> using options -Wvalue-discard + +import scala.collection.mutable + +def example: Unit = { + val set = mutable.Set.empty[String] + // Use the return value + val wasRemoved: Boolean = set.remove("") + if wasRemoved then println("Removed") +} +``` + +```scala sc:compile sc-opts:-Wvalue-discard,-Werror +//> using options -Wvalue-discard + +import scala.collection.mutable + +def example: Unit = { + // Explicitly discard by adding : Unit + mutable.Set.empty[String].remove(""): Unit +} +``` + diff --git a/docs/_docs/reference/error-codes/E176.md b/docs/_docs/reference/error-codes/E176.md new file mode 100644 index 000000000000..c70d781ff213 --- /dev/null +++ b/docs/_docs/reference/error-codes/E176.md @@ -0,0 +1,59 @@ +--- +title: "E176: Unused Non-Unit Value" +kind: Warning +since: 3.4.0 +--- +# E176: Unused Non-Unit Value + +This warning is emitted when a non-Unit value is computed in statement position but never used. + +This warning helps identify situations where the result of an expression is silently discarded, which may indicate a programming error such as forgetting to use or assign a computed value. + +This warning is only emitted when the `-Wnonunit-statement` compiler flag is enabled. + +--- + +## Example + +```scala sc:fail sc-opts:-Wnonunit-statement,-Werror +//> using options -Wnonunit-statement + +def example(): Unit = + val list = List(1, 2, 3) + list.map(_ + 1) // result is unused + println("done") +``` + +### Error + +```scala sc:nocompile +-- [E176] Potential Issue Warning: example.scala:5:10 -------------------------- +5 | list.map(_ + 1) // result is unused + | ^^^^^^^^^^^^^^^ + | unused value of type List[Int] +``` + +### Solution + +If the result is intentional, explicitly discard it or use it: + +```scala sc:compile sc-opts:-Wnonunit-statement,-Werror +//> using options -Wnonunit-statement + +def example(): Unit = + val list = List(1, 2, 3) + val _ = list.map(_ + 1) // explicitly discard + println("done") +``` + +Alternatively, use the result: + +```scala sc:compile sc-opts:-Wnonunit-statement,-Werror +//> using options -Wnonunit-statement + +def example(): Unit = + val list = List(1, 2, 3) + val transformed = list.map(_ + 1) + println(s"Transformed: $transformed") +``` + diff --git a/docs/_docs/reference/error-codes/E177.md b/docs/_docs/reference/error-codes/E177.md new file mode 100644 index 000000000000..8d610954141e --- /dev/null +++ b/docs/_docs/reference/error-codes/E177.md @@ -0,0 +1,103 @@ +--- +title: "E177: Constructor Proxy Shadows" +kind: Error +since: 3.4.0 +--- +# E177: Constructor Proxy Shadows + +This error occurs when a reference to a constructor proxy for an inner class shadows an outer reference with the same name, such as a method or object. + +In Scala 3, constructor proxies are automatically generated for classes, allowing you to create instances without writing `new`. However, when an inner class shares a name with an outer definition (method, object, or value), the compiler cannot determine which one you intended to use. + +--- + +Longer explanation: + +There is an ambiguity in the meaning of the call + +```scala sc:nocompile +MyClass(...) +``` + +It could mean creating an instance of an inner class with + +```scala sc:nocompile +new MyClass(...) +``` + +Or it could mean calling an outer method/object with the same name: + +```scala sc:nocompile +MyClass(...) +``` + +To disambiguate, use an explicit `new` if you mean the former, +or use a full prefix if you mean the latter. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +object Test: + def MyClass(s: String): String = s + + class Outer: + class MyClass(s: String) + val x = MyClass("hello") // ambiguous: inner class or outer method? +``` + +### Error + +```scala sc:nocompile +-- [E177] Reference Error: example.scala:6:12 ---------------------------------- +6 | val x = MyClass("hello") // ambiguous: inner class or outer method? + | ^^^^^^^ + | Reference to constructor proxy for class MyClass in class Outer + | shadows outer reference to method MyClass in object Test + | + | The instance needs to be created with an explicit `new`. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | There is an ambiguity in the meaning of the call + | + | MyClass(...) + | + | It could mean creating an instance of class MyClass in class Outer with + | + | new MyClass(...) + | + | Or it could mean calling method MyClass in object Test as in + | + | MyClass(...) + | + | To disambiguate, use an explicit `new` if you mean the former, + | or use a full prefix for MyClass if you mean the latter. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use explicit `new` if you want to create an instance of the inner class: + +```scala sc:compile sc-opts:-Werror +object Test: + def MyClass(s: String): String = s + + class Outer: + class MyClass(s: String) + val x = new MyClass("hello") // explicitly create inner class instance +``` + +Or use a full prefix to call the outer method: + +```scala sc:compile sc-opts:-Werror +object Test: + def MyClass(s: String): String = s + + class Outer: + class MyClass(s: String) + val x = Test.MyClass("hello") // explicitly call outer method +``` + diff --git a/docs/_docs/reference/error-codes/E178.md b/docs/_docs/reference/error-codes/E178.md new file mode 100644 index 000000000000..e2663c7ce782 --- /dev/null +++ b/docs/_docs/reference/error-codes/E178.md @@ -0,0 +1,57 @@ +--- +title: "E178: Missing Argument List" +kind: Error +since: 3.4.0 +--- +# E178: Missing Argument List + +This error occurs when a method with multiple parameter lists is called without providing all the required argument lists. + +In Scala, methods can have multiple parameter lists (curried methods). When calling such methods, all parameter lists must be provided unless the partially applied method is explicitly expected as a function type. + +Unapplied methods are only converted to functions when a function type is expected. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +object Test: + def multiParam()()(x: Int): Int = x + multiParam() // missing argument lists +``` + +### Error + +```scala sc:nocompile +-- [E178] Type Error: example.scala:3:12 --------------------------------------- +3 | multiParam() // missing argument lists + | ^^^^^^^^^^^^ + | missing argument list for method multiParam in object Test + | + | def multiParam()()(x: Int): Int + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Unapplied methods are only converted to functions when a function type is expected. + ----------------------------------------------------------------------------- +``` + +### Solution + +Provide all required argument lists: + +```scala sc:compile sc-opts:-Werror +object Test: + def multiParam()()(x: Int): Int = x + val result = multiParam()()(42) // provide all argument lists +``` + +Or explicitly convert to a function if partial application is intended: + +```scala sc:compile sc-opts:-Werror +object Test: + def multiParam()()(x: Int): Int = x + val partialFn: Int => Int = multiParam()() // explicit function type +``` + diff --git a/docs/_docs/reference/error-codes/E179.md b/docs/_docs/reference/error-codes/E179.md new file mode 100644 index 000000000000..038c40c7559e --- /dev/null +++ b/docs/_docs/reference/error-codes/E179.md @@ -0,0 +1,50 @@ +--- +title: "E179: Match Type Scrutinee Cannot Be Higher-Kinded" +kind: Error +since: 3.4.0 +--- +# E179: Match Type Scrutinee Cannot Be Higher-Kinded + +This error occurs when you try to use a higher-kinded type as the scrutinee (the type being matched) in a match type definition. + +Match types in Scala 3 only support proper types (types of kind `*`) as their scrutinee. Higher-kinded types (types that take type parameters, like `F[_]`) cannot be used directly as the scrutinee. + +--- + +## Example + +```scala sc:fail +object Test: + type HigherKindedMatch[X[_]] = X match + case _ => Int +``` + +### Error + +```scala sc:nocompile +-- [E179] Type Error: example.scala:2:33 --------------------------------------- +2 | type HigherKindedMatch[X[_]] = X match + | ^ + | the scrutinee of a match type cannot be higher-kinded +``` + +### Solution + +Use a proper type (kind `*`) as the scrutinee by applying the higher-kinded type to a type parameter: + +```scala sc:compile sc-opts:-Werror +object Test: + type AppliedMatch[X[_], A] = X[A] match + case List[a] => Int + case Option[a] => String +``` + +Or match on a specific applied type: + +```scala sc:compile sc-opts:-Werror +object Test: + type ConcreteMatch[X] = X match + case List[a] => Int + case Option[a] => String +``` + diff --git a/docs/_docs/reference/error-codes/E180.md b/docs/_docs/reference/error-codes/E180.md new file mode 100644 index 000000000000..66c42ed51c59 --- /dev/null +++ b/docs/_docs/reference/error-codes/E180.md @@ -0,0 +1,89 @@ +--- +title: "E180: Ambiguous Extension Method" +kind: Error +since: 3.4.0 +--- + +# E180: Ambiguous Extension Method + +This error occurs when multiple extension methods with the same name are applicable to a type and the compiler cannot determine which one to use. + +When multiple extension methods from different imports are both valid for a receiver type, the call is ambiguous and the compiler reports this error. + +**Note:** This error is always reported as a nested error inside E008 (Not Found Error) because extension method resolution failures are wrapped in member lookup errors. The E180 message appears in the detailed error explanation. + +--- + +## Example + +```scala sc:nocompile +object Ext1: + extension (i: Int) + def wow: Unit = println(i) + +object Ext2: + extension (i: Int) + def wow: Unit = println(i * 2) + +def example(): Unit = + import Ext1.wow + import Ext2.wow + 5.wow // error: ambiguous extension methods +``` + +### Error + +When compiled, this produces an E008 error with the E180 ambiguous extension method message nested inside: + +```scala sc:nocompile +-- [E008] Not Found Error: example.scala:12:2 ---------------------------------- +12 | 5.wow + | ^^^^^ + | value wow is not a member of Int. + | An extension method was tried, but could not be fully constructed: + | + | Ext2.wow(5) + | + | failed with: + | + | Ambiguous extension methods: + | both Ext2.wow(5) + | and Ext1.wow(5) + | are possible expansions of 5.wow +``` + +### Solution + +Disambiguate by using a qualified name: + +```scala sc:nocompile +object Ext1: + extension (i: Int) + def wow: Unit = println(i) + +object Ext2: + extension (i: Int) + def wow: Unit = println(i * 2) + +def example(): Unit = + import Ext1.wow + import Ext2.wow + Ext1.wow(5) // explicitly call Ext1's version +``` + +Or import only one extension method: + +```scala sc:nocompile +object Ext1: + extension (i: Int) + def wow: Unit = println(i) + +object Ext2: + extension (i: Int) + def wow: Unit = println(i * 2) + +def example(): Unit = + import Ext1.wow // only import Ext1's extension + 5.wow // unambiguous +``` + diff --git a/docs/_docs/reference/error-codes/E181.md b/docs/_docs/reference/error-codes/E181.md new file mode 100644 index 000000000000..db67d7652c8e --- /dev/null +++ b/docs/_docs/reference/error-codes/E181.md @@ -0,0 +1,62 @@ +--- +title: "E181: Unqualified Call to AnyRef Method" +kind: Warning +since: 3.4.0 +--- +# E181: Unqualified Call to AnyRef Method + +This warning is emitted when you make an unqualified call to an `AnyRef` or `Any` method (such as `synchronized`, `wait`, `notify`, `hashCode`, `toString`, `getClass`) at the top level of a method or function. + +Top-level unqualified calls to `AnyRef` or `Any` methods are resolved to calls on `Predef` or on imported methods. This might not be what you intended, as these calls typically expect to operate on a specific object instance. + +--- + +## Example + +```scala sc:compile custom-sc:fail sc-opts:-Werror,-explain +def example(): Unit = + synchronized { + println("hello") + } +``` + +### Error + +```scala sc:nocompile +-- [E181] Potential Issue Warning: example.scala:2:2 --------------------------- +2 | synchronized { + | ^^^^^^^^^^^^ + | Suspicious top-level unqualified call to synchronized + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Top-level unqualified calls to AnyRef or Any methods such as synchronized are + | resolved to calls on Predef or on imported methods. This might not be what + | you intended. + ----------------------------------------------------------------------------- +``` + +### Solution + +If you intend to synchronize on a specific object, qualify the call: + +```scala sc:compile sc-opts:-Werror +object Lock + +def example(): Unit = + Lock.synchronized { + println("hello") + } +``` + +Or if inside a class, use `this.synchronized`: + +```scala sc:compile sc-opts:-Werror +class Counter: + private var count = 0 + def increment(): Int = this.synchronized { + count += 1 + count + } +``` + diff --git a/docs/_docs/reference/error-codes/E182.md b/docs/_docs/reference/error-codes/E182.md new file mode 100644 index 000000000000..dfb5cc70c182 --- /dev/null +++ b/docs/_docs/reference/error-codes/E182.md @@ -0,0 +1,49 @@ +--- +title: "E182: Not Constant" +kind: Error +since: 3.4.0 +--- +# E182: Not Constant + +This error occurs when attempting to use `constValue` (or similar compile-time operations) on a type that is not a constant type. + +A constant type in Scala 3 is a type that represents a single, literal value known at compile time, such as `1`, `"hello"`, or `true`. Types like `Int`, `String`, or opaque types that cannot be resolved to a single constant value cannot be used where a constant type is required. + +--- + +## Example + +```scala sc:fail +import scala.compiletime.constValue + +def example(): Int = constValue[Int] +``` + +### Error + +```scala sc:nocompile +-- [E182] Type Error: example.scala:3:32 --------------------------------------- +3 |def example(): Int = constValue[Int] + | ^^^ + | Int is not a constant type; cannot take constValue +``` + +### Solution + +Use a literal singleton type instead: + +```scala sc:compile sc-opts:-Werror +import scala.compiletime.constValue + +def example(): Int = constValue[42] +``` + +Or use a type alias that resolves to a constant type: + +```scala sc:compile sc-opts:-Werror +import scala.compiletime.constValue + +type MyConstant = 100 +def example(): Int = constValue[MyConstant] +``` + diff --git a/docs/_docs/reference/error-codes/E183.md b/docs/_docs/reference/error-codes/E183.md new file mode 100644 index 000000000000..eae174ed15ef --- /dev/null +++ b/docs/_docs/reference/error-codes/E183.md @@ -0,0 +1,52 @@ +--- +title: "E183: Closure Cannot Have Internal Parameter Dependencies" +kind: Error +since: 3.4.0 +--- +# E183: Closure Cannot Have Internal Parameter Dependencies + +This error occurs when you try to create a closure (anonymous function) where one parameter's type depends on another parameter from the same parameter list. This is called a "parameter dependency" and is not supported for closures. + +In Scala, closures are converted to function types like `Function1`, `Function2`, etc. These standard function types cannot represent dependent parameter types, where the type of one parameter refers to another parameter using `.type` (singleton types). + +This limitation applies to both polymorphic closures (with type parameters like `[T]`) and monomorphic closures. + +## Example + +```scala sc:fail +def example = [T] => (x: T, y: List[x.type]) => List(y) +``` + +Here, the type of parameter `y` is `List[x.type]`, which depends on the value of parameter `x`. This internal dependency between parameters in the same list makes it impossible to represent this closure as a standard function type. + +### Error + +```scala sc:nocompile +-- [E183] Type Error: example.scala:1:18 --------------------------------------- +1 |def example = [T] => (x: T, y: List[x.type]) => List(y) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |cannot turn method type [T](x: T, y: List[(x : T)]): List[List[(x : T)]] into closure + |because it has internal parameter dependencies +``` + +### Solution + +There are two common approaches to work around this limitation: + +**1. Use a regular method instead of a closure** + +Convert the closure to a named method definition: + +```scala sc:compile sc-opts:-Werror +def example[T](x: T, y: List[x.type]): List[List[x.type]] = List(y) +``` + +**2. Use curried parameters** + +Split the dependent parameters into separate parameter lists. The dependent parameter can then reference parameters from earlier lists: + +```scala sc:compile sc-opts:-Werror +def curriedExample = [T] => (x: T) => (y: List[x.type]) => List(y) +``` + +This works because each parameter list produces a separate closure, and the inner closure captures `x` from its enclosing scope rather than having a parameter-to-parameter dependency. diff --git a/docs/_docs/reference/error-codes/E184.md b/docs/_docs/reference/error-codes/E184.md new file mode 100644 index 000000000000..46edeb3475b9 --- /dev/null +++ b/docs/_docs/reference/error-codes/E184.md @@ -0,0 +1,79 @@ +--- +title: "E184: Match Type No Cases" +kind: Error +since: 3.4.0 +--- + +# E184: Match Type No Cases + +This error would be emitted when a match type reduction fails because the scrutinee matches none of the cases defined in the match type. + +**Note:** This error code exists in the compiler but is currently not emitted. The information about failed match type reduction is instead included as part of other error messages (like E172 MissingImplicitArgument) when implicit resolution fails. + +--- + +## Example + +```scala sc:nocompile +object Record { + opaque type Rec[A <: Tuple] = Map[String, Any] + object Rec { + type HasKey[A <: Tuple, K] = + A match + case (K, t) *: _ => t + case _ *: t => HasKey[t, K] + + val empty: Rec[EmptyTuple] = Map.empty + + extension [A <: Tuple](toMap: Rec[A]) + def fetch[K <: String & Singleton](key: K): HasKey[A, K] = + toMap(key).asInstanceOf[HasKey[A, K]] + } +} + +def example = + val foo: Any = Record.Rec.empty.fetch("foo") + +``` + +### Error + +When this error code is eventually enabled, it would produce: + +```scala sc:nocompile +-- [E184] Type Error: example.scala:18:39 ------- +18 | val foo: Any = Record.Rec.empty.fetch("foo") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Match type reduction failed since selector EmptyTuple.type + | matches none of the cases + | + | case (("foo" : String), t) *: _ => t + | case _ *: t => Record.Rec.HasKey[t, ("foo" : String)] +``` + +### Solution + +Ensure the match types includes additional missing case: + +```scala sc:compile +object Record { + opaque type Rec[A <: Tuple] = Map[String, Any] + object Rec { + type HasKey[A <: Tuple, K] = + A match + case (K, t) *: _ => t + case _ *: t => HasKey[t, K] + case EmptyTuple => Nothing // additional case to satisfy missing case + + val empty: Rec[EmptyTuple] = Map.empty + + extension [A <: Tuple](toMap: Rec[A]) + def fetch[K <: String & Singleton](key: K): HasKey[A, K] = + toMap(key).asInstanceOf[HasKey[A, K]] + } +} + +def example = + val foo: Any = Record.Rec.empty.fetch("foo") +``` + diff --git a/docs/_docs/reference/error-codes/E185.md b/docs/_docs/reference/error-codes/E185.md new file mode 100644 index 000000000000..9feac569eda1 --- /dev/null +++ b/docs/_docs/reference/error-codes/E185.md @@ -0,0 +1,58 @@ +--- +title: "E185: Unimported and Imported" +kind: Error +since: 3.4.0 +--- +# E185: Unimported and Imported + +This error occurs when the same identifier is both imported and unimported (or unimported twice) on the same import line. + +In Scala 3, you can selectively unimport members using `as _` syntax. However, it doesn't make sense to both import and unimport the same identifier on the same line, as this represents contradictory intentions. + +--- + +## Example + +```scala sc:fail +object MyLib: + val value = 42 + +import MyLib.{value, value as _} +``` + +### Error + +```scala sc:nocompile +-- [E185] Syntax Error: example.scala:4:21 ------------------------------------- +4 |import MyLib.{value, value as _} + | ^^^^^ + | value is unimported and imported on the same import line. +``` + +### Solution + +Choose either to import or unimport the identifier: + +```scala sc:compile sc-opts:-Werror +object MyLib: + val value = 42 + +// Either import it: +import MyLib.value + +def example(): Int = value +``` + +Or unimport it if you want to exclude it from a wildcard import: + +```scala sc:compile sc-opts:-Werror +object MyLib: + val value = 42 + val other = 100 + +// Unimport value, import everything else: +import MyLib.{value as _, *} + +def example(): Int = other +``` + diff --git a/docs/_docs/reference/error-codes/E186.md b/docs/_docs/reference/error-codes/E186.md new file mode 100644 index 000000000000..8ddeb4ee9837 --- /dev/null +++ b/docs/_docs/reference/error-codes/E186.md @@ -0,0 +1,77 @@ +--- +title: "E186: Implausible Pattern Warning" +kind: Warning +since: 3.4.0 +--- +# E186: Implausible Pattern Warning + +This warning is emitted when a pattern match case appears implausible—the pattern could only match the selector type if there is a custom `equals` method that identifies elements of the two unrelated types. + +This typically occurs when matching against singleton objects or values of unrelated types, where the pattern is technically possible due to Java's `equals` semantics but is unlikely to be intentional. + +This warning requires the `-Wimplausible-patterns` compiler flag. + +--- + +## Example + +```scala sc:fail sc-opts:-Wimplausible-patterns,-Werror +//> using options -Wimplausible-patterns + +abstract class Recovery +object Recovery extends Recovery + +abstract class TypedRecovery +object TypedRecovery extends TypedRecovery + +def example(x: TypedRecovery): Unit = x match + case Recovery => println("Recovery") + case TypedRecovery => println("TypedRecovery") +``` + +### Error + +```scala sc:nocompile +-- [E186] Type Warning: example.scala:10:7 ------------------------------------- +10 | case Recovery => println("Recovery") + | ^^^^^^^^ + |Implausible pattern: + |Recovery could match selector of type TypedRecovery + |only if there is an `equals` method identifying elements of the two types. +``` + +### Solution + +Remove the implausible pattern if it was unintentional: + +```scala sc:compile sc-opts:-Wimplausible-patterns,-Werror +//> using options -Wimplausible-patterns + +abstract class Recovery +object Recovery extends Recovery + +abstract class TypedRecovery +object TypedRecovery extends TypedRecovery + +def example(x: TypedRecovery): Unit = x match + case TypedRecovery => println("TypedRecovery") +``` + +Or use a common supertype if you need to match against both: + +```scala sc:compile sc-opts:-Wimplausible-patterns,-Werror +//> using options -Wimplausible-patterns + +trait RecoveryEvent + +abstract class Recovery extends RecoveryEvent +object Recovery extends Recovery + +abstract class TypedRecovery extends RecoveryEvent +object TypedRecovery extends TypedRecovery + +def example(x: RecoveryEvent): Unit = x match + case Recovery => println("Recovery") + case TypedRecovery => println("TypedRecovery") +``` + diff --git a/docs/_docs/reference/error-codes/E187.md b/docs/_docs/reference/error-codes/E187.md new file mode 100644 index 000000000000..7fbbea05b823 --- /dev/null +++ b/docs/_docs/reference/error-codes/E187.md @@ -0,0 +1,70 @@ +--- +title: "E187: Synchronized Call on Boxed Class" +kind: Warning +since: 3.4.0 +--- +# E187: Synchronized Call on Boxed Class + +This warning is emitted when you call the `synchronized` method on a boxed primitive value (like `Int`, `Boolean`, `Double`, etc.). + +Calling `synchronized` on a boxed primitive is suspicious because: +- The boxed object may be a different instance each time due to boxing +- It's unlikely to provide the synchronization behavior you expect +- Different boxed values of the same primitive may or may not share the same lock + +--- + +Longer explanation: + +You called the `synchronized` method on a boxed primitive. This might not be what you intended. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +def example(): Unit = + 1.synchronized { + println("hello") + } +``` + +### Error + +```scala sc:nocompile +-- [E187] Potential Issue Warning: example.scala:2:4 --------------------------- +2 | 1.synchronized { + | ^^^^^^^^^^^^^^ + | Suspicious synchronized call on boxed class + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | You called the synchronized method on a boxed primitive. This might not be what + | you intended. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use a dedicated lock object instead: + +```scala sc:compile sc-opts:-Werror +object Lock + +def example(): Unit = + Lock.synchronized { + println("hello") + } +``` + +Or use `this` if inside a class: + +```scala sc:compile sc-opts:-Werror +class Counter: + private var count = 0 + def increment(): Int = this.synchronized { + count += 1 + count + } +``` + diff --git a/docs/_docs/reference/error-codes/E188.md b/docs/_docs/reference/error-codes/E188.md new file mode 100644 index 000000000000..b528c273c7b0 --- /dev/null +++ b/docs/_docs/reference/error-codes/E188.md @@ -0,0 +1,53 @@ +--- +title: "E188: VarArgs Param Cannot Be Given" +kind: Error +since: 3.4.0 +--- +# E188: VarArgs Param Cannot Be Given + +This error occurs when a repeated parameter (varargs) is declared in a `using` or `implicit` clause. + +Repeated parameters cannot be used as given/implicit parameters because they could always be satisfied by providing zero arguments, which defeats the purpose of an implicit argument. + +--- + +Longer explanation: + +It is not possible to define a given with a repeated parameter type. This hypothetical given parameter could always be satisfied by providing 0 arguments, which defeats the purpose of a given argument. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +def example(using xs: Int*): Seq[Int] = xs +``` + +### Error + +```scala sc:nocompile +-- [E188] Syntax Error: example.scala:1:22 ------------------------------------- +1 |def example(using xs: Int*): Seq[Int] = xs + | ^^^^ + | repeated parameters are not allowed in a using clause + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | It is not possible to define a given with a repeated parameter type. This hypothetical given parameter could always be satisfied by providing 0 arguments, which defeats the purpose of a given argument. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use a regular parameter list for varargs: + +```scala sc:compile sc-opts:-Werror +def example(xs: Int*): Seq[Int] = xs +``` + +Or use a sequence type for the given parameter: + +```scala sc:compile sc-opts:-Werror +def example(using xs: Seq[Int]): Seq[Int] = xs +``` + diff --git a/docs/_docs/reference/error-codes/E189.md b/docs/_docs/reference/error-codes/E189.md new file mode 100644 index 000000000000..9653e1567daf --- /dev/null +++ b/docs/_docs/reference/error-codes/E189.md @@ -0,0 +1,85 @@ +--- +title: "E189: Extractor Not Found" +kind: Error +since: 3.4.0 +--- +# E189: Extractor Not Found + +This error occurs when an extractor pattern is used with a name that does not refer to an object with an `unapply` or `unapplySeq` method. + +Extractors in pattern matching require an object with an `unapply` or `unapplySeq` method that can deconstruct values. Case classes and enum cases automatically provide these extractors. + +--- + +Longer explanation: + +An application `name(...)` in a pattern can refer to an extractor which defines an `unapply` or `unapplySeq` method. Example: + +```scala sc:nocompile +object split: + def unapply(x: String) = + val (leading, trailing) = x.splitAt(x.length / 2) + Some((leading, trailing)) + +val split(fst, snd) = "HiHo" +``` + +The extractor pattern `split(fst, snd)` defines `fst` as the first half "Hi" and `snd` as the second half "Ho" of the right hand side "HiHo". Case classes and enum cases implicitly define extractors with the name of the class or enum case. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +def example(): Unit = + val s(): String = "hello" +``` + +### Error + +```scala sc:nocompile +-- [E189] Not Found Error: example.scala:2:6 ----------------------------------- +2 | val s(): String = "hello" + | ^ + | no pattern match extractor named s was found + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | An application s(...) in a pattern can refer to an extractor + | which defines an unapply or unapplySeq method. Example: + | + | object split: + | def unapply(x: String) = + | val (leading, trailing) = x.splitAt(x.length / 2) + | Some((leading, trailing)) + | + | val split(fst, snd) = "HiHo" + | + | The extractor pattern `split(fst, snd)` defines `fst` as the first half "Hi" and + | `snd` as the second half "Ho" of the right hand side "HiHo". Case classes and + | enum cases implicitly define extractors with the name of the class or enum case. + | Here, no extractor named s was found, so the pattern could not be typed. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use a simple value binding without parentheses: + +```scala sc:compile sc-opts:-Werror +def example(): Unit = + val s: String = "hello" + println(s) +``` + +Or if you need an extractor, define one and use it in a match: + +```scala sc:compile sc-opts:-Werror +object MyString: + def unapply(s: String): Option[String] = Some(s) + +def example(): Unit = + "hello" match + case MyString(s) => println(s) +``` + diff --git a/docs/_docs/reference/error-codes/E190.md b/docs/_docs/reference/error-codes/E190.md new file mode 100644 index 000000000000..03a659fc47e4 --- /dev/null +++ b/docs/_docs/reference/error-codes/E190.md @@ -0,0 +1,55 @@ +--- +title: "E190: Pure Unit Expression" +kind: Warning +since: 3.4.0 +--- +# E190: Pure Unit Expression + +This warning is emitted when a pure non-Unit expression is discarded in a context expecting `Unit`. + +When an expression of non-Unit type is used where Unit is expected, the compiler inserts a discarding conversion. If the expression is pure (has no side effects), this conversion produces no useful effect and the code is effectively equivalent to `()`. + +--- + +Longer explanation: + +As this expression is not of type Unit, it is desugared into `{ expression; () }`. Here the expression is a pure statement that can be discarded. Therefore the expression is effectively equivalent to `()`. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +def example: Unit = 42 +``` + +### Error + +```scala sc:nocompile +-- [E190] Potential Issue Warning: example.scala:1:20 -------------------------- +1 |def example: Unit = 42 + | ^^ + | Discarded non-Unit value of type Int. Add `: Unit` to discard silently. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | As this expression is not of type Unit, it is desugared into `{ 42; () }`. + | Here the `42` expression is a pure statement that can be discarded. + | Therefore the expression is effectively equivalent to `()`. + ----------------------------------------------------------------------------- +``` + +### Solution + +Return Unit explicitly: + +```scala sc:compile sc-opts:-Werror +def example: Unit = () +``` + +Or change the return type if you want to return the value: + +```scala sc:compile sc-opts:-Werror +def example: Int = 42 +``` + diff --git a/docs/_docs/reference/error-codes/E191.md b/docs/_docs/reference/error-codes/E191.md new file mode 100644 index 000000000000..db7838602711 --- /dev/null +++ b/docs/_docs/reference/error-codes/E191.md @@ -0,0 +1,57 @@ +--- +title: "E191: Match Type Legacy Pattern" +kind: Error +since: 3.4.0 +--- +# E191: Match Type Legacy Pattern + +This error occurs when a match type pattern contains an illegal case with an unaccounted type parameter in a contravariant position. + +In match types, type parameters extracted from patterns must be properly accounted for. When a type parameter appears in a contravariant position (e.g., inside a `Consumer[-T]`), the compiler cannot reliably extract it. + +--- + +## Example + +```scala sc:fail +class Consumer[-T] + +type Illegal[X] = X match + case Consumer[List[t]] => t +``` + +### Error + +```scala sc:nocompile +-- [E191] Type Error: example.scala:3:20 --------------------------------------- +3 |type Illegal[X] = X match + | ^ + | The match type contains an illegal case: + | case Consumer[List[t]] => t + | The pattern contains an unaccounted type parameter `t`. + | (this error can be ignored for now with `-source:3.3`) +4 | case Consumer[List[t]] => t +``` + +### Solution + +Extract type parameters from covariant positions instead: + +```scala sc:compile sc-opts:-Werror +class Consumer[-T] + +// Extract from covariant position (List is covariant) +type Legal[X] = X match + case List[t] => t +``` + +Or redesign the type structure to avoid contravariant type extraction: + +```scala sc:compile sc-opts:-Werror +class Producer[+T] + +// Type parameter in covariant position +type Extract[X] = X match + case Producer[t] => t +``` + diff --git a/docs/_docs/reference/error-codes/E192.md b/docs/_docs/reference/error-codes/E192.md new file mode 100644 index 000000000000..b81e98844030 --- /dev/null +++ b/docs/_docs/reference/error-codes/E192.md @@ -0,0 +1,86 @@ +--- +title: "E192: Unstable Inline Accessor" +kind: Warning +since: 3.4.0 +--- +# E192: Unstable Inline Accessor + +This warning is emitted when an inline method accesses a non-public member, causing the compiler to generate an unstable accessor. + +When an `inline` method references a private or package-private member, the compiler must generate an accessor method to make that member accessible at the inlining site. This accessor has an automatically generated name that may change between compiler versions, which can break binary compatibility. + +This warning requires the `-WunstableInlineAccessors` compiler flag. + +--- + +Longer explanation: + +Access to a non-public member causes the automatic generation of an accessor. This accessor is not stable, its name may change or it may disappear if not needed in a future version. + +To make sure that the inlined code is binary compatible you must make sure that the member is public in the binary API: +- Option 1: Annotate the member with `@publicInBinary` +- Option 2: Make the member public + +--- + +## Example + +```scala sc:fail sc-opts:-WunstableInlineAccessors,-Werror,-explain +//> using options -WunstableInlineAccessors +class Example: + private val secret = 42 + inline def getSecret: Int = secret +``` + +### Error + +```scala sc:nocompile +-- [E192] Compatibility Warning: example.scala:4:30 ---------------------------- +4 | inline def getSecret: Int = secret + | ^^^^^^ + |Unstable inline accessor Example$$inline$secret was generated in class Example. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Access to non-public value secret causes the automatic generation of an accessor. + | This accessor is not stable, its name may change or it may disappear + | if not needed in a future version. + | + | To make sure that the inlined code is binary compatible you must make sure that + | value secret is public in the binary API. + | * Option 1: Annotate value secret with @publicInBinary + | * Option 2: Make value secret public + | + | This change may break binary compatibility if a previous version of this + | library was compiled with generated accessors. Binary compatibility should + | be checked using MiMa. If binary compatibility is broken, you should add the + | old accessor explicitly in the source code. The following code should be + | added to class Example: + | @publicInBinary private[Example] final def Example$$inline$secret: Int = this.secret + ----------------------------------------------------------------------------- +``` + +### Solution + +Use `@publicInBinary` with package-private access: + +```scala sc:nocompile custom-sc:compile sc-opts:-WunstableInlineAccessors,-Werror +//> using options -WunstableInlineAccessors +package foo +import scala.annotation.publicInBinary + +class Example: + @publicInBinary private[foo] val secret = 42 + inline def getSecret: Int = secret +``` + +Or make the member public: + +```scala sc:compile sc-opts:-WunstableInlineAccessors,-Werror +//> using options -WunstableInlineAccessors + +class Example: + val secret = 42 + inline def getSecret: Int = secret +``` + diff --git a/docs/_docs/reference/error-codes/E193.md b/docs/_docs/reference/error-codes/E193.md new file mode 100644 index 000000000000..3c545c225d78 --- /dev/null +++ b/docs/_docs/reference/error-codes/E193.md @@ -0,0 +1,45 @@ +--- +title: "E193: Volatile on Val" +kind: Warning +since: 3.4.1 +--- +# E193: Volatile on Val + +This warning is emitted when the `@volatile` annotation is applied to a `val` (immutable value). + +The `@volatile` annotation is meaningful only for mutable fields (`var`) because it ensures visibility of changes across threads. Since `val` is immutable and can only be assigned once during initialization, the volatile annotation has no effect and is likely a mistake. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +class Example: + @volatile val x: Int = 42 +``` + +### Error + +```scala sc:nocompile +-- [E193] Syntax Warning: example.scala:2:16 ----------------------------------- +2 | @volatile val x: Int = 42 + | ^ + | values cannot be volatile +``` + +### Solution + +If you need a volatile field, use `var`: + +```scala sc:compile sc-opts:-Werror +class Example: + @volatile var x: Int = 42 +``` + +If the value should be immutable, remove the `@volatile` annotation: + +```scala sc:compile sc-opts:-Werror +class Example: + val x: Int = 42 +``` + diff --git a/docs/_docs/reference/error-codes/E194.md b/docs/_docs/reference/error-codes/E194.md new file mode 100644 index 000000000000..09752ac0ea97 --- /dev/null +++ b/docs/_docs/reference/error-codes/E194.md @@ -0,0 +1,67 @@ +--- +title: "E194: Extension Nullified by Member" +kind: Warning +since: 3.5.0 +--- +# E194: Extension Nullified by Member + +This warning is emitted when an extension method will never be selected because the target type already has a member with the same name and compatible parameter types. + +Extensions can be overloaded, but they do not overload existing member methods. When you call a method on a value, the compiler will always prefer the existing member method over an extension method with the same signature. + +--- + +Longer explanation: + +Although extensions can be overloaded, they do not overload existing member methods. An extension method can be invoked as a regular method, but if that is the intended usage, it should not be defined as an extension. + +The extension may be invoked as though selected from an arbitrary type if conversions are in play. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +class Person + +object PersonOps: + extension (p: Person) def toString: String = "custom" +``` + +### Error + +```scala sc:nocompile +-- [E194] Potential Issue Warning: example.scala:4:28 -------------------------- +4 | extension (p: Person) def toString: String = "custom" + | ^ + |Extension method toString will never be selected from type Person + |because Person already has a member with the same name and compatible parameter types. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Although extensions can be overloaded, they do not overload existing member methods. + | An extension method can be invoked as a regular method, but if that is the intended usage, + | it should not be defined as an extension. + | + | The extension may be invoked as though selected from an arbitrary type if conversions are in play. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use a different method name: + +```scala sc:compile sc-opts:-Werror +class Person + +object PersonOps: + extension (p: Person) def toCustomString: String = "custom" +``` + +Or override the method in the class itself: + +```scala sc:compile sc-opts:-Werror +class Person: + override def toString: String = "custom" +``` + diff --git a/docs/_docs/reference/error-codes/E195.md b/docs/_docs/reference/error-codes/E195.md new file mode 100644 index 000000000000..ac4422f4a468 --- /dev/null +++ b/docs/_docs/reference/error-codes/E195.md @@ -0,0 +1,70 @@ +--- +title: "E195: Phantom Symbol Not Value" +kind: Error +since: 3.5.0 +--- +# E195: Phantom Symbol Not Value + +This error occurs when you try to use a compiler-generated phantom symbol as a standalone value. Phantom symbols are synthetic entries created by the compiler for various features but cannot be used as actual values. + +This error is triggered for: +- **Constructor proxies**: Symbols representing factory methods for non-case classes (since 3.3.1) +- **Context bound companions**: Symbols representing witnesses for context bounds (since 3.5.0) +- **Dummy capture parameters**: Symbols representing references to capture parameters in experimental capture checking (since 3.7.2) + +**Note:** This error code is used by multiple message classes and the exact message varies depending on the context. + +--- + +## Example + +The following example demonstrates a dummy capture parameter being incorrectly used as a value. This occurs when using the experimental capture checking feature: + +```scala sc:fail +import language.experimental.captureChecking + +class A: + type C^ + +def example(a: A): a.C = a.C +``` + +Here, `C^` declares a capture parameter type, and the compiler creates a synthetic term `C` to allow referring to it in capture sets. However, this term cannot be used as an actual value. + +### Error + +```scala sc:nocompile +-- [E195] Type Error: example.scala:6:27 --------------------------------------- +6 |def example(a: A): a.C = a.C + | ^^^ + | dummy term capture parameter value C cannot be used as a value + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A term capture parameter is a symbol made up by the compiler to represent a reference + | to a real capture parameter in capture sets. For instance, in + | + | class A: + | type C^ + | + | there is just a type `A` declared but not a value `A`. Nevertheless, one can write + | the selection `(a: A).C` and use a a value, which works because the compiler created a + | term capture parameter for `C`. However, these term capture parameters are not real values, + | they can only be referred in capture sets. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use a real declared member instead of the phantom symbol: + +```scala sc:nocompile custom-sc:compile +import language.experimental.captureChecking + +class A: + type C^ + val getC: C = ??? + +def example(a: A): a.C = a.getC +``` + diff --git a/docs/_docs/reference/error-codes/E196.md b/docs/_docs/reference/error-codes/E196.md new file mode 100644 index 000000000000..9a4ff48979f3 --- /dev/null +++ b/docs/_docs/reference/error-codes/E196.md @@ -0,0 +1,55 @@ +--- +title: "E196: Context Bound Companion Not Value" +kind: Error +since: 3.5.0 +until: 3.5.0 +--- + +This error was introduced and made inactive in the same release (Scala 3.5.0) and was never emitted by a released version of the Scala 3 compiler. + +## What it did + +This error was triggered when attempting to use a context bound companion as a standalone value, rather than in a selection. + +### Example + +```scala sc:nocompile +//> using options -experimental -language:experimental.modularity -source:future + +class C[Self] +class D[Self] + +trait Test: + def foo[A: {C, D}] = A + type A: C + val x = A + val y: A.type = ??? +``` + +### Error + +```scala sc:nocompile +-- [E196] Type Error: example.scala:7:23 -------------------------------------- +7 | def foo[A: {C, D}] = A + | ^ + | context bound companion value A cannot be used as a value +``` + +## Explanation + +Context bound companions are synthetic symbols created by the compiler to represent witnesses generated for context bounds of type parameters. For example, in: + +```scala sc:nocompile +class Monoid: + type Self + def unit: Self + +type A: Monoid +``` + +There is just a type `A` declared but not a value `A`. Nevertheless, one can write the selection `A.unit`, which works because the compiler created a context bound companion value with the (term-)name `A`. + +The error E196 was introduced in commit becdf887a5 (April 2024) as part of implementing context bound companions. However, the restriction was relaxed before the 3.5.0 release, and the error was made inactive. + +Since Scala 3.5.0, context bound companions can be used more freely, making this specific error obsolete. + diff --git a/docs/_docs/reference/error-codes/E197.md b/docs/_docs/reference/error-codes/E197.md new file mode 100644 index 000000000000..cd01e09ae2a5 --- /dev/null +++ b/docs/_docs/reference/error-codes/E197.md @@ -0,0 +1,61 @@ +--- +title: "E197: Inlined Anonymous Class Warning" +kind: Warning +since: 3.5.0 +--- +# E197: Inlined Anonymous Class Warning + +This warning is emitted when an `inline` method creates an anonymous class. Since inline methods are expanded at each call site, the anonymous class definition will be duplicated in the generated bytecode, potentially leading to a large number of classfiles. + +--- + +Longer explanation: + +Anonymous class will be defined at each use site, which may lead to a larger number of classfiles. + +To inline class definitions, you may provide an explicit class name to avoid this warning. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +inline def createObject(): Object = + new Object {} +``` + +### Error + +```scala sc:nocompile +-- [E197] Potential Issue Warning: example.scala:2:2 --------------------------- +2 | new Object {} + | ^ + | New anonymous class definition will be duplicated at each inline site + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Anonymous class will be defined at each use site, which may lead to a larger number of classfiles. + | + | To inline class definitions, you may provide an explicit class name to avoid this warning. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use a named class inside the inline method: + +```scala sc:compile sc-opts:-Werror +inline def createObject(): Object = + class NamedClass extends Object + new NamedClass +``` + +Or define the class outside the inline method: + +```scala sc:compile sc-opts:-Werror +class MyObject extends Object + +inline def createObject(): Object = + new MyObject +``` + diff --git a/docs/_docs/reference/error-codes/E198.md b/docs/_docs/reference/error-codes/E198.md new file mode 100644 index 000000000000..5d37c01c0bf6 --- /dev/null +++ b/docs/_docs/reference/error-codes/E198.md @@ -0,0 +1,70 @@ +--- +title: "E198: Unused Symbol" +kind: Warning +since: 3.5.1 +--- +# E198: Unused Symbol + +This warning is emitted when a symbol (variable, parameter, import, etc.) is declared but never used. + +This warning helps identify dead code and potential mistakes where a value was intended to be used but was forgotten. The warning can identify various types of unused symbols: +- Unused imports +- Unused local definitions (vals, vars, defs) +- Unused parameters (explicit and implicit) +- Unused private members +- Pattern variables that are not used + +This warning requires the `-Wunused` compiler flag with appropriate sub-options (e.g., `-Wunused:all`). + +--- + +## Example + +```scala sc:nocompile custom-sc:fail sc-opts:-Wunused:all,-Werror +//> using options -Wunused:all + +def example(): Unit = + val unused = 42 + println("hello") +``` + +### Error + +```scala sc:nocompile +-- [E198] Unused Symbol Warning: example.scala:4:6 ----------------------------- +4 | val unused = 42 + | ^^^^^^ + | unused local definition +``` + +### Solution + +Remove the unused symbol: + +```scala sc:nocompile custom-sc:compile sc-opts:-Wunused:all,-Werror +//> using options -Wunused:all + +def example(): Unit = + println("hello") +``` + +Or use the symbol: + +```scala sc:nocompile custom-sc:compile sc-opts:-Wunused:all,-Werror +//> using options -Wunused:all + +def example(): Unit = + val value = 42 + println(s"The value is $value") +``` + +Or suppress the warning by using val with underscore identifier + +```scala sc:nocompile custom-sc:compile sc-opts:-Wunused:all,-Werror +//> using options -Wunused:all + +def example(): Unit = + val _ = 42 + println("hello") +``` + diff --git a/docs/_docs/reference/error-codes/E199.md b/docs/_docs/reference/error-codes/E199.md new file mode 100644 index 000000000000..408c948a71c7 --- /dev/null +++ b/docs/_docs/reference/error-codes/E199.md @@ -0,0 +1,74 @@ +--- +title: "E199: Tailrec Nested Call" +kind: Warning +since: 3.5.1 +--- +# E199: Tailrec Nested Call + +This warning is emitted when a `@tailrec` method contains a recursive call inside a non-inlined inner definition. + +Tail recursion optimization can only be applied directly in the method's body. Recursive calls made through inner defs cannot be validated as tail recursive, nor can they be optimized. This means such calls could lead to stack overflow for deeply recursive calls. + +--- + +Longer explanation: + +Tail recursion is only validated and optimized directly in the definition. Any calls to the recursive method via an inner def cannot be validated as tail recursive, nor optimized if they are. To enable tail recursion from inner calls, mark the inner def as `inline`. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +import scala.annotation.tailrec + +@tailrec +def countdown(n: Int): Unit = + def helper(): Unit = + countdown(n - 1) // recursive call from inner def + if n > 0 then helper() + else countdown(n - 1) +``` + +### Error + +```scala sc:nocompile +-- [E199] Syntax Warning: example.scala:6:13 ----------------------------------- +6 | countdown(n - 1) // recursive call from inner def + | ^^^^^^^^^^^^^^^^ + |The tail recursive def countdown contains a recursive call inside the non-inlined inner def helper + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Tail recursion is only validated and optimised directly in the definition. + | Any calls to the recursive method via an inner def cannot be validated as + | tail recursive, nor optimised if they are. To enable tail recursion from + | inner calls, mark the inner def as inline. + ----------------------------------------------------------------------------- +``` + +### Solution + +Mark the inner def as `inline`: + +```scala sc:compile sc-opts:-Werror +import scala.annotation.tailrec + +@tailrec +def countdown(n: Int): Unit = + inline def helper(): Unit = + countdown(n - 1) + if n > 0 then helper() + else countdown(n - 1) +``` + +Or restructure the code to avoid nested recursive calls: + +```scala sc:compile sc-opts:-Werror +import scala.annotation.tailrec + +@tailrec +def countdown(n: Int): Unit = + if n > 0 then countdown(n - 1) +``` + diff --git a/docs/_docs/reference/error-codes/E200.md b/docs/_docs/reference/error-codes/E200.md new file mode 100644 index 000000000000..5d2b55e15bbf --- /dev/null +++ b/docs/_docs/reference/error-codes/E200.md @@ -0,0 +1,47 @@ +--- +title: "E200: Final Local Def" +kind: Error +since: 3.5.1 +--- +# E200: Final Local Def + +This error occurs when the `final` modifier is used on a local definition (inside a method or block). + +The `final` modifier is only meaningful for class members, where it prevents overriding in subclasses. Local definitions inside methods cannot be overridden, so `final` has no effect and is not allowed. + +--- + +## Example + +```scala sc:fail +def example(): Unit = + final val local = 42 +``` + +### Error + +```scala sc:nocompile +-- [E200] Syntax Error: example.scala:2:8 -------------------------------------- +2 | final val local = 42 + | ^^^ + | The final modifier is not allowed on local definitions +``` + +### Solution + +Remove the `final` modifier from local definitions: + +```scala sc:compile sc-opts:-Werror +def example(): Unit = + val local = 42 + println(local) +``` + +If you want an inline constant, use `inline val`: + +```scala sc:compile sc-opts:-Werror +def example(): Unit = + inline val local = 42 + println(local) +``` + diff --git a/docs/_docs/reference/error-codes/E201.md b/docs/_docs/reference/error-codes/E201.md new file mode 100644 index 000000000000..eae85af2ca98 --- /dev/null +++ b/docs/_docs/reference/error-codes/E201.md @@ -0,0 +1,58 @@ +--- +title: "E201: Non-Named Argument in Java Annotation" +kind: Error +since: 3.6.2 +--- +# E201: Non-Named Argument in Java Annotation + +This error occurs when using positional (unnamed) arguments in a Java-defined annotation. Starting from Scala 3.6.0, named arguments are required for all Java annotations. + +Java annotations don't have an exact constructor representation in Scala, and the compiler previously relied on the order of annotation fields to match positional arguments. This approach is fragile because reordering annotation fields in Java is binary-compatible but can silently change the meaning of positional arguments. + +## Example + +```scala sc:fail +class Foo: + @Deprecated("reason") + def oldMethod(): Unit = () +``` + +### Error + +```scala sc:nocompile +-- [E201] Syntax Error: example.scala:2:14 ------------------------------------- +2 | @Deprecated("reason") + | ^^^^^^^^ + | Named arguments are required for Java defined annotations + | This can be rewritten automatically under -rewrite -source 3.6-migration. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Starting from Scala 3.6.0, named arguments are required for Java defined annotations. + | Java defined annotations don't have an exact constructor representation + | and we previously relied on the order of the fields to create one. + | One possible issue with this representation is the reordering of the fields. + | Lets take the following example: + | + | public @interface Annotation { + | int a() default 41; + | int b() default 42; + | } + | + | Reordering the fields is binary-compatible but it might affect the meaning of @Annotation(1) + | + ----------------------------------------------------------------------------- +``` + +### Solution + +Use named arguments when applying Java annotations: + +```scala sc:compile sc-opts:-Werror +class Foo: + @Deprecated(since = "reason") + def oldMethod(): Unit = () +``` + +Alternatively, you can use the automatic rewrite feature by compiling with `-rewrite -source 3.6-migration` to automatically convert positional arguments to named arguments. + diff --git a/docs/_docs/reference/error-codes/E202.md b/docs/_docs/reference/error-codes/E202.md new file mode 100644 index 000000000000..4955c1fa48e1 --- /dev/null +++ b/docs/_docs/reference/error-codes/E202.md @@ -0,0 +1,69 @@ +--- +title: "E202: Quoted Type Missing" +kind: Error +since: 3.6.2 +--- +# E202: Quoted Type Missing + +This error occurs when referencing a type parameter inside a quoted expression (`'{ ... }`) without a corresponding `Type[T]` instance in scope. + +Since Scala uses type erasure at runtime, type information is lost during execution. When using macros and quotes, the compiler needs a `scala.quoted.Type[T]` instance to carry the type information into the quoted code. + +## Example + +```scala sc:fail +import scala.quoted.{Expr, Quotes} + +case class Thing[T]() + +def foo[T](using Quotes): Expr[Thing[T]] = '{ Thing[T]() } +``` + +### Error + +```scala sc:nocompile +-- [E202] Staging Issue Error: example.scala:5:52 ------------------------------ +5 |def foo[T](using Quotes): Expr[Thing[T]] = '{ Thing[T]() } + | ^ + |Reference to T within quotes requires a given scala.quoted.Type[T] in scope + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Referencing `T` inside a quoted expression requires a `scala.quoted.Type[T]` to be in scope. + | Since Scala is subject to erasure at runtime, the type information will be missing during the execution of the code. + | `scala.quoted.Type[T]` is therefore needed to carry `T`'s type information into the quoted code. + | Without an implicit `scala.quoted.Type[T]`, the type `T` cannot be properly referenced within the expression. + | To resolve this, ensure that a `scala.quoted.Type[T]` is available, either through a context-bound or explicitly. + ----------------------------------------------------------------------------- +``` + +### Explanation + +Referencing `T` inside a quoted expression requires a `scala.quoted.Type[T]` to be in scope. +Since Scala is subject to erasure at runtime, the type information will be missing during the execution of the code. +`scala.quoted.Type[T]` is therefore needed to carry `T`'s type information into the quoted code. +Without an implicit `scala.quoted.Type[T]`, the type `T` cannot be properly referenced within the expression. +To resolve this, ensure that a `scala.quoted.Type[T]` is available, either through a context-bound or explicitly. + +### Solution + +Add a context bound `T: Type` to make the type information available: + +```scala sc:compile sc-opts:-Werror +import scala.quoted.{Expr, Quotes, Type} + +case class Thing[T]() + +def foo[T: Type](using Quotes): Expr[Thing[T]] = '{ Thing[T]() } +``` + +Alternatively, you can provide the `Type[T]` explicitly as a using parameter: + +```scala sc:compile sc-opts:-Werror +import scala.quoted.{Expr, Quotes, Type} + +case class Thing[T]() + +def bar[T](using Quotes, Type[T]): Expr[Thing[T]] = '{ Thing[T]() } +``` + diff --git a/docs/_docs/reference/error-codes/E203.md b/docs/_docs/reference/error-codes/E203.md new file mode 100644 index 000000000000..b26ebe06621c --- /dev/null +++ b/docs/_docs/reference/error-codes/E203.md @@ -0,0 +1,44 @@ +--- +title: "E203: Deprecated Assignment Syntax" +kind: Warning +since: 3.6.2 +--- +# E203: Deprecated Assignment Syntax + +This warning occurs when using parentheses around an assignment expression like `(x = value)`. Starting from Scala 3.7, this syntax is interpreted as a named tuple with one element rather than an assignment. + +This is a migration warning to help transition code from the old assignment interpretation to the new named tuple semantics. + +## Example + +```scala sc:fail sc-opts:-Werror +def example() = + var age: Int = 28 + (age = 29) +``` + +### Error + +```scala sc:nocompile +-- [E203] Syntax Migration Warning: example.scala:3:2 -------------------------- +3 | (age = 29) + | ^^^^^^^^^^ + |Deprecated syntax: since 3.7 this is interpreted as a named tuple with one element, + |not as an assignment. + | + |To assign a value, use curly braces: `{age = 29}`. + |This can be rewritten automatically under -rewrite -source 3.6-migration. +``` + +### Solution + +Use curly braces instead of parentheses for assignments: + +```scala sc:compile sc-opts:-Werror +def example() = + var age: Int = 28 + { age = 29 } +``` + +Alternatively, you can use the automatic rewrite feature by compiling with `-rewrite -source 3.6-migration` to automatically update the syntax. + diff --git a/docs/_docs/reference/error-codes/E204.md b/docs/_docs/reference/error-codes/E204.md new file mode 100644 index 000000000000..243b96854bff --- /dev/null +++ b/docs/_docs/reference/error-codes/E204.md @@ -0,0 +1,50 @@ +--- +title: "E204: Deprecated Infix Named Argument Syntax" +kind: Warning +since: 3.6.2 +--- +# E204: Deprecated Infix Named Argument Syntax + +This warning occurs when using named arguments with infix method calls like `obj `method` (x = 1, y = 2)`. Starting from Scala 3.7, this syntax is interpreted as passing a single named tuple argument rather than multiple named arguments. + +This is a migration warning to help transition code from the old named arguments interpretation to the new named tuple semantics. + +## Example + +```scala sc:fail sc-opts:-Werror +class C: + def combine(x: Int, y: Int): Int = x + y + def example = new C() `combine` (x = 42, y = 27) +``` + +### Error + +```scala sc:nocompile +-- [E204] Syntax Warning: example.scala:3:34 ----------------------------------- +3 | def example = new C() `combine` (x = 42, y = 27) + | ^^^^^^^^^^^^^^^^ + |Deprecated syntax: infix named arguments lists are deprecated; since 3.7 it is interpreted as a single name tuple argument. + |To avoid this warning, either remove the argument names or use dotted selection. + |This can be rewritten automatically under -rewrite -source 3.7-migration. +``` + +### Solution + +Use dotted selection instead of infix notation when using named arguments: + +```scala sc:compile sc-opts:-Werror +class C: + def combine(x: Int, y: Int): Int = x + y + def example = new C().combine(x = 42, y = 27) +``` + +Alternatively, remove the argument names and use positional arguments with infix notation: + +```scala sc:compile sc-opts:-Werror +class D: + def combine(x: Int, y: Int): Int = x + y + def example = new D() `combine` (42, 27) +``` + +You can also use the automatic rewrite feature by compiling with `-rewrite -source 3.7-migration` to automatically update the syntax. + diff --git a/docs/_docs/reference/error-codes/E205.md b/docs/_docs/reference/error-codes/E205.md new file mode 100644 index 000000000000..822e49860c00 --- /dev/null +++ b/docs/_docs/reference/error-codes/E205.md @@ -0,0 +1,63 @@ +--- +title: "E205: Given Search Priority Warning" +kind: Warning +since: 3.6.3 +--- +# E205: Given Search Priority Warning + +This warning occurs when the implicit search algorithm would select a different given instance under Scala 3.7 rules compared to Scala 3.6 rules. This is a migration warning to alert users about behavior changes in given instance resolution. + +In Scala 3.7, the given search priority rules have been refined. When multiple given instances are available for the same type, the selection algorithm may choose differently than it did in Scala 3.6, particularly regarding how type specificity is evaluated. + +## Example + +```scala sc:fail sc-opts:-Werror,-source:3.6 +//> using options -source:3.6 + +trait A +trait B extends A +given b: B = ??? +given a: A = ??? + +def example = summon[A] +``` + +### Error + +```scala sc:nocompile +-- [E205] Potential Issue Warning: example.scala:8:23 -------------------------- +8 |def example = summon[A] + | ^ + | Given search preference for A between alternatives + | (b : B) + | and + | (a : A) + | will change in the future release. + | Current choice : the first alternative + | Choice from Scala 3.7 : the second alternative + | + | Suppress this warning by choosing -source 3.5, -source 3.7, or + | by using @annotation.nowarn("id=205") +``` + +### Solution + +Explicitly reference the desired given instance to avoid ambiguity: + +```scala sc:compile sc-opts:-Werror,-source,3.6 +//> using options -source:3.6 + +trait A +trait B extends A +given b: B = ??? +given a: A = ??? + +def example: A = a +``` + +Alternatively, you can suppress the warning by: + +- Using `-source 3.5` to keep the old behavior +- Using `-source 3.7` to use the new behavior +- Adding `@annotation.nowarn("id=205")` to suppress the warning locally + diff --git a/docs/_docs/reference/error-codes/E206.md b/docs/_docs/reference/error-codes/E206.md new file mode 100644 index 000000000000..d18f80bffd53 --- /dev/null +++ b/docs/_docs/reference/error-codes/E206.md @@ -0,0 +1,47 @@ +--- +title: "E206: Enum May Not Be Value Class" +kind: Error +since: 3.6.4 +--- +# E206: Enum May Not Be Value Class + +This error occurs when attempting to define an enum that extends `AnyVal`. Enums cannot be value classes in Scala 3. + +Value classes are a mechanism for defining types that avoid runtime object allocation, but this is incompatible with the way enums are implemented in Scala 3. Enums require a class hierarchy to represent their cases, which is not possible with value classes. + +## Example + +```scala sc:fail +enum Orientation extends AnyVal: + case North, South, East, West +``` + +### Error + +```scala sc:nocompile +-- [E206] Syntax Error: example.scala:1:5 -------------------------------------- +1 |enum Orientation extends AnyVal: + | ^ + | class Orientation may not be a value class +``` + +### Solution + +Remove the `extends AnyVal` clause from the enum definition: + +```scala sc:compile sc-opts:-Werror +enum Orientation: + case North, South, East, West +``` + +If you need a lightweight representation for performance reasons, consider using an opaque type instead: + +```scala sc:compile sc-opts:-Werror +object Orientation: + opaque type Orientation = Int + val North: Orientation = 0 + val South: Orientation = 1 + val East: Orientation = 2 + val West: Orientation = 3 +``` + diff --git a/docs/_docs/reference/error-codes/E207.md b/docs/_docs/reference/error-codes/E207.md new file mode 100644 index 000000000000..6c91999de125 --- /dev/null +++ b/docs/_docs/reference/error-codes/E207.md @@ -0,0 +1,49 @@ +--- +title: "E207: Illegal Unroll Placement" +kind: Error +since: 3.7.0 +--- +# E207: Illegal Unroll Placement + +This error occurs when the `@unroll` annotation is used in an invalid location. The `@unroll` annotation is an experimental feature that can only be applied to method parameters with default values. + +The `@unroll` annotation is used to generate multiple overloaded versions of a method to maintain binary compatibility when adding new parameters with default values. + +## Example + +```scala sc:fail sc-opts:-experimental +import scala.annotation.unroll + +@unroll +class UnrollClass +``` + +### Error + +```scala sc:nocompile +-- [E207] Declaration Error: example.scala:4:6 --------------------------------- +4 |class UnrollClass + | ^ + | @unroll is only allowed on a method parameter +``` + +### Solution + +Use the `@unroll` annotation only on method or constructor parameters that have default values: + +```scala sc:compile sc-opts:-Werror +import scala.annotation.unroll +import scala.annotation.experimental + +@experimental +final class Unrolled(s: String, n: Int = 1, @unroll b: Boolean = true): + def foo = s + n + b +``` + +Note that `@unroll` has additional restrictions: +- The method must be effectively final (cannot be overridden) +- The method cannot be local +- For case classes, the annotation should be on the class constructor, not on generated methods + +This is an experimental feature and requires the `-experimental` compiler flag. + diff --git a/docs/_docs/reference/error-codes/E208.md b/docs/_docs/reference/error-codes/E208.md new file mode 100644 index 000000000000..5a517ad23862 --- /dev/null +++ b/docs/_docs/reference/error-codes/E208.md @@ -0,0 +1,62 @@ +--- +title: "E208: Extension Has Default Receiver" +kind: Warning +since: 3.7.0 +--- +# E208: Extension Has Default Receiver + +This warning occurs when an extension method has a default argument for its receiver parameter. This is discouraged because the default value would never be used when the extension method is invoked as a selection on an object. + +Extension methods are typically invoked as `receiver.method()`, where the receiver is always provided. A default argument for the receiver makes sense only when calling the method as a regular function, but in that case it should not be defined as an extension. + +## Example + +```scala sc:fail sc-opts:-Werror +extension (s: String = "hello, world") def invert = s.reverse.toUpperCase +``` + +### Error + +```scala sc:nocompile +-- [E208] Potential Issue Warning: example.scala:1:23 -------------------------- +1 |extension (s: String = "hello, world") def invert = s.reverse.toUpperCase + | ^ + |Extension method invert should not have a default argument for its receiver. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The receiver cannot be omitted when an extension method is invoked as a selection. + | A default argument for that parameter would never be used in that case. + | An extension method can be invoked as a regular method, but if that is the intended usage, + | it should not be defined as an extension. + ----------------------------------------------------------------------------- +``` + +### Explanation + +The receiver cannot be omitted when an extension method is invoked as a selection. +A default argument for that parameter would never be used in that case. +An extension method can be invoked as a regular method, but if that is the intended usage, +it should not be defined as an extension. + +### Solution + +Remove the default argument from the receiver parameter: + +```scala sc:compile sc-opts:-Werror +extension (s: String) def invert = s.reverse.toUpperCase +``` + +If you need a function with a default argument, define it as a regular method instead of an extension: + +```scala sc:compile sc-opts:-Werror +def invert(s: String = "hello, world"): String = s.reverse.toUpperCase +``` + +Note that default arguments are allowed for non-receiver parameters in extension methods: + +```scala sc:compile sc-opts:-Werror +extension (s: String) + def combine(other: String = ", world") = s + other +``` + diff --git a/docs/_docs/reference/error-codes/E209.md b/docs/_docs/reference/error-codes/E209.md new file mode 100644 index 000000000000..9f1a8ac40266 --- /dev/null +++ b/docs/_docs/reference/error-codes/E209.md @@ -0,0 +1,59 @@ +--- +title: "E209: Format Interpolation Error" +kind: Error +since: 3.7.1 +--- +# E209: Format Interpolation Error + +This error occurs when there is a type mismatch or invalid format specifier in an `f""` string interpolator. The `f` interpolator uses Java's `Formatter` syntax and requires that the format specifiers match the types of the interpolated values. + +## Example + +```scala sc:fail +def example = + val s = "hello" + f"$s%d" +``` + +### Error + +```scala sc:nocompile +-- [E209] Interpolation Error: example.scala:3:5 ------------------------------- +3 | f"$s%d" + | ^ + | Found: (s : String), Required: Int, Long, Byte, Short, BigInt +``` + +### Solution + +Use the correct format specifier for the value's type. For strings, use `%s`: + +```scala sc:compile sc-opts:-Werror +def example = + val s = "hello" + f"$s%s" +``` + +### Common Format Specifiers + +Here are some common format specifiers and their expected types: + +| Specifier | Expected Type | Example | +|-----------|--------------|---------| +| `%s` | Any (converted to String) | `f"$name%s"` | +| `%d` | Int, Long, Byte, Short, BigInt | `f"$count%d"` | +| `%f` | Double, Float, BigDecimal | `f"$price%f"` | +| `%x` | Int, Long, Byte, Short, BigInt | `f"$hex%x"` | +| `%c` | Char, Byte, Short, Int | `f"$char%c"` | +| `%b` | Boolean (or any for null check) | `f"$flag%b"` | +| `%e` | Double, Float, BigDecimal | `f"$scientific%e"` | + +### Example with Numeric Formatting + +```scala sc:compile sc-opts:-Werror +def formatNumbers = + val price = 19.99 + val count = 42 + f"Price: $$$price%.2f, Count: $count%04d" +``` + diff --git a/docs/_docs/reference/error-codes/E210.md b/docs/_docs/reference/error-codes/E210.md new file mode 100644 index 000000000000..9e8f9da2e6c9 --- /dev/null +++ b/docs/_docs/reference/error-codes/E210.md @@ -0,0 +1,47 @@ +--- +title: "E210: Value Class Cannot Extend Alias of AnyVal" +kind: Error +since: 3.7.1 +--- +# E210: Value Class Cannot Extend Alias of AnyVal + +This error occurs when attempting to define a value class that extends a type alias of `AnyVal` instead of extending `AnyVal` directly. + +Value classes must directly extend `AnyVal`. Using a type alias introduces an indirection that the compiler cannot resolve for the special treatment value classes require. + +## Example + +```scala sc:fail +type MyAnyVal = AnyVal + +class Wrapper(val value: Int) extends MyAnyVal +``` + +### Error + +```scala sc:nocompile +-- [E210] Syntax Error: example.scala:3:6 -------------------------------------- +3 |class Wrapper(val value: Int) extends MyAnyVal + |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |A value class cannot extend a type alias (type MyAnyVal) of AnyVal +``` + +### Solution + +Extend `AnyVal` directly instead of using a type alias: + +```scala sc:compile sc-opts:-Werror +class Wrapper(val value: Int) extends AnyVal +``` + +Alternatively, if you need an abstraction, consider using an opaque type instead of a value class: + +```scala sc:compile sc-opts:-Werror +object Types: + opaque type Wrapper = Int + object Wrapper: + def apply(value: Int): Wrapper = value + extension (w: Wrapper) + def value: Int = w +``` + diff --git a/docs/_docs/reference/error-codes/E211.md b/docs/_docs/reference/error-codes/E211.md new file mode 100644 index 000000000000..e47b3bd7640b --- /dev/null +++ b/docs/_docs/reference/error-codes/E211.md @@ -0,0 +1,80 @@ +--- +title: "E211: Match Is Not Partial Function" +kind: Warning +since: 3.7.1 +--- +# E211: Match Is Not Partial Function + +This warning is emitted when a match expression in the result of a block will not be used to synthesize a partial function. + +A `PartialFunction` can be synthesized from a function literal if its body is just a pattern match. However, blocks of statements are not supported by this idiom. + +This restriction is enforced to simplify the evaluation semantics of the partial function. Otherwise, it might not be clear what is computed by `isDefinedAt`. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +def example: PartialFunction[Int, Int] = { x => + val y = x + 1 + y match { case n => n * 2 } +} +``` + +### Error + +```scala sc:nocompile +-- [E211] Syntax Warning: example.scala:3:4 ------------------------------------ +3 | y match { case n => n * 2 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |match expression in result of block will not be used to synthesize partial function + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | A `PartialFunction` can be synthesized from a function literal if its body is just a pattern match. + | + | For example, `collect` takes a `PartialFunction`. + | (1 to 10).collect(i => i match { case n if n % 2 == 0 => n }) + | is equivalent to using a "pattern-matching anonymous function" directly: + | (1 to 10).collect { case n if n % 2 == 0 => n } + | Compare an operation that requires a `Function1` instead: + | (1 to 10).map { case n if n % 2 == 0 => n case n => n + 1 } + | + | As a convenience, the "selector expression" of the match can be an arbitrary expression: + | List("1", "two", "3").collect(x => Try(x.toInt) match { case Success(i) => i }) + | In this example, `isDefinedAt` evaluates the selector expression and any guard expressions + | in the pattern match in order to report whether an input is in the domain of the function. + | + | However, blocks of statements are not supported by this idiom: + | List("1", "two", "3").collect: x => + | val maybe = Try(x.toInt) // statements preceding the match + | maybe match + | case Success(i) if i % 2 == 0 => i // throws MatchError on cases not covered + | + | This restriction is enforced to simplify the evaluation semantics of the partial function. + | Otherwise, it might not be clear what is computed by `isDefinedAt`. + | + | Efficient operations will use `applyOrElse` to avoid computing the match twice, + | but the `apply` body would be executed "per element" in the example. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use a pattern-matching anonymous function directly without a selector expression: + +```scala sc:compile sc-opts:-Werror +def example: PartialFunction[Int, Int] = { + case n => (n + 1) * 2 +} +``` + +Or use a simple match on the parameter without preceding statements: + +```scala sc:compile sc-opts:-Werror +def example: PartialFunction[Int, Int] = x => x match { + case n => (n + 1) * 2 +} +``` + diff --git a/docs/_docs/reference/error-codes/E212.md b/docs/_docs/reference/error-codes/E212.md new file mode 100644 index 000000000000..5ad0f182fc1b --- /dev/null +++ b/docs/_docs/reference/error-codes/E212.md @@ -0,0 +1,60 @@ +--- +title: "E212: Only Fully Dependent Applied Constructor Type" +kind: Warning +since: 3.7.2 +--- +# E212: Only Fully Dependent Applied Constructor Type + +This warning is emitted when using an applied constructor type (a type that includes constructor arguments) with a class where not all parameters in the first parameter list are marked as `tracked`. + +Applied constructor types are an experimental feature that allows you to express more precise types by including constructor arguments in the type itself. However, this feature only works correctly when all parameters in the first parameter list are `tracked`, meaning their values are part of the type. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror +import scala.language.experimental.modularity + +class MyBox(val value: Int) + +def example = + val box: MyBox(42) = MyBox(42) + box +``` + +### Error + +```scala sc:nocompile +-- [E212] Type Warning: example.scala:6:11 ------------------------------------- +6 | val box: MyBox(42) = MyBox(42) + | ^^^^^^^^^ + |Applied constructor type can only be used with classes where all parameters in the first parameter list are tracked +``` + +### Solution + +Mark the class parameter as `tracked` to enable applied constructor types: + +```scala sc:compile sc-opts:-Werror +import scala.language.experimental.modularity + +class MyBox(tracked val value: Int) + +def example = + val box: MyBox(42) = MyBox(42) + box +``` + +Alternatively, remove the applied constructor type syntax if you don't need the precise type tracking: + +```scala sc:compile sc-opts:-Werror +import scala.language.experimental.modularity + +class MyBox(val value: Int) + +def example = + val box: MyBox = MyBox(42) + box +``` + diff --git a/docs/_docs/reference/error-codes/E213.md b/docs/_docs/reference/error-codes/E213.md new file mode 100644 index 000000000000..8f2b2146b871 --- /dev/null +++ b/docs/_docs/reference/error-codes/E213.md @@ -0,0 +1,72 @@ +--- +title: "E213: Pointless Applied Constructor Type" +kind: Warning +since: 3.7.2 +--- +# E213: Pointless Applied Constructor Type + +This warning is emitted when using an applied constructor type that has no effect because the resulting type is the same as the base class type. + +Applied constructor types are an experimental feature that allows you to express more precise types by including constructor arguments in the type itself. However, the feature only provides benefit when the tracked parameter's type can be refined to a more specific singleton or dependent type. + +If the tracked parameter's type is a regular type like `List[T]` or `String`, applying constructor arguments won't produce a more precise type than the class itself. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +import scala.language.experimental.modularity + +class Container[T](tracked val items: List[T]) + +def example = + val c: Container[Int](List(1,2,3)) = Container[Int](List(1,2,3)) + c +``` + +### Error + +```scala sc:nocompile +-- [E213] Type Warning: example.scala:6:9 -------------------------------------- +6 | val c: Container[Int](List(1,2,3)) = Container[Int](List(1,2,3)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |Applied constructor type Container[Int](List(1, 2, 3)) has no effect. + |The resulting type of Container[Int](List(1, 2, 3)) is the same as its base type, namely: Container[Int] + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Applied constructor types are used to ascribe specialized types of constructor applications. + | To benefit from this feature, the constructor in question has to have a more specific type than the class itself. + | + | If you want to track a precise type of any of the class parameters, make sure to mark the parameter as `tracked`. + | Otherwise, you can safely remove the argument list from the type. + ----------------------------------------------------------------------------- +``` + +### Solution + +Remove the applied constructor type syntax since it provides no benefit: + +```scala sc:compile sc-opts:-Werror +import scala.language.experimental.modularity + +class Container[T](tracked val items: List[T]) + +def example = + val c: Container[Int] = Container[Int](List(1,2,3)) + c +``` + +Alternatively, if you need precise type tracking, use a parameter type that can be refined (like singleton types): + +```scala sc:compile sc-opts:-Werror +import scala.language.experimental.modularity + +class Box(tracked val value: Int) + +def example = + val box: Box(42) = Box(42) + box +``` + diff --git a/docs/_docs/reference/error-codes/E214.md b/docs/_docs/reference/error-codes/E214.md new file mode 100644 index 000000000000..b186a0a3c6c9 --- /dev/null +++ b/docs/_docs/reference/error-codes/E214.md @@ -0,0 +1,55 @@ +--- +title: "E214: Illegal Context Bounds" +kind: Error +since: 3.7.2 +--- +# E214: Illegal Context Bounds + +This error is emitted when context bounds are used in a position where they are not allowed. + +Context bounds (like `T: Ordering`) are a shorthand for requiring an implicit instance of a type class for a type parameter. However, they can only be used in certain positions, such as method or class type parameters, not in type alias definitions. + +--- + +## Example + +```scala sc:fail +trait Equatable[T] + +type Foo[T: Equatable] +``` + +### Error + +```scala sc:nocompile +-- [E214] Syntax Error: example.scala:3:21 ------------------------------------- +3 |type Foo[T: Equatable] + | ^^^^^^^^^ + | Context bounds are not allowed in this position +``` + +### Solution + +Context bounds are allowed in method or class definitions where implicit parameters can be added: + +```scala sc:compile sc-opts:-Werror +trait Equatable[T] + +def foo[T: Equatable](value: T): Unit = () +``` + +```scala sc:compile sc-opts:-Werror +trait Equatable[T] + +class Foo[T: Equatable](value: T) +``` + +For type aliases, you cannot use context bounds. If you need to express a constraint, consider using a class or trait instead: + +```scala sc:compile sc-opts:-Werror +trait Equatable[T] + +trait Foo[T]: + given Equatable[T] = ??? +``` + diff --git a/docs/_docs/reference/error-codes/E215.md b/docs/_docs/reference/error-codes/E215.md new file mode 100644 index 000000000000..191ed45e666a --- /dev/null +++ b/docs/_docs/reference/error-codes/E215.md @@ -0,0 +1,64 @@ +--- +title: "E215: Named Pattern Not Applicable" +kind: Error +since: 3.7.3 +--- +# E215: Named Pattern Not Applicable + +This error is emitted when using named patterns in pattern matching on a type that is not a named tuple or case class. + +Named patterns allow you to match elements by name (like `name = n`) rather than by position. However, this feature is only available for named tuples and case classes, which have known field names that the compiler can use for pattern matching. + +--- + +## Example + +```scala sc:fail +class MyClass(val name: String, val age: Int) + +object MyExtractor: + def unapply(x: MyClass): Some[(String, Int)] = Some((x.name, x.age)) + +def example(obj: MyClass) = obj match + case MyExtractor(name = n, age = a) => println(s"$n is $a years old") +``` + +### Error + +```scala sc:nocompile +-- [E215] Pattern Match Error: example.scala:7:18 ------------------------------ +7 | case MyExtractor(name = n, age = a) => println(s"$n is $a years old") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |Named patterns cannot be used with (String, Int), because it is not a named tuple or case class +``` + +### Solution + +Use positional pattern matching instead: + +```scala sc:compile sc-opts:-Werror +class MyClass(val name: String, val age: Int) + +object MyExtractor: + def unapply(x: MyClass): Some[(String, Int)] = Some((x.name, x.age)) + +def example(obj: MyClass) = obj match + case MyExtractor(n, a) => println(s"$n is $a years old") +``` + +Or use a case class which supports named patterns: + +```scala sc:compile sc-opts:-Werror +case class Person(name: String, age: Int) + +def example(person: Person) = person match + case Person(name = n, age = a) => println(s"$n is $a years old") +``` + +Named tuples also support named patterns: + +```scala sc:compile sc-opts:-Werror +def example(data: (name: String, age: Int)) = data match + case (name = n, age = a) => println(s"$n is $a years old") +``` + diff --git a/docs/_docs/reference/error-codes/E216.md b/docs/_docs/reference/error-codes/E216.md new file mode 100644 index 000000000000..567f2c8931d9 --- /dev/null +++ b/docs/_docs/reference/error-codes/E216.md @@ -0,0 +1,61 @@ +--- +title: "E216: Unnecessary .nn" +kind: Warning +since: 3.7.3 +--- +# E216: Unnecessary .nn + +This warning is emitted when the `.nn` (not null) method is used unnecessarily. This warning only appears when explicit nulls are enabled with the `-Yexplicit-nulls` compiler flag. + +The `.nn` method is used to assert that a nullable value is not null, converting `T | Null` to `T`. However, it is unnecessary in two cases: + +1. **Qualifier is already not null**: When the value is already of a non-nullable type, calling `.nn` has no effect. +2. **Expected type admits null**: When the expected type already accepts null values, asserting non-nullability is pointless. + +--- + +## Example + +When the qualifier is already not null: + +```scala sc:fail sc-opts:-Yexplicit-nulls,-Werror +//> using options -Yexplicit-nulls + +def example: String = + val s: String = "hello" + s.nn +``` + +### Error + +```scala sc:nocompile +-- [E216] Syntax Warning: example.scala:5:4 ------------------------------------ +5 | s.nn + | ^^^^ + | Unnecessary .nn: qualifier is already not null +``` + +### Solution + +Remove the unnecessary `.nn` call: + +```scala sc:compile sc-opts:-Yexplicit-nulls,-Werror +//> using options -Yexplicit-nulls + +def example: String = + val s: String = "hello" + s +``` + +When the expected type admits null, only use `.nn` if you need to narrow the type for subsequent operations: + +```scala sc:compile sc-opts:-Yexplicit-nulls,-Werror +//> using options -Yexplicit-nulls + +def example: String = + val s: String | Null = getSomeValue() + s.nn // necessary to convert String | Null to String + +def getSomeValue(): String | Null = "value" +``` + diff --git a/docs/_docs/reference/error-codes/E217.md b/docs/_docs/reference/error-codes/E217.md new file mode 100644 index 000000000000..41ee88784d73 --- /dev/null +++ b/docs/_docs/reference/error-codes/E217.md @@ -0,0 +1,79 @@ +--- +title: "E217: Erased Not Pure" +kind: Error +since: 3.7.3 +--- +# E217: Erased Not Pure + +This error is emitted when an argument to an erased parameter or the right-hand-side of an erased value is not a pure expression. + +Erased definitions are a feature that allows values to exist at compile time but be completely removed at runtime. Because erased values don't exist at runtime, their arguments must be pure expressions - expressions that are clearly side-effect free and terminating. + +Pure expressions include: +- Literals +- References to values +- Side-effect-free instance creations +- Applications of inline functions to pure arguments + +--- + +## Example + +```scala sc:fail sc-opts:-explain +import scala.language.experimental.erasedDefinitions + +def foo(erased a: Int): Int = 42 + +def example: Int = + foo(println("side effect").asInstanceOf[Int]) +``` + +### Error + +```scala sc:nocompile +-- [E217] Type Error: example.scala:6:41 --------------------------------------- +6 | foo(println("side effect").asInstanceOf[Int]) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | argument to an erased parameter fails to be a pure expression + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The argument to an erased parameter must be a pure expression, but I found: + | + | println("side effect").asInstanceOf[Int] + | + | This expression is not classified to be pure. + | A pure expression is an expression that is clearly side-effect free and terminating. + | |Some examples of pure expressions are: + | | - literals, + | | - references to values, + | | - side-effect-free instance creations, + | | - applications of inline functions to pure arguments. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use a pure expression as the argument to the erased parameter: + +```scala sc:compile sc-opts:-Werror +import scala.language.experimental.erasedDefinitions + +def foo(erased a: Int): Int = 42 + +def example: Int = + foo(0) // literal is a pure expression +``` + +Or use a value reference: + +```scala sc:compile sc-opts:-Werror +import scala.language.experimental.erasedDefinitions + +def foo(erased a: Int): Int = 42 + +def example: Int = + val pureValue = 123 + foo(pureValue) // reference to a value is pure +``` + diff --git a/docs/_docs/reference/error-codes/E218.md b/docs/_docs/reference/error-codes/E218.md new file mode 100644 index 000000000000..df075197376f --- /dev/null +++ b/docs/_docs/reference/error-codes/E218.md @@ -0,0 +1,62 @@ +--- +title: "E218: Illegal Erased Definition" +kind: Error +since: 3.7.3 +--- +# E218: Illegal Erased Definition + +This error is emitted when the `erased` modifier is used with a definition that doesn't support it. + +Only non-lazy immutable values (`val`) can be marked as `erased`. The `erased` modifier is not allowed for: +- Methods (except macros) +- Lazy values (`lazy val`) +- Mutable values (`var`) +- Type definitions +- Objects + +Additionally, this error can occur when a value's type implicitly makes it erased (by extending `compiletime.Erased`) but the definition kind doesn't support erasure. + +--- + +## Example + +```scala sc:fail sc-opts:-explain +import scala.language.experimental.erasedDefinitions + +object Test: + erased lazy val x: Int = 42 +``` + +### Error + +```scala sc:nocompile +-- [E218] Type Error: example.scala:4:18 --------------------------------------- +4 | erased lazy val x: Int = 42 + | ^ + | `erased` is not allowed for this kind of definition. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Only non-lazy immutable values can be `erased` + ----------------------------------------------------------------------------- +``` + +### Solution + +Use `erased` only with non-lazy `val` definitions: + +```scala sc:compile sc-opts:-Werror +import scala.language.experimental.erasedDefinitions + +object Test: + erased val x: Int = 42 +``` + +If you need a method with erased parameters, use erased parameters instead: + +```scala sc:compile sc-opts:-Werror +import scala.language.experimental.erasedDefinitions + +def compute(erased hint: Int): Int = 42 +``` + diff --git a/docs/_docs/reference/error-codes/E219.md b/docs/_docs/reference/error-codes/E219.md new file mode 100644 index 000000000000..51bd9d9e162e --- /dev/null +++ b/docs/_docs/reference/error-codes/E219.md @@ -0,0 +1,68 @@ +--- +title: "E219: Cannot Instantiate Quoted Type Variable" +kind: Error +since: 3.7.3 +--- +# E219: Cannot Instantiate Quoted Type Variable + +This error is emitted when a type variable in a quoted pattern is used after `new`, which is not allowed. + +In quoted patterns (used in macros), lowercase type names are treated as type variables that match any type. However, type variables cannot be instantiated with `new` because the compiler cannot know at compile time which constructor to call. + +If you meant to refer to an actual class, wrap the name in backticks to escape it. If you need to create instances in pattern matching, consider using the lower-level `quotes.reflect` API. + +--- + +## Example + +```scala sc:fail +import scala.quoted.* + +def inspectMacro(x: Expr[Any])(using Quotes): Expr[String] = + x match + case '{ new t($arg) } => '{ "found new with arg" } + case _ => '{ "other" } +``` + +### Error + +```scala sc:nocompile +-- [E219] Staging Issue Error: example.scala:5:16 ------------------------------ +5 | case '{ new t($arg) } => '{ "found new with arg" } + | ^ + |Quoted pattern type variable `t` cannot be instantiated. + |If you meant to refer to a class named `t`, wrap it in backticks. + |If you meant to introduce a binding, this is not allowed after `new`. You might + |want to use the lower-level `quotes.reflect` API instead. + |Read more about type variables in quoted pattern in the Scala documentation: + |https://docs.scala-lang.org/scala3/guides/macros/quotes.html#type-variables-in-quoted-patterns + | +``` + +### Solution + +If you want to match a specific class, use backticks to escape the name: + +```scala sc:compile sc-opts:-Werror +import scala.quoted.* + +class MyClass(val value: Int) + +def inspectMacro(x: Expr[Any])(using Quotes): Expr[String] = + x match + case '{ new `MyClass`($arg) } => '{ "found MyClass" } + case _ => '{ "other" } +``` + +For more complex pattern matching involving `new`, use the `quotes.reflect` API: + +```scala sc:compile sc-opts:-Werror +import scala.quoted.* + +def inspectMacro(x: Expr[Any])(using Quotes): Expr[String] = + import quotes.reflect.* + x.asTerm match + case Apply(Select(New(tpt), _), args) => '{ "found new expression" } + case _ => '{ "other" } +``` + diff --git a/docs/_docs/reference/error-codes/E220.md b/docs/_docs/reference/error-codes/E220.md new file mode 100644 index 000000000000..e0577f57dd2a --- /dev/null +++ b/docs/_docs/reference/error-codes/E220.md @@ -0,0 +1,69 @@ +--- +title: "E220: Default Shadows Given" +kind: Warning +since: 3.7.3 +--- +# E220: Default Shadows Given + +This warning is emitted when a default argument is used for an implicit parameter even though there is a given instance in scope. + +When you explicitly provide some `using` arguments but not all, the remaining implicit parameters are filled using default arguments rather than searching for given instances. This can lead to surprising behavior where a given in scope is ignored. + +--- + +## Example + +```scala sc:fail sc-opts:-Werror,-explain +def f(using s: String, i: Int = 1): String = s * i + +def example: String = + given Int = 2 + f(using s = "ab") +``` + +### Error + +```scala sc:nocompile +-- [E220] Type Warning: example.scala:5:3 -------------------------------------- +5 | f(using s = "ab") + | ^^^^^^^^^^^^^^^^^ + | Argument for implicit parameter i was supplied using a default argument. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Usually the given in scope is intended, but you must specify it after explicit `using`. + ----------------------------------------------------------------------------- +``` + +### Solution + +If you want to use the given in scope, specify it explicitly after the `using` keyword: + +```scala sc:compile sc-opts:-Werror +def f(using s: String, i: Int = 1): String = s * i + +def example: String = + given Int = 2 + f(using s = "ab", i = summon[Int]) +``` + +Or use separate parameter clauses so the given is resolved properly: + +```scala sc:compile sc-opts:-Werror +def g(using s: String)(using i: Int = 1): String = s * i + +def example: String = + given Int = 2 + g(using s = "ab") // given Int is used from the second clause +``` + +If you intentionally want to use the default argument, you can suppress the warning by explicitly passing the default value: + +```scala sc:compile sc-opts:-Werror +def f(using s: String, i: Int = 1): String = s * i + +def example: String = + given Int = 2 + f(using s = "ab", i = 1) // explicit default value, no warning +``` + diff --git a/docs/_docs/reference/error-codes/E221.md b/docs/_docs/reference/error-codes/E221.md new file mode 100644 index 000000000000..43edcf5c66cc --- /dev/null +++ b/docs/_docs/reference/error-codes/E221.md @@ -0,0 +1,61 @@ +--- +title: "E221: Recurse With Default" +kind: Warning +since: 3.7.3 +--- +# E221: Recurse With Default + +This warning is emitted when a recursive call uses a default argument for a parameter, which may lead to unintended behavior. + +In recursive functions, using default arguments can be confusing because the default value is used on each recursive call rather than passing the current value down the stack. This warning helps catch potential bugs where you meant to pass the current parameter value but accidentally relied on the default. + +This warning is enabled with the `-Wrecurse-with-default` compiler flag. + +--- + +## Example + +```scala sc:fail sc-opts:-Wrecurse-with-default,-Werror,-explain +//> using options -Wrecurse-with-default + +def fun(x: Int)(using p: Int, q: Int = 0): Int = + if x <= 0 then p * q + else fun(x - 1)(using p = p + x) +``` + +### Error + +```scala sc:nocompile +-- [E221] Type Warning: example.scala:5:17 ------------------------------------- +5 | else fun(x - 1)(using p = p + x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Recursive call used a default argument for parameter q. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | It's more explicit to pass current or modified arguments in a recursion. + ----------------------------------------------------------------------------- +``` + +### Solution + +Pass all arguments explicitly in the recursive call: + +```scala sc:compile sc-opts:-Wrecurse-with-default,-Werror +//> using options -Wrecurse-with-default + +def fun(x: Int)(using p: Int, q: Int = 0): Int = + if x <= 0 then p * q + else fun(x - 1)(using p = p + x, q = q) +``` + +Or use a different design that avoids default arguments in recursive functions: + +```scala sc:compile sc-opts:-Wrecurse-with-default,-Werror +//> using options -Wrecurse-with-default + +def fun(x: Int)(using p: Int)(q: Int): Int = + if x <= 0 then p * q + else fun(x - 1)(using p = p + x)(q) +``` + diff --git a/docs/_docs/reference/error-codes/E222.md b/docs/_docs/reference/error-codes/E222.md new file mode 100644 index 000000000000..b03e5fd5e8e8 --- /dev/null +++ b/docs/_docs/reference/error-codes/E222.md @@ -0,0 +1,62 @@ +--- +title: "E222: Encoded Package Name" +kind: Warning +since: 3.8.0 +--- +# E222: Encoded Package Name + +This warning is emitted when a package name contains characters that will be encoded differently on the classpath, which can lead to undefined behavior. + +When package names contain characters that need encoding (like spaces, hyphens, or special symbols), they are transformed when written to the file system. For example, `p-q` becomes `p$minusq`. This can cause tools to malfunction because the directory names won't match the package names. + +Note: The examples below require package statements and cannot be compiled by Scaladoc's snippet compiler. + +--- + +## Example + +```scala sc:nocompile custom-sc:fail +package `with spaces` { + class Foo +} +``` + +### Error + +```scala sc:nocompile +-- [E222] Syntax Warning: example.scala:1:8 ------------------------------------ +1 |package `with spaces` { + | ^^^^^^^^^^^^^ + |The package name `with spaces` will be encoded on the classpath, and can lead to undefined behaviour. + |----------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Tools may not handle directories whose names differ from their corresponding package names. + | For example, `p-q` is encoded as `p$minusq` when written to the file system. + | + | Package objects derive their names from the file names, so files such as `myfile.test.scala` + | or `myfile-test.scala` can produce encoded names for the generated package objects. + | + | In this case, the name `with spaces` is encoded as `with$u0020spaces`. + ----------------------------------------------------------------------------- +``` + +### Solution + +Use package names that don't require encoding. Stick to alphanumeric characters and underscores: + +```scala sc:nocompile custom-sc:compile +package with_spaces { + class Foo +} +``` + +Or use a naming convention that avoids special characters entirely: + +```scala sc:nocompile custom-sc:compile +package withspaces { + class Foo +} +``` + +When working with files that have special characters in their names (like `myfile-test.scala`), be aware that the generated package objects will have encoded names. Consider renaming files to avoid this issue. diff --git a/docs/sidebar.yml b/docs/sidebar.yml index 7741ab57df46..9dba1d470d1f 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -202,11 +202,11 @@ subsection: - page: reference/error-codes/E007.md - page: reference/error-codes/E008.md - page: reference/error-codes/E009.md - # - page: reference/error-codes/E010.md + - page: reference/error-codes/E010.md - page: reference/error-codes/E011.md - page: reference/error-codes/E012.md - page: reference/error-codes/E013.md - # - page: reference/error-codes/E014.md + - page: reference/error-codes/E014.md - page: reference/error-codes/E015.md - page: reference/error-codes/E016.md - page: reference/error-codes/E017.md @@ -228,7 +228,7 @@ subsection: - page: reference/error-codes/E033.md - page: reference/error-codes/E034.md - page: reference/error-codes/E035.md - # - page: reference/error-codes/E036.md + - page: reference/error-codes/E036.md - page: reference/error-codes/E037.md - page: reference/error-codes/E038.md - page: reference/error-codes/E039.md @@ -246,14 +246,14 @@ subsection: - page: reference/error-codes/E051.md - page: reference/error-codes/E052.md - page: reference/error-codes/E053.md - # - page: reference/error-codes/E054.md + - page: reference/error-codes/E054.md - page: reference/error-codes/E055.md - page: reference/error-codes/E056.md - page: reference/error-codes/E057.md - page: reference/error-codes/E058.md - page: reference/error-codes/E059.md - page: reference/error-codes/E060.md - # - page: reference/error-codes/E061.md + - page: reference/error-codes/E061.md - page: reference/error-codes/E062.md - page: reference/error-codes/E063.md - page: reference/error-codes/E064.md @@ -271,8 +271,8 @@ subsection: - page: reference/error-codes/E076.md - page: reference/error-codes/E077.md - page: reference/error-codes/E078.md - # - page: reference/error-codes/E079.md - # - page: reference/error-codes/E080.md + - page: reference/error-codes/E079.md + - page: reference/error-codes/E080.md - page: reference/error-codes/E081.md - page: reference/error-codes/E082.md - page: reference/error-codes/E083.md @@ -292,4 +292,126 @@ subsection: - page: reference/error-codes/E097.md - page: reference/error-codes/E098.md - page: reference/error-codes/E099.md - - page: reference/error-codes/E100.md \ No newline at end of file + - page: reference/error-codes/E100.md + - page: reference/error-codes/E101.md + - page: reference/error-codes/E102.md + - page: reference/error-codes/E103.md + - page: reference/error-codes/E104.md + - page: reference/error-codes/E105.md + - page: reference/error-codes/E106.md + - page: reference/error-codes/E107.md + - page: reference/error-codes/E108.md + - page: reference/error-codes/E109.md + - page: reference/error-codes/E110.md + - page: reference/error-codes/E111.md + - page: reference/error-codes/E112.md + - page: reference/error-codes/E113.md + - page: reference/error-codes/E114.md + - page: reference/error-codes/E115.md + - page: reference/error-codes/E116.md + - page: reference/error-codes/E117.md + - page: reference/error-codes/E118.md + - page: reference/error-codes/E119.md + - page: reference/error-codes/E120.md + - page: reference/error-codes/E121.md + - page: reference/error-codes/E122.md + - page: reference/error-codes/E123.md + - page: reference/error-codes/E124.md + - page: reference/error-codes/E125.md + - page: reference/error-codes/E126.md + - page: reference/error-codes/E127.md + - page: reference/error-codes/E128.md + - page: reference/error-codes/E129.md + - page: reference/error-codes/E130.md + - page: reference/error-codes/E131.md + - page: reference/error-codes/E132.md + - page: reference/error-codes/E133.md + - page: reference/error-codes/E134.md + - page: reference/error-codes/E135.md + - page: reference/error-codes/E136.md + - page: reference/error-codes/E137.md + - page: reference/error-codes/E138.md + - page: reference/error-codes/E139.md + - page: reference/error-codes/E140.md + - page: reference/error-codes/E141.md + - page: reference/error-codes/E142.md + - page: reference/error-codes/E143.md + - page: reference/error-codes/E144.md + - page: reference/error-codes/E145.md + - page: reference/error-codes/E146.md + - page: reference/error-codes/E147.md + - page: reference/error-codes/E148.md + - page: reference/error-codes/E149.md + - page: reference/error-codes/E150.md + - page: reference/error-codes/E151.md + - page: reference/error-codes/E152.md + - page: reference/error-codes/E153.md + - page: reference/error-codes/E154.md + - page: reference/error-codes/E155.md + - page: reference/error-codes/E156.md + - page: reference/error-codes/E157.md + - page: reference/error-codes/E158.md + - page: reference/error-codes/E159.md + - page: reference/error-codes/E160.md + - page: reference/error-codes/E161.md + - page: reference/error-codes/E162.md + - page: reference/error-codes/E163.md + - page: reference/error-codes/E164.md + - page: reference/error-codes/E165.md + - page: reference/error-codes/E166.md + - page: reference/error-codes/E167.md + - page: reference/error-codes/E168.md + - page: reference/error-codes/E169.md + - page: reference/error-codes/E170.md + - page: reference/error-codes/E171.md + - page: reference/error-codes/E172.md + - page: reference/error-codes/E173.md + - page: reference/error-codes/E174.md + - page: reference/error-codes/E175.md + - page: reference/error-codes/E176.md + - page: reference/error-codes/E177.md + - page: reference/error-codes/E178.md + - page: reference/error-codes/E179.md + - page: reference/error-codes/E180.md + - page: reference/error-codes/E181.md + - page: reference/error-codes/E182.md + - page: reference/error-codes/E183.md + - page: reference/error-codes/E184.md + - page: reference/error-codes/E185.md + - page: reference/error-codes/E186.md + - page: reference/error-codes/E187.md + - page: reference/error-codes/E188.md + - page: reference/error-codes/E189.md + - page: reference/error-codes/E190.md + - page: reference/error-codes/E191.md + - page: reference/error-codes/E192.md + - page: reference/error-codes/E193.md + - page: reference/error-codes/E194.md + - page: reference/error-codes/E195.md + - page: reference/error-codes/E196.md + - page: reference/error-codes/E197.md + - page: reference/error-codes/E198.md + - page: reference/error-codes/E199.md + - page: reference/error-codes/E200.md + - page: reference/error-codes/E201.md + - page: reference/error-codes/E202.md + - page: reference/error-codes/E203.md + - page: reference/error-codes/E204.md + - page: reference/error-codes/E205.md + - page: reference/error-codes/E206.md + - page: reference/error-codes/E207.md + - page: reference/error-codes/E208.md + - page: reference/error-codes/E209.md + - page: reference/error-codes/E210.md + - page: reference/error-codes/E211.md + - page: reference/error-codes/E212.md + - page: reference/error-codes/E213.md + - page: reference/error-codes/E214.md + - page: reference/error-codes/E215.md + - page: reference/error-codes/E216.md + - page: reference/error-codes/E217.md + - page: reference/error-codes/E218.md + - page: reference/error-codes/E219.md + - page: reference/error-codes/E220.md + - page: reference/error-codes/E221.md + - page: reference/error-codes/E222.md \ No newline at end of file From 3521254c49ee3f83be94901aa80f9cd1b871f475 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 19:08:16 +0100 Subject: [PATCH 04/11] Mark inactive error codes found when documenting, remove dead code from messages.scala --- .../tools/dotc/reporting/ErrorMessageID.scala | 16 +++++------ .../dotty/tools/dotc/reporting/messages.scala | 28 ------------------- 2 files changed, 8 insertions(+), 36 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index 5f5a0c01db17..b3dbcb1e648b 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -98,7 +98,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case SuperCallsNotAllowedInlineableID // errorNumber: 82 case NotAPathID // errorNumber: 83 case WildcardOnTypeArgumentNotAllowedOnNewID // errorNumber: 84 - case FunctionTypeNeedsNonEmptyParameterListID // errorNumber: 85 + case FunctionTypeNeedsNonEmptyParameterListID extends ErrorMessageID(isActive = false) // errorNumber: 85 case WrongNumberOfParametersID // errorNumber: 86 case DuplicatePrivateProtectedQualifierID // errorNumber: 87 case ExpectedStartOfTopLevelDefinitionID // errorNumber: 88 @@ -107,7 +107,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case ReturnOutsideMethodDefinitionID // errorNumber: 91 case UncheckedTypePatternID // errorNumber: 92 case ExtendFinalClassID // errorNumber: 93 - case EnumCaseDefinitionInNonEnumOwnerID // errorNumber: 94 + case EnumCaseDefinitionInNonEnumOwnerID extends ErrorMessageID(isActive = false) // errorNumber: 94 case ExpectedTypeBoundOrEqualsID // errorNumber: 95 case ClassAndCompanionNameClashID // errorNumber: 96 case TailrecNotApplicableID // errorNumber: 97 @@ -118,7 +118,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case UndefinedNamedTypeParameterID // errorNumber: 102 case IllegalStartOfStatementID // errorNumber: 1033 case TraitIsExpectedID // errorNumber: 104 - case TraitRedefinedFinalMethodFromAnyRefID // errorNumber: 105 + case TraitRedefinedFinalMethodFromAnyRefID extends ErrorMessageID(isActive = false) // errorNumber: 105 case PackageNameAlreadyDefinedID // errorNumber: 106 case UnapplyInvalidNumberOfArgumentsID // errorNumber: 107 case UnapplyInvalidReturnTypeID // errorNumber: 108 @@ -126,7 +126,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case CyclicInheritanceID // errorNumber: 110 case BadSymbolicReferenceID // errorNumber: 111 case UnableToExtendSealedClassID // errorNumber: 112 - case SymbolHasUnparsableVersionNumberID // errorNumber: 113 + case SymbolHasUnparsableVersionNumberID // errorNumber: 113 case SymbolChangedSemanticsInVersionID // errorNumber: 114 case UnableToEmitSwitchID // errorNumber: 115 case MissingCompanionForStaticID // errorNumber: 116 @@ -163,9 +163,9 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case RedundantModifierID // errorNumber: 147 case TypedCaseDoesNotExplicitlyExtendTypedEnumID // errorNumber: 148 case IllegalRedefinitionOfStandardKindID // errorNumber: 149 - case NoExtensionMethodAllowedID // errorNumber: 150 - case ExtensionMethodCannotHaveTypeParamsID // errorNumber: 151 - case ExtensionCanOnlyHaveDefsID // errorNumber: 152 + case NoExtensionMethodAllowedID extends ErrorMessageID(isActive = false) // errorNumber: 150 + case ExtensionMethodCannotHaveTypeParamsID extends ErrorMessageID(isActive = false) // errorNumber: 151 + case ExtensionCanOnlyHaveDefsID extends ErrorMessageID(isActive = false) // errorNumber: 152 case UnexpectedPatternForSummonFromID // errorNumber: 153 case AnonymousInstanceCannotBeEmptyID // errorNumber: 154 case TypeSpliceInValPatternID extends ErrorMessageID(isActive = false) // errorNumber: 155 @@ -209,7 +209,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case VolatileOnValID // errorNumber: 193 case ExtensionNullifiedByMemberID // errorNumber: 194 case PhantomSymbolNotValueID // errorNumber: 195 - case ContextBoundCompanionNotValueID // errorNumber: 196 + case ContextBoundCompanionNotValueID extends ErrorMessageID(isActive = false) // errorNumber: 196 case InlinedAnonClassWarningID // errorNumber: 197 case UnusedSymbolID // errorNumber: 198 case TailrecNestedCallID //errorNumber: 199 diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 159b3c9a905e..869dcb951d53 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -2108,11 +2108,6 @@ class TraitIsExpected(symbol: Symbol)(using Context) extends SyntaxMsg(TraitIsEx } } -class TraitRedefinedFinalMethodFromAnyRef(method: Symbol)(using Context) extends SyntaxMsg(TraitRedefinedFinalMethodFromAnyRefID) { - def msg(using Context) = i"Traits cannot redefine final $method from ${hl("class AnyRef")}." - def explain(using Context) = "" -} - class AlreadyDefined(name: Name, owner: Symbol, conflicting: Symbol)(using Context) extends NamingMsg(AlreadyDefinedID): def msg(using Context) = @@ -2823,29 +2818,6 @@ class IllegalRedefinitionOfStandardKind(kindType: String, name: Name)(using Cont | Please choose a different name to avoid conflicts |""" } - -class NoExtensionMethodAllowed(mdef: untpd.DefDef)(using Context) - extends SyntaxMsg(NoExtensionMethodAllowedID) { - def msg(using Context) = i"No extension method allowed here, since collective parameters are given" - def explain(using Context) = - i"""|Extension method: - | `${mdef}` - |is defined inside an extension clause which has collective parameters. - |""" -} - -class ExtensionMethodCannotHaveTypeParams(mdef: untpd.DefDef)(using Context) - extends SyntaxMsg(ExtensionMethodCannotHaveTypeParamsID) { - def msg(using Context) = i"Extension method cannot have type parameters since some were already given previously" - - def explain(using Context) = - i"""|Extension method: - | `${mdef}` - |has type parameters `[${mdef.leadingTypeParams.map(_.show).mkString(",")}]`, while the extension clause has - |it's own type parameters. Please consider moving these to the extension clause's type parameter list. - |""" -} - class ExtensionCanOnlyHaveDefs(mdef: untpd.Tree)(using Context) extends SyntaxMsg(ExtensionCanOnlyHaveDefsID) { def msg(using Context) = i"Only methods allowed here, since collective parameters are given" From 7dc49e450e60e5ab4130b2abc2f818ec6867574b Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 19:09:56 +0100 Subject: [PATCH 05/11] Add GHA job enusre error codes are up to date and snippets fail with expected error --- .github/workflows/scaladoc.yaml | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/workflows/scaladoc.yaml b/.github/workflows/scaladoc.yaml index cc483c4af6cc..ea38904ee425 100644 --- a/.github/workflows/scaladoc.yaml +++ b/.github/workflows/scaladoc.yaml @@ -85,3 +85,43 @@ jobs: - name: Test sourcelinks to stdlib run: true # ./project/scripts/sbt scaladoc/sourceLinksIntegrationTest:test + + check-error-code-snippets: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: coursier/cache-action@v7 + - uses: VirtusLab/scala-cli-setup@v1 + - with: + jvm: temurin:17 + - name: Publish compiler locally + run: | + version=$(./project/scripts/sbt "print scala3-compiler-bootstrapped-new/version" | tail -n1) + echo "SCALA_VERSION=$version" >> $GITHUB_ENV + echo "Would test snippets using Scala $version" + + # Publish locally minimal set of artifacts that would be required to test snippets + sbt "set every doc := new File(\"unused\");\ + all \ + scala-library-bootstrapped/publishLocal \ + scala3-compiler-bootstrapped-new/publishLocal \ + scala3-interfaces/publishLocal \ + scala3-library-bootstrapped-new/publishLocal \ + " + - name: Test error code snippets + shell: bash + run: scala-cli test -S ${{ env.SCALA_VERSION }} --with-compiler project/scripts/checkErrorCodeSnippets.test.scala -- +l +a +c + - if: failure() + run: | + cat << EOF >> $GITHUB_STEP_SUMMARY + Snippets validation for error codes failed + + If you've modified messages of positions of error codes, you might need to update the expected outputs, to do it run: following command: + scala -S ${{ env.SCALA_VERSION }} project/scripts/checkErrorCodeSnippets.scala --with-compiler --main-class=updateAllErrorCodeOutputs + + Single error code validation can be performed using: + scala -S ${{ env.SCALA_VERSION }} project/scripts/checkErrorCodeSnippets.scala --with-compiler -- docs/_docs/reference/error-codes/E001.md [--verbose --update-output] + + To check the validation use dedicated test suite: + scala test -S ${{ env.SCALA_VERSION }} --with-compiler project/scripts/checkErrorCodeSnippets.test.scala -- +l +a +c + EOF From 61b838c9d4e39c2908607520947237e580a0ae0c Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 20:47:43 +0100 Subject: [PATCH 06/11] Fix building code snippets in markdown files when using `scaladoc/generateReferenceDocumentation` (crashed) --- project/Build.scala | 3 +-- scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 473fd21f6d19..86d5caa5f3e5 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -2830,7 +2830,7 @@ object Build { val languageReferenceConfig = Def.task { Scala3.value - .add(OutputDir("scaladoc/output/reference")) + .add(OutputDir(file("scaladoc/output/reference").getAbsoluteFile.getAbsolutePath)) .add(SiteRoot(docs.getAbsolutePath)) .add(ProjectName("Scala 3 Reference")) .add(ProjectVersion(baseVersion)) @@ -2838,7 +2838,6 @@ object Build { .add(SourceLinks(List( s"${docs.getParentFile().getAbsolutePath}=github://scala/scala3/language-reference-stable" ))) - .withTargets(List("___fake___.scala")) } val expectedLinksRegeneration = Def.task { diff --git a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala index abf073aa53aa..dc79a90e355b 100644 --- a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala +++ b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala @@ -131,7 +131,7 @@ object Scaladoc: roots.split(File.pathSeparatorChar).toList.map(new File(_)) argumentFilesOrNone.fold((None, newContext)) { argumentFiles => - val inFiles = argumentFiles.map(File(_)).filter(_.getName != "___fake___.scala") + val inFiles = argumentFiles.map(File(_)) val (existing, nonExisting) = inFiles.partition(_.exists) if nonExisting.nonEmpty then report.warning( From 683dbff09fbd9f2fb431db63416d00c26b6133be Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 20:48:28 +0100 Subject: [PATCH 07/11] Setup error-codes/index --- .../reference/error-codes/error-codes.md | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/_docs/reference/error-codes/error-codes.md b/docs/_docs/reference/error-codes/error-codes.md index f93145b0f4de..a1244814f864 100644 --- a/docs/_docs/reference/error-codes/error-codes.md +++ b/docs/_docs/reference/error-codes/error-codes.md @@ -1,3 +1,27 @@ --- +layout: index title: Error codes ---- \ No newline at end of file +--- + +The Scala 3 compiler assigns a unique error code to each type of error it can emit. +These codes appear in compiler output in the format `[E001]`, `[E007]`, etc. + +This section documents each error code with: + +- **Description** — what the error means and when it occurs +- **Example** — code that triggers the error +- **Error output** — the actual compiler message you'll see +- **Solution** — how to fix the problem + +## Using error codes + +When you encounter an error, you can use the `-explain` flag to get more detailed information: + +```bash +scala compile -explain MyFile.scala +``` + +You can also look up any error code directly in this documentation by its number (e.g., E007 for type mismatch errors). + +Browse the full list in the sidebar to find documentation for any specific error code. + From 799aa84b599863b9c98500977b280aa4ab10c8b8 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 20:56:13 +0100 Subject: [PATCH 08/11] Fix typo in scaladoc.yaml workflow --- .github/workflows/scaladoc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scaladoc.yaml b/.github/workflows/scaladoc.yaml index ea38904ee425..1024cd0ea54e 100644 --- a/.github/workflows/scaladoc.yaml +++ b/.github/workflows/scaladoc.yaml @@ -92,7 +92,7 @@ jobs: - uses: actions/checkout@v6 - uses: coursier/cache-action@v7 - uses: VirtusLab/scala-cli-setup@v1 - - with: + with: jvm: temurin:17 - name: Publish compiler locally run: | From a85ced0056fba3087f153e40392a6323b50ea3cb Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 20:58:01 +0100 Subject: [PATCH 09/11] scaladoc.yaml: Ensure to install sbt --- .github/workflows/scaladoc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/scaladoc.yaml b/.github/workflows/scaladoc.yaml index 1024cd0ea54e..ab14a1ff3663 100644 --- a/.github/workflows/scaladoc.yaml +++ b/.github/workflows/scaladoc.yaml @@ -94,6 +94,7 @@ jobs: - uses: VirtusLab/scala-cli-setup@v1 with: jvm: temurin:17 + apps: scala-cli, sbt - name: Publish compiler locally run: | version=$(./project/scripts/sbt "print scala3-compiler-bootstrapped-new/version" | tail -n1) From 0040b6e6bad3b1c43f23a77e7be69d46d5be3885 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 20:59:17 +0100 Subject: [PATCH 10/11] scaladoc.yaml: Fix scala-cli-setup --- .github/workflows/scaladoc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scaladoc.yaml b/.github/workflows/scaladoc.yaml index ab14a1ff3663..979954ca2134 100644 --- a/.github/workflows/scaladoc.yaml +++ b/.github/workflows/scaladoc.yaml @@ -94,7 +94,7 @@ jobs: - uses: VirtusLab/scala-cli-setup@v1 with: jvm: temurin:17 - apps: scala-cli, sbt + apps: sbt - name: Publish compiler locally run: | version=$(./project/scripts/sbt "print scala3-compiler-bootstrapped-new/version" | tail -n1) From e3f3f867099a8035fc08325e363ef62881028246 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 14 Dec 2025 21:18:20 +0100 Subject: [PATCH 11/11] scaladoc.yaml: publish all bootstrapped artifacts, scala-cli requires repl, tasty-inspector, staging, etc. --- .github/workflows/scaladoc.yaml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/scaladoc.yaml b/.github/workflows/scaladoc.yaml index 979954ca2134..796697e449fd 100644 --- a/.github/workflows/scaladoc.yaml +++ b/.github/workflows/scaladoc.yaml @@ -103,16 +103,13 @@ jobs: # Publish locally minimal set of artifacts that would be required to test snippets sbt "set every doc := new File(\"unused\");\ - all \ - scala-library-bootstrapped/publishLocal \ - scala3-compiler-bootstrapped-new/publishLocal \ - scala3-interfaces/publishLocal \ - scala3-library-bootstrapped-new/publishLocal \ - " + scala3-bootstrapped-new/publishLocal + " - name: Test error code snippets shell: bash run: scala-cli test -S ${{ env.SCALA_VERSION }} --with-compiler project/scripts/checkErrorCodeSnippets.test.scala -- +l +a +c - - if: failure() + - name: "[On failure] Print reproduction/fix steps" + if: failure() run: | cat << EOF >> $GITHUB_STEP_SUMMARY Snippets validation for error codes failed