diff options
author | Paul Phillips <paulp@improving.org> | 2013-04-23 13:55:41 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-04-23 15:39:21 -0700 |
commit | 1da48a45b62879c2bd2904342eeff7e6e568350a (patch) | |
tree | cdf5f7b1903d1523cb0391bda745bc9ca29836da | |
parent | 0f1a004048089dc2f51c5e1a11419072102b896b (diff) | |
download | scala-1da48a45b62879c2bd2904342eeff7e6e568350a.tar.gz scala-1da48a45b62879c2bd2904342eeff7e6e568350a.tar.bz2 scala-1da48a45b62879c2bd2904342eeff7e6e568350a.zip |
Eliminate a pile of -Xlint warnings.
Some unused private code, unused imports, and points where
an extra pair of parentheses is necessary for scalac to have
confidence in our intentions.
19 files changed, 56 insertions, 90 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 1b183ddd3f..9603aab338 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -2245,13 +2245,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { case x :: y :: ys => nextBlock = y; genBlock(x); genBlocks(y :: ys) } - def isAccessibleFrom(target: Symbol, site: Symbol): Boolean = { - target.isPublic || target.isProtected && { - (site.enclClass isSubClass target.enclClass) || - (site.enclosingPackage == target.privateWithin) - } - } // end of genCode()'s isAccessibleFrom() - def genCallMethod(call: CALL_METHOD) { val CALL_METHOD(method, style) = call val siteSymbol = clasz.symbol diff --git a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala index ff93206ffd..8a85873e94 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala @@ -17,7 +17,7 @@ import scala.annotation.tailrec * null checks. * * With some more work it could be extended to - * - cache stable values (final fields, modules) in locals + * - cache stable values (final fields, modules) in locals * - replace the copy propagation in ClosureElilmination * - fold constants * - eliminate unnecessary stores and loads @@ -118,18 +118,18 @@ abstract class ConstantOptimization extends SubComponent { * * // left must be 1 or 2, right must be 2 or 3 then we must have a 1, 2 or 3 * Possible(xs) merge Possible(ys) => Possible(xs union ys) - * + * * // Left says can't be 2 or 3, right says can't be 3 or 4 * // then it's not 3 (it could be 2 from the right or 4 from the left) * Impossible(xs) merge Impossible(ys) => Impossible(xs intersect ys) - * + * * // Left says it can't be 2 or 3, right says it must be 3 or 4, then * // it can't be 2 (left rules out 4 and right says 3 is possible) * Impossible(xs) merge Possible(ys) => Impossible(xs -- ys) - * + * * Intuitively, Possible(empty) says that a location can't hold anything, * it's uninitialized. However, Possible(empty) never appears in the code. - * + * * Conversely, Impossible(empty) says nothing is impossible, it could be * anything. Impossible(empty) is given a synonym UNKNOWN and is used * for, e.g., the result of an arbitrary method call. @@ -155,7 +155,7 @@ abstract class ConstantOptimization extends SubComponent { def mightNotEqual(other: Contents): Boolean } private def SingleImpossible(x: Datum) = new Impossible(Set(x)) - + /** * The location is known to have one of a set of values. */ @@ -299,32 +299,32 @@ abstract class ConstantOptimization extends SubComponent { private def interpretInst(in: State, inst: Instruction): State = { // pop the consumed number of values off the `in` state's stack, producing a new state def dropConsumed: State = in drop inst.consumed - + inst match { case THIS(_) => in load THIS_LOCAL - + case CONSTANT(k) => // treat NaN as UNKNOWN because NaN must never equal NaN val const = if (k.isNaN) UNKNOWN else SinglePossible(Const(k)) in push const - + case LOAD_ARRAY_ITEM(_) | LOAD_FIELD(_, _) | CALL_PRIMITIVE(_) => dropConsumed push UNKNOWN case LOAD_LOCAL(local) => // TODO if a local is known to hold a constant then we can replace this instruction with a push of that constant in load local - + case STORE_LOCAL(local) => in store local - + case STORE_THIS(_) => // if a local is already known to have a constant and we're replacing with the same constant then we can // replace this with a drop in store THIS_LOCAL - + case CALL_METHOD(_, _) => // TODO we could special case implementations of equals that are known, e.g. String#equals // We could turn Possible(string constants).equals(Possible(string constants) into an eq check @@ -332,7 +332,7 @@ abstract class ConstantOptimization extends SubComponent { // and eliminate the null check that likely precedes this call val initial = dropConsumed (0 until inst.produced).foldLeft(initial) { case (know, _) => know push UNKNOWN } - + case BOX(_) => val value = in peek 0 // we simulate boxing by, um, boxing the possible/impossible contents @@ -345,7 +345,7 @@ abstract class ConstantOptimization extends SubComponent { case Impossible(values) => Impossible(values map Boxed) } dropConsumed push newValue - + case UNBOX(_) => val value = in peek 0 val newValue = value match { @@ -373,42 +373,42 @@ abstract class ConstantOptimization extends SubComponent { } } dropConsumed push newValue - + case LOAD_MODULE(_) | NEW(_) | LOAD_EXCEPTION(_) => in push NOT_NULL case CREATE_ARRAY(_, _) => dropConsumed push NOT_NULL - + case IS_INSTANCE(_) => // TODO IS_INSTANCE is going to be followed by a C(Z)JUMP // and if IS_INSTANCE/C(Z)JUMP the branch for "true" can // know that whatever was checked was not a null // see the TODO on CJUMP for more information about propagating null // information - // TODO if the top of stack is guaranteed null then we can eliminate this IS_INSTANCE check and + // TODO if the top of stack is guaranteed null then we can eliminate this IS_INSTANCE check and // replace with a constant false, but how often is a knowable null checked for instanceof? // TODO we could track type information and statically know to eliminate IS_INSTANCE // which might be a nice win under specialization dropConsumed push UNKNOWN // it's actually a Possible(true, false) but since the following instruction // will be a conditional jump comparing to true or false there // nothing to be gained by being more precise - + case CHECK_CAST(_) => // TODO we could track type information and statically know to eliminate CHECK_CAST // but that's probably not a huge win in - + case DUP(_) => val value = in peek 0 in push value - + case DROP(_) | MONITOR_ENTER() | MONITOR_EXIT() | STORE_ARRAY_ITEM(_) | STORE_FIELD(_, _) => dropConsumed case SCOPE_ENTER(_) | SCOPE_EXIT(_) => in - + case JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | RETURN(_) | THROW(_) | SWITCH(_, _) => dumpClassesAndAbort("Unexpected block ending instruction: " + inst) } @@ -468,7 +468,7 @@ abstract class ConstantOptimization extends SubComponent { val replacements = if (result.size == 1) List.fill(inst.consumed)(DROP(kind)) :+ JUMP(result.keySet.head) else inst :: Nil - + (result, replacements) } @@ -488,8 +488,7 @@ abstract class ConstantOptimization extends SubComponent { case SWITCH(tags, labels) => val in1 = in peek 0 - val newStuff = tags zip labels filter { case (tagSet, _) => canSwitch(in1, tagSet) } - val (reachableTags, reachableNormalLabels) = (tags zip labels filter { case (tagSet, _) => canSwitch(in1, tagSet) }).unzip + val reachableNormalLabels = tags zip labels collect { case (tagSet, label) if canSwitch(in1, tagSet) => label } val reachableLabels = if (labels.lengthCompare(tags.length) > 0) { // if we've got an extra label then it's the default val defaultLabel = labels.last @@ -533,7 +532,7 @@ abstract class ConstantOptimization extends SubComponent { // number of instructions excluding the last one val normalCount = block.size - 1 - var exceptionState = in.cleanStack + val exceptionState = in.cleanStack var normalExitState = in var idx = 0 while (idx < normalCount) { @@ -569,7 +568,7 @@ abstract class ConstantOptimization extends SubComponent { // worklist of basic blocks to process, initially the start block val worklist = MSet(m.startBlock) - // worklist of exception basic blocks. They're kept in a separate set so they can be + // worklist of exception basic blocks. They're kept in a separate set so they can be // processed after normal flow basic blocks. That's because exception basic blocks // are more likely to have multiple predecessors and queueing them for later // increases the chances that they'll only need to be interpreted once diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala index a591482392..8f7794fa90 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala @@ -30,9 +30,8 @@ trait Plugins { val dirs = (settings.pluginsDir.value split File.pathSeparator).toList map injectDefault map Path.apply val maybes = Plugin.loadAllFrom(jars, dirs, settings.disable.value) val (goods, errors) = maybes partition (_.isSuccess) - errors foreach (_ recover { - case e: Exception => inform(e.getMessage) - }) + // Explicit parameterization of recover to suppress -Xlint warning about inferred Any + errors foreach (_.recover[Any] { case e: Exception => inform(e.getMessage) }) val classes = goods map (_.get) // flatten // Each plugin must only be instantiated once. A common pattern diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 2ece06c801..d498949b03 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -32,19 +32,6 @@ abstract class CleanUp extends Transform with ast.TreeDSL { newStaticInits.clear() symbolsStoredAsStatic.clear() } - private def savingStatics[T](body: => T): T = { - val savedNewStaticMembers : mutable.Buffer[Tree] = newStaticMembers.clone() - val savedNewStaticInits : mutable.Buffer[Tree] = newStaticInits.clone() - val savedSymbolsStoredAsStatic : mutable.Map[String, Symbol] = symbolsStoredAsStatic.clone() - val result = body - - clearStatics() - newStaticMembers ++= savedNewStaticMembers - newStaticInits ++= savedNewStaticInits - symbolsStoredAsStatic ++= savedSymbolsStoredAsStatic - - result - } private def transformTemplate(tree: Tree) = { val Template(_, _, body) = tree clearStatics() diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index c531caa2e8..7e36b90b31 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -336,11 +336,13 @@ trait SyntheticMethods extends ast.TreeDSL { def shouldGenerate(m: Symbol) = { !hasOverridingImplementation(m) || { clazz.isDerivedValueClass && (m == Any_hashCode || m == Any_equals) && { - if (settings.lint) { - (clazz.info nonPrivateMember m.name) filter (m => (m.owner != AnyClass) && (m.owner != clazz) && !m.isDeferred) andAlso { m => - currentUnit.warning(clazz.pos, s"Implementation of ${m.name} inherited from ${m.owner} overridden in $clazz to enforce value class semantics") - } - } + // Without a means to suppress this warning, I've thought better of it. + // + // if (settings.lint) { + // (clazz.info nonPrivateMember m.name) filter (m => (m.owner != AnyClass) && (m.owner != clazz) && !m.isDeferred) andAlso { m => + // currentUnit.warning(clazz.pos, s"Implementation of ${m.name} inherited from ${m.owner} overridden in $clazz to enforce value class semantics") + // } + // } true } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 02ab456046..2ea986def7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1512,7 +1512,7 @@ trait Typers extends Adaptations with Tags { */ private def typedParentType(encodedtpt: Tree, templ: Template, inMixinPosition: Boolean): Tree = { val app = treeInfo.dissectApplied(encodedtpt) - val (treeInfo.Applied(core, targs, argss), decodedtpt) = ((app, app.callee)) + val (treeInfo.Applied(core, _, argss), decodedtpt) = ((app, app.callee)) val argssAreTrivial = argss == Nil || argss == ListOfNil // we cannot avoid cyclic references with `initialize` here, because when type macros arrive, diff --git a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala index c5136c752b..b4d3fd8aa0 100644 --- a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala @@ -43,8 +43,6 @@ import scala.tools.nsc.util.InterruptReq */ trait CompilerControl { self: Global => - import syntaxAnalyzer.UnitParser - type Response[T] = scala.tools.nsc.interactive.Response[T] /** The scheduler by which client and compiler communicate diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala index dbdb2d02b6..43b8bd2738 100644 --- a/src/interactive/scala/tools/nsc/interactive/Global.scala +++ b/src/interactive/scala/tools/nsc/interactive/Global.scala @@ -22,7 +22,6 @@ import scala.language.implicitConversions trait InteractiveScaladocAnalyzer extends InteractiveAnalyzer with ScaladocAnalyzer { val global : Global - import global._ override def newTyper(context: Context) = new Typer(context) with InteractiveTyper with ScaladocTyper { override def canAdaptConstantTypeToLiteral = false } diff --git a/src/interactive/scala/tools/nsc/interactive/RangePositions.scala b/src/interactive/scala/tools/nsc/interactive/RangePositions.scala index a24be50b33..410f919daa 100644 --- a/src/interactive/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/interactive/scala/tools/nsc/interactive/RangePositions.scala @@ -7,9 +7,8 @@ package scala.tools.nsc package interactive @deprecated("Use scala.reflect.internal.Positions", "2.11.0") -trait RangePositions extends { - override val useOffsetPositions = false -} with scala.reflect.internal.Positions with ast.Trees with ast.Positions { +trait RangePositions extends scala.reflect.internal.Positions with ast.Trees with ast.Positions { self: scala.tools.nsc.Global => + override val useOffsetPositions = false } diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 692d6b8d6a..3ec84a17ab 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -93,7 +93,7 @@ extends AbstractMap[A, B] def -=(key: A): this.type = { removeEntry(key); this } - def iterator = entriesIterator map {e => (e.key, e.value)} + def iterator = entriesIterator map (e => ((e.key, e.value))) override def foreach[C](f: ((A, B)) => C): Unit = foreachEntry(e => f((e.key, e.value))) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index cd41f533bb..51611cb9db 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -4327,7 +4327,7 @@ trait Types // transpose freaked out because of irregular argss // catching just in case (shouldn't happen, but also doesn't cost us) // [JZ] It happens: see SI-5683. - debuglog("transposed irregular matrix!?" +(tps, argss)) + debuglog(s"transposed irregular matrix!? tps=$tps argss=$argss") None case Some(argsst) => val args = map2(sym.typeParams, argsst) { (tparam, as0) => diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index 921d2e3d66..c84870bff9 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -291,7 +291,7 @@ private[internal] trait GlbLubs { case ts @ AnnotatedType(annots, tpe, _) :: rest => annotationsLub(lub0(ts map (_.withoutAnnotations)), ts) case ts => - lubResults get (depth, ts) match { + lubResults get ((depth, ts)) match { case Some(lubType) => lubType case None => @@ -449,7 +449,7 @@ private[internal] trait GlbLubs { case ts @ TypeBounds(_, _) :: rest => TypeBounds(lub(ts map (_.bounds.lo), depth), glb(ts map (_.bounds.hi), depth)) case ts => - glbResults get (depth, ts) match { + glbResults get ((depth, ts)) match { case Some(glbType) => glbType case _ => diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala index c1fb0c0107..e18b21aa76 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala @@ -3,7 +3,6 @@ package internal package tpe import scala.collection.{ mutable } -import Flags._ import util.Statistics import scala.annotation.tailrec diff --git a/src/reflect/scala/reflect/io/Directory.scala b/src/reflect/scala/reflect/io/Directory.scala index 4bf9ed8a36..c11119286f 100644 --- a/src/reflect/scala/reflect/io/Directory.scala +++ b/src/reflect/scala/reflect/io/Directory.scala @@ -14,7 +14,7 @@ import java.io.{ File => JFile } * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object Directory { - import scala.util.Properties.{ userHome, userDir } + import scala.util.Properties.userDir private def normalizePath(s: String) = Some(apply(Path(s).normalize)) def Current: Option[Directory] = if (userDir == "") None else normalizePath(userDir) diff --git a/src/reflect/scala/reflect/io/VirtualFile.scala b/src/reflect/scala/reflect/io/VirtualFile.scala index 8cc83b6a50..d34eece3f0 100644 --- a/src/reflect/scala/reflect/io/VirtualFile.scala +++ b/src/reflect/scala/reflect/io/VirtualFile.scala @@ -60,9 +60,13 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF /** @inheritdoc */ override def isVirtual: Boolean = true + // private var _lastModified: Long = 0 + // _lastModified + /** Returns the time that this abstract file was last modified. */ - private var _lastModified: Long = 0 - def lastModified: Long = _lastModified + // !!! Except it doesn't - it's private and never set - so I replaced it + // with constant 0 to save the field. + def lastModified: Long = 0 /** Returns all abstract subfiles of this abstract directory. */ def iterator: Iterator[AbstractFile] = { diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 3211bb7919..d67687368c 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -13,9 +13,7 @@ import java.lang.reflect.{ import java.lang.annotation.{Annotation => jAnnotation} import java.io.IOException import scala.reflect.internal.{ MissingRequirementError, JavaAccFlags, JMethodOrConstructor } -import JavaAccFlags._ import internal.pickling.ByteCodecs -import internal.ClassfileConstants._ import internal.pickling.UnPickler import scala.collection.mutable.{ HashMap, ListBuffer } import internal.Flags._ @@ -1280,14 +1278,12 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni if (name.isTermName && !owner.isEmptyPackageClass) return mirror.makeScalaPackage( if (owner.isRootSymbol) name.toString else owner.fullName+"."+name) - syntheticCoreClasses get (owner.fullName, name) match { - case Some(tsym) => - // synthetic core classes are only present in root mirrors - // because Definitions.scala, which initializes and enters them, only affects rootMirror - // therefore we need to enter them manually for non-root mirrors - if (mirror ne thisUniverse.rootMirror) owner.info.decls enter tsym - return tsym - case None => + syntheticCoreClasses get ((owner.fullName, name)) foreach { tsym => + // synthetic core classes are only present in root mirrors + // because Definitions.scala, which initializes and enters them, only affects rootMirror + // therefore we need to enter them manually for non-root mirrors + if (mirror ne thisUniverse.rootMirror) owner.info.decls enter tsym + return tsym } } info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass) diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 4ba81b634a..83cd9829e4 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -555,7 +555,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set @throws(classOf[ScriptException]) def compile(script: String): CompiledScript = { if (!bound) { - quietBind("engine", this.asInstanceOf[ScriptEngine]) + quietBind("engine" -> this.asInstanceOf[ScriptEngine]) bound = true } val cat = code + script diff --git a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala index a895944c15..2eaf8595b0 100644 --- a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala +++ b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala @@ -234,8 +234,6 @@ class JavapClass( } class JavapTool7 extends JavapTool { - - import JavapTool._ type Task = { def call(): Boolean // true = ok //def run(args: Array[String]): Int // all args @@ -606,7 +604,7 @@ object JavapClass { // s = "f" and $line.$read$$etc$#f is what we're after, // ignoring any #member (except take # as filter on #apply) orElse (intp flatMap (_ translateEnclosingClass k) map ((_, Some(k), filter, true))) - getOrElse (k, member, filter, false)) + getOrElse ((k, member, filter, false))) } /** Find the classnames of anonfuns associated with k, * where k may be an available class or a symbol in scope. diff --git a/test/files/neg/t6534.check b/test/files/neg/t6534.check index 52e70cfa8a..c2e80b377a 100644 --- a/test/files/neg/t6534.check +++ b/test/files/neg/t6534.check @@ -1,9 +1,3 @@ -t6534.scala:4: warning: Implementation of equals inherited from trait Foo overridden in class Bippy1 to enforce value class semantics -class Bippy1(val x: Int) extends AnyVal with Foo { } // warn - ^ -t6534.scala:5: warning: Implementation of hashCode inherited from trait Ding overridden in class Bippy2 to enforce value class semantics -class Bippy2(val x: Int) extends AnyVal with Ding { } // warn - ^ t6534.scala:6: error: redefinition of equals method. See SIP-15, criterion 4. is not allowed in value class class Bippy3(val x: Int) extends AnyVal { override def equals(x: Any) = false } // error ^ @@ -13,5 +7,4 @@ class Bippy4(val x: Int) extends AnyVal { override def hashCode = -1 } t6534.scala:9: error: redefinition of equals method. See SIP-15, criterion 4. is not allowed in value class case class Bippy6(val x: Int) extends AnyVal { override def productPrefix = "Dingo" ; override def equals(x: Any) = false } // error ^ -two warnings found three errors found |