Skip to content

Commit 3bfb683

Browse files
committed
A warning for recursive calls that use defaults
Unfortunately it's a bit noisy, as this isn't always a bug.
1 parent d55f9c1 commit 3bfb683

File tree

5 files changed

+76
-1
lines changed

5 files changed

+76
-1
lines changed

src/compiler/scala/tools/nsc/settings/Warnings.scala

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ trait Warnings {
5555
val warnNullaryOverride = BooleanSetting ("-Ywarn-nullary-override",
5656
"Warn when non-nullary overrides nullary, e.g. `def foo()` over `def foo`.")
5757
val warnInferAny = BooleanSetting ("-Ywarn-infer-any", "Warn when a type argument is inferred to be `Any`.")
58+
val warnDefaultedRecurse = BooleanSetting ("-Ywarn-default-recursion", "Warn when a recursive method call relies on a default argument")
5859

5960
// Backward compatibility.
6061
def Xwarnfatal = fatalWarnings

src/compiler/scala/tools/nsc/typechecker/Typers.scala

+7-1
Original file line numberDiff line numberDiff line change
@@ -3071,7 +3071,13 @@ trait Typers extends Modes with Adaptations with Tags {
30713071
// useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]()
30723072
val note = "Error occurred in an application involving default arguments."
30733073
if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic
3074-
doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
3074+
val resultTree = doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
3075+
3076+
if (settings.warnDefaultedRecurse.value && !resultTree.isErroneous && (context.owner.ownerChain contains fun.symbol))
3077+
3078+
unit.warning(tree.pos, s"recursive call relies on defaults for some parameters")
3079+
3080+
resultTree
30753081
} else {
30763082
tryTupleApply getOrElse duplErrorTree(NotEnoughArgsError(tree, fun, missing))
30773083
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
recursive-method-default.scala:4: warning: recursive call relies on defaults for some parameters
2+
rec1(0) // warn
3+
^
4+
recursive-method-default.scala:9: warning: recursive call relies on defaults for some parameters
5+
rec2(0) // warn
6+
^
7+
recursive-method-default.scala:12: warning: recursive call relies on defaults for some parameters
8+
rec2(0) // warn
9+
^
10+
recursive-method-default.scala:15: warning: recursive call relies on defaults for some parameters
11+
rec2(0) // warn
12+
^
13+
recursive-method-default.scala:26: warning: recursive call relies on defaults for some parameters
14+
rec4(0)() // warn
15+
^
16+
recursive-method-default.scala:30: warning: recursive call relies on defaults for some parameters
17+
rec5(0)() // warn
18+
^
19+
recursive-method-default.scala:34: warning: recursive call relies on defaults for some parameters
20+
rec6()(0) // warn
21+
^
22+
recursive-method-default.scala:38: warning: recursive call relies on defaults for some parameters
23+
rec7()(0) // one warning only
24+
^
25+
error: No warnings can be incurred under -Xfatal-warnings.
26+
8 warnings found
27+
one error found
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Ywarn-default-recursion -Xfatal-warnings
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
object Test {
2+
def rec1(a: Any, b: Any = "".reverse): Any = {
3+
rec1(0, 0) // okay
4+
rec1(0) // warn
5+
}
6+
7+
def rec2(a: Any, b: Any = "".reverse): Any = {
8+
def nested {
9+
rec2(0) // warn
10+
}
11+
object X {
12+
rec2(0) // warn
13+
}
14+
class X {
15+
rec2(0) // warn
16+
}
17+
}
18+
19+
20+
def rec3(a: Any) {}
21+
def rec3(a: Any, b: Any = "".reverse): Any = {
22+
rec3(0) // okay
23+
}
24+
25+
def rec4(a: Any)(b: Any = "".reverse): Any = {
26+
rec4(0)() // warn
27+
}
28+
29+
def rec5(a: Any)(b: Any = 0): Any = {
30+
rec5(0)() // warn
31+
}
32+
33+
def rec6(a: Any = 0)(b: Any = 0): Any = {
34+
rec6()(0) // warn
35+
}
36+
37+
def rec7(a: Any = 0)(b: Any = 0): Any = {
38+
rec7()(0) // one warning only
39+
}
40+
}

0 commit comments

Comments
 (0)