Skip to content

Commit c8f81bc

Browse files
committed
Fold tuple-destructuring extract and write into one node
1 parent d30162b commit c8f81bc

3 files changed

Lines changed: 73 additions & 65 deletions

File tree

go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -506,17 +506,19 @@ module GoCfg {
506506
// (see `skipCfg`): the per-case implicit variables are written at the
507507
// case match nodes (see `IR::TypeSwitchImplicitVariableInstruction`),
508508
// so the guard itself emits no assignment write node.
509-
not n = any(Go::TypeSwitchStmt ts).getAssign()
509+
not n = any(Go::TypeSwitchStmt ts).getAssign() and
510+
// A tuple-destructuring assignment (`x, y = f()`) folds its per-target
511+
// write into the `extract` node (see `IR::ExtractWriteInstruction`).
512+
not extractNodeCondition(n, i)
510513
or
511514
// A `ValueSpec` without an initializer is written by its `zero-init`
512-
// node directly (see `IR::InitVariableInstruction`), so only specs
513-
// *with* an initializer emit an `assign` write node.
515+
// node directly (see `IR::InitVariableInstruction`), and a
516+
// tuple-destructuring declaration (`var x, y = f()`) is written by its
517+
// `extract` node; only specs with a per-name initializer emit
518+
// `assign:i`.
514519
notBlankIdent(n.(Go::ValueSpec).getNameExpr(i)) and
515-
exists(n.(Go::ValueSpec).getAnInit())
516-
or
517-
notBlankIdent(n.(Go::RangeElementExpr).getKey()) and i = 0
518-
or
519-
notBlankIdent(n.(Go::RangeElementExpr).getValue()) and i = 1
520+
exists(n.(Go::ValueSpec).getAnInit()) and
521+
not extractNodeCondition(n, i)
520522
) and
521523
tag = "assign:" + i.toString()
522524
)
@@ -1105,16 +1107,17 @@ module GoCfg {
11051107
notBlankIdent(assgn.(Go::Assignment).getLhs(j)) and
11061108
// Compound assignments fold their write into `compound-rhs` (ord -1)
11071109
// above, so they emit no separate `assign:j` node.
1108-
not assgn instanceof Go::CompoundAssignStmt
1110+
not assgn instanceof Go::CompoundAssignStmt and
1111+
// Tuple-destructuring targets are written by their `extract` node.
1112+
not extractNodeCondition(assgn, j)
11091113
or
11101114
// A `ValueSpec` without an initializer is written by its `zero-init`
1111-
// node directly, so only specs *with* an initializer emit `assign:j`.
1115+
// node directly, and a tuple-destructuring declaration by its
1116+
// `extract` node, so only specs with a per-name initializer emit
1117+
// `assign:j`.
11121118
notBlankIdent(assgn.(Go::ValueSpec).getNameExpr(j)) and
1113-
exists(assgn.(Go::ValueSpec).getAnInit())
1114-
or
1115-
notBlankIdent(assgn.(Go::RangeElementExpr).getKey()) and j = 0
1116-
or
1117-
notBlankIdent(assgn.(Go::RangeElementExpr).getValue()) and j = 1
1119+
exists(assgn.(Go::ValueSpec).getAnInit()) and
1120+
not extractNodeCondition(assgn, j)
11181121
) and
11191122
result = "assign:" + j.toString() and
11201123
ord = 2 * j + 1

go/ql/lib/semmle/go/controlflow/IR.qll

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -646,8 +646,6 @@ module IR {
646646
// specs *with* an initializer produce an `assign` node.
647647
exists(assgn.(ValueSpec).getNameExpr(i)) and
648648
exists(assgn.(ValueSpec).getAnInit())
649-
or
650-
assgn instanceof RangeElementExpr and i in [0, 1]
651649
)
652650
}
653651

