mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 20:17:42 +00:00
fixes #11809
This commit is contained in:
@@ -31,7 +31,7 @@ proc importPureEnumField*(c: PContext; s: PSym) =
|
||||
incl(c.ambiguousSymbols, checkB.id)
|
||||
incl(c.ambiguousSymbols, s.id)
|
||||
|
||||
proc rawImportSymbol(c: PContext, s: PSym) =
|
||||
proc rawImportSymbol(c: PContext, s, origin: PSym) =
|
||||
# This does not handle stubs, because otherwise loading on demand would be
|
||||
# pointless in practice. So importing stubs is fine here!
|
||||
# check if we have already a symbol of the same name:
|
||||
@@ -63,13 +63,14 @@ proc rawImportSymbol(c: PContext, s: PSym) =
|
||||
check = nextIdentIter(it, c.importTable.symbols)
|
||||
if e != nil:
|
||||
if sfPure notin s.flags:
|
||||
rawImportSymbol(c, e)
|
||||
rawImportSymbol(c, e, origin)
|
||||
else:
|
||||
importPureEnumField(c, e)
|
||||
else:
|
||||
# rodgen assures that converters and patterns are no stubs
|
||||
if s.kind == skConverter: addConverter(c, s)
|
||||
if hasPattern(s): addPattern(c, s)
|
||||
if s.owner != origin:
|
||||
c.exportIndirections.incl(idPairToInt(origin.id, s.id))
|
||||
|
||||
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
|
||||
let ident = lookups.considerQuotedIdent(c, n)
|
||||
@@ -88,10 +89,10 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
|
||||
while e != nil:
|
||||
if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3")
|
||||
if s.kind in ExportableSymKinds:
|
||||
rawImportSymbol(c, e)
|
||||
rawImportSymbol(c, e, fromMod)
|
||||
e = nextIdentIter(it, fromMod.tab)
|
||||
else:
|
||||
rawImportSymbol(c, s)
|
||||
rawImportSymbol(c, s, fromMod)
|
||||
suggestSym(c.config, n.info, s, c.graph.usageSym, false)
|
||||
|
||||
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
|
||||
@@ -103,14 +104,14 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
|
||||
if s.kind notin ExportableSymKinds:
|
||||
internalError(c.config, s.info, "importAllSymbols: " & $s.kind & " " & s.name.s)
|
||||
if exceptSet.isNil or s.name.id notin exceptSet:
|
||||
rawImportSymbol(c, s)
|
||||
rawImportSymbol(c, s, fromMod)
|
||||
s = nextIter(i, fromMod.tab)
|
||||
|
||||
proc importAllSymbols*(c: PContext, fromMod: PSym) =
|
||||
var exceptSet: IntSet
|
||||
importAllSymbolsExcept(c, fromMod, exceptSet)
|
||||
|
||||
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
|
||||
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym) =
|
||||
if n.isNil: return
|
||||
case n.kind
|
||||
of nkExportStmt:
|
||||
@@ -120,12 +121,12 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
|
||||
if s.kind == skModule:
|
||||
importAllSymbolsExcept(c, s, exceptSet)
|
||||
elif exceptSet.isNil or s.name.id notin exceptSet:
|
||||
rawImportSymbol(c, s)
|
||||
rawImportSymbol(c, s, fromMod)
|
||||
of nkExportExceptStmt:
|
||||
localError(c.config, n.info, "'export except' not implemented")
|
||||
else:
|
||||
for i in 0..safeLen(n)-1:
|
||||
importForwarded(c, n.sons[i], exceptSet)
|
||||
importForwarded(c, n.sons[i], exceptSet, fromMod)
|
||||
|
||||
proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
|
||||
result = realModule
|
||||
@@ -186,7 +187,7 @@ proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
|
||||
# ``addDecl`` needs to be done before ``importAllSymbols``!
|
||||
addDecl(c, m, it.info) # add symbol to symbol table of module
|
||||
importAllSymbolsExcept(c, m, emptySet)
|
||||
#importForwarded(c, m.ast, emptySet)
|
||||
#importForwarded(c, m.ast, emptySet, m)
|
||||
|
||||
proc evalImport*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkImportStmt, n.info)
|
||||
@@ -233,4 +234,4 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
|
||||
n.sons[0] = newSymNode(m)
|
||||
addDecl(c, m, n.info) # add symbol to symbol table of module
|
||||
importAllSymbolsExcept(c, m, readExceptSet(c, n))
|
||||
#importForwarded(c, m.ast, exceptSet)
|
||||
#importForwarded(c, m.ast, exceptSet, m)
|
||||
|
||||
@@ -138,6 +138,9 @@ type
|
||||
# tests/destructor/topttree.nim for an example that
|
||||
# would otherwise fail.
|
||||
unusedImports*: seq[(PSym, TLineInfo)]
|
||||
exportIndirections*: IntSet
|
||||
|
||||
template idPairToInt*(a, b: int): int = a * 10_000_000 + b
|
||||
|
||||
template config*(c: PContext): ConfigRef = c.graph.config
|
||||
|
||||
|
||||
@@ -2130,30 +2130,42 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
result = n
|
||||
case s.magic # magics that need special treatment
|
||||
of mAddr:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result[0] = newSymNode(s, n[0].info)
|
||||
result[1] = semAddrArg(c, n.sons[1], s.name.s == "unsafeAddr")
|
||||
result.typ = makePtrType(c, result[1].typ)
|
||||
of mTypeOf:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semTypeOf(c, n)
|
||||
#of mArrGet: result = semArrGet(c, n, flags)
|
||||
#of mArrPut: result = semArrPut(c, n, flags)
|
||||
#of mAsgn: result = semAsgnOpr(c, n)
|
||||
of mDefined: result = semDefined(c, setMs(n, s), false)
|
||||
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
||||
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
|
||||
#of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||
#of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||
of mIs: result = semIs(c, setMs(n, s), flags)
|
||||
#of mOf: result = semOf(c, setMs(n, s))
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
||||
of mQuoteAst: result = semQuoteAst(c, n)
|
||||
of mDefined:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semDefined(c, setMs(n, s), false)
|
||||
of mDefinedInScope:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semDefined(c, setMs(n, s), true)
|
||||
of mCompiles:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semCompiles(c, setMs(n, s), flags)
|
||||
of mIs:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semIs(c, setMs(n, s), flags)
|
||||
of mShallowCopy:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semShallowCopy(c, n, flags)
|
||||
of mExpandToAst:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semExpandToAst(c, n, s, flags)
|
||||
of mQuoteAst:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semQuoteAst(c, n)
|
||||
of mAstToStr:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, c.graph)
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
of mParallel:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
if parallel notin c.features:
|
||||
localError(c.config, n.info, "use the {.experimental.} pragma to enable 'parallel'")
|
||||
result = setMs(n, s)
|
||||
@@ -2163,6 +2175,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
result.sons[1] = semStmt(c, x, {})
|
||||
dec c.inParallelStmt
|
||||
of mSpawn:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
when defined(leanCompiler):
|
||||
localError(c.config, n.info, "compiler was built without 'spawn' support")
|
||||
result = n
|
||||
@@ -2180,10 +2193,12 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
else:
|
||||
result.add c.graph.emptyNode
|
||||
of mProcCall:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = setMs(n, s)
|
||||
result.sons[1] = semExpr(c, n.sons[1])
|
||||
result.typ = n[1].typ
|
||||
of mPlugin:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
# semDirectOp with conditional 'afterCallActions':
|
||||
let nOrig = n.copyTree
|
||||
#semLazyOpAux(c, n)
|
||||
@@ -2200,6 +2215,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
if callee.magic != mNone:
|
||||
result = magicsAfterOverloadResolution(c, result, flags)
|
||||
of mRunnableExamples:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
if c.config.cmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList:
|
||||
when false:
|
||||
# some of this dead code was moved to `prepareExamples`
|
||||
@@ -2216,8 +2232,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
result = setMs(n, s)
|
||||
else:
|
||||
result = c.graph.emptyNode
|
||||
of mSizeOf: result =
|
||||
semSizeof(c, setMs(n, s))
|
||||
of mSizeOf:
|
||||
markUsed(c, n.info, s, c.graph.usageSym)
|
||||
result = semSizeof(c, setMs(n, s))
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
|
||||
|
||||
@@ -535,7 +535,8 @@ proc markOwnerModuleAsUsed(c: PContext; s: PSym) =
|
||||
if module != nil and module != c.module:
|
||||
var i = 0
|
||||
while i <= high(c.unusedImports):
|
||||
if c.unusedImports[i][0] == module:
|
||||
let candidate = c.unusedImports[i][0]
|
||||
if candidate == module or c.exportIndirections.contains(idPairToInt(candidate.id, s.id)):
|
||||
# mark it as used:
|
||||
c.unusedImports.del(i)
|
||||
else:
|
||||
|
||||
27
tests/tools/tunused_imports.nim
Normal file
27
tests/tools/tunused_imports.nim
Normal file
@@ -0,0 +1,27 @@
|
||||
discard """
|
||||
cmd: '''nim c --hint[Processing]:off $file'''
|
||||
nimout: '''
|
||||
tunused_imports.nim(11, 10) Warning: BEGIN [User]
|
||||
tunused_imports.nim(27, 10) Warning: END [User]
|
||||
tunused_imports.nim(25, 8) Warning: imported and not used: 'strutils' [UnusedImport]
|
||||
'''
|
||||
action: "compile"
|
||||
"""
|
||||
|
||||
{.warning: "BEGIN".}
|
||||
|
||||
import net
|
||||
|
||||
echo AF_UNIX
|
||||
|
||||
import macros
|
||||
# bug #11809
|
||||
macro bar(): untyped =
|
||||
template baz() = discard
|
||||
result = getAst(baz())
|
||||
|
||||
bar()
|
||||
|
||||
import strutils
|
||||
|
||||
{.warning: "END".}
|
||||
Reference in New Issue
Block a user