Thread overview | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 11, 2014 immutable bug? | ||||
---|---|---|---|---|
| ||||
Attachments:
| I just managed to assign a const(char)[] to a string... caused crashes when the original memory disappeared. inout(char)[] todstr(inout(char)* cstr) pure nothrow { return cstr ? cstr[0 .. std.c.string.strlen(cstr)] : cstr[0 .. 0]; } struct Data { char buffer[256] = void; @property const(char)[] filename() const pure nothrow { return todstr(buffer.ptr); } } struct MyThing { private this(in Data* p) { filename = p.filename; // *** Uh oh! assigned a const(char)[] @property to a string! *** } string filename; } Surely that assignment shouldn't be legal? Shouldn't I need to idup? |
January 11, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Saturday, 11 January 2014 at 18:29:36 UTC, Manu wrote:
> I just managed to assign a const(char)[] to a string... caused crashes when
> the original memory disappeared.
>
> inout(char)[] todstr(inout(char)* cstr) pure nothrow
> {
> return cstr ? cstr[0 .. std.c.string.strlen(cstr)] : cstr[0 .. 0];
> }
>
> struct Data
> {
> char buffer[256] = void;
> @property const(char)[] filename() const pure nothrow { return
> todstr(buffer.ptr); }
> }
>
> struct MyThing
> {
> private this(in Data* p)
> {
> filename = p.filename; // *** Uh oh! assigned a const(char)[] @property to
> a string! ***
> }
>
> string filename;
> }
>
> Surely that assignment shouldn't be legal? Shouldn't I need to idup?
I don't know about the details of what is/isn't legal here, but the only reason the compiler accepts it is because filename is marked as pure.
|
January 11, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Saturday, 11 January 2014 at 18:43:39 UTC, John Colvin wrote:
>
> I don't know about the details of what is/isn't legal here, but the only reason the compiler accepts it is because filename is marked as pure.
It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable.
|
January 11, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote:
> It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable.
It shouldn't be here though... the reason it is implicitly convertable is that pure means the result is unique. But, with the hidden this pointer having a reference to the data as well, it obviously is not unique. I think the compiler should catch this; i'd call it a bug.
|
January 11, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote:
> On Saturday, 11 January 2014 at 18:43:39 UTC, John Colvin wrote:
>>
>> I don't know about the details of what is/isn't legal here, but the only reason the compiler accepts it is because filename is marked as pure.
>
> It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable.
I had heard this mentioned before; is it true in all cases?
Even when the function returns a reference to external data?
|
January 11, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On Saturday, 11 January 2014 at 18:29:36 UTC, Manu wrote:
> I just managed to assign a const(char)[] to a string... caused crashes when
> the original memory disappeared.
>
> inout(char)[] todstr(inout(char)* cstr) pure nothrow
> {
> return cstr ? cstr[0 .. std.c.string.strlen(cstr)] : cstr[0 .. 0];
> }
>
> struct Data
> {
> char buffer[256] = void;
> @property const(char)[] filename() const pure nothrow { return
> todstr(buffer.ptr); }
> }
>
> struct MyThing
> {
> private this(in Data* p)
> {
> filename = p.filename; // *** Uh oh! assigned a const(char)[] @property to
> a string! ***
> }
>
> string filename;
> }
>
> Surely that assignment shouldn't be legal? Shouldn't I need to idup?
Simplified:
const(char)[] slice(ref const char[1] c) pure nothrow
{
return c[];
}
void main()
{
char[1] m = ".";
immutable i = slice(m); // should not compile
assert(i == ".");
m = "!"; // uh-oh
assert(i == "."); // fails
}
|
January 11, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Saturday, 11 January 2014 at 18:52:39 UTC, Adam D. Ruppe wrote:
> On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote:
>> It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable.
>
> It shouldn't be here though... the reason it is implicitly convertable is that pure means the result is unique. But, with the hidden this pointer having a reference to the data as well, it obviously is not unique. I think the compiler should catch this; i'd call it a bug.
Creating undefined behavior is not a sufficient reason to be a bug.
Changelog mentions example with pure struct constructors which provide value implicitly castable to immutable. So, strictly speaking current behavior is conforming to spec.
You can still argue that the example does not address the issue with 'this' parameter, so code should be rejected (which should happen from safity aspect). I think this case was not considered when 'unique expression' was introduced, so it is yet another hole in type system (to be more precise, bug is in spec-language, not compiler).
|
January 11, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | On 01/11/2014 08:16 PM, Maxim Fomin wrote: > On Saturday, 11 January 2014 at 18:52:39 UTC, Adam D. Ruppe wrote: >> On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: >>> It is legal exactly because function is marked as pure. Result of >>> pure function is implicitly convertible to immutable. >> >> It shouldn't be here though... the reason it is implicitly convertable >> is that pure means the result is unique. But, with the hidden this >> pointer having a reference to the data as well, it obviously is not >> unique. I think the compiler should catch this; i'd call it a bug. > > Creating undefined behavior is not a sufficient reason to be a bug. > ... Add a @safe annotation and it is. > Changelog mentions example with pure struct constructors which provide > value implicitly castable to immutable. So, strictly speaking current > behavior is conforming to spec. > > You can still argue that the example does not address the issue with > 'this' parameter, so code should be rejected (which should happen from > safity aspect). I think this case was not considered when 'unique > expression' was introduced, so it is yet another hole in type system (to > be more precise, bug is in spec-language, not compiler). It is an implementation bug. Implicit conversion to immutable is only supposed to work for strongly pure functions. |
January 12, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Saturday, 11 January 2014 at 21:16:55 UTC, Timon Gehr wrote: > It is an implementation bug. Implicit conversion to immutable is only supposed to work for strongly pure functions. Can someone that knows all the details of the purity strength semantic differences please open a PR to get some documentation in the spec? I've updated this bug with a comment: https://d.puremagic.com/issues/show_bug.cgi?id=7456 |
January 12, 2014 Re: immutable bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe Attachments:
| On 12 January 2014 04:52, Adam D. Ruppe <destructionator@gmail.com> wrote: > On Saturday, 11 January 2014 at 18:48:15 UTC, Maxim Fomin wrote: > >> It is legal exactly because function is marked as pure. Result of pure function is implicitly convertible to immutable. >> > > It shouldn't be here though... the reason it is implicitly convertable is that pure means the result is unique. Can you explain how this is true? I can't see anything about the concept of purity that suggests the result should be unique... Pure just means given the same inputs, it will produce the same outputs; external state can't affect the calculation. In this case, that's perfectly true. 'this' is just a function arg; it's not mutated by external state (or at all), given the same this, it will return the same thing every time. That doesn't make any claims about what 'this' is though, and whether it's immutable or 'unique' or whatever. It just promises to transform it in an identical way given the same inputs... ? But, with the hidden this pointer having a reference to the data as well, > it obviously is not unique. I think the compiler should catch this; i'd call it a bug. > |
Copyright © 1999-2021 by the D Language Foundation