Skip to content

Commit 3bbd9e3

Browse files
committed
Mark import used after implicit ranking chooses it
1 parent 1072aa9 commit 3bbd9e3

File tree

5 files changed

+52
-6
lines changed

5 files changed

+52
-6
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -2736,8 +2736,8 @@ object Types {
27362736
override def eql(that: Type): Boolean = this eq that // safe because named types are hash-consed separately
27372737
}
27382738

2739-
/** A reference to an implicit definition. This can be either a TermRef or a
2740-
* Implicits.RenamedImplicitRef.
2739+
/** A reference to an implicit definition. This can be either a TermRef or
2740+
* an Implicits.{ImportedImplicitRef, RenamedImplicitRef}.
27412741
*/
27422742
trait ImplicitRef {
27432743
def implicitName(using Context): TermName

compiler/src/dotty/tools/dotc/typer/Implicits.scala

+16-4
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,15 @@ object Implicits:
4444
*/
4545
class ImportedImplicitRef(val underlyingRef: TermRef, val importInfo: ImportInfo, val selector: Int) extends ImplicitRef:
4646
def implicitName(using Context): TermName = underlyingRef.implicitName
47+
override def toString = s"ImportedImplicitRef($underlyingRef, $importInfo, selector=$selector)"
4748

4849
/** An implicit definition `ImplicitRef` that is visible under a different name, `alias`.
4950
* Gets generated if an implicit ref is imported via a renaming import.
5051
*/
5152
class RenamedImplicitRef(underlyingRef: TermRef, importInfo: ImportInfo, selector: Int, val alias: TermName)
5253
extends ImportedImplicitRef(underlyingRef, importInfo, selector):
5354
override def implicitName(using Context): TermName = alias
55+
override def toString = s"ImportedImplicitRef($underlyingRef, $importInfo, selector=$selector, alias=$alias)"
5456

5557
/** Both search candidates and successes are references with a specific nesting level. */
5658
sealed trait RefAndLevel {
@@ -1157,9 +1159,6 @@ trait Implicits:
11571159
SearchFailure(adapted.withType(new MismatchedImplicit(ref, pt, argument)))
11581160
}
11591161
else
1160-
cand match
1161-
case Candidate(k: ImportedImplicitRef, _, _) => ctx.usages.use(k.importInfo, k.importInfo.selectors(k.selector))
1162-
case _ =>
11631162
SearchSuccess(adapted, ref, cand.level, cand.isExtension)(ctx.typerState, ctx.gadt)
11641163
}
11651164
end typedImplicit
@@ -1485,7 +1484,20 @@ trait Implicits:
14851484
validateOrdering(ord)
14861485
throw ex
14871486

1488-
rank(sort(eligible), NoMatchingImplicitsFailure, Nil)
1487+
@tailrec
1488+
def markSelector(allEligible: List[Candidate], foundRef: ImplicitRef): Unit =
1489+
allEligible match
1490+
case Candidate(k: ImportedImplicitRef, _, _) :: _ if k.underlyingRef == foundRef =>
1491+
ctx.usages.use(k.importInfo, k.importInfo.selectors(k.selector))
1492+
case _ :: rest => markSelector(rest, foundRef)
1493+
case nil => ()
1494+
1495+
rank(sort(eligible), NoMatchingImplicitsFailure, Nil) match {
1496+
case res: SearchSuccess if !ctx.mode.is(Mode.ImplicitExploration) =>
1497+
markSelector(eligible, res.ref)
1498+
res
1499+
case res => res
1500+
}
14891501
end searchImplicit
14901502

14911503
def isUnderSpecifiedArgument(tp: Type): Boolean =

compiler/src/dotty/tools/dotc/typer/ImportInfo.scala

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class ImportInfo(symf: Context ?=> Symbol,
5959
val enclosingSpan: Span,
6060
val isRootImport: Boolean = false) extends Showable {
6161

62+
override def toString = selectors.mkString(s"ImportInfo#$hashCode(", ",", s") at $enclosingSpan")
63+
6264
private def symNameOpt = qualifier match {
6365
case ref: untpd.RefTree => Some(ref.name.asTermName)
6466
case _ => None

tests/neg/t12690a.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
// scalac: -Werror -Wunused:imports
3+
4+
class X
5+
class Y extends X
6+
object A { implicit val x: X = new X }
7+
object B { implicit val y: Y = new Y }
8+
class C {
9+
import B._
10+
import A._ // error: unused
11+
def t = implicitly[X]
12+
}
13+
14+
object Test extends App {
15+
println(new C().t)
16+
}

tests/neg/t12690b.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
// scalac: -Werror -Wunused:imports
3+
4+
class X
5+
class Y extends X
6+
object A { implicit val x: X = new X }
7+
object B { implicit val y: Y = new Y }
8+
class C {
9+
import A._ // error: unused
10+
import B._
11+
def t = implicitly[X]
12+
}
13+
14+
object Test extends App {
15+
println(new C().t)
16+
}

0 commit comments

Comments
 (0)