diff options
38 files changed, 280 insertions, 130 deletions
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 4d236b226d..dae8539c66 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -133,6 +133,7 @@ trait ScalaSettings extends AbsScalaSettings val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.") val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.") + val XgenMixinForwarders = BooleanSetting("-Xgen-mixin-forwarders", "Generate forwarder methods in classes inhering concrete methods from traits.") // XML parsing options object XxmlSettings extends MultiChoiceEnumeration { diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 6c8904f5d0..f781426f1a 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -243,43 +243,51 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { case NoSymbol => val isMemberOfClazz = clazz.info.findMember(member.name, 0, 0L, stableOnly = false).alternatives.contains(member) if (isMemberOfClazz) { - // `member` is a concrete method defined in `mixinClass`, which is a base class of - // `clazz`, and the method is not overridden in `clazz`. A forwarder is needed if: - // - // - A non-trait base class of `clazz` defines a matching method. Example: - // class C {def f: Int}; trait T extends C {def f = 1}; class D extends T - // Even if C.f is abstract, the forwarder in D is needed, otherwise the JVM would - // resolve `D.f` to `C.f`, see jvms-6.5.invokevirtual. - // - // - There exists another concrete, matching method in a parent interface `p` of - // `clazz`, and the `mixinClass` does not itself extend `p`. In this case the - // forwarder is needed to disambiguate. Example: - // trait T1 {def f = 1}; trait T2 extends T1 {override def f = 2}; class C extends T2 - // In C we don't need a forwarder for f because T2 extends T1, so the JVM resolves - // C.f to T2.f non-ambiguously. See jvms-5.4.3.3, "maximally-specific method". - // trait U1 {def f = 1}; trait U2 {self:U1 => override def f = 2}; class D extends U2 - // In D the forwarder is needed, the interfaces U1 and U2 are unrelated at the JVM - // level. - - @tailrec - def existsCompetingMethod(baseClasses: List[Symbol]): Boolean = baseClasses match { - case baseClass :: rest => - if (baseClass ne mixinClass) { - val m = member.overriddenSymbol(baseClass) - val isCompeting = m.exists && { - !m.owner.isTraitOrInterface || - (!m.isDeferred && !mixinClass.isNonBottomSubClass(m.owner)) - } - isCompeting || existsCompetingMethod(rest) - } else existsCompetingMethod(rest) - - case _ => false + def genForwarder(): Unit = { + cloneAndAddMixinMember(mixinClass, member).asInstanceOf[TermSymbol] setAlias member } - if (existsCompetingMethod(clazz.baseClasses)) - cloneAndAddMixinMember(mixinClass, member).asInstanceOf[TermSymbol] setAlias member - else if (!settings.nowarnDefaultJunitMethods && JUnitTestClass.exists && member.hasAnnotation(JUnitTestClass)) - warning(member.pos, "JUnit tests in traits that are compiled as default methods are not executed by JUnit 4. JUnit 5 will fix this issue.") + if (settings.XgenMixinForwarders) genForwarder() + else { + + // `member` is a concrete method defined in `mixinClass`, which is a base class of + // `clazz`, and the method is not overridden in `clazz`. A forwarder is needed if: + // + // - A non-trait base class of `clazz` defines a matching method. Example: + // class C {def f: Int}; trait T extends C {def f = 1}; class D extends T + // Even if C.f is abstract, the forwarder in D is needed, otherwise the JVM would + // resolve `D.f` to `C.f`, see jvms-6.5.invokevirtual. + // + // - There exists another concrete, matching method in a parent interface `p` of + // `clazz`, and the `mixinClass` does not itself extend `p`. In this case the + // forwarder is needed to disambiguate. Example: + // trait T1 {def f = 1}; trait T2 extends T1 {override def f = 2}; class C extends T2 + // In C we don't need a forwarder for f because T2 extends T1, so the JVM resolves + // C.f to T2.f non-ambiguously. See jvms-5.4.3.3, "maximally-specific method". + // trait U1 {def f = 1}; trait U2 {self:U1 => override def f = 2}; class D extends U2 + // In D the forwarder is needed, the interfaces U1 and U2 are unrelated at the JVM + // level. + + @tailrec + def existsCompetingMethod(baseClasses: List[Symbol]): Boolean = baseClasses match { + case baseClass :: rest => + if (baseClass ne mixinClass) { + val m = member.overriddenSymbol(baseClass) + val isCompeting = m.exists && { + !m.owner.isTraitOrInterface || + (!m.isDeferred && !mixinClass.isNonBottomSubClass(m.owner)) + } + isCompeting || existsCompetingMethod(rest) + } else existsCompetingMethod(rest) + + case _ => false + } + + if (existsCompetingMethod(clazz.baseClasses)) + genForwarder() + else if (!settings.nowarnDefaultJunitMethods && JUnitTestClass.exists && member.hasAnnotation(JUnitTestClass)) + warning(member.pos, "JUnit tests in traits that are compiled as default methods are not executed by JUnit 4. JUnit 5 will fix this issue.") + } } case _ => diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 130f2f9aa5..33cf5b9a09 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2437,13 +2437,36 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } } val stats1 = if (isPastTyper) block.stats else - block.stats.flatMap(stat => stat match { + block.stats.flatMap { case vd@ValDef(_, _, _, _) if vd.symbol.isLazy => namer.addDerivedTrees(Typer.this, vd) - case _ => stat::Nil - }) - val stats2 = typedStats(stats1, context.owner) + case stat => stat::Nil + } + val stats2 = typedStats(stats1, context.owner, warnPure = false) val expr1 = typed(block.expr, mode &~ (FUNmode | QUALmode), pt) + + // sanity check block for unintended expr placement + if (!isPastTyper) { + val (count, result0, adapted) = + expr1 match { + case Block(expr :: Nil, Literal(Constant(()))) => (1, expr, true) + case Literal(Constant(())) => (0, EmptyTree, false) + case _ => (1, EmptyTree, false) + } + def checkPure(t: Tree, supple: Boolean): Unit = + if (treeInfo.isPureExprForWarningPurposes(t)) { + val msg = "a pure expression does nothing in statement position" + val parens = if (stats2.length + count > 1) "multiline expressions might require enclosing parentheses" else "" + val discard = if (adapted) "; a value can be silently discarded when Unit is expected" else "" + val text = + if (supple) s"${parens}${discard}" + else if (!parens.isEmpty) s"${msg}; ${parens}" else msg + context.warning(t.pos, text) + } + stats2.foreach(checkPure(_, supple = false)) + if (result0.nonEmpty) checkPure(result0, supple = true) + } + treeCopy.Block(block, stats2, expr1) .setType(if (treeInfo.isExprSafeToInline(block)) expr1.tpe else expr1.tpe.deconst) } finally { @@ -3018,7 +3041,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper case _ => log("unhandled import: "+imp+" in "+unit); imp } - def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { + def typedStats(stats: List[Tree], exprOwner: Symbol, warnPure: Boolean = true): List[Tree] = { val inBlock = exprOwner == context.owner def includesTargetPos(tree: Tree) = tree.pos.isRange && context.unit.exists && (tree.pos includes context.unit.targetPos) @@ -3049,9 +3072,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper ConstructorsOrderError(stat) } } - if (!isPastTyper && treeInfo.isPureExprForWarningPurposes(result)) context.warning(stat.pos, - "a pure expression does nothing in statement position; you may be omitting necessary parentheses" - ) + if (warnPure && !isPastTyper && treeInfo.isPureExprForWarningPurposes(result)) { + val msg = "a pure expression does nothing in statement position" + val clause = if (stats.lengthCompare(1) > 0) "; multiline expressions may require enclosing parentheses" else "" + context.warning(stat.pos, s"${msg}${clause}") + } result } diff --git a/test/files/neg/macro-invalidret.check b/test/files/neg/macro-invalidret.check index ebdc8ec7da..a4d4fc6f34 100644 --- a/test/files/neg/macro-invalidret.check +++ b/test/files/neg/macro-invalidret.check @@ -27,7 +27,7 @@ java.lang.NullPointerException Macros_Test_2.scala:15: error: macro implementation is missing foo4 ^ -Macros_Test_2.scala:17: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +Macros_Test_2.scala:17: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses foo6 ^ two warnings found diff --git a/test/files/neg/scopes.check b/test/files/neg/scopes.check index f8e8c3758a..2db9678185 100644 --- a/test/files/neg/scopes.check +++ b/test/files/neg/scopes.check @@ -7,7 +7,7 @@ scopes.scala:5: error: x is already defined as value x scopes.scala:8: error: y is already defined as value y val y: Float = .0f ^ -scopes.scala:6: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +scopes.scala:6: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses { ^ scopes.scala:11: error: x is already defined as value x diff --git a/test/files/neg/stmt-expr-discard.check b/test/files/neg/stmt-expr-discard.check index 1207e6da50..4a80765365 100644 --- a/test/files/neg/stmt-expr-discard.check +++ b/test/files/neg/stmt-expr-discard.check @@ -1,7 +1,7 @@ -stmt-expr-discard.scala:3: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +stmt-expr-discard.scala:3: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses + 2 ^ -stmt-expr-discard.scala:4: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +stmt-expr-discard.scala:4: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses - 4 ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/neg/t1181.check b/test/files/neg/t1181.check index 13b73d5381..a9c102853d 100644 --- a/test/files/neg/t1181.check +++ b/test/files/neg/t1181.check @@ -1,10 +1,10 @@ -t1181.scala:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - case (Nil, Nil) => map - ^ t1181.scala:9: error: type mismatch; found : scala.collection.immutable.Map[Symbol,Symbol] required: Symbol _ => buildMap(map.updated(keyList.head, valueList.head), keyList.tail, valueList.tail) ^ +t1181.scala:8: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses + case (Nil, Nil) => map + ^ one warning found one error found diff --git a/test/files/neg/t9847.check b/test/files/neg/t9847.check new file mode 100644 index 0000000000..e55109b3ef --- /dev/null +++ b/test/files/neg/t9847.check @@ -0,0 +1,45 @@ +t9847.scala:4: warning: discarded non-Unit value + def f(): Unit = 42 + ^ +t9847.scala:4: warning: a pure expression does nothing in statement position + def f(): Unit = 42 + ^ +t9847.scala:5: warning: discarded non-Unit value + def g = (42: Unit) + ^ +t9847.scala:5: warning: a pure expression does nothing in statement position + def g = (42: Unit) + ^ +t9847.scala:7: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses + 1 + ^ +t9847.scala:12: warning: discarded non-Unit value + + 1 + ^ +t9847.scala:12: warning: a pure expression does nothing in statement position + + 1 + ^ +t9847.scala:11: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses + 1 + ^ +t9847.scala:12: warning: multiline expressions might require enclosing parentheses; a value can be silently discarded when Unit is expected + + 1 + ^ +t9847.scala:16: warning: discarded non-Unit value + x + 1 + ^ +t9847.scala:19: warning: discarded non-Unit value + def j(): Unit = x + 1 + ^ +t9847.scala:21: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses + class C { 42 } + ^ +t9847.scala:22: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses + class D { 42 ; 17 } + ^ +t9847.scala:22: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses + class D { 42 ; 17 } + ^ +error: No warnings can be incurred under -Xfatal-warnings. +14 warnings found +one error found diff --git a/test/files/neg/t9847.flags b/test/files/neg/t9847.flags new file mode 100644 index 0000000000..065e3ca61e --- /dev/null +++ b/test/files/neg/t9847.flags @@ -0,0 +1 @@ +-Xfatal-warnings -Ywarn-value-discard diff --git a/test/files/neg/t9847.scala b/test/files/neg/t9847.scala new file mode 100644 index 0000000000..51c16d815f --- /dev/null +++ b/test/files/neg/t9847.scala @@ -0,0 +1,23 @@ + +trait T { + + def f(): Unit = 42 + def g = (42: Unit) + def h = { + 1 + + 1 + } + def hh(): Unit = { + 1 + + 1 + } + def i(): Unit = { + val x = 1 + x + 1 + } + def x = 42 + def j(): Unit = x + 1 + + class C { 42 } + class D { 42 ; 17 } +} diff --git a/test/files/neg/unit-returns-value.check b/test/files/neg/unit-returns-value.check index f30a506ebe..7ebfbfde29 100644 --- a/test/files/neg/unit-returns-value.check +++ b/test/files/neg/unit-returns-value.check @@ -1,13 +1,13 @@ -unit-returns-value.scala:4: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +unit-returns-value.scala:4: warning: a pure expression does nothing in statement position if (b) return 5 ^ unit-returns-value.scala:4: warning: enclosing method f has result type Unit: return value discarded if (b) return 5 ^ -unit-returns-value.scala:22: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +unit-returns-value.scala:22: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses i1 // warn ^ -unit-returns-value.scala:23: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +unit-returns-value.scala:23: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses i2 // warn ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/files/run/contrib674.check b/test/files/run/contrib674.check index 78325c1810..98c72f34dd 100644 --- a/test/files/run/contrib674.check +++ b/test/files/run/contrib674.check @@ -1,3 +1,6 @@ -contrib674.scala:15: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +contrib674.scala:15: warning: a pure expression does nothing in statement position + 1 + ^ +contrib674.scala:15: warning: multiline expressions might require enclosing parentheses; a value can be silently discarded when Unit is expected 1 ^ diff --git a/test/files/run/contrib674.scala b/test/files/run/contrib674.scala index 45c9871fc4..bb9dad3686 100644 --- a/test/files/run/contrib674.scala +++ b/test/files/run/contrib674.scala @@ -1,7 +1,7 @@ // causes VerifyError with scala-2.5.1 object Test extends App { - def bad() { + def bad(): Unit = { try { 1 } catch { diff --git a/test/files/run/delay-bad.check b/test/files/run/delay-bad.check index fcd05c827f..bf41c79a3a 100644 --- a/test/files/run/delay-bad.check +++ b/test/files/run/delay-bad.check @@ -1,7 +1,7 @@ -delay-bad.scala:53: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +delay-bad.scala:53: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses f(new C { 5 }) ^ -delay-bad.scala:73: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +delay-bad.scala:73: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses f(new { val x = 5 } with E() { 5 }) ^ warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/delay-good.check b/test/files/run/delay-good.check index b4f6b04af7..ed35b9225f 100644 --- a/test/files/run/delay-good.check +++ b/test/files/run/delay-good.check @@ -1,7 +1,7 @@ -delay-good.scala:53: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +delay-good.scala:53: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses f(new C { 5 }) ^ -delay-good.scala:73: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +delay-good.scala:73: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses f(new { val x = 5 } with E() { 5 }) ^ diff --git a/test/files/run/exceptions-2.check b/test/files/run/exceptions-2.check index 4f8244800a..5cf5e71f41 100644 --- a/test/files/run/exceptions-2.check +++ b/test/files/run/exceptions-2.check @@ -1,4 +1,4 @@ -exceptions-2.scala:267: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +exceptions-2.scala:267: warning: a pure expression does nothing in statement position try { 1 } catch { case e: java.io.IOException => () } ^ nested1: diff --git a/test/files/run/lazy-locals.check b/test/files/run/lazy-locals.check index 9e88a55d18..4565326bea 100644 --- a/test/files/run/lazy-locals.check +++ b/test/files/run/lazy-locals.check @@ -1,7 +1,7 @@ -lazy-locals.scala:153: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +lazy-locals.scala:153: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses { ^ -lazy-locals.scala:159: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +lazy-locals.scala:159: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses { ^ forced lazy val q diff --git a/test/files/run/macro-duplicate.check b/test/files/run/macro-duplicate.check index 58781b719a..7006b16611 100644 --- a/test/files/run/macro-duplicate.check +++ b/test/files/run/macro-duplicate.check @@ -1,3 +1,3 @@ -Test_2.scala:5: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +Test_2.scala:5: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses Macros.foo ^ diff --git a/test/files/run/misc.check b/test/files/run/misc.check index 56116f8104..075dfeff2f 100644 --- a/test/files/run/misc.check +++ b/test/files/run/misc.check @@ -1,25 +1,25 @@ -misc.scala:46: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +misc.scala:46: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses 42; ^ -misc.scala:47: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +misc.scala:47: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses 42l; ^ -misc.scala:48: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +misc.scala:48: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses 23.5f; ^ -misc.scala:49: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +misc.scala:49: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses 23.5; ^ -misc.scala:50: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +misc.scala:50: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses "Hello"; ^ -misc.scala:51: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +misc.scala:51: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses 32 + 45; ^ -misc.scala:62: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +misc.scala:62: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses x; ^ -misc.scala:74: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +misc.scala:74: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses 1 < 2; ^ ### Hello diff --git a/test/files/run/names-defaults.check b/test/files/run/names-defaults.check index c358dc5849..722d28dd11 100644 --- a/test/files/run/names-defaults.check +++ b/test/files/run/names-defaults.check @@ -1,4 +1,7 @@ -names-defaults.scala:269: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +names-defaults.scala:269: warning: a pure expression does nothing in statement position + spawn(b = { val ttt = 1; ttt }, a = 0) + ^ +names-defaults.scala:269: warning: multiline expressions might require enclosing parentheses; a value can be silently discarded when Unit is expected spawn(b = { val ttt = 1; ttt }, a = 0) ^ warning: there were four deprecation warnings; re-run with -deprecation for details diff --git a/test/files/run/patmatnew.check b/test/files/run/patmatnew.check index 56b8ac2f4f..117bc28c2d 100644 --- a/test/files/run/patmatnew.check +++ b/test/files/run/patmatnew.check @@ -1,10 +1,16 @@ -patmatnew.scala:351: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +patmatnew.scala:351: warning: a pure expression does nothing in statement position case 1 => "OK" ^ -patmatnew.scala:352: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +patmatnew.scala:352: warning: a pure expression does nothing in statement position case 2 => assert(false); "KO" ^ -patmatnew.scala:353: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +patmatnew.scala:352: warning: multiline expressions might require enclosing parentheses; a value can be silently discarded when Unit is expected + case 2 => assert(false); "KO" + ^ +patmatnew.scala:353: warning: a pure expression does nothing in statement position + case 3 => assert(false); "KO" + ^ +patmatnew.scala:353: warning: multiline expressions might require enclosing parentheses; a value can be silently discarded when Unit is expected case 3 => assert(false); "KO" ^ patmatnew.scala:670: warning: This catches all Throwables. If this is really intended, use `case e : Throwable` to clear this warning. diff --git a/test/files/run/reify_lazyunit.check b/test/files/run/reify_lazyunit.check index 579ecfe8aa..e6acf5d17b 100644 --- a/test/files/run/reify_lazyunit.check +++ b/test/files/run/reify_lazyunit.check @@ -1,4 +1,4 @@ -reify_lazyunit.scala:6: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +reify_lazyunit.scala:6: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses lazy val x = { 0; println("12")} ^ 12 diff --git a/test/files/run/repl-bare-expr.check b/test/files/run/repl-bare-expr.check index e0a1f4ecd6..bdf8842bb0 100644 --- a/test/files/run/repl-bare-expr.check +++ b/test/files/run/repl-bare-expr.check @@ -1,12 +1,12 @@ scala> 2 ; 3 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 2 ;; ^ res0: Int = 3 scala> { 2 ; 3 } -<console>:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:12: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses { 2 ; 3 } ^ res1: Int = 3 @@ -15,16 +15,16 @@ scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Mooo 1 + 2 + 3 } ; bippy+88+11 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ defined object Cow diff --git a/test/files/run/repl-no-imports-no-predef.check b/test/files/run/repl-no-imports-no-predef.check index c2c8d21c0a..7c4ee82c78 100644 --- a/test/files/run/repl-no-imports-no-predef.check +++ b/test/files/run/repl-no-imports-no-predef.check @@ -76,13 +76,13 @@ y: Int = 13 scala> scala> 2 ; 3 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 2 ;; ^ res14: Int = 3 scala> { 2 ; 3 } -<console>:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:12: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses { 2 ; 3 } ^ res15: Int = 3 @@ -92,16 +92,16 @@ bippy = { 1 + 2 + 3 } ; bippy+88+11 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def ^ defined object Cow @@ -143,10 +143,10 @@ scala> ( (2 + 2 ) ) res24: Int = 4 scala> 5 ; ( (2 + 2 ) ) ; ((5)) -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; ( (2 + 2 ) ) ;; ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; ( (2 + 2 ) ) ;; ^ res25: Int = 5 @@ -163,16 +163,16 @@ res28: String = 4423 scala> scala> 55 ; ((2 + 2)) ; (1, 2, 3) -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; ((2 + 2)) ;; ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; ((2 + 2)) ;; ^ res29: (Int, Int, Int) = (1,2,3) scala> 55 ; (x: scala.Int) => x + 1 ; () => ((5)) -<console>:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:12: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; (x: scala.Int) => x + 1 ;; ^ res30: () => Int = <function0> @@ -183,7 +183,7 @@ scala> () => 5 res31: () => Int = <function0> scala> 55 ; () => 5 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ;; ^ res32: () => Int = <function0> diff --git a/test/files/run/repl-parens.check b/test/files/run/repl-parens.check index 6516f4ea90..477d4d462f 100644 --- a/test/files/run/repl-parens.check +++ b/test/files/run/repl-parens.check @@ -18,10 +18,10 @@ scala> ( (2 + 2 ) ) res5: Int = 4 scala> 5 ; ( (2 + 2 ) ) ; ((5)) -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; ( (2 + 2 ) ) ;; ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; ( (2 + 2 ) ) ;; ^ res6: Int = 5 @@ -38,16 +38,16 @@ res9: String = 4423 scala> scala> 55 ; ((2 + 2)) ; (1, 2, 3) -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; ((2 + 2)) ;; ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; ((2 + 2)) ;; ^ res10: (Int, Int, Int) = (1,2,3) scala> 55 ; (x: Int) => x + 1 ; () => ((5)) -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; (x: Int) => x + 1 ;; ^ res11: () => Int = <function0> @@ -58,7 +58,7 @@ scala> () => 5 res12: () => Int = <function0> scala> 55 ; () => 5 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ;; ^ res13: () => Int = <function0> diff --git a/test/files/run/t3488.check b/test/files/run/t3488.check index 314dfc7838..75b2c3b07f 100644 --- a/test/files/run/t3488.check +++ b/test/files/run/t3488.check @@ -1,7 +1,13 @@ -t3488.scala:4: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t3488.scala:4: warning: a pure expression does nothing in statement position println(foo { val List(_*)=List(0); 1 } ()) ^ -t3488.scala:5: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t3488.scala:4: warning: multiline expressions might require enclosing parentheses; a value can be silently discarded when Unit is expected + println(foo { val List(_*)=List(0); 1 } ()) + ^ +t3488.scala:5: warning: a pure expression does nothing in statement position + println(foo { val List(_*)=List(0); 1 } (1)) + ^ +t3488.scala:5: warning: multiline expressions might require enclosing parentheses; a value can be silently discarded when Unit is expected println(foo { val List(_*)=List(0); 1 } (1)) ^ 0 diff --git a/test/files/run/t4047.check b/test/files/run/t4047.check index 3c41e6e244..c31f2f0858 100644 --- a/test/files/run/t4047.check +++ b/test/files/run/t4047.check @@ -1,13 +1,13 @@ -t4047.scala:23: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t4047.scala:23: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses a.foo ^ -t4047.scala:24: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t4047.scala:24: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses a.foo ^ -t4047.scala:26: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t4047.scala:26: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses b.foo ^ -t4047.scala:27: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t4047.scala:27: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses b.foo ^ Unit: called A.foo diff --git a/test/files/run/t4680.check b/test/files/run/t4680.check index 21c5f9e567..749ce4c627 100644 --- a/test/files/run/t4680.check +++ b/test/files/run/t4680.check @@ -1,7 +1,7 @@ -t4680.scala:51: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t4680.scala:51: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses new C { 5 } ^ -t4680.scala:69: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t4680.scala:69: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses new { val x = 5 } with E() { 5 } ^ warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details diff --git a/test/files/run/t5380.check b/test/files/run/t5380.check index 731a798301..19471ac2d2 100644 --- a/test/files/run/t5380.check +++ b/test/files/run/t5380.check @@ -1,7 +1,7 @@ -t5380.scala:3: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t5380.scala:3: warning: a pure expression does nothing in statement position val f = () => return try { 1 } catch { case _: Throwable => 0 } ^ -t5380.scala:3: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t5380.scala:3: warning: a pure expression does nothing in statement position val f = () => return try { 1 } catch { case _: Throwable => 0 } ^ t5380.scala:3: warning: enclosing method main has result type Unit: return value discarded diff --git a/test/files/run/t7047.check b/test/files/run/t7047.check index 32bd581094..129ce3eeca 100644 --- a/test/files/run/t7047.check +++ b/test/files/run/t7047.check @@ -1,3 +1,3 @@ -Test_2.scala:2: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +Test_2.scala:2: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses Macros.foo ^ diff --git a/test/files/run/t7747-repl.check b/test/files/run/t7747-repl.check index c5e92e9d79..621a70205e 100644 --- a/test/files/run/t7747-repl.check +++ b/test/files/run/t7747-repl.check @@ -15,13 +15,13 @@ scala> val z = x * y z: Int = 156 scala> 2 ; 3 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 2 ;; ^ res0: Int = 3 scala> { 2 ; 3 } -<console>:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:12: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses { 2 ; 3 } ^ res1: Int = 3 @@ -30,16 +30,16 @@ scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Mooo 1 + 2 + 3 } ; bippy+88+11 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ defined object Cow @@ -81,10 +81,10 @@ scala> ( (2 + 2 ) ) res10: Int = 4 scala> 5 ; ( (2 + 2 ) ) ; ((5)) -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; ( (2 + 2 ) ) ;; ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 5 ; ( (2 + 2 ) ) ;; ^ res11: Int = 5 @@ -101,16 +101,16 @@ res14: String = 4423 scala> scala> 55 ; ((2 + 2)) ; (1, 2, 3) -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; ((2 + 2)) ;; ^ -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; ((2 + 2)) ;; ^ res15: (Int, Int, Int) = (1,2,3) scala> 55 ; (x: Int) => x + 1 ; () => ((5)) -<console>:13: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:13: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ; (x: Int) => x + 1 ;; ^ res16: () => Int = <function0> @@ -121,7 +121,7 @@ scala> () => 5 res17: () => Int = <function0> scala> 55 ; () => 5 -<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +<console>:11: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses 55 ;; ^ res18: () => Int = <function0> diff --git a/test/files/run/t8196.check b/test/files/run/t8196.check index d11dc27e68..8a07ebb6d7 100644 --- a/test/files/run/t8196.check +++ b/test/files/run/t8196.check @@ -1,4 +1,4 @@ -t8196.scala:26: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +t8196.scala:26: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses form2.g1 // comment this line in order to make the test pass ^ warning: there were two feature warnings; re-run with -feature for details diff --git a/test/files/run/try-2.check b/test/files/run/try-2.check index 987d3462df..7fd45414da 100644 --- a/test/files/run/try-2.check +++ b/test/files/run/try-2.check @@ -1,4 +1,4 @@ -try-2.scala:41: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +try-2.scala:41: warning: a pure expression does nothing in statement position 10; ^ exception happened diff --git a/test/files/run/try.check b/test/files/run/try.check index f742ccb0df..d9521c2362 100644 --- a/test/files/run/try.check +++ b/test/files/run/try.check @@ -1,4 +1,4 @@ -try.scala:65: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +try.scala:65: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses 1+1; ^ 1 + 1 = 2 diff --git a/test/files/specialized/tb3651.check b/test/files/specialized/tb3651.check index 8a3f686ef5..8e104f13ff 100644 --- a/test/files/specialized/tb3651.check +++ b/test/files/specialized/tb3651.check @@ -1,4 +1,4 @@ -tb3651.scala:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +tb3651.scala:8: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses lk.a ^ 0 diff --git a/test/files/specialized/tc3651.check b/test/files/specialized/tc3651.check index e2dbadf22c..1e56d196fd 100644 --- a/test/files/specialized/tc3651.check +++ b/test/files/specialized/tc3651.check @@ -1,4 +1,4 @@ -tc3651.scala:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +tc3651.scala:12: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses lk.a ^ 0 diff --git a/test/files/specialized/td3651.check b/test/files/specialized/td3651.check index 1a709fd0a7..697443ffe9 100644 --- a/test/files/specialized/td3651.check +++ b/test/files/specialized/td3651.check @@ -1,7 +1,7 @@ -td3651.scala:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +td3651.scala:12: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses b.a ^ -td3651.scala:16: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +td3651.scala:16: warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses der.a ^ 0 diff --git a/test/junit/scala/lang/traits/BytecodeTest.scala b/test/junit/scala/lang/traits/BytecodeTest.scala index ec8508df99..e6c74b86ab 100644 --- a/test/junit/scala/lang/traits/BytecodeTest.scala +++ b/test/junit/scala/lang/traits/BytecodeTest.scala @@ -230,6 +230,35 @@ class BytecodeTest extends BytecodeTesting { List(ALOAD, ILOAD, PUTFIELD, ALOAD, ACONST_NULL, "<init>", RETURN)) } + @Test + def mixinForwarders(): Unit = { + val code = + """trait T { def f = 1 } + |class C extends T + """.stripMargin + val List(c1, _) = compileClasses(code) + val List(c2, _) = newCompiler(extraArgs = "-Xgen-mixin-forwarders").compileClasses(code) + assert(getMethods(c1, "f").isEmpty) + assertSameCode(getMethod(c2, "f"), + List(VarOp(ALOAD, 0), Invoke(INVOKESTATIC, "T", "f$", "(LT;)I", true), Op(IRETURN))) + } + + @Test + def sd143(): Unit = { + // this tests the status quo, which is wrong. + val code = + """class A { def m = 1 } + |class B extends A { override def m = 2 } + |trait T extends A + |class C extends B with T { + | override def m = super[T].m // should invoke A.m + |} + """.stripMargin + val List(_, _, c, _) = compileClasses(code) + // even though the bytecode refers to A.m, invokespecial will resolve to B.m + assertSameCode(getMethod(c, "m"), + List(VarOp(ALOAD, 0), Invoke(INVOKESPECIAL, "A", "m", "()I", false), Op(IRETURN))) + } } object invocationReceiversTestCode { |