From 34778d35cf99079720c8ba8f1b20311ba4795fee Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Fri, 12 Dec 2025 00:37:39 +0100 Subject: [PATCH 1/3] Allow to set scala compiler options on snipets. Use the extra scalacOptions in snippet compiler --- .../src/dotty/tools/scaladoc/site/templates.scala | 4 ++-- .../snippets/FlexmarkSnippetProcessor.scala | 15 ++++++++++++++- .../tools/scaladoc/snippets/SnippetChecker.scala | 2 +- .../tools/scaladoc/snippets/SnippetCompiler.scala | 9 ++++++++- .../scaladoc/snippets/SnippetCompilerArgs.scala | 5 ++++- .../tools/scaladoc/tasty/comments/Comments.scala | 4 ++-- 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/site/templates.scala b/scaladoc/src/dotty/tools/scaladoc/site/templates.scala index 56a0f7f6d6b6..6d5eeb06267a 100644 --- a/scaladoc/src/dotty/tools/scaladoc/site/templates.scala +++ b/scaladoc/src/dotty/tools/scaladoc/site/templates.scala @@ -81,8 +81,8 @@ case class TemplateFile( val path = Some(Paths.get(file.getAbsolutePath)) val pathBasedArg = ssctx.snippetCompilerArgs.get(path) val sourceFile = dotty.tools.dotc.util.SourceFile(dotty.tools.io.AbstractFile.getFile(path.get), scala.io.Codec.UTF8) - (str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SCFlags]) => { - val arg = argOverride.fold(pathBasedArg)(pathBasedArg.overrideFlag(_)) + (str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SnippetCompilerArg]) => { + val arg = argOverride.fold(pathBasedArg)(pathBasedArg.merge(_)) val compilerData = SnippetCompilerData( "staticsitesnippet", SnippetCompilerData.Position(configOffset - 1, 0) diff --git a/scaladoc/src/dotty/tools/scaladoc/snippets/FlexmarkSnippetProcessor.scala b/scaladoc/src/dotty/tools/scaladoc/snippets/FlexmarkSnippetProcessor.scala index c92853816d16..75a280376f50 100644 --- a/scaladoc/src/dotty/tools/scaladoc/snippets/FlexmarkSnippetProcessor.scala +++ b/scaladoc/src/dotty/tools/scaladoc/snippets/FlexmarkSnippetProcessor.scala @@ -21,7 +21,7 @@ object FlexmarkSnippetProcessor: val lineOffset = node.getStartLineNumber + preparsed.fold(0)(_.strippedLinesBeforeNo) val info = node.getInfo.toString.split(" ") if info.contains("scala") then { - val argOverride = info + val flagOverride = info .find(_.startsWith("sc:")) .map(_.stripPrefix("sc:")) .map(SCFlagsParser.parse) @@ -34,6 +34,19 @@ object FlexmarkSnippetProcessor: ) None }) + + val scalacOptions = info + .filter(_.startsWith("sc-opts:")) + .map(_.stripPrefix("sc-opts:")) + .toSeq + + val argOverride: Option[SnippetCompilerArg] = + (flagOverride, scalacOptions) match { + case (None, Seq()) => None + case (Some(flag), opts) => Some(SnippetCompilerArg(flag, opts)) + case (None, opts) => Some(SnippetCompilerArg(SCFlags.Compile, opts)) + } + val id = info .find(_.startsWith("sc-name:")) .map(_.stripPrefix("sc-name:")) diff --git a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetChecker.scala b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetChecker.scala index 8f8b73a576d1..4f90fbcee984 100644 --- a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetChecker.scala +++ b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetChecker.scala @@ -59,4 +59,4 @@ class SnippetChecker(val args: Scaladoc.Args)(using cctx: CompilerContext): object SnippetChecker: type LineOffset = Int - type SnippetCheckingFunc = (String, LineOffset, Option[SCFlags]) => Option[SnippetCompilationResult] + type SnippetCheckingFunc = (String, LineOffset, Option[SnippetCompilerArg]) => Option[SnippetCompilationResult] diff --git a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala index b13b5e9756ea..971e7ec6357c 100644 --- a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala +++ b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala @@ -100,12 +100,19 @@ class SnippetCompiler( arg: SnippetCompilerArg, sourceFile: SourceFile ): SnippetCompilationResult = { - val context = SnippetDriver.currentCtx.fresh + val baseContext = SnippetDriver.currentCtx.fresh .setSetting( SnippetDriver.currentCtx.settings.outputDir, target ) .setReporter(new StoreReporter) + val context = + if arg.scalacOptions.isEmpty then baseContext + else + val args = arg.scalacOptions.toArray + SnippetDriver.setup(args, baseContext) match + case Some((_, ctx)) => ctx + case None => baseContext val run = newRun(using context) run.compileFromStrings(List(wrappedSnippet.snippet)) diff --git a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerArgs.scala b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerArgs.scala index 35a89d985d8e..b5a3f7dfe123 100644 --- a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerArgs.scala +++ b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerArgs.scala @@ -3,8 +3,11 @@ package snippets import java.nio.file.Path -case class SnippetCompilerArg(flag: SCFlags): +case class SnippetCompilerArg(flag: SCFlags, scalacOptions: Seq[String] = Seq.empty): def overrideFlag(f: SCFlags): SnippetCompilerArg = copy(flag = f) + def withScalacOptions(opts: Seq[String]): SnippetCompilerArg = copy(scalacOptions = scalacOptions ++ opts) + def merge(other: SnippetCompilerArg): SnippetCompilerArg = + SnippetCompilerArg(other.flag, scalacOptions ++ other.scalacOptions) enum SCFlags(val flagName: String): case Compile extends SCFlags("compile") diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala index 5b72e9eb5c42..9659bce44369 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala @@ -137,8 +137,8 @@ abstract class MarkupConversion[T](val repr: Repr)(using dctx: DocContext) { val scDataCollector = SnippetCompilerDataCollector[qctx.type](qctx) val data = scDataCollector.getSnippetCompilerData(s, s) val sourceFile = scDataCollector.getSourceFile(s) - (str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SCFlags]) => { - val arg = argOverride.fold(pathBasedArg)(pathBasedArg.overrideFlag(_)) + (str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SnippetCompilerArg]) => { + val arg = argOverride.fold(pathBasedArg)(pathBasedArg.merge(_)) val res = snippetChecker.checkSnippet(str, Some(data), arg, lineOffset, sourceFile) res.filter(r => !r.isSuccessful).foreach(_.reportMessages()(using compilerContext)) res From 73b97291da51930bfb888a2be2434dd3985b033d Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Fri, 12 Dec 2025 00:38:42 +0100 Subject: [PATCH 2/3] Show position of code snippets that failed to compile --- .../src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala index 971e7ec6357c..780eea53c10b 100644 --- a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala +++ b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala @@ -86,7 +86,9 @@ class SnippetCompiler( private def additionalMessages(wrappedSnippet: WrappedSnippet, arg: SnippetCompilerArg, sourceFile: SourceFile, context: Context): Seq[SnippetCompilerMessage] = { Option.when(arg.flag == SCFlags.Fail && !context.reporter.hasErrors)( - SnippetCompilerMessage(None, "Snippet should not compile but compiled successfully", MessageLevel.Error) + SnippetCompilerMessage( + Some(Position(SourcePosition(sourceFile, NoSpan), wrappedSnippet.outerLineOffset)), + "Snippet should not compile but compiled successfully", MessageLevel.Error) ).toList } From f310b118d4535ebf9f51744cb5fe2ab310fed5f7 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Fri, 12 Dec 2025 00:39:35 +0100 Subject: [PATCH 3/3] 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 06949fcd325c..adb65a6b2a40 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -189,3 +189,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