Skip to content

Commit

Permalink
Check span.exists where necessary
Browse files Browse the repository at this point in the history
  • Loading branch information
som-snytt committed Feb 3, 2025
1 parent 0be00ad commit 91c9b26
Showing 1 changed file with 16 additions and 8 deletions.
24 changes: 16 additions & 8 deletions compiler/src/dotty/tools/dotc/transform/CheckUnused.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
// import x.y; y may be rewritten x.y, also import x.z as y
override def transformSelect(tree: Select)(using Context): tree.type =
val name = tree.removeAttachment(OriginalName).getOrElse(nme.NO_NAME)
if tree.span.isSynthetic && tree.symbol == defn.TypeTest_unapply then
if tree.srcPos.isSynthetic && tree.symbol == defn.TypeTest_unapply then
tree.qualifier.tpe.underlying.finalResultType match
case AppliedType(_, args) => // tycon.typeSymbol == defn.TypeTestClass
val res = args(1) // T in TypeTest[-S, T]
val target = res.dealias.typeSymbol
resolveUsage(target, target.name, res.importPrefix.skipPackageObject) // case _: T =>
case _ =>
else if tree.qualifier.span.isSynthetic || name.exists(_ != tree.symbol.name) then
else if tree.qualifier.srcPos.isSynthetic || name.exists(_ != tree.symbol.name) then
if !ignoreTree(tree) then
resolveUsage(tree.symbol, name, tree.qualifier.tpe)
else
Expand Down Expand Up @@ -597,12 +597,12 @@ object CheckUnused:
warnAt(pos)(UnusedSymbol.localDefs)

def checkPatvars() =
// convert the one non-synthetic span so all are comparable
// convert the one non-synthetic span so all are comparable; filter NoSpan below
def uniformPos(sym: Symbol, pos: SrcPos): SrcPos =
if pos.span.isSynthetic then pos else pos.sourcePos.withSpan(pos.span.toSynthetic)
// patvars in for comprehensions share the pos of where the name was introduced
val byPos = infos.pats.groupMap(uniformPos(_, _))((sym, pos) => sym)
for (pos, syms) <- byPos if !syms.exists(_.hasAnnotation(defn.UnusedAnnot)) do
for (pos, syms) <- byPos if pos.span.exists && !syms.exists(_.hasAnnotation(defn.UnusedAnnot)) do
if !syms.exists(infos.refs(_)) then
if !syms.exists(v => !v.isLocal && !v.is(Private)) then
warnAt(pos)(UnusedSymbol.patVars)
Expand Down Expand Up @@ -663,7 +663,10 @@ object CheckUnused:
val selector = textAt(sel.srcPos) // keep original
s"$qual.$selector" // don't succumb to vagaries of show
// begin actionable
val sortedImps = infos.imps.keySet.nn.asScala.toArray.sortBy(_.srcPos.span.point) // sorted by pos
val sortedImps = infos.imps.keySet.nn.asScala
.filter(_.srcPos.span.exists) // extra caution
.toArray
.sortBy(_.srcPos.span.point) // sorted by pos, not sort in place
var index = 0
while index < sortedImps.length do
val nextImport = sortedImps.indexSatisfying(from = index + 1)(_.isPrimaryClause) // next import statement
Expand Down Expand Up @@ -762,7 +765,11 @@ object CheckUnused:
if ctx.settings.WunusedHas.imports || ctx.settings.WunusedHas.strictNoImplicitWarn then
checkImports()

warnings.result().sortBy(_._2.span.point)
def sortOrder(msgInfo: MessageInfo): Int =
val srcPos = msgInfo._2
if srcPos.span.exists then srcPos.span.point else 0

warnings.result().sortBy(sortOrder)
end warnings

// Specific exclusions
Expand Down Expand Up @@ -880,7 +887,7 @@ object CheckUnused:
/** Is it the first import clause in a statement? `a.x` in `import a.x, b.{y, z}` */
def isPrimaryClause(using Context): Boolean =
val span = imp.srcPos.span
span.start != span.point // primary clause starts at `import` keyword
span.exists && span.start != span.point // primary clause starts at `import` keyword

/** Generated import of cases from enum companion. */
def isGeneratedByEnum(using Context): Boolean =
Expand All @@ -902,7 +909,8 @@ object CheckUnused:
else imp.expr.tpe.member(sel.name.toTermName).hasAltWith(_.symbol.isCanEqual)

extension (pos: SrcPos)
def isZeroExtentSynthetic: Boolean = pos.span.isSynthetic && pos.span.start == pos.span.end
def isZeroExtentSynthetic: Boolean = pos.span.isSynthetic && pos.span.isZeroExtent
def isSynthetic: Boolean = pos.span.isSynthetic && pos.span.exists

extension [A <: AnyRef](arr: Array[A])
// returns `until` if not satisfied
Expand Down

0 comments on commit 91c9b26

Please sign in to comment.