Skip to content

Fix #4936: Forbid (or warn on) redundant/illegal object flags #4973

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Definitions._

object NameOps {

final object compactify {
object compactify {
lazy val md5: MessageDigest = MessageDigest.getInstance("MD5")

/** COMPACTIFY
Expand Down
10 changes: 10 additions & 0 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2415,6 +2415,16 @@ object Parsers {

def objectDefRest(start: Offset, mods: Modifiers, name: TermName): ModuleDef = {
val template = templateOpt(emptyConstructor)

def flagPos(flag: FlagSet) = mods.mods.find(_.flags == flag).get.pos
if (mods is Abstract)
syntaxError(hl"""${Abstract} modifier cannot be used for objects""", flagPos(Abstract))
if (mods is Sealed)
syntaxError(hl"""${Sealed} modifier is redundant for objects""", flagPos(Sealed))
// Maybe this should be an error; see https://github.com/scala/bug/issues/11094.
if (mods is Final)
warning(hl"""${Final} modifier is redundant for objects""", source atPos flagPos(Final))

finalizeDef(ModuleDef(name, template), mods, start)
}

Expand Down
5 changes: 2 additions & 3 deletions compiler/src/dotty/tools/dotc/printing/Formatting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,8 @@ object Formatting {
hl.show
case hb: HighlightBuffer =>
hb.toString
case str: String =>
SyntaxHighlighting.highlight(str)
case _ => super.showArg(arg)
case _ =>
SyntaxHighlighting.highlight(super.showArg(arg))
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/vulpix/Status.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ package vulpix
sealed trait Status
final case class Success(output: String) extends Status
final case class Failure(output: String) extends Status
final case object Timeout extends Status
case object Timeout extends Status
2 changes: 1 addition & 1 deletion doc-tool/src/dotty/tools/dottydoc/model/references.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ object references {
final case class BoundsReference(low: Reference, high: Reference) extends Reference
final case class NamedReference(title: String, ref: Reference, isByName: Boolean = false, isRepeated: Boolean = false) extends Reference
final case class ConstantReference(title: String) extends Reference
final case object EmptyReference extends Reference
case object EmptyReference extends Reference

/** Use MaterializableLink for entities that need be picklable */
sealed trait MaterializableLink { def title: String }
Expand Down
2 changes: 1 addition & 1 deletion semanticdb/src/dotty/semanticdb/Scala.scala
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ object Scala {
}
}
object Descriptor {
final case object None extends Descriptor { def value: String = "" }
case object None extends Descriptor { def value: String = "" }
final case class Term(value: String) extends Descriptor
final case class Method(value: String, disambiguator: String) extends Descriptor
final case class Type(value: String) extends Descriptor
Expand Down
1 change: 1 addition & 0 deletions tests/neg-custom-args/fatal-warnings/i4936.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
final object Foo // error
1 change: 1 addition & 0 deletions tests/neg/i3471.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sealed object Fun // error
4 changes: 4 additions & 0 deletions tests/neg/i4936.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
abstract object Foo // error
sealed final abstract case object Bar // error // error

abstract override object Baz // error
4 changes: 2 additions & 2 deletions tests/patmat/i3645.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ object App {
}

sealed abstract class K[A]
final case object KAge extends K[Age]
final case object KInt extends K[Int]
case object KAge extends K[Age]
case object KInt extends K[Int]

val kint: K[Age] = Age.subst[K](KInt)
def get(k: K[Age]): String = k match {
Expand Down
6 changes: 3 additions & 3 deletions tests/patmat/i3645b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ object App {
type Bar = Foo

sealed abstract class K[A]
final case object K1 extends K[Int]
final case object K2 extends K[Foo]
final case object K3 extends K[Bar]
case object K1 extends K[Int]
case object K2 extends K[Foo]
case object K3 extends K[Bar]

val foo: K[Int] = Foo.subst[K](K2)
def get(k: K[Int]): Unit = k match {
Expand Down
6 changes: 3 additions & 3 deletions tests/patmat/i3645c.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ object App {
type Bar = Foo

sealed abstract class K[+A]
final case object K1 extends K[Int]
final case object K2 extends K[Foo]
final case object K3 extends K[Bar]
case object K1 extends K[Int]
case object K2 extends K[Foo]
case object K3 extends K[Bar]

val foo: K[Int] = Foo.subst[K](K2)
def get(k: K[Int]): Unit = k match {
Expand Down
6 changes: 3 additions & 3 deletions tests/patmat/i3645d.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ object App {
type Bar = Foo

sealed abstract class K[-A]
final case object K1 extends K[Int]
final case object K2 extends K[Foo]
final case object K3 extends K[Bar]
case object K1 extends K[Int]
case object K2 extends K[Foo]
case object K3 extends K[Bar]

val foo: K[Int] = Foo.subst[K](K2)
def get(k: K[Int]): Unit = k match {
Expand Down
4 changes: 2 additions & 2 deletions tests/patmat/i3645e.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ object App {
type Foo = Module.Foo.Type

sealed abstract class K[F]
final case object K1 extends K[Int]
final case object K2 extends K[Foo]
case object K1 extends K[Int]
case object K2 extends K[Foo]

val kv: K[Foo] = Module.Foo.subst[K](K1)
def test(k: K[Foo]): Unit = k match {
Expand Down
4 changes: 2 additions & 2 deletions tests/patmat/i3645f.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ object App {
type Foo = Module.Foo.Type

sealed abstract class K[F]
final case object K1 extends K[Int]
final case object K2 extends K[Foo]
case object K1 extends K[Int]
case object K2 extends K[Foo]

val kv: K[Foo] = Module.Foo.subst[K](K1)
def test(k: K[Foo]): Unit = k match {
Expand Down
4 changes: 2 additions & 2 deletions tests/patmat/i3645g.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ object App {
type Foo = Module.Foo.Type

sealed abstract class K[F]
final case object K1 extends K[Int]
final case object K2 extends K[Foo]
case object K1 extends K[Int]
case object K2 extends K[Foo]

val kv: K[Foo] = Module.Foo.subst[K](K1)
def test(k: K[Foo]): Unit = k match {
Expand Down
4 changes: 2 additions & 2 deletions tests/patmat/t7353.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
sealed trait EthernetType

object EthernetType {
final case object Gigabit extends EthernetType
final case object FastEthernet extends EthernetType
case object Gigabit extends EthernetType
case object FastEthernet extends EthernetType

final def toInt(t: EthernetType) = t match {
case Gigabit => 1
Expand Down
2 changes: 1 addition & 1 deletion tests/pos-kind-polymorphism/anykind.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ object Test {
sealed trait HList
final case class ::[+H, +T <: HList](head : H, tail : T) extends HList
sealed trait HNil extends HList
final case object HNil extends HNil
case object HNil extends HNil

object New {
// The Kind Polymorphic List
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/byname-implicits-13.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ case class Cat(name: String, friend: Either[Cat, Dog])
sealed trait HList extends Product with Serializable
final case class ::[+H, +T <: HList](head: H, tail: T) extends HList
sealed trait HNil extends HList
final case object HNil extends HNil
case object HNil extends HNil

sealed trait Coproduct extends Product with Serializable
sealed trait :+:[+H, +T <: Coproduct] extends Coproduct
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/byname-implicits-14.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ case class Cat(name: String, friend: Either[Cat, Dog])
sealed trait HList extends Product with Serializable
final case class ::[+H, +T <: HList](head: H, tail: T) extends HList
sealed trait HNil extends HList
final case object HNil extends HNil
case object HNil extends HNil

sealed trait Coproduct extends Product with Serializable
sealed trait :+:[+H, +T <: Coproduct] extends Coproduct
Expand Down
1 change: 0 additions & 1 deletion tests/pos/i3471.scala

This file was deleted.

4 changes: 2 additions & 2 deletions tests/pos/i3647.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ object App {
type T = String
type Bar[A] = J[A]
sealed abstract class J[A]
final case object JName extends J[T]
final case object JInt extends J[Int]
case object JName extends J[T]
case object JInt extends J[Int]

def get(k: J[T]): String = k match {
case JName => "Age"
Expand Down
2 changes: 1 addition & 1 deletion tests/run/erased-frameless.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import scala.annotation.implicitNotFound

sealed trait HList
sealed trait HNil extends HList
final case object HNil extends HNil
case object HNil extends HNil
final case class ::[H, T <: HList](h: H, t: T) extends HList

/** Generic representation os type T as a labelled sum of product. */
Expand Down
2 changes: 1 addition & 1 deletion tests/run/hmap-covariant.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
trait Tuple
case class TCons[+H, +T <: Tuple](h: H, t: T) extends Tuple
final case object TNil extends Tuple
case object TNil extends Tuple

// Type level natural numbers -------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion tests/run/hmap.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
trait Tuple
case class TCons[H, T <: Tuple](h: H, t: T) extends Tuple
final case object TNil extends Tuple
case object TNil extends Tuple

// Type level natural numbers -------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion tests/run/phantom-OnHList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ sealed trait HNil extends HList

// HList values -----------------------------------------------------------------------------------

final case object HNil extends HNil {
case object HNil extends HNil {
val underlying: Array[Any] = Array.empty[Any]
override def toString(): String = "()"
}
Expand Down