diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 13 | ||||
-rw-r--r-- | test/files/neg/override.check | 2 | ||||
-rwxr-xr-x | test/files/neg/override.scala | 2 | ||||
-rw-r--r-- | test/files/neg/t6276.check | 13 | ||||
-rw-r--r-- | test/files/neg/t6276.flags | 1 | ||||
-rw-r--r-- | test/files/neg/t6276.scala | 29 |
6 files changed, 58 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 166bb2d18c..dd4f13fd7b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1197,6 +1197,18 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R case _ => } + // SI-6276 warn for `def foo = foo` or `val bar: X = bar`, which come up more frequently than you might think. + def checkInfiniteLoop(valOrDef: ValOrDefDef) { + val trivialInifiniteLoop = ( + !valOrDef.isErroneous + && !valOrDef.symbol.isValueParameter + && valOrDef.symbol.paramss.isEmpty + && valOrDef.rhs.hasSymbolWhich(_.accessedOrSelf == valOrDef.symbol) + ) + if (trivialInifiniteLoop) + unit.warning(valOrDef.rhs.pos, s"${valOrDef.symbol.fullLocationString} does nothing other than call itself recursively") + } + // Transformation ------------------------------------------------------------ /* Convert a reference to a case factory of type `tpe` to a new of the class it produces. */ @@ -1640,6 +1652,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R case ValDef(_, _, _, _) | DefDef(_, _, _, _, _, _) => checkDeprecatedOvers(tree) + checkInfiniteLoop(tree.asInstanceOf[ValOrDefDef]) if (settings.warnNullaryUnit.value) checkNullaryMethodReturnType(sym) if (settings.warnInaccessible.value) { diff --git a/test/files/neg/override.check b/test/files/neg/override.check index fc152cb3b1..8be98bf4d0 100644 --- a/test/files/neg/override.check +++ b/test/files/neg/override.check @@ -1,5 +1,5 @@ override.scala:9: error: overriding type T in trait A with bounds >: Int <: Int; type T in trait B with bounds >: String <: String has incompatible type - lazy val x : A with B = x + lazy val x : A with B = {println(""); x} ^ one error found diff --git a/test/files/neg/override.scala b/test/files/neg/override.scala index 3e589b52e3..7975516061 100755 --- a/test/files/neg/override.scala +++ b/test/files/neg/override.scala @@ -6,7 +6,7 @@ trait X { trait Y extends X { trait B { type T >: String <: String } - lazy val x : A with B = x + lazy val x : A with B = {println(""); x} n = "foo" } diff --git a/test/files/neg/t6276.check b/test/files/neg/t6276.check new file mode 100644 index 0000000000..8bd92cf293 --- /dev/null +++ b/test/files/neg/t6276.check @@ -0,0 +1,13 @@ +t6276.scala:4: error: method a does nothing other than call itself recursively + def a: Any = a // warn + ^ +t6276.scala:5: error: value b does nothing other than call itself recursively + val b: Any = b // warn + ^ +t6276.scala:10: error: method a does nothing other than call itself recursively + def a: Any = a // warn + ^ +t6276.scala:19: error: method a does nothing other than call itself recursively + def a = a // warn + ^ +four errors found diff --git a/test/files/neg/t6276.flags b/test/files/neg/t6276.flags new file mode 100644 index 0000000000..85d8eb2ba2 --- /dev/null +++ b/test/files/neg/t6276.flags @@ -0,0 +1 @@ +-Xfatal-warnings diff --git a/test/files/neg/t6276.scala b/test/files/neg/t6276.scala new file mode 100644 index 0000000000..8333618964 --- /dev/null +++ b/test/files/neg/t6276.scala @@ -0,0 +1,29 @@ +object Test { + def foo(a: Int, b: Int, c: Int) { + new { + def a: Any = a // warn + val b: Any = b // warn + } + + def method { + // method local + def a: Any = a // warn + } + + trait T { + def a: Any + } + + new T { + // inherited return type + def a = a // warn + } + + // no warnings below + new { + def a: Any = {println(""); a} + val b: Any = {println(""); b} + def c(i: Int): Any = c(i - 0) + } + } +} |