Bug with writeln?

Steven Schveighoffer schveiguy at gmail.com
Thu Sep 6 19:05:03 UTC 2018


On 9/6/18 2:52 PM, Jonathan M Davis wrote:
> On Thursday, September 6, 2018 12:21:24 PM MDT Steven Schveighoffer via
> Digitalmars-d-learn wrote:
>> On 9/6/18 12:55 PM, Jonathan M Davis wrote:
>>> It's not a bug in writeln. Any time that a range is copied, you must not
>>> do _anything_ else with the original unless copying it is equivalent to
>>> calling save on it, because the semantics of copying a range are
>>> unspecified. They vary wildly depending on the range type (e.g. copying
>>> a dynamic array is equivalent to calling save, but copying a class
>>> reference is not). When you pass the range to writeln, you must assumed
>>> that it may have been consumed. And since you have range of ranges, you
>>> must assume that the ranges that are contained may have been consumed.
>>> If you want to pass them to writeln and then do anything else with
>>> them, then you'll need to call save on every range involved (which is a
>>> bit of a pain with a range of ranges, but it's necessary all the same).
>>
>> This is not necessarily true. It depends how the sub-ranges are returned.
>>
>> The bug is that formattedWrite takes ranges sometimes by ref, sometimes
>> not.
>>
>> formattedWrite should call save on a forward range whenever it makes a
>> copy, and it doesn't.
>>
>> Case in point, it doesn't matter if you call writeln(b.save), the same
>> thing happens.
> 
> That's still not a bug in formattedWrite. save only duplicates the
> outer-most range. And since writeln will ultimately iterate through the
> inner ranges - which weren't saved - you end up with them being consumed.

That is the bug -- formattedWrite should save all the inner ranges 
(writeln calls formattedWrite, and lets it do all the work). To not do 
so leaves it open to problems such as consuming the sub ranges.

I can't imagine that anyone would expect or desire the current behavior.

Ironically, when that bug is fixed, you *don't* have to call save on the 
outer range!

> When you're passing a range of ranges to a function, you need to recursively
> save them if you don't want the inner ranges in the original range to be
> consumed. Regardless of what formattedWrite does, it's a general issue with
> any function that you pass a range of ranges. It comes right back to the
> same issue of the semantics of copying ranges being unspecified and that you
> therefore must always use save on any ranges involved if you want to then
> use those ranges after having passed them to a function or copy them doing
> anything else. It's that much more annoying when you're dealing with a range
> of ranges rather than a range of something else, but the issue is the same.
> 

It's only a problem if the subranges are returned by reference. If they 
aren't, then no save is required (because they are already copies). The 
fix in this case is to make a copy if possible (using save as expected).

I think the save semantics have to be one of the worst designs in D.

-Steve


More information about the Digitalmars-d-learn mailing list