Skip to content

Commit f1e8a44

Browse files
author
Dean Wampler
committed
Fixed bug where top-level classes are not allowed to have the @TargetNAME annotation, as of Scala 3.2
1 parent b76dcf8 commit f1e8a44

File tree

3 files changed

+47
-36
lines changed

3 files changed

+47
-36
lines changed

src/main/scala/progscala3/typesystem/bounds/list/AbbrevList.scala

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,48 @@ package progscala3.typesystem.bounds.list
44
import scala.annotation.targetName
55
import java.util.NoSuchElementException
66

7-
sealed abstract class AbbrevList[+A]:
8-
9-
def isEmpty: Boolean
10-
def head: A
11-
def tail: AbbrevList[A]
12-
13-
@targetName("prepend")
14-
def ::[B >: A] (x: B): AbbrevList[B] = new ::(x, this)
15-
16-
final def foreach(f: A => Unit) =
17-
var these = this
18-
while !these.isEmpty do
19-
f(these.head)
20-
these = these.tail
21-
22-
// The empty AbbrevList.
23-
24-
case object AbbrevNil extends AbbrevList[Nothing]:
25-
override def isEmpty = true
26-
27-
def head: Nothing =
28-
throw NoSuchElementException("head of empty AbbrevList")
29-
30-
def tail: AbbrevList[Nothing] =
31-
throw NoSuchElementException("tail of empty AbbrevList")
32-
33-
// A non-empty AbbrevList characterized by a head and a tail.
34-
35-
@targetName("AbbrevListCons")
36-
final case class ::[B](private var hd: B,
37-
private[list] var tl: AbbrevList[B]) extends AbbrevList[B]:
38-
39-
override def isEmpty: Boolean = false
40-
def head : B = hd
41-
def tail : AbbrevList[B] = tl
7+
/**
8+
* Scala 3.2 no longer allows top-level classes to have @targetName annotations.
9+
* From the error message printed by the compiler:
10+
* This restriction is due to the naming convention of Java classfiles, whose filenames
11+
* are based on the name of the class defined within. If @targetName were permitted
12+
* here, the name of the classfile would be based on the target name, and the compiler
13+
* could not associate that classfile with the Scala-visible defined name of the class.
14+
* One solution is to wrap the types in an object, as done here, which is not shown in the book.
15+
*/
16+
object AbbrevListModule:
17+
sealed abstract class AbbrevList[+A]:
18+
19+
def isEmpty: Boolean
20+
def head: A
21+
def tail: AbbrevList[A]
22+
23+
@targetName("prepend")
24+
def ::[B >: A] (x: B): AbbrevList[B] = new ::(x, this)
25+
26+
final def foreach(f: A => Unit) =
27+
var these = this
28+
while !these.isEmpty do
29+
f(these.head)
30+
these = these.tail
31+
32+
// The empty AbbrevList.
33+
34+
case object AbbrevNil extends AbbrevList[Nothing]:
35+
override def isEmpty = true
36+
37+
def head: Nothing =
38+
throw NoSuchElementException("head of empty AbbrevList")
39+
40+
def tail: AbbrevList[Nothing] =
41+
throw NoSuchElementException("tail of empty AbbrevList")
42+
43+
// A non-empty AbbrevList characterized by a head and a tail.
44+
45+
@targetName("AbbrevListCons")
46+
final case class ::[B](private var hd: B,
47+
private[list] var tl: AbbrevList[B]) extends AbbrevList[B]:
48+
49+
override def isEmpty: Boolean = false
50+
def head : B = hd
51+
def tail : AbbrevList[B] = tl

src/script/scala/progscala3/typesystem/bounds/list/ListAb.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// src/script/scala/progscala3/typesystem/bounds/list/ListAb.scala
22
import progscala3.typesystem.bounds.list.*
3+
import AbbrevListModule.*
34

45
//val languages = AbbrevList("Scala", "Java", "Ruby", "C#", "C++", "Python")
56
val languages: AbbrevList[String] =

src/test/scala/progscala3/typesystem/bounds/list/AbbrevListSuite.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// src/test/scala/progscala3/typesystem/bounds/list/AbbrevListSuite.scala
22
package progscala3.typesystem.bounds.list
3-
3+
import AbbrevListModule.*
44
import munit.*
55

66
/**

0 commit comments

Comments
 (0)