Skip to content

Commit ec41e0d

Browse files
Revert "Backport "Always traverse Inlined.call in linter" to 3.7.4"
1 parent 9f5ca71 commit ec41e0d

File tree

5 files changed

+48
-182
lines changed

5 files changed

+48
-182
lines changed

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

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
1-
package dotty.tools.dotc
2-
package transform
3-
4-
import ast.*, desugar.{ForArtifact, PatternVar}, tpd.*, untpd.ImportSelector
5-
import config.ScalaSettings
6-
import core.*, Contexts.*, Flags.*
7-
import Names.{Name, SimpleName, DerivedName, TermName, termName}
8-
import NameKinds.{BodyRetainerName, ContextBoundParamName, ContextFunctionParamName, DefaultGetterName, WildcardParamName}
9-
import NameOps.{isAnonymousFunctionName, isReplWrapperName, setterName}
10-
import Scopes.newScope
11-
import StdNames.nme
12-
import Symbols.{ClassSymbol, NoSymbol, Symbol, defn, isDeprecated, requiredClass, requiredModule}
13-
import Types.*
14-
import reporting.{CodeAction, UnusedSymbol}
15-
import rewrites.Rewrites
16-
17-
import MegaPhase.MiniPhase
18-
import typer.{ImportInfo, Typer}
19-
import typer.Deriving.OriginalTypeClass
20-
import typer.Implicits.{ContextualImplicits, RenamedImplicitRef}
21-
import util.{Property, Spans, SrcPos}, Spans.Span
22-
import util.Chars.{isLineBreakChar, isWhitespace}
23-
import util.chaining.*
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.ast.desugar.{ForArtifact, PatternVar}
4+
import dotty.tools.dotc.ast.tpd.*
5+
import dotty.tools.dotc.ast.untpd, untpd.ImportSelector
6+
import dotty.tools.dotc.config.ScalaSettings
7+
import dotty.tools.dotc.core.Contexts.*
8+
import dotty.tools.dotc.core.Flags.*
9+
import dotty.tools.dotc.core.Names.{Name, SimpleName, DerivedName, TermName, termName}
10+
import dotty.tools.dotc.core.NameOps.{isAnonymousFunctionName, isReplWrapperName, setterName}
11+
import dotty.tools.dotc.core.NameKinds.{
12+
BodyRetainerName, ContextBoundParamName, ContextFunctionParamName, DefaultGetterName, WildcardParamName}
13+
import dotty.tools.dotc.core.StdNames.nme
14+
import dotty.tools.dotc.core.Symbols.{ClassSymbol, NoSymbol, Symbol, defn, isDeprecated, requiredClass, requiredModule}
15+
import dotty.tools.dotc.core.Types.*
16+
import dotty.tools.dotc.report
17+
import dotty.tools.dotc.reporting.{CodeAction, UnusedSymbol}
18+
import dotty.tools.dotc.rewrites.Rewrites
19+
import dotty.tools.dotc.transform.MegaPhase.MiniPhase
20+
import dotty.tools.dotc.typer.{ImportInfo, Typer}
21+
import dotty.tools.dotc.typer.Deriving.OriginalTypeClass
22+
import dotty.tools.dotc.util.{Property, Spans, SrcPos}, Spans.Span
23+
import dotty.tools.dotc.util.Chars.{isLineBreakChar, isWhitespace}
24+
import dotty.tools.dotc.util.chaining.*
2425

2526
import java.util.IdentityHashMap
2627

@@ -55,16 +56,17 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
5556
if tree.symbol.exists then
5657
// if in an inline expansion, resolve at summonInline (synthetic pos) or in an enclosing call site
5758
val resolving =
58-
tree.srcPos.isUserCode
59-
|| tree.srcPos.isZeroExtentSynthetic // take as summonInline
60-
if !ignoreTree(tree) then
59+
refInfos.inlined.isEmpty
60+
|| tree.srcPos.isZeroExtentSynthetic
61+
|| refInfos.inlined.exists(_.sourcePos.contains(tree.srcPos.sourcePos))
62+
if resolving && !ignoreTree(tree) then
6163
def loopOverPrefixes(prefix: Type, depth: Int): Unit =
6264
if depth < 10 && prefix.exists && !prefix.classSymbol.isEffectiveRoot then
63-
resolveUsage(prefix.classSymbol, nme.NO_NAME, NoPrefix, imports = resolving)
65+
resolveUsage(prefix.classSymbol, nme.NO_NAME, NoPrefix)
6466
loopOverPrefixes(prefix.normalizedPrefix, depth + 1)
6567
if tree.srcPos.isZeroExtentSynthetic then
6668
loopOverPrefixes(tree.typeOpt.normalizedPrefix, depth = 0)
67-
resolveUsage(tree.symbol, tree.name, tree.typeOpt.importPrefix.skipPackageObject, imports = resolving)
69+
resolveUsage(tree.symbol, tree.name, tree.typeOpt.importPrefix.skipPackageObject)
6870
else if tree.hasType then
6971
resolveUsage(tree.tpe.classSymbol, tree.name, tree.tpe.importPrefix.skipPackageObject)
7072
refInfos.isAssignment = false
@@ -140,8 +142,14 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
140142
case _ =>
141143
tree
142144

