Skip to content

Commit 9d51be0

Browse files
authored
Fix WUnused with idents in derived code (#17095)
Resolve #16679
2 parents 18259db + 7fed80e commit 9d51be0

File tree

2 files changed

+48
-9
lines changed

2 files changed

+48
-9
lines changed

compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package dotty.tools.dotc.transform
22

33
import dotty.tools.dotc.ast.tpd
4-
import dotty.tools.dotc.ast.tpd.TreeTraverser
4+
import dotty.tools.dotc.ast.tpd.{Inlined, TreeTraverser}
55
import dotty.tools.dotc.ast.untpd
66
import dotty.tools.dotc.ast.untpd.ImportSelector
77
import dotty.tools.dotc.config.ScalaSettings
@@ -15,19 +15,14 @@ import dotty.tools.dotc.reporting.Message
1515
import dotty.tools.dotc.typer.ImportInfo
1616
import dotty.tools.dotc.util.{Property, SrcPos}
1717
import dotty.tools.dotc.core.Mode
18-
import dotty.tools.dotc.core.Types.TypeTraverser
19-
import dotty.tools.dotc.core.Types.Type
20-
import dotty.tools.dotc.core.Types.AnnotatedType
18+
import dotty.tools.dotc.core.Types.{AnnotatedType, ConstantType, NoType, TermRef, Type, TypeTraverser}
2119
import dotty.tools.dotc.core.Flags.flagsString
2220
import dotty.tools.dotc.core.Flags
2321
import dotty.tools.dotc.core.Names.Name
2422
import dotty.tools.dotc.transform.MegaPhase.MiniPhase
2523
import dotty.tools.dotc.core.Annotations
2624
import dotty.tools.dotc.core.Definitions
27-
import dotty.tools.dotc.core.Types.ConstantType
2825
import dotty.tools.dotc.core.NameKinds.WildcardParamName
29-
import dotty.tools.dotc.core.Types.TermRef
30-
import dotty.tools.dotc.core.Types.NameFilter
3126
import dotty.tools.dotc.core.Symbols.Symbol
3227

3328

@@ -80,8 +75,16 @@ class CheckUnused extends MiniPhase:
8075
traverser.traverse(tree)
8176
ctx
8277

78+
override def prepareForInlined(tree: tpd.Inlined)(using Context): Context =
79+
traverser.traverse(tree.call)
80+
ctx
81+
8382
override def prepareForIdent(tree: tpd.Ident)(using Context): Context =
8483
if tree.symbol.exists then
84+
val prefixes = LazyList.iterate(tree.typeOpt.normalizedPrefix)(_.normalizedPrefix).takeWhile(_ != NoType)
85+
.take(10) // Failsafe for the odd case if there was an infinite cycle
86+
for prefix <- prefixes do
87+
unusedDataApply(_.registerUsed(prefix.classSymbol, None))
8588
unusedDataApply(_.registerUsed(tree.symbol, Some(tree.name)))
8689
else if tree.hasType then
8790
unusedDataApply(_.registerUsed(tree.tpe.classSymbol, Some(tree.name)))
@@ -409,7 +412,6 @@ object CheckUnused:
409412
val kept = used.filterNot { t =>
410413
val (sym, isAccessible, optName) = t
411414
// keep the symbol for outer scope, if it matches **no** import
412-
413415
// This is the first matching wildcard selector
414416
var selWildCard: Option[ImportSelector] = None
415417

tests/neg-custom-args/fatal-warnings/i15503i.scala

+38-1
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,41 @@ package foo.test.i16925:
207207
for {
208208
i <- 1 to 2 if true
209209
_ = println(i) // OK
210-
} yield ()
210+
} yield ()
211+
212+
package foo.test.i16679a:
213+
object myPackage:
214+
trait CaseClassName[A]:
215+
def name: String
216+
object CaseClassName:
217+
trait CaseClassByStringName[A] extends CaseClassName[A]
218+
import scala.deriving.Mirror
219+
object CaseClassByStringName:
220+
inline final def derived[A](using inline A: Mirror.Of[A]): CaseClassByStringName[A] =
221+
new CaseClassByStringName[A]:
222+
def name: String = A.toString
223+
224+
object secondPackage:
225+
import myPackage.CaseClassName // OK
226+
case class CoolClass(i: Int) derives CaseClassName.CaseClassByStringName
227+
println(summon[CaseClassName[CoolClass]].name)
228+
229+
package foo.test.i16679b:
230+
object myPackage:
231+
trait CaseClassName[A]:
232+
def name: String
233+
234+
object CaseClassName:
235+
import scala.deriving.Mirror
236+
inline final def derived[A](using inline A: Mirror.Of[A]): CaseClassName[A] =
237+
new CaseClassName[A]:
238+
def name: String = A.toString
239+
240+
object Foo:
241+
given x: myPackage.CaseClassName[secondPackage.CoolClass] = null
242+
243+
object secondPackage:
244+
import myPackage.CaseClassName // OK
245+
import Foo.x
246+
case class CoolClass(i: Int)
247+
println(summon[myPackage.CaseClassName[CoolClass]])

0 commit comments

Comments
 (0)