Skip to content

Commit 9b68c38

Browse files
committed
[GR-22536] Fix list comprehensions raising StopIteration when empty due to condition
PullRequest: graalpython/894
2 parents 45828e2 + f19919a commit 9b68c38

File tree

2 files changed

+44
-15
lines changed

2 files changed

+44
-15
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/generator/BuiltinIntrinsificationTests.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -38,4 +38,18 @@ public void simpleListComp() {
3838
"print(ll)";
3939
assertPrints("[0, 1, 2, 3, 4]\n", source);
4040
}
41+
42+
@Test
43+
public void simpleListCompCondition() {
44+
String source = "ll = list(i for i in range(5) if i % 2 == 0)\n" + //
45+
"print(ll)";
46+
assertPrints("[0, 2, 4]\n", source);
47+
}
48+
49+
@Test
50+
public void emptyListComp() {
51+
String source = "ll = list(i for i in range(5) if i == 6)\n" + //
52+
"print(ll)";
53+
assertPrints("[]\n", source);
54+
}
4155
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
import com.oracle.truffle.api.dsl.TypeSystemReference;
113113
import com.oracle.truffle.api.frame.VirtualFrame;
114114
import com.oracle.truffle.api.library.CachedLibrary;
115+
import com.oracle.truffle.api.nodes.UnexpectedResultException;
115116
import com.oracle.truffle.api.profiles.ConditionProfile;
116117

117118
@CoreFunctions(extendClasses = PythonBuiltinClassType.PList)
@@ -217,36 +218,50 @@ PNone listRange(PList list, PRange range) {
217218
return PNone.NONE;
218219
}
219220

220-
@Specialization(guards = "iterable.isPRangeIterator()")
221+
@Specialization(guards = "iterable.isPRangeIterator()", rewriteOn = UnexpectedResultException.class)
221222
PNone listPGenerator(VirtualFrame frame, PList list, PGenerator iterable,
222223
@Cached GetIteratorNode getIteratorNode,
223224
@Cached SequenceStorageNodes.AppendNode appendNode,
224225
@Cached GetNextNode getNextNode,
225226
@Cached IsBuiltinClassProfile errorProfile,
226227
@Cached("createBinaryProfile()") ConditionProfile stepProfile,
227-
@Cached("createBinaryProfile()") ConditionProfile positiveRangeProfile) {
228+
@Cached("createBinaryProfile()") ConditionProfile positiveRangeProfile) throws UnexpectedResultException {
228229
clearStorage(list);
229230
Object iterObj = getIteratorNode.executeWith(frame, iterable);
230231
SequenceStorage storage = EmptySequenceStorage.INSTANCE;
231232

232233
PRangeIterator range = (PRangeIterator) iterable.getIterator();
233-
final int len = range.getLength(stepProfile, positiveRangeProfile);
234-
if (len > 0) {
235-
Object value = getNextNode.execute(frame, iterObj);
236-
storage = SequenceStorageFactory.createStorage(value, len);
237-
storage = appendNode.execute(storage, value, ListGeneralizationNode.SUPPLIER);
238-
while (true) {
239-
try {
240-
storage = appendNode.execute(storage, getNextNode.execute(frame, iterObj), ListGeneralizationNode.SUPPLIER);
241-
} catch (PException e) {
242-
e.expectStopIteration(errorProfile);
243-
break;
234+
final int estimatedMaxLen = range.getLength(stepProfile, positiveRangeProfile);
235+
int realLen = 0;
236+
if (estimatedMaxLen > 0) {
237+
Object value = null;
238+
try {
239+
value = getNextNode.execute(frame, iterObj);
240+
realLen++;
241+
} catch (PException e) {
242+
e.expectStopIteration(errorProfile);
243+
}
244+
if (value != null) {
245+
storage = SequenceStorageFactory.createStorage(value, estimatedMaxLen);
246+
storage = appendNode.execute(storage, value, ListGeneralizationNode.SUPPLIER);
247+
while (true) {
248+
try {
249+
storage = appendNode.execute(storage, getNextNode.execute(frame, iterObj), ListGeneralizationNode.SUPPLIER);
250+
realLen++;
251+
} catch (PException e) {
252+
e.expectStopIteration(errorProfile);
253+
break;
254+
}
244255
}
245256
}
246257
}
247258

248259
list.setSequenceStorage(storage);
249-
return PNone.NONE;
260+
if (realLen == estimatedMaxLen) {
261+
return PNone.NONE;
262+
} else {
263+
throw new UnexpectedResultException(PNone.NONE);
264+
}
250265
}
251266

252267
@Specialization(guards = {"!isNoValue(iterable)", "!isString(iterable)"})

0 commit comments

Comments
 (0)