scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
230 stars 21 forks source link

False positive on unused implicit parameter from trait #12876

Closed ashleymercer closed 9 months ago

ashleymercer commented 9 months ago

Reproduction steps

Scala version: 2.13.12

import scala.concurrent.*

trait Foo {

  def fooExplicit(i: Int): Int
  def fooImplicit(implicit i: Int): Int
  def fooImplicit2()(implicit i: Int): Int

  def barExplicit(ec: ExecutionContext): Future[Int]
  def barImplicit(implicit ec: ExecutionContext): Future[Int]
  def barImplicit2()(implicit ec: ExecutionContext): Future[Int]
}

class FooImpl extends Foo {

  override def fooExplicit(i: Int): Int = i
  override def fooImplicit(implicit i: Int): Int = i
  override def fooImplicit2()(implicit i: Int): Int = i

  override def barExplicit(ec: ExecutionContext): Future[Int] = Future(42)(ec)
  override def barImplicit(implicit ec: ExecutionContext): Future[Int] = Future(42)
  override def barImplicit2()(implicit ec: ExecutionContext): Future[Int] = Future(42)
}

class FooMock extends Foo {

  override def fooExplicit(i: Int): Int = 42
  override def fooImplicit(implicit i: Int): Int = 42
  override def fooImplicit2()(implicit i: Int): Int = 42

  override def barExplicit(ec: ExecutionContext): Future[Int] = Future.successful(42)
  override def barImplicit(implicit ec: ExecutionContext): Future[Int] = Future.successful(42)
  override def barImplicit2()(implicit ec: ExecutionContext): Future[Int] = Future.successful(42)
}

Problem

Under scala 2.13.10 the above compiles just fine without any warnings at all.

Under scala 2.13.12 it gives a (false?) positive for unused parameter only on FooMock.barImplicit2 - all other cases correctly compile without warnings.

ashleymercer commented 9 months ago

Reproduced in scastie here, can confirm this behaviour by switching between Scala 2.13.10 and 2.13.12 in the Build Settings.

EDIT: looks like it compiles fine under 2.13.11 as well, so the regression is fairly recent. I've seen some other tickets in both Scala 2 and 3 around changes to the heuristics for detecting unused parameters, wonder if something has crept in unintended?

som-snytt commented 9 months ago

The unused implicit is supposed to go unreported because the parameter is required by the signature of the overridden method.

(Explaining to myself before I forget.)

I confirmed that it warns without -Xsource:3. -Wunused:implicits is the switch.

The Int-typed parameter will also warn if the RHS is not deemed a trivial placeholder:

override def fooImplicit2()(implicit i: Int): Int = 42 max -1

I intend to contribute a flag to make those "heuristics" opt-in, since they are deceptive; perhaps the warnings also need a verbose flag to report when warnings are intentionally suppressed.

ashleymercer commented 9 months ago

Awesome! Thanks so much for the quick response on this :)