Skip to content

Commit 882cb84

Browse files
committed
Don't ignore params of public methods
1 parent 1d4db7f commit 882cb84

File tree

6 files changed

+212
-15
lines changed

6 files changed

+212
-15
lines changed

Diff for: compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

+3-4
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ class CheckUnused private (phaseMode: CheckUnused.PhaseMode, suffix: String, _ke
145145
override def prepareForDefDef(tree: DefDef)(using Context): Context =
146146
preparing:
147147
ud.registerTrivial(tree)
148-
if !tree.symbol.is(Private) then
149-
tree.termParamss.flatten.foreach(p => ud.addIgnoredParam(p.symbol))
150148
ud.addIgnoredUsage(tree.symbol)
151149

152150
override def transformDefDef(tree: DefDef)(using Context): tree.type =
@@ -571,10 +569,11 @@ object CheckUnused:
571569
private def isConstructorOfSynth(sym: Symbol)(using Context): Boolean =
572570
sym.exists && sym.isConstructor && sym.owner.isPackageObject && sym.owner.is(Synthetic)
573571

574-
/** This is used to avoid reporting the parameters of the synthetic main method generated by `@main`.
572+
/** Avoid reporting unused parameter in required main method signature.
573+
* The method may be user-written or generated by `@main`.
575574
*/
576575
private def isSyntheticMainParam(sym: Symbol)(using Context): Boolean =
577-
sym.exists && ctx.platform.isMainMethod(sym.owner) && sym.owner.is(Synthetic)
576+
sym.exists && ctx.platform.isMainMethod(sym.owner) //&& sym.owner.is(Synthetic)
578577

579578
/** If -Wunused:strict-no-implicit-warn import and this import selector could potentially import implicit.
580579
*/

Diff for: tests/warn/i15503e.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//> using options -Wunused:explicits
1+
//> using options -Wunused:explicits
22

33
object Foo {
44
/* This goes around the "trivial method" detection */
@@ -31,7 +31,7 @@ package scala3main:
3131
package foo.test.lambda.param:
3232
val default_val = 1
3333
val a = (i: Int) => i // OK
34-
val b = (i: Int) => default_val // OK
34+
val b = (i: Int) => default_val // warn
3535
val c = (_: Int) => default_val // OK
3636

3737
package foo.test.trivial:
@@ -67,4 +67,4 @@ package foo.test.i16865:
6767
def fn(a: Int, b: Int): Int = b + 3 // OK
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 // OK

Diff for: tests/warn/i15503h.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//> using options -Wunused:linted
1+
//> using options -Wunused:linted
22

33
import collection.mutable.Set // warn
44

@@ -7,14 +7,14 @@ class A {
77
val b = 2 // OK
88

99
private def c = 2 // warn
10-
def d(using x:Int): Int = b // ok
10+
def d(using x: Int): Int = b // warn
1111
def e(x: Int) = 1 // OK
1212
def f =
1313
val x = 1 // warn
1414
def f = 2 // warn
1515
3
1616

1717
def g(x: Int): Int = x match
18-
case x:1 => 0 // OK
18+
case x: 1 => 0 // OK
1919
case _ => 1
20-
}
20+
}

Diff for: tests/warn/i15503i.scala

+6-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ class A {
1717
private def c2 = 2 // OK
1818
def c3 = c2
1919

20-
def d1(using x:Int): Int = default_int // ok
21-
def d2(using x:Int): Int = x // OK
20+
def d1(using x: Int): Int = default_int // warn param
21+
def d2(using x: Int): Int = x // OK
22+
def d3(using Int): Int = summon[Int] // OK
23+
def d4(using Int): Int = default_int // warn
2224

23-
def e1(x: Int) = default_int // ok
25+
def e1(x: Int) = default_int // warn param
2426
def e2(x: Int) = x // OK
2527
def f =
2628
val x = 1 // warn
@@ -44,7 +46,7 @@ package foo.test.scala.annotation:
4446
val default_int = 12
4547

4648
def a1(a: Int) = a // OK
47-
def a2(a: Int) = default_int // ok
49+
def a2(a: Int) = default_int // warn
4850

4951
def a3(@unused a: Int) = default_int //OK
5052

Diff for: tests/warn/unused-locals.scala

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//> using options -Wunused:locals
2+
3+
class Outer {
4+
class Inner
5+
}
6+
7+
trait Locals {
8+
def f0 = {
9+
var x = 1 // warn
10+
var y = 2 // no warn
11+
y = 3
12+
y + y
13+
}
14+
def f1 = {
15+
val a = new Outer // no warn
16+
val b = new Outer // warn
17+
new a.Inner
18+
}
19+
def f2 = {
20+
var x = 100 // warn about it being a var
21+
x
22+
}
23+
}
24+
25+
object Types {
26+
def l1() = {
27+
object HiObject { def f = this } // warn
28+
class Hi { // warn
29+
def f1: Hi = new Hi
30+
def f2(x: Hi) = x
31+
}
32+
class DingDongDoobie // warn
33+
class Bippy // no warn
34+
type Something = Bippy // no warn
35+
type OtherThing = String // warn
36+
(new Bippy): Something
37+
}
38+
}
39+
40+
// breakage: local val x$1 in method skolemize is never used
41+
case class SymbolKind(accurate: String, sanitized: String, abbreviation: String) {
42+
def skolemize: SymbolKind = copy(accurate = s"$accurate skolem", abbreviation = s"$abbreviation#SKO")
43+
}

Diff for: tests/warn/unused-params.scala

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
//> using options -Wunused:params -Werror
2+
//
3+
4+
import Answers._
5+
6+
trait InterFace {
7+
/** Call something. */
8+
def call(a: Int, b: String, c: Double): Int
9+
}
10+
11+
trait BadAPI extends InterFace {
12+
def f(a: Int,
13+
b: String, // warn
14+
c: Double): Int = {
15+
println(c)
16+
a
17+
}
18+
@deprecated("no warn in deprecated API", since="yesterday")
19+
def g(a: Int,
20+
b: String, // no warn
21+
c: Double): Int = {
22+
println(c)
23+
a
24+
}
25+
override def call(a: Int,
26+
b: String, // no warn, required by superclass
27+
c: Double): Int = {
28+
println(c)
29+
a
30+
}
31+
32+
def meth(x: Int) = x
33+
34+
override def equals(other: Any): Boolean = true // no warn
35+
36+
def i(implicit s: String) = answer // yes, warn
37+
38+
/*
39+
def future(x: Int): Int = {
40+
val y = 42
41+
val x = y // maybe option to warn only if shadowed
42+
x
43+
}
44+
*/
45+
}
46+
47+
// mustn't alter warnings in super
48+
trait PoorClient extends BadAPI {
49+
override def meth(x: Int) = ??? // no warn
50+
override def f(a: Int, b: String, c: Double): Int = a + b.toInt + c.toInt
51+
}
52+
53+
class Unusing(u: Int) { // warn
54+
def f = ???
55+
}
56+
57+
class Valuing(val u: Int) // no warn
58+
59+
class Revaluing(u: Int) { def f = u } // no warn
60+
61+
case class CaseyKasem(k: Int) // no warn
62+
63+
case class CaseyAtTheBat(k: Int)(s: String) // warn
64+
65+
trait Ignorance {
66+
def f(readResolve: Int) = answer // warn
67+
}
68+
69+
class Reusing(u: Int) extends Unusing(u) // no warn
70+
71+
class Main {
72+
def main(args: Array[String]): Unit = println("hello, args") // no warn
73+
}
74+
75+
trait Unimplementation {
76+
def f(u: Int): Int = ??? // no warn for param in unimplementation
77+
}
78+
79+
trait DumbStuff {
80+
def f(implicit dummy: DummyImplicit) = answer
81+
def g(dummy: DummyImplicit) = answer
82+
}
83+
trait Proofs {
84+
def f[A, B](implicit ev: A =:= B) = answer
85+
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
88+
}
89+
90+
trait Anonymous {
91+
def f = (i: Int) => answer // warn
92+
93+
def f1 = (_: Int) => answer // no warn underscore parameter (a fresh name)
94+
95+
def f2: Int => Int = _ + 1 // no warn placeholder syntax (a fresh name and synthetic parameter)
96+
97+
def g = for (i <- List(1)) yield answer // no warn patvar elaborated as map.(i => 42)
98+
}
99+
trait Context[A] { def m(a: A): A = a }
100+
trait Implicits {
101+
def f[A](implicit ctx: Context[A]) = answer
102+
def g[A: Context] = answer
103+
}
104+
class Bound[A: Context]
105+
object Answers {
106+
def answer: Int = 42
107+
}
108+
109+
trait BadMix { _: InterFace =>
110+
def f(a: Int,
111+
b: String, // warn
112+
c: Double): Int = {
113+
println(c)
114+
a
115+
}
116+
@deprecated("no warn in deprecated API", since="yesterday")
117+
def g(a: Int,
118+
b: String, // no warn
119+
c: Double): Int = {
120+
println(c)
121+
a
122+
}
123+
override def call(a: Int,
124+
b: String, // no warn, required by superclass
125+
c: Double): Int = {
126+
println(c)
127+
a
128+
}
129+
130+
def meth(x: Int) = x
131+
132+
override def equals(other: Any): Boolean = true // no warn
133+
134+
def i(implicit s: String) = answer // yes, warn
135+
}
136+
137+
class Unequal {
138+
override def equals(other: Any) = toString.nonEmpty // no warn non-trivial RHS, required by universal method
139+
}
140+
141+
class Seriously {
142+
def f(s: Serializable) = toString.nonEmpty // warn explicit param of marker trait
143+
}
144+
145+
class TryStart(start: String) {
146+
def FINALLY(end: END.type) = start
147+
}
148+
149+
object END
150+
151+
class Nested {
152+
@annotation.unused private def actuallyNotUsed(fresh: Int, stale: Int) = fresh
153+
}

0 commit comments

Comments
 (0)