Skip to content

Commit

Permalink
Check only stable qual for import prefix (#22633)
Browse files Browse the repository at this point in the history
Selection from a tree with synthetic span looks like a rewrite from
imported symbol, but only check that if the qualifier is stable.

In the example, it was an implicit class (`EitherOps`), which in turn
induced many costly, unnecessary type comparisons.

Fixes #22629
  • Loading branch information
sjrd authored Feb 25, 2025
2 parents b2b0115 + 5429dfa commit 7995e9b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
val target = res.dealias.typeSymbol
resolveUsage(target, target.name, res.importPrefix.skipPackageObject) // case _: T =>
case _ =>
else if tree.qualifier.srcPos.isSynthetic || name.exists(_ != tree.symbol.name) then
else if tree.qualifier.srcPos.isSynthetic && tree.qualifier.tpe.isStable || name.exists(_ != tree.symbol.name) then
if !ignoreTree(tree) then
resolveUsage(tree.symbol, name, tree.qualifier.tpe)
else
Expand Down
42 changes: 42 additions & 0 deletions tests/warn/i22629.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//> using options -Wunused:all -Yno-deep-subtypes "-Wconf:msg=set repeatedly:s"

//import either.*

trait ResultMapper[A] {
final def map[B](f: A => B): ResultMapper[B] = ???

infix final def and[B](other: ResultMapper[B]): ResultMapper[(A, B)] = ???
}

trait BoilerplateResultMappers {

def and[B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W](
b: ResultMapper[B], c: ResultMapper[C], d: ResultMapper[D], e: ResultMapper[E], f: ResultMapper[F], g: ResultMapper[G], h: ResultMapper[H], i: ResultMapper[I], j: ResultMapper[J], k: ResultMapper[K], l: ResultMapper[L], m: ResultMapper[M], n: ResultMapper[N], o: ResultMapper[O], p: ResultMapper[P], q: ResultMapper[Q], r: ResultMapper[R], s: ResultMapper[S], t: ResultMapper[T], u: ResultMapper[U], v: ResultMapper[V], w: ResultMapper[W]
): ResultMapper[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W)] =
(b and c and d and e and f and g and h and i and j and k and l and m and n and o and p and q and r and s and t and u and v and w).map {
case ((((((((((((((((((((((b), c), d), e), f), g), h), i), j), k), l), m), n), o), p), q), r), s), t), u), v), w) =>
(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w)
}
}

/*
object either {
type ResultMapperException = RuntimeException
implicit class EitherOps[A](private val ea: Either[ResultMapperException, A]) extends AnyVal {
def and[B](eb: Either[ResultMapperException, B]): Either[ResultMapperException, (A, B)] =
(ea, eb) match {
case (Right(a), Right(b)) =>
Right((a, b))
case (Right(_), Left(ex)) =>
Left(ex)
case (Left(ex), Right(_)) =>
Left(ex)
case (Left(_), Left(_)) =>
Left(RuntimeException())
}
}
}
*/

0 comments on commit 7995e9b

Please sign in to comment.