From 7c28f83271fe8141b01027374c8776c411250e77 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 18 Mar 2024 22:13:16 -0700 Subject: [PATCH 1/2] Preliminary ported edits [Cherry-picked 11eff96ba77830f44fd196dd4d5e40ce7aeb921c] --- docs/_spec/11-annotations.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_spec/11-annotations.md b/docs/_spec/11-annotations.md index 3381856d78fb..e8b23be0e007 100644 --- a/docs/_spec/11-annotations.md +++ b/docs/_spec/11-annotations.md @@ -20,7 +20,7 @@ Here, ´c´ is a constructor of a class ´C´, which must conform to the class ` Annotations may apply to definitions, types, or expressions. An annotation of a definition appears in front of that definition. An annotation of a type appears after that type. -An annotation of an expression ´e´ appears after the expression ´e´, separated by a colon. +An annotation of an expression appears after that expression, separated by a colon. More than one annotation clause may apply to an entity. The order in which these annotations are given does not matter. @@ -86,7 +86,7 @@ def f(x: Option[Int]) = (x: @unchecked) match { ``` Without the `@unchecked` annotation, a Scala compiler could infer that the pattern match is non-exhaustive, and could produce a warning because `Option` is a `sealed` class. -* `@uncheckedStable` When applied a value definition, it allows the defined value to appear in a path, even if its type is [volatile](03-types.html#volatile-types). +* `@uncheckedStable` When applied to a value definition, it allows the defined value to appear in a path, even if its type is [volatile](03-types.html#volatile-types). For instance, the following member definitions are legal: ```scala type A { type T } @@ -97,7 +97,7 @@ val y: x.T // OK since `x' is still a path Without the `@uncheckedStable` annotation, the designator `x` would not be a path since its type `A with B` is volatile. Hence, the reference `x.T` would be malformed. -When applied to value definitions that have non-volatile types, the annotation has no effect. +When applied to value definitions that have no volatile types, the annotation has no effect. * `@specialized` When applied to the definition of a type parameter, this annotation causes the compiler to generate specialized definitions for primitive types. An optional list of primitive types may be given, in which case specialization takes into account only those types. From ac72874b65eef450ce8812a861a24cf43e52d7b9 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 18 Mar 2024 23:43:07 -0700 Subject: [PATCH 2/2] Port tailrec spec [Cherry-picked f7d5a8daaf9ce71ff182fd7a36c4823b04949e0c] --- docs/_spec/04-basic-definitions.md | 16 +++++ docs/_spec/11-annotations.md | 93 ++++++++++++++++-------------- 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/docs/_spec/04-basic-definitions.md b/docs/_spec/04-basic-definitions.md index 369709b52bff..28eb2d43a627 100644 --- a/docs/_spec/04-basic-definitions.md +++ b/docs/_spec/04-basic-definitions.md @@ -710,6 +710,22 @@ class C extends I { Here, it is OK to leave out the result type of `factorial` in `C`, even though the method is recursive. +### Tail-Recursive Call Elimination + +Method definitions which contain self-recursive invocations in tail position are optimized for stack safety. +Self-invocations which are the last operation before returning from the method are replaced with jumps to the beginning of the method, much as in a while loop. +Sibling-invocations, in which a method calls itself but with a different instance as receiver, are also optimized. + +This transform is performed automatically by the compiler whenever possible. +A method definition bearing the annotation, `scala.annotation.tailrec`, will fail to compile if the transform is not possible. +(The annotation is intended for cases where deoptimization would likely result in a stack overflow.) + +```scala +@annotation.tailrec +def sum(xs: List[Int], acc: Int): Int = + xs match { case h :: t => sum(t, acc + h) case _ => acc } +``` +