From 833724b131f86b978f0831f637d386d7ca37a2aa Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 19 Oct 2016 12:09:40 -0700 Subject: SI-7860 No warn private implicit value class Previously, warned on unused synthetic companion. Also avoid false negative via hashcode reference to the underlying value. Avoid the synthetic conversion method for the implicit class (whose RHS always uses the class); the def itself is synthetic so is normally not warned. --- .../tools/nsc/typechecker/TypeDiagnostics.scala | 13 +++++-- test/files/neg/t7860.check | 9 +++++ test/files/neg/t7860.flags | 1 + test/files/neg/t7860.scala | 42 ++++++++++++++++++++++ test/files/neg/warn-unused-privates.check | 5 ++- test/files/neg/warn-unused-privates.scala | 8 +++++ 6 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 test/files/neg/t7860.check create mode 100644 test/files/neg/t7860.flags create mode 100644 test/files/neg/t7860.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index ee2d00900a..b30972f931 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -355,7 +355,10 @@ trait TypeDiagnostics { // functions to manipulate the name def preQualify() = modifyName(trueOwner.fullName + "." + _) - def postQualify() = if (!(postQualifiedWith contains trueOwner)) { postQualifiedWith ::= trueOwner; modifyName(_ + "(in " + trueOwner + ")") } + def postQualify() = if (!(postQualifiedWith contains trueOwner)) { + postQualifiedWith ::= trueOwner + modifyName(s => s"$s(in $trueOwner)") + } def typeQualify() = if (sym.isTypeParameterOrSkolem) postQualify() def nameQualify() = if (trueOwner.isPackageClass) preQualify() else postQualify() @@ -498,11 +501,13 @@ trait TypeDiagnostics { override def traverse(t: Tree): Unit = { t match { - case m: MemberDef if qualifies(t.symbol) => defnTrees += m + case m: MemberDef if qualifies(t.symbol) => + defnTrees += m t match { case DefDef(mods@_, name@_, tparams@_, vparamss, tpt@_, rhs@_) if !t.symbol.isAbstract && !t.symbol.isDeprecated => if (t.symbol.isPrimaryConstructor) for (cpa <- t.symbol.owner.constrParamAccessors if cpa.isPrivateLocal) params += cpa + else if (t.symbol.isSynthetic && t.symbol.isImplicit) return else if (!t.symbol.isConstructor) for (vs <- vparamss) params ++= vs.map(_.symbol) case _ => @@ -525,6 +530,7 @@ trait TypeDiagnostics { case NoType | NoPrefix => case NullaryMethodType(_) => case MethodType(_, _) => + case SingleType(_, _) => case _ => log(s"$tp referenced from $currentOwner") treeTypes += tp @@ -547,6 +553,7 @@ trait TypeDiagnostics { def isSyntheticWarnable(sym: Symbol) = ( sym.isDefaultGetter ) + def isUnusedTerm(m: Symbol): Boolean = ( (m.isTerm) && (!m.isSynthetic || isSyntheticWarnable(m)) @@ -562,7 +569,7 @@ trait TypeDiagnostics { def treepos(t: Tree): Int = if (t.pos.isDefined) t.pos.point else sympos(t.symbol) - def unusedTypes = defnTrees.toList filter (t => isUnusedType(t.symbol)) sortBy treepos + def unusedTypes = defnTrees.toList.filter(t => isUnusedType(t.symbol)).sortBy(treepos) def unusedTerms = { val all = defnTrees.toList.filter(v => isUnusedTerm(v.symbol)) diff --git a/test/files/neg/t7860.check b/test/files/neg/t7860.check new file mode 100644 index 0000000000..9b9d86c89d --- /dev/null +++ b/test/files/neg/t7860.check @@ -0,0 +1,9 @@ +t7860.scala:5: warning: private class for your eyes only in object Test is never used + private implicit class `for your eyes only`(i: Int) { // warn + ^ +t7860.scala:31: warning: private class C in object Test3 is never used + private implicit class C(val i: Int) extends AnyVal { // warn + ^ +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/t7860.flags b/test/files/neg/t7860.flags new file mode 100644 index 0000000000..6ff0dea0b2 --- /dev/null +++ b/test/files/neg/t7860.flags @@ -0,0 +1 @@ +-Xfatal-warnings -Ywarn-unused:privates diff --git a/test/files/neg/t7860.scala b/test/files/neg/t7860.scala new file mode 100644 index 0000000000..6cc0d3e7f5 --- /dev/null +++ b/test/files/neg/t7860.scala @@ -0,0 +1,42 @@ + +class Test + +object Test { + private implicit class `for your eyes only`(i: Int) { // warn + def f = i + } +} + +class Test2 { + import Test2._ + println(5.toStr) +} + +object Test2 { + // was: warning: private object in object Test2 is never used + // i.e. synthetic object C + private implicit class C(val i: Int) extends AnyVal { // no warn + def toStr = i.toString + } +} + +class Test3 { + import Test3._ + //println(5.toStr) +} + +object Test3 { + // was: warning: private object in object Test2 is never used + // i.e. synthetic object C + private implicit class C(val i: Int) extends AnyVal { // warn + def toStr = i.toString + } +} + +object Test4 { + class A { class B } + + private val a: A = new A + + def b = (new a.B).## +} diff --git a/test/files/neg/warn-unused-privates.check b/test/files/neg/warn-unused-privates.check index 490e070794..d4853847fd 100644 --- a/test/files/neg/warn-unused-privates.check +++ b/test/files/neg/warn-unused-privates.check @@ -97,6 +97,9 @@ warn-unused-privates.scala:118: warning: local class DingDongDoobie is never use warn-unused-privates.scala:121: warning: local type OtherThing is never used type OtherThing = String // warn ^ +warn-unused-privates.scala:216: warning: private class for your eyes only in object not even using companion privates is never used + private implicit class `for your eyes only`(i: Int) { // warn + ^ warn-unused-privates.scala:201: warning: pattern var z in method f is never used; `z@_' suppresses this warning case z => "warn" ^ @@ -104,5 +107,5 @@ warn-unused-privates.scala:208: warning: pattern var z in method f is never used case Some(z) => "warn" ^ error: No warnings can be incurred under -Xfatal-warnings. -35 warnings found +36 warnings found one error found diff --git a/test/files/neg/warn-unused-privates.scala b/test/files/neg/warn-unused-privates.scala index 777e0f1579..6f16ab4138 100644 --- a/test/files/neg/warn-unused-privates.scala +++ b/test/files/neg/warn-unused-privates.scala @@ -209,3 +209,11 @@ trait CaseyAtTheBat { case None => "no warn" } } + +class `not even using companion privates` + +object `not even using companion privates` { + private implicit class `for your eyes only`(i: Int) { // warn + def f = i + } +} -- cgit v1.2.3