Skip to content

Commit

Permalink
Merge pull request #10677 from som-snytt/issue/3764-lint-cloneable
Browse files Browse the repository at this point in the history
Lint cloneable modules
  • Loading branch information
SethTisue committed Jan 29, 2024
2 parents 25f7035 + a52d12c commit d0bcece
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/compiler/scala/tools/nsc/settings/Warnings.scala
Expand Up @@ -218,6 +218,7 @@ trait Warnings {
val IntDivToFloat = LintWarning("int-div-to-float", "Warn when an integer division is converted (widened) to floating point: `(someInt / 2): Double`.")
val NamedBooleans = LintWarning("named-booleans", "Boolean literals should be named args unless param is @deprecatedName.")
val PatternShadow = LintWarning("pattern-shadow", "Pattern variable id is also a term in scope.")
val CloneableObject = LintWarning("cloneable", "Modules (objects) should not be Cloneable.")

def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]]
}
Expand Down Expand Up @@ -256,6 +257,7 @@ trait Warnings {
def lintIntDivToFloat = lint.contains(IntDivToFloat)
def lintNamedBooleans = lint.contains(NamedBooleans)
def warnPatternShadow = lint.contains(PatternShadow)
def warnCloneableObject = lint.contains(CloneableObject)

// The Xlint warning group.
val lint = MultiChoiceSetting(
Expand Down
28 changes: 13 additions & 15 deletions src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
Expand Up @@ -886,41 +886,39 @@ abstract class RefChecks extends Transform {
*/
private def validateBaseTypes(clazz: Symbol): Unit = {
val seenParents = mutable.HashSet[Type]()
val seenTypes = new Array[List[Type]](clazz.info.baseTypeSeq.length)
for (i <- 0 until seenTypes.length)
seenTypes(i) = Nil
val seenTypes = Array.fill[List[Type]](clazz.info.baseTypeSeq.length)(Nil)
val warnCloneable = settings.warnCloneableObject && clazz.isModuleClass

/* validate all base types of a class in reverse linear order. */
def register(tp: Type): Unit = {
// if (clazz.fullName.endsWith("Collection.Projection"))
// println("validate base type "+tp)
val baseClass = tp.typeSymbol
if (baseClass.isClass) {
if (!baseClass.isTrait && !baseClass.isJavaDefined && !currentRun.compiles(baseClass) && !separatelyCompiledScalaSuperclass.contains(baseClass))
separatelyCompiledScalaSuperclass.update(baseClass, ())
val index = clazz.info.baseTypeIndex(baseClass)
if (index >= 0) {
if (seenTypes(index) forall (tp1 => !(tp1 <:< tp)))
seenTypes(index) =
tp :: (seenTypes(index) filter (tp1 => !(tp <:< tp1)))
if (!seenTypes(index).exists(_ <:< tp))
seenTypes(index) = tp :: seenTypes(index).filterNot(tp <:< _)
}
}
val remaining = tp.parents filterNot seenParents
if (warnCloneable && baseClass.eq(JavaCloneableClass))
reporter.warning(clazz.pos, s"$clazz should not extend Cloneable.")
val remaining = tp.parents.filterNot(seenParents)
seenParents ++= remaining
remaining foreach register
remaining.foreach(register)
}
register(clazz.tpe)
for (i <- 0 until seenTypes.length) {
val baseClass = clazz.info.baseTypeSeq(i).typeSymbol
seenTypes(i) match {
case Nil =>
devWarning(s"base $baseClass not found in basetypes of $clazz. This might indicate incorrect caching of TypeRef#parents.")
case _ :: Nil =>
;// OK
case _ :: Nil => // OK
case tp1 :: tp2 :: _ =>
reporter.error(clazz.pos, "illegal inheritance;\n " + clazz +
" inherits different type instances of " + baseClass +
":\n" + tp1 + " and " + tp2)
reporter.error(clazz.pos,
sm"""|illegal inheritance;
| $clazz inherits different type instances of $baseClass:
|$tp1 and $tp2""")
explainTypes(tp1, tp2)
explainTypes(tp2, tp1)
}
Expand Down
6 changes: 6 additions & 0 deletions test/files/neg/cloneable.check
@@ -0,0 +1,6 @@
cloneable.scala:6: warning: object X should not extend Cloneable.
object X extends Base
^
error: No warnings can be incurred under -Werror.
1 warning
1 error
8 changes: 8 additions & 0 deletions test/files/neg/cloneable.scala
@@ -0,0 +1,8 @@

//> using options -Werror -Xlint:cloneable

class Base extends Cloneable

object X extends Base

class Y extends Base

0 comments on commit d0bcece

Please sign in to comment.