Skip to content

Commit 1907775

Browse files
committed
Enable more param warnings
1 parent e8ca0cc commit 1907775

File tree

9 files changed

+53
-37
lines changed

9 files changed

+53
-37
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ class Compiler {
4848
List(new sbt.ExtractAPI) :: // Sends a representation of the API of classes to sbt via callbacks
4949
List(new Inlining) :: // Inline and execute macros
5050
List(new PostInlining) :: // Add mirror support for inlined code
51-
List(new CheckUnused.PostInlining) :: // Check for unused elements
5251
List(new Staging) :: // Check staging levels and heal staged types
5352
List(new Splicing) :: // Replace level 1 splices with holes
5453
List(new PickleQuotes) :: // Turn quoted trees into explicit run-time data structures
54+
List(new CheckUnused.PostInlining) :: // Check for unused elements
5555
Nil
5656

5757
/** Phases dealing with the transformation from pickled trees to backend trees */

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ class Definitions {
494494
@tu lazy val Predef_undefined: Symbol = ScalaPredefModule.requiredMethod(nme.???)
495495
@tu lazy val ScalaPredefModuleClass: ClassSymbol = ScalaPredefModule.moduleClass.asClass
496496

497+
@tu lazy val SameTypeClass: ClassSymbol = requiredClass("scala.=:=")
498+
@tu lazy val SameType_refl: Symbol = SameTypeClass.companionModule.requiredMethod(nme.refl)
497499
@tu lazy val SubTypeClass: ClassSymbol = requiredClass("scala.<:<")
498500
@tu lazy val SubType_refl: Symbol = SubTypeClass.companionModule.requiredMethod(nme.refl)
499501

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import dotty.tools.dotc.core.Types.{AnnotatedType, ClassInfo, ConstantType, Name
1616
import dotty.tools.dotc.core.Flags
1717
import dotty.tools.dotc.core.Names.{Name, TermName, termName}
1818
import dotty.tools.dotc.core.NameOps.isReplWrapperName
19-
import dotty.tools.dotc.core.NameKinds.WildcardParamName
19+
import dotty.tools.dotc.core.NameKinds.{ContextFunctionParamName, WildcardParamName}
2020
import dotty.tools.dotc.core.Symbols.{NoSymbol, Symbol, defn, isDeprecated}
2121
import dotty.tools.dotc.report
2222
import dotty.tools.dotc.reporting.{Message, UnusedSymbol as UnusedSymbolMessage}
@@ -517,13 +517,25 @@ object CheckUnused:
517517
warnings.addOne(UnusedSymbol(d.namePos, d.name, WarnTypes.LocalDefs))
518518

519519
if ctx.settings.WunusedHas.explicits then
520+
def forgiven(sym: Symbol) =
521+
containsSyntheticSuffix(sym)
522+
|| sym.owner.hasAnnotation(defn.UnusedAnnot)
523+
|| sym.info.isSingleton
520524
for d <- explicitParamInScope do
521-
if !d.symbol.usedDefContains && !isUsedInPosition(d.symbol.name, d.span) && !containsSyntheticSuffix(d.symbol) then
525+
if !d.symbol.usedDefContains && !isUsedInPosition(d.symbol.name, d.span) && !forgiven(d.symbol) then
522526
warnings.addOne(UnusedSymbol(d.namePos, d.name, WarnTypes.ExplicitParams))
523527

524528
if ctx.settings.WunusedHas.implicits then
529+
def forgiven(sym: Symbol) =
530+
val dd = defn
531+
sym.name.is(ContextFunctionParamName)
532+
|| sym.owner.hasAnnotation(defn.UnusedAnnot)
533+
|| sym.info.typeSymbol.match
534+
case dd.DummyImplicitClass | dd.SubTypeClass | dd.SameTypeClass => true
535+
case _ => false
536+
|| sym.info.isSingleton
525537
for d <- implicitParamInScope do
526-
if !d.symbol.usedDefContains && !containsSyntheticSuffix(d.symbol) then
538+
if !d.symbol.usedDefContains && !forgiven(d.symbol) then
527539
warnings.addOne(UnusedSymbol(d.namePos, d.name, WarnTypes.ImplicitParams))
528540

529541
// Partition to extract unset private variables from usedPrivates
@@ -556,7 +568,9 @@ object CheckUnused:
556568
/** Heuristic to detect synthetic suffixes in names of symbols.
557569
*/
558570
private def containsSyntheticSuffix(symbol: Symbol)(using Context): Boolean =
559-
symbol.name.mangledString.contains("$")
571+
val mangled = symbol.name.mangledString
572+
val index = mangled.indexOf('$')
573+
index >= 0 && !(index == mangled.length - 1 && symbol.is(Module))
560574

561575
/**
562576
* Is the constructor of synthetic package object
@@ -659,8 +673,7 @@ object CheckUnused:
659673
owner.isPrimaryConstructor ||
660674
owner.isDeprecated ||
661675
owner.isAllOf(Synthetic | PrivateLocal) ||
662-
owner.is(Accessor) ||
663-
owner.isOverridden
676+
owner.is(Accessor)
664677
}
665678

666679
private def usedDefContains(using Context): Boolean =
@@ -669,9 +682,10 @@ object CheckUnused:
669682
private def everySymbol(using Context): List[Symbol] =
670683
List(sym, sym.companionClass, sym.companionModule, sym.moduleClass).filter(_.exists)
671684

672-
/** A function is overridden. Either has `override flags` or parent has a matching member (type and name) */
685+
/** A function is overridden. Either has `override flags` or parent has a matching member (type and name)
673686
private def isOverridden(using Context): Boolean =
674687
sym.is(Flags.Override) || (sym.exists && sym.owner.thisType.parents.exists(p => sym.matchingMember(p).exists))
688+
*/
675689

676690
end extension
677691

@@ -688,7 +702,7 @@ object CheckUnused:
688702
case ConstantType(_) => true
689703
case tp: TermRef =>
690704
// Detect Scala 2 SingleType
691-
tp.underlying.classSymbol.is(Flags.Module)
705+
tp.underlying.classSymbol.is(Module)
692706
case _ =>
693707
false
694708
def registerTrivial(using Context): Unit =

tests/warn/i15503b.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ package foo.scala2.tests:
117117

118118
object Types {
119119
def l1() = {
120-
object HiObject { def f = this } // OK
120+
object HiObject { def f = this } // warn
121121
class Hi { // warn
122122
def f1: Hi = new Hi
123123
def f2(x: Hi) = x
@@ -141,4 +141,4 @@ package test.foo.twisted.i16682:
141141
}
142142
isInt
143143

144-
def f = myPackage("42")
144+
def f = myPackage("42")

tests/warn/i15503e.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ package foo.test.i16865:
6464
trait Bar extends Foo
6565

6666
object Ex extends Bar:
67-
def fn(a: Int, b: Int): Int = b + 3 // OK
67+
def fn(a: Int, b: Int): Int = b + 3 // warn
6868

6969
object Ex2 extends Bar:
70-
override def fn(a: Int, b: Int): Int = b + 3 // OK
70+
override def fn(a: Int, b: Int): Int = b + 3 // warn

tests/warn/i15503f.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ val default_int = 1
66
object Xd {
77
private def f1(a: Int) = a // OK
88
private def f2(a: Int) = 1 // OK
9-
private def f3(a: Int)(using Int) = a // OK
10-
private def f4(a: Int)(using Int) = default_int // OK
9+
private def f3(a: Int)(using Int) = a // warn
10+
private def f4(a: Int)(using Int) = default_int // warn
1111
private def f6(a: Int)(using Int) = summon[Int] // OK
1212
private def f7(a: Int)(using Int) = summon[Int] + a // OK
1313
private def f8(a: Int)(using foo: Int) = a // warn

tests/warn/i15503g.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ object Foo {
66

77
private def f1(a: Int) = a // OK
88
private def f2(a: Int) = default_int // warn
9-
private def f3(a: Int)(using Int) = a // OK
10-
private def f4(a: Int)(using Int) = default_int // warn
9+
private def f3(a: Int)(using Int) = a // warn
10+
private def f4(a: Int)(using Int) = default_int // warn // warn
1111
private def f6(a: Int)(using Int) = summon[Int] // warn
1212
private def f7(a: Int)(using Int) = summon[Int] + a // OK
1313
/* --- Trivial method check --- */
@@ -20,4 +20,4 @@ package foo.test.i17101:
2020
extension[A] (x: Test[A]) { // OK
2121
def value: A = x
2222
def causesIssue: Unit = println("oh no")
23-
}
23+
}

tests/warn/unused-params.scala

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//> using options -Wunused:params -Werror
1+
//> using options -Wunused:params
22
//
33

44
import Answers._
@@ -23,7 +23,7 @@ trait BadAPI extends InterFace {
2323
a
2424
}
2525
override def call(a: Int,
26-
b: String, // no warn, required by superclass
26+
b: String, // warn
2727
c: Double): Int = {
2828
println(c)
2929
a
@@ -33,7 +33,7 @@ trait BadAPI extends InterFace {
3333

3434
override def equals(other: Any): Boolean = true // no warn
3535

36-
def i(implicit s: String) = answer // yes, warn
36+
def i(implicit s: String) = answer // warn
3737

3838
/*
3939
def future(x: Int): Int = {
@@ -60,7 +60,7 @@ class Revaluing(u: Int) { def f = u } // no warn
6060

6161
case class CaseyKasem(k: Int) // no warn
6262

63-
case class CaseyAtTheBat(k: Int)(s: String) // warn
63+
case class CaseyAtTheBat(k: Int)(s: String) // NO warn
6464

6565
trait Ignorance {
6666
def f(readResolve: Int) = answer // warn
@@ -78,13 +78,13 @@ trait Unimplementation {
7878

7979
trait DumbStuff {
8080
def f(implicit dummy: DummyImplicit) = answer
81-
def g(dummy: DummyImplicit) = answer
81+
def g(dummy: DummyImplicit) = answer // warn
8282
}
8383
trait Proofs {
8484
def f[A, B](implicit ev: A =:= B) = answer
8585
def g[A, B](implicit ev: A <:< B) = answer
86-
def f2[A, B](ev: A =:= B) = answer
87-
def g2[A, B](ev: A <:< B) = answer
86+
def f2[A, B](ev: A =:= B) = answer // warn
87+
def g2[A, B](ev: A <:< B) = answer // warn
8888
}
8989

9090
trait Anonymous {
@@ -94,19 +94,19 @@ trait Anonymous {
9494

9595
def f2: Int => Int = _ + 1 // no warn placeholder syntax (a fresh name and synthetic parameter)
9696

97-
def g = for (i <- List(1)) yield answer // no warn patvar elaborated as map.(i => 42)
97+
def g = for (i <- List(1)) yield answer // warn // TODO no warn patvar elaborated as map.(i => 42)
9898
}
9999
trait Context[A] { def m(a: A): A = a }
100100
trait Implicits {
101-
def f[A](implicit ctx: Context[A]) = answer
102-
def g[A: Context] = answer
101+
def f[A](implicit ctx: Context[A]) = answer // warn
102+
def g[A: Context] = answer // warn
103103
}
104-
class Bound[A: Context]
104+
class Bound[A: Context] // warn
105105
object Answers {
106106
def answer: Int = 42
107107
}
108108

109-
trait BadMix { _: InterFace =>
109+
trait BadMix { self: InterFace =>
110110
def f(a: Int,
111111
b: String, // warn
112112
c: Double): Int = {
@@ -121,7 +121,7 @@ trait BadMix { _: InterFace =>
121121
a
122122
}
123123
override def call(a: Int,
124-
b: String, // no warn, required by superclass
124+
XXXX: String, // warn no longer excused because required by superclass
125125
c: Double): Int = {
126126
println(c)
127127
a
@@ -131,23 +131,23 @@ trait BadMix { _: InterFace =>
131131

132132
override def equals(other: Any): Boolean = true // no warn
133133

134-
def i(implicit s: String) = answer // yes, warn
134+
def i(implicit s: String) = answer // warn
135135
}
136136

137137
class Unequal {
138-
override def equals(other: Any) = toString.nonEmpty // no warn non-trivial RHS, required by universal method
138+
override def equals(other: Any) = toString.nonEmpty // warn
139139
}
140140

141141
class Seriously {
142142
def f(s: Serializable) = toString.nonEmpty // warn explicit param of marker trait
143143
}
144144

145145
class TryStart(start: String) {
146-
def FINALLY(end: END.type) = start
146+
def FINALLY(end: END.type) = start // no warn for DSL taking a singleton
147147
}
148148

149149
object END
150150

151151
class Nested {
152-
@annotation.unused private def actuallyNotUsed(fresh: Int, stale: Int) = fresh
152+
@annotation.unused private def actuallyNotUsed(fresh: Int, stale: Int) = fresh // no warn if owner is unused
153153
}

tests/warn/unused-privates.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ trait Locals {
9595
}
9696

9797
object Types {
98-
private object Dongo { def f = this } // NO warn
98+
private object Dongo { def f = this } // warn
9999
private class Bar1 // warn
100100
private class Bar2 // no warn
101101
private type Alias1 = String // warn
@@ -105,7 +105,7 @@ object Types {
105105
def f(x: Alias2) = x.length
106106

107107
def l1() = {
108-
object HiObject { def f = this } // NO warn
108+
object HiObject { def f = this } // warn
109109
class Hi { // warn
110110
def f1: Hi = new Hi
111111
def f2(x: Hi) = x

0 commit comments

Comments
 (0)