Python: Remove support for late *args arguments

I found this to cause bad performance, so the implementation of this has
to be thought out more carefully.
This commit is contained in:
Rasmus Wriedt Larsen
2023-02-12 21:03:34 +01:00
parent 5c23b47ef4
commit 9e2eb56032
4 changed files with 1 additions and 77 deletions

View File

@@ -64,7 +64,6 @@ newtype TParameterPosition =
index = any(Parameter p).getPosition() + 1
} or
TSynthStarArgsElementParameterPosition(int index) { exists(TStarArgsParameterPosition(index)) } or
TSynthLateStarArgsParameterPosition(int index) { exists(TStarArgsParameterPosition(index)) } or
TDictSplatParameterPosition()
/** A parameter position. */
@@ -90,14 +89,6 @@ class ParameterPosition extends TParameterPosition {
this = TSynthStarArgsElementParameterPosition(index)
}
/**
* Holds if this position represents a synthetic `*args` parameter after the real
* `*args` parameter. The real `*args` parameter is at the 0-based index `index`.
*/
predicate isSynthLateStarArgsParameterPosition(int index) {
this = TSynthLateStarArgsParameterPosition(index)
}
/** Holds if this position represents a `**kwargs` parameter. */
predicate isDictSplat() { this = TDictSplatParameterPosition() }
@@ -116,11 +107,6 @@ class ParameterPosition extends TParameterPosition {
result = "synthetic *args element at (or after) " + index
)
or
exists(int index |
this.isSynthLateStarArgsParameterPosition(index) and
result = "synthetic late *args after " + index
)
or
this.isDictSplat() and result = "**"
}
}
@@ -192,10 +178,6 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
ppos.isSynthStarArgsElement(paramIndex) and apos.isPositional(argIndex)
)
or
exists(int realStarArgsIndex, int argIndex | argIndex > realStarArgsIndex |
ppos.isSynthLateStarArgsParameterPosition(realStarArgsIndex) and apos.isStarArgs(argIndex)
)
or
ppos.isDictSplat() and apos.isDictSplat()
}
@@ -329,9 +311,6 @@ abstract class DataFlowFunction extends DataFlowCallable, TFunction {
or
ppos.isSynthStarArgsElement(index) and
result = TSynthStarArgsElementParameterNode(this)
or
ppos.isSynthLateStarArgsParameterPosition(index) and
result = TSynthLateStarArgsParameterNode(this)
)
|
// a `*args` parameter comes after the last positional parameter. We need to take

View File

@@ -135,49 +135,6 @@ predicate synthStarArgsElementParameterNodeStoreStep(
)
}
/**
* A synthetic node to capture a `*args` argument that is passed to a `*args`
* parameter, but "too late" in the argument list, so we cannot just do a 1-1 mapping
* without messing up the indexes; instead we make a list/tuple/set read step to
* `SynthStarArgsElementParameterNode`.
*
* Example. The `*args` arguments starts at index 1, while the `*args` parameter accepts
* arguments starting at index 0.
*
* ```py
* def func(*args): ...
* func(1, *args)
*/
class SynthLateStarArgsParameterNode extends ParameterNodeImpl, TSynthLateStarArgsParameterNode {
DataFlowCallable callable;
SynthLateStarArgsParameterNode() { this = TSynthLateStarArgsParameterNode(callable) }
override string toString() { result = "SynthLateStarArgsParameterNode" }
override Scope getScope() { result = callable.getScope() }
override Location getLocation() { result = callable.getLocation() }
override Parameter getParameter() { none() }
}
predicate synthLateStarArgsParameterNodeReadStep(
SynthLateStarArgsParameterNode nodeFrom, Content c, ParameterNode nodeTo
) {
(
c instanceof ListElementContent
or
c instanceof TupleElementContent
or
c instanceof SetElementContent
) and
exists(DataFlowCallable callable |
nodeFrom = TSynthLateStarArgsParameterNode(callable) and
nodeTo = TSynthStarArgsElementParameterNode(callable)
)
}
// =============================================================================
// **kwargs (DictSplat) related
// =============================================================================
@@ -843,8 +800,6 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
or
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom, c, nodeTo)
or
synthLateStarArgsParameterNodeReadStep(nodeFrom, c, nodeTo)
or
synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo)
}
@@ -1006,8 +961,6 @@ predicate nodeIsHidden(Node n) {
or
n instanceof SynthStarArgsElementParameterNode
or
n instanceof SynthLateStarArgsParameterNode
or
n instanceof SynthDictSplatArgumentNode
or
n instanceof SynthDictSplatParameterNode

View File

@@ -117,14 +117,6 @@ newtype TNode =
TSynthStarArgsElementParameterNode(DataFlowCallable callable) {
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))
} or
/**
* A synthetic node to capture a `*args` argument that is passed to a `*args`
* parameter, but "too late" in the argument list, so we cannot just do a 1-1 mapping
* without messing up the indexes.
*/
TSynthLateStarArgsParameterNode(DataFlowCallable callable) {
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))
} or
/** A synthetic node to capture keyword arguments that are passed to a `**kwargs` parameter. */
TSynthDictSplatArgumentNode(CallNode call) { exists(call.getArgByName(_)) } or
/** A synthetic node to allow flow to keyword parameters from a `**kwargs` argument. */

View File

@@ -213,7 +213,7 @@ def starargs_only(*args):
def test_only_starargs():
starargs_only(arg1, arg2, "safe") # $ arg1 arg2 SPURIOUS: bad2,bad3="arg1" bad1,bad3="arg2"
args = (arg2, "safe") # $ arg2 func=starargs_only SPURIOUS: bad1,bad3="arg2"
args = (arg2, "safe") # $ MISSING: arg2
starargs_only(arg1, *args) # $ arg1 SPURIOUS: bad2,bad3="arg1"
args = (arg1, arg2, "safe") # $ arg1 arg2 func=starargs_only