@@ -661,8 +659,6 @@ module IR {
661659
spec.getNumName() = spec.getNumInit() and
662660
result = evalExprInstruction(spec.getInit(i))
663661
)
664-
or
665-
result.(ExtractTupleElementInstruction).isAdditional(assgn, "extract:" + i.toString())
666662
}
667663

668664
override ControlFlow::Root getRoot() { result.isRootOf(assgn) }
@@ -776,6 +772,19 @@ module IR {
776772
override ControlFlow::Root getRoot() { result.isRootOf(s) }
777773
}
778774

775+
/**
776+
* An `ExtractTupleElementInstruction` that also writes the extracted component
777+
* to a left-hand side, as in a tuple-destructuring assignment (`x, y = f()`),
778+
* a multi-variable declaration (`var x, y = f()`), or a `range` statement
779+
* (`k, v := range m`).
780+
*
781+
* The extraction node performs the write directly, rather than feeding a
782+
* separate `assign` node.
783+
*/
784+
class ExtractWriteInstruction extends WriteInstruction, ExtractTupleElementInstruction {
785+
override Instruction getRhs() { result = this }
786+
}
787+
779788
/**
780789
* An instruction that computes the zero value to which a variable without an initializer
781790
* expression is initialized.
@@ -1151,6 +1160,23 @@ module IR {
11511160
write.isAdditional(spec, "zero-init:" + idx.toString()) and
11521161
lhs = spec.getNameExpr(idx)
11531162
)
1163+
or
1164+
// A tuple-destructuring `extract` node writes its component directly (see
1165+
// `ExtractWriteInstruction`); blank-identifier targets are not written.
1166+
exists(AstNode assgn, int i | write.isAdditional(assgn, "extract:" + i.toString()) |
1167+
(
1168+
lhs = assgn.(Assignment).getLhs(i).stripParens()
1169+
or
1170+
lhs = assgn.(ValueSpec).getNameExpr(i)
1171+
or
1172+
exists(RangeElementExpr p | p = assgn |
1173+
i = 0 and lhs = p.getKey().stripParens()
1174+
or
1175+
i = 1 and lhs = p.getValue().stripParens()
1176+
)
1177+
) and
1178+
not lhs instanceof BlankIdent
1179+
)
11541180
} or
11551181
/** A composite literal element target. */
11561182
MkLiteralElementTarget(ControlFlow::Node write) {
@@ -1389,16 +1415,16 @@ module IR {
13891415
* Gets the instruction corresponding to the assignment of the key variable
13901416
* of range statement `rs`.
13911417
*/
1392-
AssignInstruction assignKeyInstruction(RangeStmt rs) {
1393-
result.isAdditional(rs.getPattern(), "assign:0")
1418+
ExtractWriteInstruction assignKeyInstruction(RangeStmt rs) {
1419+
result.isAdditional(rs.getPattern(), "extract:0")
13941420
}
13951421

13961422
/**
13971423
* Gets the instruction corresponding to the assignment of the value variable
13981424
* of range statement `rs`.
13991425
*/
1400-
AssignInstruction assignValueInstruction(RangeStmt rs) {
1401-
result.isAdditional(rs.getPattern(), "assign:1")
1426+
ExtractWriteInstruction assignValueInstruction(RangeStmt rs) {
1427+
result.isAdditional(rs.getPattern(), "extract:1")
14021428
}
14031429

14041430
/**

go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/ControlFlowNode_getASuccessor.expected

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,10 +1183,8 @@
11831183
| exprs.go:33:2:35:2 | if statement | exprs.go:33:5:33:24 | ... := ... |
11841184
| exprs.go:33:5:33:24 | ... := ... | exprs.go:33:14:33:24 | Before type assertion |
11851185
| exprs.go:33:5:33:24 | After ... := ... | exprs.go:33:27:33:28 | Before ok |
1186-
| exprs.go:33:5:33:24 | assign:0 ... := ... | exprs.go:33:5:33:24 | extract:1 ... := ... |
1187-
| exprs.go:33:5:33:24 | assign:1 ... := ... | exprs.go:33:5:33:24 | After ... := ... |
1188-
| exprs.go:33:5:33:24 | extract:0 ... := ... | exprs.go:33:5:33:24 | assign:0 ... := ... |
1189-
| exprs.go:33:5:33:24 | extract:1 ... := ... | exprs.go:33:5:33:24 | assign:1 ... := ... |
1186+
| exprs.go:33:5:33:24 | extract:0 ... := ... | exprs.go:33:5:33:24 | extract:1 ... := ... |
1187+
| exprs.go:33:5:33:24 | extract:1 ... := ... | exprs.go:33:5:33:24 | After ... := ... |
11901188
| exprs.go:33:14:33:16 | After arg | exprs.go:33:14:33:24 | type assertion |
11911189
| exprs.go:33:14:33:16 | Before arg | exprs.go:33:14:33:16 | arg |
11921190
| exprs.go:33:14:33:16 | arg | exprs.go:33:14:33:16 | After arg |
@@ -1238,10 +1236,8 @@
12381236
| exprs.go:41:6:41:12 | zero-init:0 value declaration specifier | exprs.go:41:6:41:12 | After value declaration specifier |
12391237
| exprs.go:42:2:42:20 | ... = ... | exprs.go:42:10:42:20 | Before type assertion |
12401238
| exprs.go:42:2:42:20 | After ... = ... | exprs.go:43:2:45:2 | if statement |
1241-
| exprs.go:42:2:42:20 | assign:0 ... = ... | exprs.go:42:2:42:20 | extract:1 ... = ... |
1242-
| exprs.go:42:2:42:20 | assign:1 ... = ... | exprs.go:42:2:42:20 | After ... = ... |
1243-
| exprs.go:42:2:42:20 | extract:0 ... = ... | exprs.go:42:2:42:20 | assign:0 ... = ... |
1244-
| exprs.go:42:2:42:20 | extract:1 ... = ... | exprs.go:42:2:42:20 | assign:1 ... = ... |
1239+
| exprs.go:42:2:42:20 | extract:0 ... = ... | exprs.go:42:2:42:20 | extract:1 ... = ... |
1240+
| exprs.go:42:2:42:20 | extract:1 ... = ... | exprs.go:42:2:42:20 | After ... = ... |
12451241
| exprs.go:42:10:42:12 | After arg | exprs.go:42:10:42:20 | type assertion |
12461242
| exprs.go:42:10:42:12 | Before arg | exprs.go:42:10:42:12 | arg |
12471243
| exprs.go:42:10:42:12 | arg | exprs.go:42:10:42:12 | After arg |
@@ -1515,10 +1511,8 @@
15151511
| exprs.go:81:35:87:1 | param-init:0 block statement | exprs.go:82:2:82:16 | ... := ... |
15161512
| exprs.go:82:2:82:16 | ... := ... | exprs.go:82:13:82:16 | Before <-... |
15171513
| exprs.go:82:2:82:16 | After ... := ... | exprs.go:83:2:85:2 | if statement |
1518-
| exprs.go:82:2:82:16 | assign:0 ... := ... | exprs.go:82:2:82:16 | extract:1 ... := ... |
1519-
| exprs.go:82:2:82:16 | assign:1 ... := ... | exprs.go:82:2:82:16 | After ... := ... |
1520-
| exprs.go:82:2:82:16 | extract:0 ... := ... | exprs.go:82:2:82:16 | assign:0 ... := ... |
1521-
| exprs.go:82:2:82:16 | extract:1 ... := ... | exprs.go:82:2:82:16 | assign:1 ... := ... |
1514+
| exprs.go:82:2:82:16 | extract:0 ... := ... | exprs.go:82:2:82:16 | extract:1 ... := ... |
1515+
| exprs.go:82:2:82:16 | extract:1 ... := ... | exprs.go:82:2:82:16 | After ... := ... |
15221516
| exprs.go:82:13:82:16 | <-... | exprs.go:82:13:82:16 | After <-... |
15231517
| exprs.go:82:13:82:16 | After <-... | exprs.go:82:2:82:16 | extract:0 ... := ... |
15241518
| exprs.go:82:13:82:16 | Before <-... | exprs.go:82:15:82:16 | Before ch |
@@ -1770,10 +1764,8 @@
17701764
| generic.go:30:24:30:24 | c | generic.go:30:24:30:24 | After c |
17711765
| generic.go:31:2:31:53 | ... := ... | generic.go:31:10:31:53 | Before call to genericIdentity2 |
17721766
| generic.go:31:2:31:53 | After ... := ... | generic.go:32:2:32:31 | ... := ... |
1773-
| generic.go:31:2:31:53 | assign:0 ... := ... | generic.go:31:2:31:53 | extract:1 ... := ... |
1774-
| generic.go:31:2:31:53 | assign:1 ... := ... | generic.go:31:2:31:53 | After ... := ... |
1775-
| generic.go:31:2:31:53 | extract:0 ... := ... | generic.go:31:2:31:53 | assign:0 ... := ... |
1776-
| generic.go:31:2:31:53 | extract:1 ... := ... | generic.go:31:2:31:53 | assign:1 ... := ... |
1767+
| generic.go:31:2:31:53 | extract:0 ... := ... | generic.go:31:2:31:53 | extract:1 ... := ... |
1768+
| generic.go:31:2:31:53 | extract:1 ... := ... | generic.go:31:2:31:53 | After ... := ... |
17771769
| generic.go:31:10:31:25 | After genericIdentity2 | generic.go:31:10:31:41 | generic function instantiation expression |
17781770
| generic.go:31:10:31:25 | Before genericIdentity2 | generic.go:31:10:31:25 | genericIdentity2 |
17791771
| generic.go:31:10:31:25 | genericIdentity2 | generic.go:31:10:31:25 | After genericIdentity2 |
@@ -1792,10 +1784,8 @@
17921784
| generic.go:31:46:31:52 | Before "hello" | generic.go:31:46:31:52 | "hello" |
17931785
| generic.go:32:2:32:31 | ... := ... | generic.go:32:10:32:31 | Before call to genericIdentity2 |
17941786
| generic.go:32:2:32:31 | After ... := ... | generic.go:33:2:33:6 | ... = ... |
1795-
| generic.go:32:2:32:31 | assign:0 ... := ... | generic.go:32:2:32:31 | extract:1 ... := ... |
1796-
| generic.go:32:2:32:31 | assign:1 ... := ... | generic.go:32:2:32:31 | After ... := ... |
1797-
| generic.go:32:2:32:31 | extract:0 ... := ... | generic.go:32:2:32:31 | assign:0 ... := ... |
1798-
| generic.go:32:2:32:31 | extract:1 ... := ... | generic.go:32:2:32:31 | assign:1 ... := ... |
1787+
| generic.go:32:2:32:31 | extract:0 ... := ... | generic.go:32:2:32:31 | extract:1 ... := ... |
1788+
| generic.go:32:2:32:31 | extract:1 ... := ... | generic.go:32:2:32:31 | After ... := ... |
17991789
| generic.go:32:10:32:25 | After genericIdentity2 | generic.go:32:27:32:27 | Before e |
18001790
| generic.go:32:10:32:25 | Before genericIdentity2 | generic.go:32:10:32:25 | genericIdentity2 |
18011791
| generic.go:32:10:32:25 | genericIdentity2 | generic.go:32:10:32:25 | After genericIdentity2 |
@@ -2587,9 +2577,8 @@
25872577
| stmts2.go:9:19:13:1 | block statement | stmts2.go:10:2:10:14 | ... := ... |
25882578
| stmts2.go:10:2:10:14 | ... := ... | stmts2.go:10:10:10:14 | Before call to gen |
25892579
| stmts2.go:10:2:10:14 | After ... := ... | stmts2.go:11:2:11:17 | declaration statement |
2590-
| stmts2.go:10:2:10:14 | assign:1 ... := ... | stmts2.go:10:2:10:14 | After ... := ... |
25912580
| stmts2.go:10:2:10:14 | extract:0 ... := ... | stmts2.go:10:2:10:14 | extract:1 ... := ... |
2592-
| stmts2.go:10:2:10:14 | extract:1 ... := ... | stmts2.go:10:2:10:14 | assign:1 ... := ... |
2581+
| stmts2.go:10:2:10:14 | extract:1 ... := ... | stmts2.go:10:2:10:14 | After ... := ... |
25932582
| stmts2.go:10:10:10:12 | After gen | stmts2.go:10:10:10:14 | call to gen |
25942583
| stmts2.go:10:10:10:12 | Before gen | stmts2.go:10:10:10:12 | gen |
25952584
| stmts2.go:10:10:10:12 | gen | stmts2.go:10:10:10:12 | After gen |
@@ -2602,9 +2591,8 @@
26022591
| stmts2.go:11:2:11:17 | declaration statement | stmts2.go:11:2:11:17 | variable declaration |
26032592
| stmts2.go:11:2:11:17 | variable declaration | stmts2.go:11:6:11:17 | value declaration specifier |
26042593
| stmts2.go:11:6:11:17 | After value declaration specifier | stmts2.go:11:2:11:17 | After variable declaration |
2605-
| stmts2.go:11:6:11:17 | assign:1 value declaration specifier | stmts2.go:11:6:11:17 | After value declaration specifier |
26062594
| stmts2.go:11:6:11:17 | extract:0 value declaration specifier | stmts2.go:11:6:11:17 | extract:1 value declaration specifier |
2607-
| stmts2.go:11:6:11:17 | extract:1 value declaration specifier | stmts2.go:11:6:11:17 | assign:1 value declaration specifier |
2595+
| stmts2.go:11:6:11:17 | extract:1 value declaration specifier | stmts2.go:11:6:11:17 | After value declaration specifier |
26082596
| stmts2.go:11:6:11:17 | value declaration specifier | stmts2.go:11:13:11:17 | Before call to gen |
26092597
| stmts2.go:11:13:11:15 | After gen | stmts2.go:11:13:11:17 | call to gen |
26102598
| stmts2.go:11:13:11:15 | Before gen | stmts2.go:11:13:11:15 | gen |
@@ -2649,8 +2637,7 @@
26492637
| stmts2.go:18:7:18:7 | After x | stmts2.go:18:10:18:10 | Before _ |
26502638
| stmts2.go:18:7:18:7 | Before x | stmts2.go:18:7:18:7 | x |
26512639
| stmts2.go:18:7:18:7 | x | stmts2.go:18:7:18:7 | After x |
2652-
| stmts2.go:18:7:18:18 | assign:0 ... := ... | stmts2.go:18:7:18:18 | extract:1 ... := ... |
2653-
| stmts2.go:18:7:18:18 | extract:0 ... := ... | stmts2.go:18:7:18:18 | assign:0 ... := ... |
2640+
| stmts2.go:18:7:18:18 | extract:0 ... := ... | stmts2.go:18:7:18:18 | extract:1 ... := ... |
26542641
| stmts2.go:18:7:18:18 | extract:1 ... := ... | stmts2.go:19:3:19:10 | Before return statement |
26552642
| stmts2.go:18:10:18:10 | After _ | stmts2.go:18:7:18:18 | extract:0 ... := ... |
26562643
| stmts2.go:18:10:18:10 | Before _ | stmts2.go:18:10:18:10 | _ |
@@ -2668,9 +2655,8 @@
26682655
| stmts2.go:20:7:20:7 | After _ | stmts2.go:20:10:20:10 | Before y |
26692656
| stmts2.go:20:7:20:7 | Before _ | stmts2.go:20:7:20:7 | _ |
26702657
| stmts2.go:20:7:20:7 | _ | stmts2.go:20:7:20:7 | After _ |
2671-
| stmts2.go:20:7:20:18 | assign:1 ... := ... | stmts2.go:21:3:23:3 | if statement |
26722658
| stmts2.go:20:7:20:18 | extract:0 ... := ... | stmts2.go:20:7:20:18 | extract:1 ... := ... |
2673-
| stmts2.go:20:7:20:18 | extract:1 ... := ... | stmts2.go:20:7:20:18 | assign:1 ... := ... |
2659+
| stmts2.go:20:7:20:18 | extract:1 ... := ... | stmts2.go:21:3:23:3 | if statement |
26742660
| stmts2.go:20:10:20:10 | After y | stmts2.go:20:7:20:18 | extract:0 ... := ... |
26752661
| stmts2.go:20:10:20:10 | Before y | stmts2.go:20:10:20:10 | y |
26762662
| stmts2.go:20:10:20:10 | y | stmts2.go:20:10:20:10 | After y |
@@ -2720,8 +2706,7 @@
27202706
| stmts2.go:30:20:34:1 | block statement | stmts2.go:31:2:31:14 | ... := ... |
27212707
| stmts2.go:31:2:31:14 | ... := ... | stmts2.go:31:10:31:14 | Before call to gen |
27222708
| stmts2.go:31:2:31:14 | After ... := ... | stmts2.go:32:2:32:17 | declaration statement |
2723-
| stmts2.go:31:2:31:14 | assign:0 ... := ... | stmts2.go:31:2:31:14 | extract:1 ... := ... |
2724-
| stmts2.go:31:2:31:14 | extract:0 ... := ... | stmts2.go:31:2:31:14 | assign:0 ... := ... |
2709+
| stmts2.go:31:2:31:14 | extract:0 ... := ... | stmts2.go:31:2:31:14 | extract:1 ... := ... |
27252710
| stmts2.go:31:2:31:14 | extract:1 ... := ... | stmts2.go:31:2:31:14 | After ... := ... |
27262711
| stmts2.go:31:10:31:12 | After gen | stmts2.go:31:10:31:14 | call to gen |
27272712
| stmts2.go:31:10:31:12 | Before gen | stmts2.go:31:10:31:12 | gen |
@@ -2735,8 +2720,7 @@
27352720
| stmts2.go:32:2:32:17 | declaration statement | stmts2.go:32:2:32:17 | variable declaration |
27362721
| stmts2.go:32:2:32:17 | variable declaration | stmts2.go:32:6:32:17 | value declaration specifier |
27372722
| stmts2.go:32:6:32:17 | After value declaration specifier | stmts2.go:32:2:32:17 | After variable declaration |
2738-
| stmts2.go:32:6:32:17 | assign:0 value declaration specifier | stmts2.go:32:6:32:17 | extract:1 value declaration specifier |
2739-
| stmts2.go:32:6:32:17 | extract:0 value declaration specifier | stmts2.go:32:6:32:17 | assign:0 value declaration specifier |
2723+
| stmts2.go:32:6:32:17 | extract:0 value declaration specifier | stmts2.go:32:6:32:17 | extract:1 value declaration specifier |
27402724
| stmts2.go:32:6:32:17 | extract:1 value declaration specifier | stmts2.go:32:6:32:17 | After value declaration specifier |
27412725
| stmts2.go:32:6:32:17 | value declaration specifier | stmts2.go:32:13:32:17 | Before call to gen |
27422726
| stmts2.go:32:13:32:15 | After gen | stmts2.go:32:13:32:17 | call to gen |
@@ -3341,10 +3325,8 @@
33413325
| stmts.go:53:7:53:10 | Before index expression | stmts.go:53:7:53:7 | Before a |
33423326
| stmts.go:53:7:53:10 | index expression | stmts.go:46:1:62:1 | Exceptional Exit |
33433327
| stmts.go:53:7:53:10 | index expression | stmts.go:53:7:53:10 | After index expression |
3344-
| stmts.go:53:7:53:21 | assign:0 ... = ... | stmts.go:53:7:53:21 | extract:1 ... = ... |
3345-
| stmts.go:53:7:53:21 | assign:1 ... = ... | stmts.go:54:3:54:16 | expression statement |
3346-
| stmts.go:53:7:53:21 | extract:0 ... = ... | stmts.go:53:7:53:21 | assign:0 ... = ... |
3347-
| stmts.go:53:7:53:21 | extract:1 ... = ... | stmts.go:53:7:53:21 | assign:1 ... = ... |
3328+
| stmts.go:53:7:53:21 | extract:0 ... = ... | stmts.go:53:7:53:21 | extract:1 ... = ... |
3329+
| stmts.go:53:7:53:21 | extract:1 ... = ... | stmts.go:54:3:54:16 | expression statement |
33483330
| stmts.go:53:9:53:9 | 0 | stmts.go:53:9:53:9 | After 0 |
33493331
| stmts.go:53:9:53:9 | After 0 | stmts.go:53:7:53:10 | index expression |
33503332
| stmts.go:53:9:53:9 | Before 0 | stmts.go:53:9:53:9 | 0 |
@@ -3873,8 +3855,7 @@
38733855
| stmts.go:146:2:151:2 | After range statement | stmts.go:153:2:155:2 | range statement |
38743856
| stmts.go:146:2:151:2 | [LoopHeader] range statement | stmts.go:146:2:151:2 | After range statement |
38753857
| stmts.go:146:2:151:2 | [LoopHeader] range statement | stmts.go:146:2:151:2 | range element |
3876-
| stmts.go:146:2:151:2 | assign:0 range element | stmts.go:146:2:151:2 | After range element |
3877-
| stmts.go:146:2:151:2 | extract:0 range element | stmts.go:146:2:151:2 | assign:0 range element |
3858+
| stmts.go:146:2:151:2 | extract:0 range element | stmts.go:146:2:151:2 | After range element |
38783859
| stmts.go:146:2:151:2 | next range element | stmts.go:146:2:151:2 | extract:0 range element |
38793860
| stmts.go:146:2:151:2 | range element | stmts.go:146:2:151:2 | next range element |
38803861
| stmts.go:146:2:151:2 | range statement | stmts.go:146:17:146:18 | Before xs |
@@ -3917,10 +3898,8 @@
39173898
| stmts.go:153:2:155:2 | After range statement | stmts.go:157:2:158:2 | range statement |
39183899
| stmts.go:153:2:155:2 | [LoopHeader] range statement | stmts.go:153:2:155:2 | After range statement |
39193900
| stmts.go:153:2:155:2 | [LoopHeader] range statement | stmts.go:153:2:155:2 | range element |
3920-
| stmts.go:153:2:155:2 | assign:0 range element | stmts.go:153:2:155:2 | extract:1 range element |
3921-
| stmts.go:153:2:155:2 | assign:1 range element | stmts.go:153:2:155:2 | After range element |
3922-
| stmts.go:153:2:155:2 | extract:0 range element | stmts.go:153:2:155:2 | assign:0 range element |
3923-
| stmts.go:153:2:155:2 | extract:1 range element | stmts.go:153:2:155:2 | assign:1 range element |
3901+
| stmts.go:153:2:155:2 | extract:0 range element | stmts.go:153:2:155:2 | extract:1 range element |
3902+
| stmts.go:153:2:155:2 | extract:1 range element | stmts.go:153:2:155:2 | After range element |
39243903
| stmts.go:153:2:155:2 | next range element | stmts.go:153:2:155:2 | extract:0 range element |
39253904
| stmts.go:153:2:155:2 | range element | stmts.go:153:2:155:2 | next range element |
39263905
| stmts.go:153:2:155:2 | range statement | stmts.go:153:20:153:21 | Before xs |

0 commit comments

Comments
 (0)