Skip to content

Commit 0f0e558

Browse files
committed
Python: a checked tuple unbox without guards chooses by if expression
A lowerer that leaves the pending check to its caller (the field dispatchers) kept the unbox inside a block value, where the if statement choosing between the tuple and its zero lost the assignment, so a tuple field read through a dynamic receiver was always zero. git-bug: 382b32e109cb0ad60931124bda7305c85457aec87934d9ad59796807b537b29f
1 parent 45cc728 commit 0f0e558

3 files changed

Lines changed: 60 additions & 6 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1)]
2+
[[0], [10], [20], [1], [11], [21]]
3+
[0, 1, 2, 1, 2, 3]
4+
a 1 ('a', 1)
5+
b 2 ('b', 2)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# A tuple held in a field, read through a receiver whose class is not
2+
# known: each read yields the tuple that instance holds.
3+
class Node(object):
4+
def __init__(self, pos, id, links):
5+
self.pos = pos
6+
self.id = id
7+
self.links = links
8+
9+
10+
class Tag(object):
11+
def __init__(self, pair):
12+
self.pair = pair
13+
14+
15+
nodes = []
16+
for y in range(2):
17+
for x in range(3):
18+
nodes.append(Node((x, y), len(nodes), []))
19+
print([n.pos for n in nodes])
20+
21+
by_id = len(nodes) * [None]
22+
for n in nodes:
23+
by_id[n.id] = n
24+
for n in by_id:
25+
(x, y) = n.pos
26+
n.links.append(x * 10 + y)
27+
print([n.links for n in by_id])
28+
29+
30+
def positions(items):
31+
out = []
32+
for item in items:
33+
a, b = item.pos
34+
out.append(a + b)
35+
return out
36+
37+
38+
print(positions(by_id))
39+
40+
tags = [None, None]
41+
tags[0] = Tag(("a", 1))
42+
tags[1] = Tag(("b", 2))
43+
for t in tags:
44+
name, count = t.pair
45+
print(name, count, t.pair)

‎crates/zyntax_python/src/lower.rs‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2595,7 +2595,10 @@ impl<'m> Lowerer<'m> {
25952595
.collect();
25962596
let value = self.tuple_of_items(items, target, span);
25972597
// Where no check leaves the function, the caller checks after
2598-
// it: a read that raised yields a value nothing reads.
2598+
// it: a read that raised yields a value nothing reads. `pre`
2599+
// stays inside the block value here, so the choice is an `if`
2600+
// expression: an `if` statement inside a block expression does
2601+
// not carry its assignments past itself.
25992602
let value = if !trusted && !self.guards {
26002603
let is_tuple = binary(
26012604
BinaryOp::Ne,
@@ -2605,13 +2608,14 @@ impl<'m> Lowerer<'m> {
26052608
span,
26062609
);
26072610
let none = self.zero_of(target, span);
2608-
self.conditional_value(
2609-
is_tuple,
2610-
(Vec::new(), value),
2611-
(Vec::new(), none),
2611+
node(
2612+
TypedExpression::If(TypedIfExpr {
2613+
condition: Box::new(is_tuple),
2614+
then_branch: Box::new(value),
2615+
else_branch: Box::new(none),
2616+
}),
26122617
target,
26132618
span,
2614-
&mut pre,
26152619
)
26162620
} else {
26172621
value

0 commit comments

Comments
 (0)