Bug 5746 – Make std.range.iota strongly pure

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2011-03-16T16:47:00Z
Last change time
2014-01-14T05:26:19Z
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2011-03-16T16:47:05Z
Generally I'd like Phobos functions/ranges to be pure unless their semantics is clearly not pure. I'd like to use iota() in pure functions too. In the semantics of iota() there is fundamentally nothing that prevents it to be pure. This D2 program: import std.range; pure void foo() { auto r = iota(10); } void main() {} With DMD 2.052 gives the error: test.d(3): Error: pure function 'foo' cannot call impure function 'iota' The purity problem is here, from std.range module, enforce() is not pure: struct Iota(N, S) if ((isIntegral!N || isPointer!N) && isIntegral!S) { private N current, pastLast; private S step; pure this(N current, N pastLast, S step) { enforce((current <= pastLast && step > 0) || (current >= pastLast && step < 0)); This is part of std.exception.enforce(), a function with a lazy argument can't be pure (and I think adding "pure lazy" to the D language can't help much because most expressions given to enforce() aren't meant to be pure): T enforce(T, string file = __FILE__, int line = __LINE__) (T value, lazy const(char)[] msg = null) { if (!value) bailOut(file, line, msg); return value; } A solution is to remove the call to enforce() from the Iota constructor, and replace it with a simpler if/throw. See also bug 5124
Comment #1 by bearophile_hugs — 2014-01-14T03:08:09Z
Fixed in recent Phobos updated, now this compiles: void main() pure { import std.range: iota; foreach (_; iota(10)) {} foreach (_; iota(1, 10)) {} foreach (_; iota(10, 1, -1)) {} }
Comment #2 by k.hara.pg — 2014-01-14T05:26:19Z
(In reply to comment #1) > Fixed in recent Phobos updated, now this compiles: > > void main() pure { > import std.range: iota; > foreach (_; iota(10)) {} > foreach (_; iota(1, 10)) {} > foreach (_; iota(10, 1, -1)) {} > } The situation has been improved by fixing issue 10329.