Merge pull request #13938 from hmac/splat-flow-2

Ruby: More precise flow into splat parameters
This commit is contained in:
Harry Maclean
2023-08-18 12:07:58 +01:00
committed by GitHub
7 changed files with 774 additions and 5 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Flow between positional arguments and splat parameters (`*args`) is now tracked more precisely.

View File

@@ -440,6 +440,7 @@ private module Cached {
THashSplatArgumentPosition() or
TSplatAllArgumentPosition() or
TSplatArgumentPosition(int pos) { exists(Call c | c.getArgument(pos) instanceof SplatExpr) } or
TSynthSplatArgumentPosition() or
TAnyArgumentPosition() or
TAnyKeywordArgumentPosition()
@@ -473,6 +474,7 @@ private module Cached {
exists(Parameter p | p.getPosition() = pos and p instanceof SplatParameter)
} or
TSynthSplatParameterPosition() or
TSynthArgSplatParameterPosition() or
TAnyParameterPosition() or
TAnyKeywordParameterPosition()
}
@@ -1295,6 +1297,9 @@ class ParameterPosition extends TParameterPosition {
predicate isSynthSplat() { this = TSynthSplatParameterPosition() }
// A fake position to indicate that this parameter node holds content from a synth arg splat node
predicate isSynthArgSplat() { this = TSynthArgSplatParameterPosition() }
predicate isSplatAll() { this = TSplatAllParameterPosition() }
predicate isSplat(int n) { this = TSplatParameterPosition(n) }
@@ -1332,6 +1337,8 @@ class ParameterPosition extends TParameterPosition {
or
this.isSynthSplat() and result = "synthetic *"
or
this.isSynthArgSplat() and result = "synthetic * (from *args)"
or
exists(int pos | this.isSplat(pos) and result = "* (position " + pos + ")")
}
}
@@ -1369,6 +1376,8 @@ class ArgumentPosition extends TArgumentPosition {
predicate isSplat(int n) { this = TSplatArgumentPosition(n) }
predicate isSynthSplat() { this = TSynthSplatArgumentPosition() }
/** Gets a textual representation of this position. */
string toString() {
this.isSelf() and result = "self"
@@ -1387,6 +1396,8 @@ class ArgumentPosition extends TArgumentPosition {
or
this.isSplatAll() and result = "*"
or
this.isSynthSplat() and result = "synthetic *"
or
exists(int pos | this.isSplat(pos) and result = "* (position " + pos + ")")
}
}
@@ -1418,8 +1429,12 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
or
ppos.isSplatAll() and apos.isSplatAll()
or
ppos.isSplatAll() and apos.isSynthSplat()
or
ppos.isSynthSplat() and apos.isSplatAll()
or
apos.isSynthSplat() and ppos.isSynthArgSplat()
or
// Exact splat match
exists(int n | apos.isSplat(n) and ppos.isSplat(n))
or

View File

@@ -344,6 +344,15 @@ private module Cached {
exists(c.asCallable()) and // exclude library callables
isParameterNode(_, c, any(ParameterPosition p | p.isPositional(_)))
} or
TSynthSplatArgParameterNode(DataFlowCallable c) {
exists(c.asCallable()) and // exclude library callables
isParameterNode(_, c, any(ParameterPosition p | p.isSplat(_)))
} or
TSynthSplatParameterElementNode(DataFlowCallable c, int n) {
exists(c.asCallable()) and // exclude library callables
isParameterNode(_, c, any(ParameterPosition p | p.isSplat(_))) and
n in [0 .. 10]
} or
TExprPostUpdateNode(CfgNodes::ExprCfgNode n) {
// filter out nodes that clearly don't need post-update nodes
isNonConstantExpr(n) and
@@ -358,11 +367,18 @@ private module Cached {
exists(Argument arg | arg.isArgumentOf(c, any(ArgumentPosition pos | pos.isKeyword(_))))
or
c.getAnArgument() instanceof CfgNodes::ExprNodes::PairCfgNode
} or
TSynthSplatArgumentNode(CfgNodes::ExprNodes::CallCfgNode c) {
exists(Argument arg, ArgumentPosition pos | pos.isPositional(_) | arg.isArgumentOf(c, pos)) and
not exists(Argument arg, ArgumentPosition pos | pos.isSplat(_) or pos.isSplatAll() |
arg.isArgumentOf(c, pos)
)
}
class TSourceParameterNode =
TNormalParameterNode or TBlockParameterNode or TSelfParameterNode or
TSynthHashSplatParameterNode or TSynthSplatParameterNode;
TSynthHashSplatParameterNode or TSynthSplatParameterNode or TSynthSplatArgParameterNode or
TSynthSplatParameterElementNode;
cached
Location getLocation(NodeImpl n) { result = n.getLocationImpl() }
@@ -562,6 +578,12 @@ predicate nodeIsHidden(Node n) {
n instanceof SynthHashSplatArgumentNode
or
n instanceof SynthSplatParameterNode
or
n instanceof SynthSplatArgumentNode
or
n instanceof SynthSplatArgParameterNode
or
n instanceof SynthSplatParameterElementNode
}
/** An SSA definition, viewed as a node in a data flow graph. */
@@ -885,6 +907,69 @@ private module ParameterNodes {
final override string toStringImpl() { result = "synthetic *args" }
}
/**
* A node that holds all positional arguments passed in a call to `c`.
* This is a mirror of the `SynthSplatArgumentNode` on the callable side.
* See `SynthSplatArgumentNode` for more information.
*/
class SynthSplatArgParameterNode extends ParameterNodeImpl, TSynthSplatArgParameterNode {
private DataFlowCallable callable;
SynthSplatArgParameterNode() { this = TSynthSplatArgParameterNode(callable) }
final override Parameter getParameter() { none() }
final override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
c = callable and pos.isSynthArgSplat()
}
final override CfgScope getCfgScope() { result = callable.asCallable() }
final override DataFlowCallable getEnclosingCallable() { result = callable }
final override Location getLocationImpl() { result = callable.getLocation() }
final override string toStringImpl() { result = "synthetic *args" }
}
/**
* A node that holds the content of a specific positional argument.
* See `SynthSplatArgumentNode` for more information.
*/
class SynthSplatParameterElementNode extends ParameterNodeImpl, TSynthSplatParameterElementNode {
private DataFlowCallable callable;
private int pos;
SynthSplatParameterElementNode() { this = TSynthSplatParameterElementNode(callable, pos) }
pragma[nomagic]
NormalParameterNode getSplatParameterNode(int splatPos) {
result
.isParameterOf(this.getEnclosingCallable(), any(ParameterPosition p | p.isSplat(splatPos)))
}
int getStorePosition() { result = pos }
int getReadPosition() {
exists(int splatPos |
exists(this.getSplatParameterNode(splatPos)) and
result = pos + splatPos
)
}
final override Parameter getParameter() { none() }
final override predicate isParameterOf(DataFlowCallable c, ParameterPosition p) { none() }
final override CfgScope getCfgScope() { result = callable.asCallable() }
final override DataFlowCallable getEnclosingCallable() { result = callable }
final override Location getLocationImpl() { result = callable.getLocation() }
final override string toStringImpl() { result = "synthetic *args[" + pos + "]" }
}
/** A parameter for a library callable with a flow summary. */
class SummaryParameterNode extends ParameterNodeImpl, FlowSummaryNode {
private ParameterPosition pos_;
@@ -1030,6 +1115,51 @@ private module ArgumentNodes {
override string toStringImpl() { result = "**" }
}
/**
* A data-flow node that represents all arguments passed to the call.
* We use this to model data flow via splat parameters.
* Consider this example:
*
* ```rb
* def foo(x, y, *z)
* end
*
* foo(1, 2, 3, 4)
* ```
*
* 1. We want `3` to flow to `z[0]` and `4` to flow to `z[1]`. We model this by first storing all arguments
* in a synthetic argument node `SynthSplatArgumentNode` (see `storeStepCommon`).
* 2. We match this to an analogous parameter node `SynthSplatArgParameterNode` on the callee side
* (see `parameterMatch`).
* 3. For each content element stored in the `SynthSplatArgParameterNode`, we add a read step to a separate
* `SynthSplatParameterElementNode`, which is parameterized by the element index (see `readStep`).
* 4. Finally, we add store steps from these `SynthSplatParameterElementNode`s to the real splat parameter node
* (see `storeStep`).
* We only add store steps for elements that will not flow to the earlier positional parameters.
* In practice that means we ignore elements at index `<= N`, where `N` is the index of the splat parameter.
* For the remaining elements we subtract `N` from their index and store them in the splat parameter.
*/
class SynthSplatArgumentNode extends ArgumentNode, NodeImpl, TSynthSplatArgumentNode {
CfgNodes::ExprNodes::CallCfgNode c;
SynthSplatArgumentNode() { this = TSynthSplatArgumentNode(c) }
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
this.sourceArgumentOf(call.asCall(), pos)
}
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
call = c and
pos.isSynthSplat()
}
override CfgScope getCfgScope() { result = c.getExpr().getCfgScope() }
override Location getLocationImpl() { result = c.getLocation() }
override string toStringImpl() { result = "*" }
}
}
import ArgumentNodes
@@ -1269,6 +1399,19 @@ predicate storeStepCommon(Node node1, ContentSet c, Node node2) {
c.isSingleton(TKnownElementContent(cv))
)
)
or
exists(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos |
node2 = TSynthSplatArgumentNode(call) and
node1.asExpr().(Argument).isArgumentOf(call, pos)
|
exists(int n | pos.isPositional(n) and c = getPositionalContent(n))
)
or
node1 =
any(SynthSplatParameterElementNode elemNode |
node2 = elemNode.getSplatParameterNode(_) and
c = getPositionalContent(elemNode.getStorePosition())
)
}
/**
@@ -1334,10 +1477,17 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
or
node2 = node1.(SynthHashSplatParameterNode).getAKeywordParameter(c)
or
node2 = node1.(SynthSplatParameterNode).getAParameter(c)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
or
node2 = node1.(SynthSplatParameterNode).getAParameter(c)
or
// Read from SynthSplatArgParameterNode into SynthSplatParameterElementNode
node2 =
any(SynthSplatParameterElementNode e |
node1.(SynthSplatArgParameterNode).isParameterOf(e.getEnclosingCallable(), _) and
c = getPositionalContent(e.getReadPosition())
)
}
/**

File diff suppressed because it is too large Load Diff

View File

@@ -55,6 +55,7 @@ edges
| params_flow.rb:51:11:51:17 | posargs [element 0] | params_flow.rb:51:11:51:20 | ...[...] |
| params_flow.rb:51:11:51:20 | ...[...] | params_flow.rb:51:10:51:21 | ( ... ) |
| params_flow.rb:55:9:55:17 | call to taint | params_flow.rb:49:13:49:14 | p1 |
| params_flow.rb:55:20:55:28 | call to taint | params_flow.rb:49:17:49:24 | *posargs [element 0] |
| params_flow.rb:57:1:57:4 | args [element 0] | params_flow.rb:58:21:58:24 | args [element 0] |
| params_flow.rb:57:9:57:17 | call to taint | params_flow.rb:57:1:57:4 | args [element 0] |
| params_flow.rb:58:9:58:17 | call to taint | params_flow.rb:49:13:49:14 | p1 |
@@ -95,8 +96,11 @@ edges
| params_flow.rb:106:15:106:23 | call to taint | params_flow.rb:98:19:98:19 | a |
| params_flow.rb:106:37:106:45 | call to taint | params_flow.rb:98:31:98:31 | b |
| params_flow.rb:108:37:108:37 | a | params_flow.rb:109:10:109:10 | a |
| params_flow.rb:108:40:108:41 | *b [element 0] | params_flow.rb:110:10:110:10 | b [element 0] |
| params_flow.rb:108:44:108:44 | c | params_flow.rb:111:10:111:10 | c |
| params_flow.rb:110:10:110:10 | b [element 0] | params_flow.rb:110:10:110:13 | ...[...] |
| params_flow.rb:114:33:114:41 | call to taint | params_flow.rb:108:37:108:37 | a |
| params_flow.rb:114:44:114:52 | call to taint | params_flow.rb:108:40:108:41 | *b [element 0] |
| params_flow.rb:114:58:114:66 | call to taint | params_flow.rb:108:44:108:44 | c |
| params_flow.rb:117:1:117:1 | [post] x [element] | params_flow.rb:118:13:118:13 | x [element] |
| params_flow.rb:117:19:117:27 | call to taint | params_flow.rb:117:1:117:1 | [post] x [element] |
@@ -167,6 +171,7 @@ nodes
| params_flow.rb:51:11:51:17 | posargs [element 0] | semmle.label | posargs [element 0] |
| params_flow.rb:51:11:51:20 | ...[...] | semmle.label | ...[...] |
| params_flow.rb:55:9:55:17 | call to taint | semmle.label | call to taint |
| params_flow.rb:55:20:55:28 | call to taint | semmle.label | call to taint |
| params_flow.rb:57:1:57:4 | args [element 0] | semmle.label | args [element 0] |
| params_flow.rb:57:9:57:17 | call to taint | semmle.label | call to taint |
| params_flow.rb:58:9:58:17 | call to taint | semmle.label | call to taint |
@@ -217,10 +222,14 @@ nodes
| params_flow.rb:106:15:106:23 | call to taint | semmle.label | call to taint |
| params_flow.rb:106:37:106:45 | call to taint | semmle.label | call to taint |
| params_flow.rb:108:37:108:37 | a | semmle.label | a |
| params_flow.rb:108:40:108:41 | *b [element 0] | semmle.label | *b [element 0] |
| params_flow.rb:108:44:108:44 | c | semmle.label | c |
| params_flow.rb:109:10:109:10 | a | semmle.label | a |
| params_flow.rb:110:10:110:10 | b [element 0] | semmle.label | b [element 0] |
| params_flow.rb:110:10:110:13 | ...[...] | semmle.label | ...[...] |
| params_flow.rb:111:10:111:10 | c | semmle.label | c |
| params_flow.rb:114:33:114:41 | call to taint | semmle.label | call to taint |
| params_flow.rb:114:44:114:52 | call to taint | semmle.label | call to taint |
| params_flow.rb:114:58:114:66 | call to taint | semmle.label | call to taint |
| params_flow.rb:117:1:117:1 | [post] x [element] | semmle.label | [post] x [element] |
| params_flow.rb:117:19:117:27 | call to taint | semmle.label | call to taint |
@@ -253,6 +262,7 @@ subpaths
| params_flow.rb:50:10:50:11 | p1 | params_flow.rb:55:9:55:17 | call to taint | params_flow.rb:50:10:50:11 | p1 | $@ | params_flow.rb:55:9:55:17 | call to taint | call to taint |
| params_flow.rb:50:10:50:11 | p1 | params_flow.rb:58:9:58:17 | call to taint | params_flow.rb:50:10:50:11 | p1 | $@ | params_flow.rb:58:9:58:17 | call to taint | call to taint |
| params_flow.rb:50:10:50:11 | p1 | params_flow.rb:60:9:60:17 | call to taint | params_flow.rb:50:10:50:11 | p1 | $@ | params_flow.rb:60:9:60:17 | call to taint | call to taint |
| params_flow.rb:51:10:51:21 | ( ... ) | params_flow.rb:55:20:55:28 | call to taint | params_flow.rb:51:10:51:21 | ( ... ) | $@ | params_flow.rb:55:20:55:28 | call to taint | call to taint |
| params_flow.rb:51:10:51:21 | ( ... ) | params_flow.rb:57:9:57:17 | call to taint | params_flow.rb:51:10:51:21 | ( ... ) | $@ | params_flow.rb:57:9:57:17 | call to taint | call to taint |
| params_flow.rb:65:10:65:13 | ...[...] | params_flow.rb:63:8:63:16 | call to taint | params_flow.rb:65:10:65:13 | ...[...] | $@ | params_flow.rb:63:8:63:16 | call to taint | call to taint |
| params_flow.rb:70:10:70:10 | x | params_flow.rb:78:10:78:18 | call to taint | params_flow.rb:70:10:70:10 | x | $@ | params_flow.rb:78:10:78:18 | call to taint | call to taint |
@@ -271,4 +281,5 @@ subpaths
| params_flow.rb:99:10:99:10 | a | params_flow.rb:106:15:106:23 | call to taint | params_flow.rb:99:10:99:10 | a | $@ | params_flow.rb:106:15:106:23 | call to taint | call to taint |
| params_flow.rb:102:10:102:10 | b | params_flow.rb:106:37:106:45 | call to taint | params_flow.rb:102:10:102:10 | b | $@ | params_flow.rb:106:37:106:45 | call to taint | call to taint |
| params_flow.rb:109:10:109:10 | a | params_flow.rb:114:33:114:41 | call to taint | params_flow.rb:109:10:109:10 | a | $@ | params_flow.rb:114:33:114:41 | call to taint | call to taint |
| params_flow.rb:110:10:110:13 | ...[...] | params_flow.rb:114:44:114:52 | call to taint | params_flow.rb:110:10:110:13 | ...[...] | $@ | params_flow.rb:114:44:114:52 | call to taint | call to taint |
| params_flow.rb:111:10:111:10 | c | params_flow.rb:114:58:114:66 | call to taint | params_flow.rb:111:10:111:10 | c | $@ | params_flow.rb:114:58:114:66 | call to taint | call to taint |

View File

@@ -48,7 +48,7 @@ positional(*args)
def posargs(p1, *posargs)
sink p1 # $ hasValueFlow=20 $ hasValueFlow=23 $ hasValueFlow=24
sink (posargs[0]) # $ hasValueFlow=22 $ MISSING: hasValueFlow=21 $ MISSING: hasValueFlow=25
sink (posargs[0]) # $ hasValueFlow=22 $ hasValueFlow=21 $ MISSING: hasValueFlow=25
sink (posargs[1])
end
@@ -107,7 +107,7 @@ splatmidsmall(taint(55), taint(56), taint(57))
def splat_followed_by_keyword_param(a, *b, c:)
sink a # $ hasValueFlow=58
sink b[0] # $ MISSING: hasValueFlow=59
sink b[0] # $ hasValueFlow=59
sink c # $ hasValueFlow=60
end

View File

@@ -14,8 +14,12 @@ track
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps with content element 0 | type_tracker.rb:3:9:3:23 | * |
| type_tracker.rb:2:16:2:18 | val | type tracker without call steps with content element 0 | type_tracker.rb:15:5:15:18 | * |
| type_tracker.rb:3:9:3:23 | * | type tracker without call steps | type_tracker.rb:3:9:3:23 | * |
| type_tracker.rb:3:9:3:23 | call to puts | type tracker without call steps | type_tracker.rb:3:9:3:23 | call to puts |
| type_tracker.rb:3:14:3:23 | call to field | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:3:14:3:23 | call to field | type tracker without call steps with content element 0 | type_tracker.rb:3:9:3:23 | * |
| type_tracker.rb:4:9:4:14 | @field | type tracker without call steps | type_tracker.rb:4:9:4:14 | @field |
| type_tracker.rb:7:5:9:7 | &block | type tracker without call steps | type_tracker.rb:7:5:9:7 | &block |
| type_tracker.rb:7:5:9:7 | field | type tracker without call steps | type_tracker.rb:7:5:9:7 | field |
@@ -23,6 +27,8 @@ track
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps with content element 0 | type_tracker.rb:3:9:3:23 | * |
| type_tracker.rb:8:9:8:14 | @field | type tracker without call steps with content element 0 | type_tracker.rb:15:5:15:18 | * |
| type_tracker.rb:12:1:16:3 | &block | type tracker without call steps | type_tracker.rb:12:1:16:3 | &block |
| type_tracker.rb:12:1:16:3 | m | type tracker without call steps | type_tracker.rb:12:1:16:3 | m |
| type_tracker.rb:12:1:16:3 | self in m | type tracker without call steps | type_tracker.rb:12:1:16:3 | self in m |
@@ -33,6 +39,7 @@ track
| type_tracker.rb:13:11:13:23 | call to new | type tracker without call steps | type_tracker.rb:13:11:13:23 | call to new |
| type_tracker.rb:14:5:14:7 | [post] var | type tracker with call steps | type_tracker.rb:7:5:9:7 | self in field |
| type_tracker.rb:14:5:14:7 | [post] var | type tracker without call steps | type_tracker.rb:14:5:14:7 | [post] var |
| type_tracker.rb:14:5:14:13 | * | type tracker without call steps | type_tracker.rb:14:5:14:13 | * |
| type_tracker.rb:14:5:14:13 | call to field= | type tracker without call steps | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker with call steps | type_tracker.rb:8:9:8:14 | @field |
@@ -41,34 +48,51 @@ track
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:14:17:14:23 | "hello" |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps with content attribute field | type_tracker.rb:14:5:14:7 | [post] var |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps with content element 0 | type_tracker.rb:14:5:14:13 | * |
| type_tracker.rb:14:17:14:23 | "hello" | type tracker without call steps with content element 0 | type_tracker.rb:15:5:15:18 | * |
| type_tracker.rb:14:17:14:23 | __synth__0 | type tracker without call steps | type_tracker.rb:14:17:14:23 | __synth__0 |
| type_tracker.rb:15:5:15:18 | * | type tracker without call steps | type_tracker.rb:15:5:15:18 | * |
| type_tracker.rb:15:5:15:18 | call to puts | type tracker without call steps | type_tracker.rb:15:5:15:18 | call to puts |
| type_tracker.rb:15:10:15:18 | call to field | type tracker without call steps | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:15:10:15:18 | call to field | type tracker without call steps with content element 0 | type_tracker.rb:15:5:15:18 | * |
| type_tracker.rb:18:1:21:3 | &block | type tracker without call steps | type_tracker.rb:18:1:21:3 | &block |
| type_tracker.rb:18:1:21:3 | positional | type tracker without call steps | type_tracker.rb:18:1:21:3 | positional |
| type_tracker.rb:18:1:21:3 | self in positional | type tracker without call steps | type_tracker.rb:18:1:21:3 | self in positional |
| type_tracker.rb:18:1:21:3 | synthetic *args | type tracker without call steps | type_tracker.rb:18:1:21:3 | synthetic *args |
| type_tracker.rb:18:16:18:17 | p1 | type tracker without call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type tracker without call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:18:16:18:17 | p1 | type tracker without call steps with content element 0 | type_tracker.rb:19:5:19:11 | * |
| type_tracker.rb:18:20:18:21 | p2 | type tracker without call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type tracker without call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type tracker without call steps with content element 0 | type_tracker.rb:20:5:20:11 | * |
| type_tracker.rb:19:5:19:11 | * | type tracker without call steps | type_tracker.rb:19:5:19:11 | * |
| type_tracker.rb:19:5:19:11 | call to puts | type tracker without call steps | type_tracker.rb:19:5:19:11 | call to puts |
| type_tracker.rb:20:5:20:11 | * | type tracker without call steps | type_tracker.rb:20:5:20:11 | * |
| type_tracker.rb:20:5:20:11 | call to puts | type tracker without call steps | type_tracker.rb:20:5:20:11 | call to puts |
| type_tracker.rb:20:5:20:11 | call to puts | type tracker without call steps | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:23:1:23:16 | * | type tracker without call steps | type_tracker.rb:23:1:23:16 | * |
| type_tracker.rb:23:1:23:16 | call to positional | type tracker without call steps | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:23:12:23:12 | 1 | type tracker with call steps | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:23:12:23:12 | 1 | type tracker with call steps with content element 0 | type_tracker.rb:19:5:19:11 | * |
| type_tracker.rb:23:12:23:12 | 1 | type tracker without call steps | type_tracker.rb:23:12:23:12 | 1 |
| type_tracker.rb:23:12:23:12 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:23:1:23:16 | * |
| type_tracker.rb:23:15:23:15 | 2 | type tracker with call steps | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:23:15:23:15 | 2 | type tracker with call steps with content element 0 | type_tracker.rb:20:5:20:11 | * |
| type_tracker.rb:23:15:23:15 | 2 | type tracker without call steps | type_tracker.rb:23:15:23:15 | 2 |
| type_tracker.rb:23:15:23:15 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:23:1:23:16 | * |
| type_tracker.rb:25:1:28:3 | &block | type tracker without call steps | type_tracker.rb:25:1:28:3 | &block |
| type_tracker.rb:25:1:28:3 | **kwargs | type tracker without call steps | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:25:1:28:3 | keyword | type tracker without call steps | type_tracker.rb:25:1:28:3 | keyword |
| type_tracker.rb:25:1:28:3 | self in keyword | type tracker without call steps | type_tracker.rb:25:1:28:3 | self in keyword |
| type_tracker.rb:25:13:25:14 | p1 | type tracker without call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type tracker without call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:25:13:25:14 | p1 | type tracker without call steps with content element 0 | type_tracker.rb:26:5:26:11 | * |
| type_tracker.rb:25:18:25:19 | p2 | type tracker without call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type tracker without call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type tracker without call steps with content element 0 | type_tracker.rb:27:5:27:11 | * |
| type_tracker.rb:26:5:26:11 | * | type tracker without call steps | type_tracker.rb:26:5:26:11 | * |
| type_tracker.rb:26:5:26:11 | call to puts | type tracker without call steps | type_tracker.rb:26:5:26:11 | call to puts |
| type_tracker.rb:27:5:27:11 | * | type tracker without call steps | type_tracker.rb:27:5:27:11 | * |
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:27:5:27:11 | call to puts |
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:30:1:30:21 | call to keyword |
| type_tracker.rb:27:5:27:11 | call to puts | type tracker without call steps | type_tracker.rb:31:1:31:21 | call to keyword |
@@ -79,12 +103,14 @@ track
| type_tracker.rb:30:9:30:10 | :p1 | type tracker without call steps | type_tracker.rb:30:9:30:10 | :p1 |
| type_tracker.rb:30:9:30:13 | Pair | type tracker without call steps | type_tracker.rb:30:9:30:13 | Pair |
| type_tracker.rb:30:13:30:13 | 3 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:30:13:30:13 | 3 | type tracker with call steps with content element 0 | type_tracker.rb:26:5:26:11 | * |
| type_tracker.rb:30:13:30:13 | 3 | type tracker with call steps with content element :p1 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:30:13:30:13 | 3 | type tracker without call steps | type_tracker.rb:30:13:30:13 | 3 |
| type_tracker.rb:30:13:30:13 | 3 | type tracker without call steps with content element :p1 | type_tracker.rb:30:1:30:21 | ** |
| type_tracker.rb:30:16:30:17 | :p2 | type tracker without call steps | type_tracker.rb:30:16:30:17 | :p2 |
| type_tracker.rb:30:16:30:20 | Pair | type tracker without call steps | type_tracker.rb:30:16:30:20 | Pair |
| type_tracker.rb:30:20:30:20 | 4 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:30:20:30:20 | 4 | type tracker with call steps with content element 0 | type_tracker.rb:27:5:27:11 | * |
| type_tracker.rb:30:20:30:20 | 4 | type tracker with call steps with content element :p2 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:30:20:30:20 | 4 | type tracker without call steps | type_tracker.rb:30:20:30:20 | 4 |
| type_tracker.rb:30:20:30:20 | 4 | type tracker without call steps with content element :p2 | type_tracker.rb:30:1:30:21 | ** |
@@ -94,12 +120,14 @@ track
| type_tracker.rb:31:9:31:10 | :p2 | type tracker without call steps | type_tracker.rb:31:9:31:10 | :p2 |
| type_tracker.rb:31:9:31:13 | Pair | type tracker without call steps | type_tracker.rb:31:9:31:13 | Pair |
| type_tracker.rb:31:13:31:13 | 5 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:31:13:31:13 | 5 | type tracker with call steps with content element 0 | type_tracker.rb:27:5:27:11 | * |
| type_tracker.rb:31:13:31:13 | 5 | type tracker with call steps with content element :p2 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:31:13:31:13 | 5 | type tracker without call steps | type_tracker.rb:31:13:31:13 | 5 |
| type_tracker.rb:31:13:31:13 | 5 | type tracker without call steps with content element :p2 | type_tracker.rb:31:1:31:21 | ** |
| type_tracker.rb:31:16:31:17 | :p1 | type tracker without call steps | type_tracker.rb:31:16:31:17 | :p1 |
| type_tracker.rb:31:16:31:20 | Pair | type tracker without call steps | type_tracker.rb:31:16:31:20 | Pair |
| type_tracker.rb:31:20:31:20 | 6 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:31:20:31:20 | 6 | type tracker with call steps with content element 0 | type_tracker.rb:26:5:26:11 | * |
| type_tracker.rb:31:20:31:20 | 6 | type tracker with call steps with content element :p1 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:31:20:31:20 | 6 | type tracker without call steps | type_tracker.rb:31:20:31:20 | 6 |
| type_tracker.rb:31:20:31:20 | 6 | type tracker without call steps with content element :p1 | type_tracker.rb:31:1:31:21 | ** |
@@ -109,12 +137,14 @@ track
| type_tracker.rb:32:9:32:11 | :p2 | type tracker without call steps | type_tracker.rb:32:9:32:11 | :p2 |
| type_tracker.rb:32:9:32:16 | Pair | type tracker without call steps | type_tracker.rb:32:9:32:16 | Pair |
| type_tracker.rb:32:16:32:16 | 7 | type tracker with call steps | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:32:16:32:16 | 7 | type tracker with call steps with content element 0 | type_tracker.rb:27:5:27:11 | * |
| type_tracker.rb:32:16:32:16 | 7 | type tracker with call steps with content element :p2 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:32:16:32:16 | 7 | type tracker without call steps | type_tracker.rb:32:16:32:16 | 7 |
| type_tracker.rb:32:16:32:16 | 7 | type tracker without call steps with content element :p2 | type_tracker.rb:32:1:32:27 | ** |
| type_tracker.rb:32:19:32:21 | :p1 | type tracker without call steps | type_tracker.rb:32:19:32:21 | :p1 |
| type_tracker.rb:32:19:32:26 | Pair | type tracker without call steps | type_tracker.rb:32:19:32:26 | Pair |
| type_tracker.rb:32:26:32:26 | 8 | type tracker with call steps | type_tracker.rb:25:13:25:14 | p1 |
| type_tracker.rb:32:26:32:26 | 8 | type tracker with call steps with content element 0 | type_tracker.rb:26:5:26:11 | * |
| type_tracker.rb:32:26:32:26 | 8 | type tracker with call steps with content element :p1 | type_tracker.rb:25:1:28:3 | **kwargs |
| type_tracker.rb:32:26:32:26 | 8 | type tracker without call steps | type_tracker.rb:32:26:32:26 | 8 |
| type_tracker.rb:32:26:32:26 | 8 | type tracker without call steps with content element :p1 | type_tracker.rb:32:1:32:27 | ** |
@@ -132,123 +162,175 @@ track
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 | type_tracker.rb:35:11:35:15 | * |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:35:11:35:15 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 0 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 1 | type_tracker.rb:39:5:39:12 | * |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 1 | type_tracker.rb:43:5:43:13 | * |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 1 | type_tracker.rb:47:5:47:13 | * |
| type_tracker.rb:34:18:34:20 | obj | type tracker without call steps with content element 1 | type_tracker.rb:51:5:51:13 | * |
| type_tracker.rb:34:23:34:23 | y | type tracker without call steps | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type tracker without call steps | type_tracker.rb:34:23:34:23 | y |
| type_tracker.rb:34:23:34:23 | y | type tracker without call steps with content element 0 | type_tracker.rb:39:5:39:12 | * |
| type_tracker.rb:34:23:34:23 | y | type tracker without call steps with content element 0 | type_tracker.rb:44:5:44:13 | * |
| type_tracker.rb:34:23:34:23 | y | type tracker without call steps with content element 0 | type_tracker.rb:51:5:51:13 | * |
| type_tracker.rb:34:26:34:26 | z | type tracker without call steps | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type tracker without call steps | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type tracker without call steps with content element 0 | type_tracker.rb:52:5:52:13 | * |
| type_tracker.rb:35:5:35:7 | tmp | type tracker without call steps | type_tracker.rb:35:5:35:7 | tmp |
| type_tracker.rb:35:11:35:15 | * | type tracker without call steps | type_tracker.rb:35:11:35:15 | * |
| type_tracker.rb:35:11:35:15 | Array | type tracker without call steps | type_tracker.rb:35:11:35:15 | Array |
| type_tracker.rb:35:11:35:15 | call to [] | type tracker without call steps | type_tracker.rb:35:11:35:15 | call to [] |
| type_tracker.rb:36:5:36:10 | * | type tracker without call steps | type_tracker.rb:36:5:36:10 | * |
| type_tracker.rb:36:5:36:10 | ...[...] | type tracker without call steps | type_tracker.rb:36:5:36:10 | ...[...] |
| type_tracker.rb:36:9:36:9 | 0 | type tracker without call steps | type_tracker.rb:36:9:36:9 | 0 |
| type_tracker.rb:36:9:36:9 | 0 | type tracker without call steps with content element 0 | type_tracker.rb:36:5:36:10 | * |
| type_tracker.rb:38:5:38:9 | array | type tracker without call steps | type_tracker.rb:38:5:38:9 | array |
| type_tracker.rb:38:13:38:25 | * | type tracker without call steps | type_tracker.rb:38:13:38:25 | * |
| type_tracker.rb:38:13:38:25 | Array | type tracker without call steps | type_tracker.rb:38:13:38:25 | Array |
| type_tracker.rb:38:13:38:25 | call to [] | type tracker without call steps | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:38:14:38:14 | 1 | type tracker without call steps | type_tracker.rb:38:14:38:14 | 1 |
| type_tracker.rb:38:14:38:14 | 1 | type tracker without call steps | type_tracker.rb:40:5:40:12 | ...[...] |
| type_tracker.rb:38:14:38:14 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:38:13:38:25 | * |
| type_tracker.rb:38:14:38:14 | 1 | type tracker without call steps with content element 0 or unknown | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:38:16:38:16 | 2 | type tracker without call steps | type_tracker.rb:38:16:38:16 | 2 |
| type_tracker.rb:38:16:38:16 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:38:13:38:25 | * |
| type_tracker.rb:38:16:38:16 | 2 | type tracker without call steps with content element 1 or unknown | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:38:18:38:18 | 3 | type tracker without call steps | type_tracker.rb:38:18:38:18 | 3 |
| type_tracker.rb:38:18:38:18 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:38:13:38:25 | * |
| type_tracker.rb:38:18:38:18 | 3 | type tracker without call steps with content element 2 or unknown | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:38:20:38:20 | 4 | type tracker without call steps | type_tracker.rb:38:20:38:20 | 4 |
| type_tracker.rb:38:20:38:20 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:38:13:38:25 | * |
| type_tracker.rb:38:20:38:20 | 4 | type tracker without call steps with content element 3 or unknown | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:38:22:38:22 | 5 | type tracker without call steps | type_tracker.rb:38:22:38:22 | 5 |
| type_tracker.rb:38:22:38:22 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:38:13:38:25 | * |
| type_tracker.rb:38:22:38:22 | 5 | type tracker without call steps with content element 4 or unknown | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:38:24:38:24 | 6 | type tracker without call steps | type_tracker.rb:38:24:38:24 | 6 |
| type_tracker.rb:38:24:38:24 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:38:13:38:25 | * |
| type_tracker.rb:38:24:38:24 | 6 | type tracker without call steps with content element 5 or unknown | type_tracker.rb:38:13:38:25 | call to [] |
| type_tracker.rb:39:5:39:9 | [post] array | type tracker without call steps | type_tracker.rb:39:5:39:9 | [post] array |
| type_tracker.rb:39:5:39:12 | * | type tracker without call steps | type_tracker.rb:39:5:39:12 | * |
| type_tracker.rb:39:5:39:12 | call to []= | type tracker without call steps | type_tracker.rb:39:5:39:12 | call to []= |
| type_tracker.rb:39:16:39:18 | __synth__0 | type tracker without call steps | type_tracker.rb:39:16:39:18 | __synth__0 |
| type_tracker.rb:40:5:40:12 | * | type tracker without call steps | type_tracker.rb:40:5:40:12 | * |
| type_tracker.rb:40:5:40:12 | ...[...] | type tracker without call steps | type_tracker.rb:40:5:40:12 | ...[...] |
| type_tracker.rb:40:11:40:11 | 0 | type tracker without call steps | type_tracker.rb:40:11:40:11 | 0 |
| type_tracker.rb:40:11:40:11 | 0 | type tracker without call steps with content element 0 | type_tracker.rb:40:5:40:12 | * |
| type_tracker.rb:42:5:42:10 | array2 | type tracker without call steps | type_tracker.rb:42:5:42:10 | array2 |
| type_tracker.rb:42:14:42:26 | * | type tracker without call steps | type_tracker.rb:42:14:42:26 | * |
| type_tracker.rb:42:14:42:26 | Array | type tracker without call steps | type_tracker.rb:42:14:42:26 | Array |
| type_tracker.rb:42:14:42:26 | call to [] | type tracker without call steps | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps | type_tracker.rb:42:15:42:15 | 1 |
| type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:42:14:42:26 | * |
| type_tracker.rb:42:15:42:15 | 1 | type tracker without call steps with content element 0 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps | type_tracker.rb:42:17:42:17 | 2 |
| type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:42:14:42:26 | * |
| type_tracker.rb:42:17:42:17 | 2 | type tracker without call steps with content element 1 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps | type_tracker.rb:42:19:42:19 | 3 |
| type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:42:14:42:26 | * |
| type_tracker.rb:42:19:42:19 | 3 | type tracker without call steps with content element 2 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps | type_tracker.rb:42:21:42:21 | 4 |
| type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:42:14:42:26 | * |
| type_tracker.rb:42:21:42:21 | 4 | type tracker without call steps with content element 3 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps | type_tracker.rb:42:23:42:23 | 5 |
| type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:42:14:42:26 | * |
| type_tracker.rb:42:23:42:23 | 5 | type tracker without call steps with content element 4 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps | type_tracker.rb:42:25:42:25 | 6 |
| type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps with content element | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:42:14:42:26 | * |
| type_tracker.rb:42:25:42:25 | 6 | type tracker without call steps with content element 5 or unknown | type_tracker.rb:42:14:42:26 | call to [] |
| type_tracker.rb:43:5:43:10 | [post] array2 | type tracker without call steps | type_tracker.rb:43:5:43:10 | [post] array2 |
| type_tracker.rb:43:5:43:13 | * | type tracker without call steps | type_tracker.rb:43:5:43:13 | * |
| type_tracker.rb:43:5:43:13 | call to []= | type tracker without call steps | type_tracker.rb:43:5:43:13 | call to []= |
| type_tracker.rb:43:12:43:12 | 0 | type tracker without call steps | type_tracker.rb:43:12:43:12 | 0 |
| type_tracker.rb:43:12:43:12 | 0 | type tracker without call steps with content element 0 | type_tracker.rb:43:5:43:13 | * |
| type_tracker.rb:43:17:43:19 | __synth__0 | type tracker without call steps | type_tracker.rb:43:17:43:19 | __synth__0 |
| type_tracker.rb:44:5:44:13 | * | type tracker without call steps | type_tracker.rb:44:5:44:13 | * |
| type_tracker.rb:44:5:44:13 | ...[...] | type tracker without call steps | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:46:5:46:10 | array3 | type tracker without call steps | type_tracker.rb:46:5:46:10 | array3 |
| type_tracker.rb:46:14:46:26 | * | type tracker without call steps | type_tracker.rb:46:14:46:26 | * |
| type_tracker.rb:46:14:46:26 | Array | type tracker without call steps | type_tracker.rb:46:14:46:26 | Array |
| type_tracker.rb:46:14:46:26 | call to [] | type tracker without call steps | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:46:15:46:15 | 1 | type tracker without call steps | type_tracker.rb:46:15:46:15 | 1 |
| type_tracker.rb:46:15:46:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:46:14:46:26 | * |
| type_tracker.rb:46:15:46:15 | 1 | type tracker without call steps with content element 0 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps | type_tracker.rb:46:17:46:17 | 2 |
| type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps | type_tracker.rb:48:5:48:13 | ...[...] |
| type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:46:14:46:26 | * |
| type_tracker.rb:46:17:46:17 | 2 | type tracker without call steps with content element 1 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:46:19:46:19 | 3 | type tracker without call steps | type_tracker.rb:46:19:46:19 | 3 |
| type_tracker.rb:46:19:46:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:46:14:46:26 | * |
| type_tracker.rb:46:19:46:19 | 3 | type tracker without call steps with content element 2 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:46:21:46:21 | 4 | type tracker without call steps | type_tracker.rb:46:21:46:21 | 4 |
| type_tracker.rb:46:21:46:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:46:14:46:26 | * |
| type_tracker.rb:46:21:46:21 | 4 | type tracker without call steps with content element 3 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:46:23:46:23 | 5 | type tracker without call steps | type_tracker.rb:46:23:46:23 | 5 |
| type_tracker.rb:46:23:46:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:46:14:46:26 | * |
| type_tracker.rb:46:23:46:23 | 5 | type tracker without call steps with content element 4 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:46:25:46:25 | 6 | type tracker without call steps | type_tracker.rb:46:25:46:25 | 6 |
| type_tracker.rb:46:25:46:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:46:14:46:26 | * |
| type_tracker.rb:46:25:46:25 | 6 | type tracker without call steps with content element 5 or unknown | type_tracker.rb:46:14:46:26 | call to [] |
| type_tracker.rb:47:5:47:10 | [post] array3 | type tracker without call steps | type_tracker.rb:47:5:47:10 | [post] array3 |
| type_tracker.rb:47:5:47:13 | * | type tracker without call steps | type_tracker.rb:47:5:47:13 | * |
| type_tracker.rb:47:5:47:13 | call to []= | type tracker without call steps | type_tracker.rb:47:5:47:13 | call to []= |
| type_tracker.rb:47:12:47:12 | 0 | type tracker without call steps | type_tracker.rb:47:12:47:12 | 0 |
| type_tracker.rb:47:12:47:12 | 0 | type tracker without call steps with content element 0 | type_tracker.rb:47:5:47:13 | * |
| type_tracker.rb:47:17:47:19 | __synth__0 | type tracker without call steps | type_tracker.rb:47:17:47:19 | __synth__0 |
| type_tracker.rb:48:5:48:13 | * | type tracker without call steps | type_tracker.rb:48:5:48:13 | * |
| type_tracker.rb:48:5:48:13 | ...[...] | type tracker without call steps | type_tracker.rb:48:5:48:13 | ...[...] |
| type_tracker.rb:48:12:48:12 | 1 | type tracker without call steps | type_tracker.rb:48:12:48:12 | 1 |
| type_tracker.rb:48:12:48:12 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:48:5:48:13 | * |
| type_tracker.rb:50:5:50:10 | array4 | type tracker without call steps | type_tracker.rb:50:5:50:10 | array4 |
| type_tracker.rb:50:14:50:26 | * | type tracker without call steps | type_tracker.rb:50:14:50:26 | * |
| type_tracker.rb:50:14:50:26 | Array | type tracker without call steps | type_tracker.rb:50:14:50:26 | Array |
| type_tracker.rb:50:14:50:26 | call to [] | type tracker without call steps | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps | type_tracker.rb:50:15:50:15 | 1 |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps with content element 0 | type_tracker.rb:50:14:50:26 | * |
| type_tracker.rb:50:15:50:15 | 1 | type tracker without call steps with content element 0 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps | type_tracker.rb:50:17:50:17 | 2 |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps with content element 1 | type_tracker.rb:50:14:50:26 | * |
| type_tracker.rb:50:17:50:17 | 2 | type tracker without call steps with content element 1 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps | type_tracker.rb:50:19:50:19 | 3 |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps with content element 2 | type_tracker.rb:50:14:50:26 | * |
| type_tracker.rb:50:19:50:19 | 3 | type tracker without call steps with content element 2 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps | type_tracker.rb:50:21:50:21 | 4 |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps with content element 3 | type_tracker.rb:50:14:50:26 | * |
| type_tracker.rb:50:21:50:21 | 4 | type tracker without call steps with content element 3 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps | type_tracker.rb:50:23:50:23 | 5 |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps with content element 4 | type_tracker.rb:50:14:50:26 | * |
| type_tracker.rb:50:23:50:23 | 5 | type tracker without call steps with content element 4 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps | type_tracker.rb:50:25:50:25 | 6 |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps with content element | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps with content element 5 | type_tracker.rb:50:14:50:26 | * |
| type_tracker.rb:50:25:50:25 | 6 | type tracker without call steps with content element 5 or unknown | type_tracker.rb:50:14:50:26 | call to [] |
| type_tracker.rb:51:5:51:10 | [post] array4 | type tracker without call steps | type_tracker.rb:51:5:51:10 | [post] array4 |
| type_tracker.rb:51:5:51:13 | * | type tracker without call steps | type_tracker.rb:51:5:51:13 | * |
| type_tracker.rb:51:5:51:13 | call to []= | type tracker without call steps | type_tracker.rb:51:5:51:13 | call to []= |
| type_tracker.rb:51:17:51:19 | __synth__0 | type tracker without call steps | type_tracker.rb:51:17:51:19 | __synth__0 |
| type_tracker.rb:52:5:52:13 | * | type tracker without call steps | type_tracker.rb:52:5:52:13 | * |
| type_tracker.rb:52:5:52:13 | ...[...] | type tracker without call steps | type_tracker.rb:52:5:52:13 | ...[...] |
trackEnd
| type_tracker.rb:1:1:10:3 | self (Container) | type_tracker.rb:1:1:10:3 | self (Container) |
@@ -285,6 +367,7 @@ trackEnd
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:8:9:8:14 | @field |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:2:16:2:18 | val | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:3:9:3:23 | * | type_tracker.rb:3:9:3:23 | * |
| type_tracker.rb:3:9:3:23 | call to puts | type_tracker.rb:3:9:3:23 | call to puts |
| type_tracker.rb:3:14:3:23 | call to field | type_tracker.rb:3:14:3:23 | call to field |
| type_tracker.rb:4:9:4:14 | @field | type_tracker.rb:4:9:4:14 | @field |
@@ -322,6 +405,7 @@ trackEnd
| type_tracker.rb:14:5:14:7 | [post] var | type_tracker.rb:8:9:8:14 | self |
| type_tracker.rb:14:5:14:7 | [post] var | type_tracker.rb:14:5:14:7 | [post] var |
| type_tracker.rb:14:5:14:7 | [post] var | type_tracker.rb:15:10:15:12 | var |
| type_tracker.rb:14:5:14:13 | * | type_tracker.rb:14:5:14:13 | * |
| type_tracker.rb:14:5:14:13 | call to field= | type_tracker.rb:14:5:14:13 | call to field= |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:2:16:2:18 | val |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:2:16:2:18 | val |
@@ -336,6 +420,7 @@ trackEnd
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:17:14:23 | __synth__0 |
| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:14:17:14:23 | __synth__0 | type_tracker.rb:14:17:14:23 | __synth__0 |
| type_tracker.rb:15:5:15:18 | * | type_tracker.rb:15:5:15:18 | * |
| type_tracker.rb:15:5:15:18 | call to puts | type_tracker.rb:15:5:15:18 | call to puts |
| type_tracker.rb:15:10:15:18 | call to field | type_tracker.rb:15:10:15:18 | call to field |
| type_tracker.rb:18:1:21:3 | &block | type_tracker.rb:18:1:21:3 | &block |
@@ -353,9 +438,12 @@ trackEnd
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:18:20:18:21 | p2 |
| type_tracker.rb:18:20:18:21 | p2 | type_tracker.rb:20:10:20:11 | p2 |
| type_tracker.rb:19:5:19:11 | * | type_tracker.rb:19:5:19:11 | * |
| type_tracker.rb:19:5:19:11 | call to puts | type_tracker.rb:19:5:19:11 | call to puts |
| type_tracker.rb:20:5:20:11 | * | type_tracker.rb:20:5:20:11 | * |
| type_tracker.rb:20:5:20:11 | call to puts | type_tracker.rb:20:5:20:11 | call to puts |
| type_tracker.rb:20:5:20:11 | call to puts | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:23:1:23:16 | * | type_tracker.rb:23:1:23:16 | * |
| type_tracker.rb:23:1:23:16 | call to positional | type_tracker.rb:23:1:23:16 | call to positional |
| type_tracker.rb:23:12:23:12 | 1 | type_tracker.rb:18:16:18:17 | p1 |
| type_tracker.rb:23:12:23:12 | 1 | type_tracker.rb:18:16:18:17 | p1 |
@@ -380,7 +468,9 @@ trackEnd
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:25:18:25:19 | p2 |
| type_tracker.rb:25:18:25:19 | p2 | type_tracker.rb:27:10:27:11 | p2 |
| type_tracker.rb:26:5:26:11 | * | type_tracker.rb:26:5:26:11 | * |
| type_tracker.rb:26:5:26:11 | call to puts | type_tracker.rb:26:5:26:11 | call to puts |
| type_tracker.rb:27:5:27:11 | * | type_tracker.rb:27:5:27:11 | * |
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:27:5:27:11 | call to puts |
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:30:1:30:21 | call to keyword |
| type_tracker.rb:27:5:27:11 | call to puts | type_tracker.rb:31:1:31:21 | call to keyword |
@@ -473,14 +563,17 @@ trackEnd
| type_tracker.rb:34:26:34:26 | z | type_tracker.rb:34:26:34:26 | z |
| type_tracker.rb:34:26:34:26 | z | type_tracker.rb:52:12:52:12 | z |
| type_tracker.rb:35:5:35:7 | tmp | type_tracker.rb:35:5:35:7 | tmp |
| type_tracker.rb:35:11:35:15 | * | type_tracker.rb:35:11:35:15 | * |
| type_tracker.rb:35:11:35:15 | Array | type_tracker.rb:35:11:35:15 | Array |
| type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:35:5:35:7 | tmp |
| type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:35:5:35:15 | ... = ... |
| type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:35:11:35:15 | call to [] |
| type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:36:5:36:7 | tmp |
| type_tracker.rb:36:5:36:10 | * | type_tracker.rb:36:5:36:10 | * |
| type_tracker.rb:36:5:36:10 | ...[...] | type_tracker.rb:36:5:36:10 | ...[...] |
| type_tracker.rb:36:9:36:9 | 0 | type_tracker.rb:36:9:36:9 | 0 |
| type_tracker.rb:38:5:38:9 | array | type_tracker.rb:38:5:38:9 | array |
| type_tracker.rb:38:13:38:25 | * | type_tracker.rb:38:13:38:25 | * |
| type_tracker.rb:38:13:38:25 | Array | type_tracker.rb:38:13:38:25 | Array |
| type_tracker.rb:38:13:38:25 | call to [] | type_tracker.rb:38:5:38:9 | array |
| type_tracker.rb:38:13:38:25 | call to [] | type_tracker.rb:38:5:38:25 | ... = ... |
@@ -496,11 +589,14 @@ trackEnd
| type_tracker.rb:38:24:38:24 | 6 | type_tracker.rb:38:24:38:24 | 6 |
| type_tracker.rb:39:5:39:9 | [post] array | type_tracker.rb:39:5:39:9 | [post] array |
| type_tracker.rb:39:5:39:9 | [post] array | type_tracker.rb:40:5:40:9 | array |
| type_tracker.rb:39:5:39:12 | * | type_tracker.rb:39:5:39:12 | * |
| type_tracker.rb:39:5:39:12 | call to []= | type_tracker.rb:39:5:39:12 | call to []= |
| type_tracker.rb:39:16:39:18 | __synth__0 | type_tracker.rb:39:16:39:18 | __synth__0 |
| type_tracker.rb:40:5:40:12 | * | type_tracker.rb:40:5:40:12 | * |
| type_tracker.rb:40:5:40:12 | ...[...] | type_tracker.rb:40:5:40:12 | ...[...] |
| type_tracker.rb:40:11:40:11 | 0 | type_tracker.rb:40:11:40:11 | 0 |
| type_tracker.rb:42:5:42:10 | array2 | type_tracker.rb:42:5:42:10 | array2 |
| type_tracker.rb:42:14:42:26 | * | type_tracker.rb:42:14:42:26 | * |
| type_tracker.rb:42:14:42:26 | Array | type_tracker.rb:42:14:42:26 | Array |
| type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:5:42:10 | array2 |
| type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:5:42:26 | ... = ... |
@@ -521,11 +617,14 @@ trackEnd
| type_tracker.rb:42:25:42:25 | 6 | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:43:5:43:10 | [post] array2 | type_tracker.rb:43:5:43:10 | [post] array2 |
| type_tracker.rb:43:5:43:10 | [post] array2 | type_tracker.rb:44:5:44:10 | array2 |
| type_tracker.rb:43:5:43:13 | * | type_tracker.rb:43:5:43:13 | * |
| type_tracker.rb:43:5:43:13 | call to []= | type_tracker.rb:43:5:43:13 | call to []= |
| type_tracker.rb:43:12:43:12 | 0 | type_tracker.rb:43:12:43:12 | 0 |
| type_tracker.rb:43:17:43:19 | __synth__0 | type_tracker.rb:43:17:43:19 | __synth__0 |
| type_tracker.rb:44:5:44:13 | * | type_tracker.rb:44:5:44:13 | * |
| type_tracker.rb:44:5:44:13 | ...[...] | type_tracker.rb:44:5:44:13 | ...[...] |
| type_tracker.rb:46:5:46:10 | array3 | type_tracker.rb:46:5:46:10 | array3 |
| type_tracker.rb:46:14:46:26 | * | type_tracker.rb:46:14:46:26 | * |
| type_tracker.rb:46:14:46:26 | Array | type_tracker.rb:46:14:46:26 | Array |
| type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:5:46:10 | array3 |
| type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:5:46:26 | ... = ... |
@@ -541,12 +640,15 @@ trackEnd
| type_tracker.rb:46:25:46:25 | 6 | type_tracker.rb:46:25:46:25 | 6 |
| type_tracker.rb:47:5:47:10 | [post] array3 | type_tracker.rb:47:5:47:10 | [post] array3 |
| type_tracker.rb:47:5:47:10 | [post] array3 | type_tracker.rb:48:5:48:10 | array3 |
| type_tracker.rb:47:5:47:13 | * | type_tracker.rb:47:5:47:13 | * |
| type_tracker.rb:47:5:47:13 | call to []= | type_tracker.rb:47:5:47:13 | call to []= |
| type_tracker.rb:47:12:47:12 | 0 | type_tracker.rb:47:12:47:12 | 0 |
| type_tracker.rb:47:17:47:19 | __synth__0 | type_tracker.rb:47:17:47:19 | __synth__0 |
| type_tracker.rb:48:5:48:13 | * | type_tracker.rb:48:5:48:13 | * |
| type_tracker.rb:48:5:48:13 | ...[...] | type_tracker.rb:48:5:48:13 | ...[...] |
| type_tracker.rb:48:12:48:12 | 1 | type_tracker.rb:48:12:48:12 | 1 |
| type_tracker.rb:50:5:50:10 | array4 | type_tracker.rb:50:5:50:10 | array4 |
| type_tracker.rb:50:14:50:26 | * | type_tracker.rb:50:14:50:26 | * |
| type_tracker.rb:50:14:50:26 | Array | type_tracker.rb:50:14:50:26 | Array |
| type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:50:5:50:10 | array4 |
| type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:50:5:50:26 | ... = ... |
@@ -567,8 +669,10 @@ trackEnd
| type_tracker.rb:50:25:50:25 | 6 | type_tracker.rb:52:5:52:13 | ...[...] |
| type_tracker.rb:51:5:51:10 | [post] array4 | type_tracker.rb:51:5:51:10 | [post] array4 |
| type_tracker.rb:51:5:51:10 | [post] array4 | type_tracker.rb:52:5:52:10 | array4 |
| type_tracker.rb:51:5:51:13 | * | type_tracker.rb:51:5:51:13 | * |
| type_tracker.rb:51:5:51:13 | call to []= | type_tracker.rb:51:5:51:13 | call to []= |
| type_tracker.rb:51:17:51:19 | __synth__0 | type_tracker.rb:51:17:51:19 | __synth__0 |
| type_tracker.rb:52:5:52:13 | * | type_tracker.rb:52:5:52:13 | * |
| type_tracker.rb:52:5:52:13 | ...[...] | type_tracker.rb:52:5:52:13 | ...[...] |
forwardButNoBackwardFlow
backwardButNoForwardFlow