/** * @name List comprehension variable used in enclosing scope * @description Using the iteration variable of a list comprehension in the enclosing scope will result in different behavior between Python 2 and 3 and is confusing. * @kind problem * @tags portability * correctness * @problem.severity warning * @sub-severity high * @precision very-high * @id py/leaking-list-comprehension */ import python import Definition from ListComprehensionDeclaration l, Name use, Name defn where use = l.getALeakedVariableUse() and defn = l.getDefinition() and l.getAFlowNode().strictlyReaches(use.getAFlowNode()) and /* Make sure we aren't in a loop, as the variable may be redefined */ not use.getAFlowNode().strictlyReaches(l.getAFlowNode()) and not l.contains(use) and not use.deletes(_) and not exists(SsaVariable v | v.getAUse() = use.getAFlowNode() and not v.getDefinition().strictlyDominates(l.getAFlowNode()) ) select use, use.getId() + " may have a different value in Python 3, as the $@ will not be in scope.", defn, "list comprehension variable"