[Issue 1654] Array concatenation should result in mutable or invariant depending on usage
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Thu Jan 31 15:49:14 PST 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1654
------- Comment #6 from schveiguy at yahoo.com 2008-01-31 17:49 -------
I still believe the rule works.
The general rule I am extending is, for any basic type(int, char, byte, etc.),
you can copy an invariant version to a mutable version without issue. i.e.:
invariant(int) x = 1;
int y = x; // works (I think :)
If we imagine that any time you copy a structure or a buffer, instead of doing
a memcpy (which is an implementation detail), you do a copy of each
member/element.
so:
char[5] x;
x[] = "hello";
is equivalent to:
foreach(i, c; "hello")
x[i] = c;
Which should work because of the first rule (I can copy an invariant(char) to a
char).
Now, for a struct, you can postulate the same thing:
struct S
{
int x;
}
invariant(S) s1 = cast(invariant)S(1);
S s2;
s2 = s1;
is equivalent to:
s2.x = s1.x;
Which should work because of the first rule.
However, if we think about pointers:
invariant(char)* cp = "hello".ptr;
char * cp2;
cp2 = cp;
this fails because now you have a mutable pointer to invariant data. Here is
the rule I am trying to exploit. Because a type has a pointer in it:
struct S
{
char *cp;
}
invariant(S) s1;
S s2;
s2 = s1;
This is equivalent to:
s2.cp = s1.cp;
which fails the rule above, so the whole thing fails.
With your new syntax, let's look at how it works:
struct Value {
int * p = null;
this() { p = new int; }
~this() { delete p; }
this(scope) { p = new int(*p); }
}
invariant(Value) v1;
Value v2;
v2 = v1;
Now, this is possible. Because instead of using p, we are using *p, which is
of type invariant(int). invariant(int) can be casted to int implicitly, and so
the rule still works.
I'm not sure if this was intended as a use for your new syntax, but I certainly
still believe that it doesn't break the rules (BTW, I like the idea).
Addressing your point about parting types if they contain pointers are not, I
don't really think of it that way. What I think of it as is that an invariant
pointer cannot be implicitly copied to a mutable pointer. If by copying a
type, you have to copy an invariant pointer to a mutable pointer, then the
compile fails. If you do not have to copy an invariant pointer to a mutable
pointer, then the copy works. It's just easier to explain as "types that
contain invariant pointers cannot be copied to a non-invariant version of the
type". The compiler can check this without adding extra runtime information,
so implementation-wise it does not affect the output. Semantic-wise, it
doesn't break existing code, it just allows operations that should be valid but
aren't under the current scheme. In fact, I think it's more consistent with
the way builtin types work.
BTW, the same applies to const.
-Steve
--
More information about the Digitalmars-d-bugs
mailing list