145+
override def prepareForInlined(tree: Inlined)(using Context): Context =
146+
refInfos.inlined.push(tree.call.srcPos)
147+
ctx
143148
override def transformInlined(tree: Inlined)(using Context): tree.type =
144-
transformAllDeep(tree.call)
149+
//transformAllDeep(tree.expansion) // traverse expansion with nonempty inlined stack to avoid registering defs
150+
val _ = refInfos.inlined.pop()
151+
if !tree.call.isEmpty && phaseMode.eq(PhaseMode.Aggregate) then
152+
transformAllDeep(tree.call)
145153
tree
146154

147155
override def prepareForBind(tree: Bind)(using Context): Context =
@@ -289,11 +297,8 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
289297
* e.g., in `scala.Int`, `scala` is in scope for typer, but here we reverse-engineer the attribution.
290298
* For Select, lint does not look up `<empty>.scala` (so top-level syms look like magic) but records `scala.Int`.
291299
* For Ident, look-up finds the root import as usual. A competing import is OK because higher precedence.
292-
*
293-
* The `imports` flag is whether an identifier can mark an import as used: the flag is false
294-
* for inlined code, except for `summonInline` (and related constructs) which are resolved at inlining.
295300
*/
296-
def resolveUsage(sym0: Symbol, name: Name, prefix: Type, imports: Boolean = true)(using Context): Unit =
301+
def resolveUsage(sym0: Symbol, name: Name, prefix: Type)(using Context): Unit =
297302
import PrecedenceLevels.*
298303
val sym = sym0.userSymbol
299304

@@ -387,7 +392,7 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha
387392
// record usage and possibly an import
388393
if !enclosed then
389394
refInfos.addRef(sym)
390-
if imports && candidate != NoContext && candidate.isImportContext && importer != null then
395+
if candidate != NoContext && candidate.isImportContext && importer != null then
391396
refInfos.sels.put(importer, ())
392397
end resolveUsage
393398
end CheckUnused
@@ -427,7 +432,7 @@ object CheckUnused:
427432
val nowarn = mutable.Set.empty[Symbol] // marked @nowarn
428433
val imps = new IdentityHashMap[Import, Unit] // imports
429434
val sels = new IdentityHashMap[ImportSelector, Unit] // matched selectors
430-
def register(tree: Tree)(using Context): Unit = if tree.srcPos.isUserCode then
435+
def register(tree: Tree)(using Context): Unit = if inlined.isEmpty then
431436
tree match
432437
case imp: Import =>
433438
if inliners == 0
@@ -457,6 +462,7 @@ object CheckUnused:
457462
if tree.symbol ne NoSymbol then
458463
defs.addOne((tree.symbol, tree.srcPos)) // TODO is this a code path
459464

465+
val inlined = Stack.empty[SrcPos] // enclosing call.srcPos of inlined code (expansions)
460466
var inliners = 0 // depth of inline def (not inlined yet)
461467

462468
// instead of refs.addOne, use addRef to distinguish a read from a write to var
@@ -998,10 +1004,6 @@ object CheckUnused:
9981004
extension (pos: SrcPos)
9991005
def isZeroExtentSynthetic: Boolean = pos.span.isSynthetic && pos.span.isZeroExtent
10001006
def isSynthetic: Boolean = pos.span.isSynthetic && pos.span.exists
1001-
def isUserCode(using Context): Boolean =
1002-
val inlineds = enclosingInlineds // per current context
1003-
inlineds.isEmpty
1004-
|| inlineds.last.srcPos.sourcePos.contains(pos.sourcePos)
10051007

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

tests/warn/i15503a.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ object FooGiven:
3939

4040
val foo = summon[Int]
4141

42-
object SomeGivenImports:
43-
given Int = 0
44-
given String = "foo"
45-
4642
/**
4743
* Import used as type name are considered
4844
* as used.
@@ -73,7 +69,7 @@ object InlineChecks:
7369
object InlinedBar:
7470
import collection.mutable.Set // warn (don't be fooled by inline expansion)
7571
import collection.mutable.Map // warn
76-
val a = InlineFoo.getSet // expansion is attributed mutable.Set.apply(1)
72+
val a = InlineFoo.getSet
7773

7874
object MacroChecks:
7975
object StringInterpol:
@@ -95,7 +91,12 @@ object IgnoreExclusion:
9591
def check =
9692
val a = Set(1)
9793
val b = Map(1 -> 2)
98-
def c = Seq(42)
94+
/**
95+
* Some given values for the test
96+
*/
97+
object SomeGivenImports:
98+
given Int = 0
99+
given String = "foo"
99100

100101
/* BEGIN : Check on packages*/
101102
package nestedpackageimport:

tests/warn/i24034/circe.scala

Lines changed: 0 additions & 97 deletions
This file was deleted.

tests/warn/i24034/iron.scala

Lines changed: 0 additions & 30 deletions
This file was deleted.

tests/warn/i24034/test.scala

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)