digitalmars.D - opEquals(const ref yadaYada)
- dsimcha (20/20) Dec 12 2009 I've noticed that, for DMD 2.037, we've started mandating that the input
- Richard Webb (7/7) Dec 12 2009 Hi,
- Steven Schveighoffer (4/16) Dec 13 2009 Note the resulting bug: http://d.puremagic.com/issues/show_bug.cgi?id=36...
- lws (18/41) Dec 14 2009 I don't know if I buy that the opEquals thing is a bug. However,
- lws (8/33) Dec 14 2009 I don't know if I believe this is necesarrily bad. It's revealing some
- Leandro Lucarella (15/52) Dec 14 2009 If you are using "garbage collected" as a general term to denote
- lws (10/56) Dec 14 2009 Unless I'm confused, classses are ALWAYS heap (unless explicitely
- Leandro Lucarella (11/34) Dec 14 2009 Yes, and classes are always references too. But that's not even the poin...
- lws (5/37) Dec 14 2009 Even if they are always references, they behave as pass-by-value types.
- dsimcha (4/10) Dec 14 2009 1. This was in DFL's code, not stuff I wrote.
- lws (15/26) Dec 14 2009 1. Well, stuff like this is good warning to whomever about the code.
- dsimcha (8/34) Dec 14 2009 Right, but only if this warning doesn't have too many false positives th...
- Steven Schveighoffer (32/57) Dec 15 2009 It's not faster, it's slower. Passing a reference to an integer or
- Simen kjaeraas (6/15) Dec 15 2009 This is hardly true on modern architectures. I don't have the numbers on
- Steven Schveighoffer (10/25) Dec 15 2009 I don't see how this is possible. It's a double-indirection vs. a singl...
- Sergey Gromov (4/21) Dec 15 2009 To return a reference you must allocate the value. And to use the value...
I've noticed that, for DMD 2.037, we've started mandating that the input parameter for struct opEquals be const ref T. This seemed like a good idea initially, but it creates the horribly leaky abstraction that the right-hand argument to opEquals can't be an rvalue. Example: struct Foo { bool opEquals(const ref Foo rhs) const { // Only signature // that compiles. return true; } } Foo getFoo() { return Foo(); } void main() { Foo foo = getFoo(); bool isEqual = foo == getFoo(); } Error: Foo.opEquals type signature should be const bool(ref const(Foo)) not const bool(Foo rhs) Will this be getting fixed witht he new operator overloading?
Dec 12 2009
Hi, I mentioned this problem in the thread http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=18405 I ran into the rvalue problem while trying to get Juno to compile, and found that it builds ok if you declare both bool opEquals(const ref Foo rhs) const and bool opEquals(Foo rhs) const
Dec 12 2009
Richard Webb Wrote:Hi, I mentioned this problem in the thread http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=18405 I ran into the rvalue problem while trying to get Juno to compile, and found that it builds ok if you declare both bool opEquals(const ref Foo rhs) const and bool opEquals(Foo rhs) constNote the resulting bug: http://d.puremagic.com/issues/show_bug.cgi?id=3607 I also don't believe Richard's workaround is a "solution". The compiler should not force you to create a const ref version if the argument can be implicitly cast from const to mutable. -Steve
Dec 13 2009
On 2009-12-13 04:29:28 -0800, Steven Schveighoffer <schveiguy yahoo.com> said:Richard Webb Wrote:IHi, I mentioned this problem in the thread http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=18405I don't know if I buy that the opEquals thing is a bug. However, that const destructor thing in the other thread needs to be fixed. //////////////////////////////// struct Foo { ~this() { } } void Bar() { const Foo f; } //////////////////////////////// Definitely produces incorrect behavior.ran into the rvalue problem while trying to get Juno to compile, and found that it builds ok if you declare both bool opEquals(const ref Foo rhs) const and bool opEquals(Foo rhs) constNote the resulting bug: http://d.puremagic.com/issues/show_bug.cgi?id=3607 I also don't believe Richard's workaround is a "solution". The compiler should not force you to create a const ref version if the argument can be implicitly cast from const to mutable. -Steve
Dec 14 2009
I don't know if I believe this is necesarrily bad. It's revealing some bad coding on your part. You shouldn't be doing opEquals with an rvalue of a class. Make getFoo return a reference. ref Foo getFoo() {} fixes the problem and avoids value-copying for no reason to an rvalue that's going to get garbage collected. -lws On 2009-12-12 07:14:50 -0800, dsimcha <dsimcha yahoo.com> said:I've noticed that, for DMD 2.037, we've started mandating that the input parameter for struct opEquals be const ref T. This seemed like a good idea initially, but it creates the horribly leaky abstraction that the right-hand argument to opEquals can't be an rvalue. Example: struct Foo { bool opEquals(const ref Foo rhs) const { // Only signature // that compiles. return true; } } Foo getFoo() { return Foo(); } void main() { Foo foo = getFoo(); bool isEqual = foo == getFoo(); } Error: Foo.opEquals type signature should be const bool(ref const(Foo)) not const bool(Foo rhs) Will this be getting fixed witht he new operator overloading?
Dec 14 2009
lws, el 14 de diciembre a las 01:06 me escribiste:I don't know if I believe this is necesarrily bad. It's revealing some bad coding on your part. You shouldn't be doing opEquals with an rvalue of a class. Make getFoo return a reference. ref Foo getFoo() {} fixes the problem and avoids value-copying for no reason to an rvalue that's going to get garbage collected.If you are using "garbage collected" as a general term to denote "automatic memory reclamation", you are right, but the garbage collector have nothing to do with rvalues, they are allocated in the stack, and they will be "garbage collected" by the compiler when unwinding the stack, not the GC. I don't know if this is relevant to the discussion, I'm clarifying, just in case :)On 2009-12-12 07:14:50 -0800, dsimcha <dsimcha yahoo.com> said:-- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- I would drape myself in velvet if it were socially acceptable. -- George ConstanzaI've noticed that, for DMD 2.037, we've started mandating that the input parameter for struct opEquals be const ref T. This seemed like a good idea initially, but it creates the horribly leaky abstraction that the right-hand argument to opEquals can't be an rvalue. Example: struct Foo { bool opEquals(const ref Foo rhs) const { // Only signature // that compiles. return true; } } Foo getFoo() { return Foo(); } void main() { Foo foo = getFoo(); bool isEqual = foo == getFoo(); } Error: Foo.opEquals type signature should be const bool(ref const(Foo)) not const bool(Foo rhs) Will this be getting fixed witht he new operator overloading?
Dec 14 2009
Unless I'm confused, classses are ALWAYS heap (unless explicitely scoped) objects in D. The garbage collector is the one that is tasked with reclaiming their memory and calling their deconstructor. If you want the semantics you're talking about Foo would need to be a "scoped Foo foo = new Foo();" I could be wrong, I haven't had a change to touch D in about a year though, some stuff could have changed. (And please don't top quote, argh! ;)) -SC On 2009-12-14 05:47:44 -0800, Leandro Lucarella <llucax gmail.com> said:lws, el 14 de diciembre a las 01:06 me escribiste:I don't know if I believe this is necesarrily bad. It's revealing some bad coding on your part. You shouldn't be doing opEquals with an rvalue of a class. Make getFoo return a reference. ref Foo getFoo() {} fixes the problem and avoids value-copying for no reason to an rvalue that's going to get garbage collected.If you are using "garbage collected" as a general term to denote "automatic memory reclamation", you are right, but the garbage collector have nothing to do with rvalues, they are allocated in the stack, and they will be "garbage collected" by the compiler when unwinding the stack, not the GC. I don't know if this is relevant to the discussion, I'm clarifying, just in case :)On 2009-12-12 07:14:50 -0800, dsimcha <dsimcha yahoo.com> said:I've noticed that, for DMD 2.037, we've started mandating that the input parameter for struct opEquals be const ref T. This seemed like a good idea initially, but it creates the horribly leaky abstraction that the right-hand argument to opEquals can't be an rvalue. Example: struct Foo { bool opEquals(const ref Foo rhs) const { // Only signature // that compiles. return true; } } Foo getFoo() { return Foo(); } void main() { Foo foo = getFoo(); bool isEqual = foo == getFoo(); } Error: Foo.opEquals type signature should be const bool(ref const(Foo)) not const bool(Foo rhs) Will this be getting fixed witht he new operator overloading?
Dec 14 2009
lws, el 14 de diciembre a las 08:31 me escribiste:Unless I'm confused, classses are ALWAYS heap (unless explicitely scoped) objects in D.Yes, and classes are always references too. But that's not even the point, the point is, the example was a struct :)[snip]struct Foo { bool opEquals(const ref Foo rhs) const { // Only signature // that compiles. return true; } } Foo getFoo() { return Foo(); } void main() { Foo foo = getFoo(); bool isEqual = foo == getFoo(); } Error: Foo.opEquals type signature should be const bool(ref const(Foo)) not const bool(Foo rhs) Will this be getting fixed witht he new operator overloading?(And please don't top quote, argh! ;))!!! -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Every day 21 new born babies will be given to the wrong parents
Dec 14 2009
On 2009-12-14 11:04:53 -0800, Leandro Lucarella <llucax gmail.com> said:lws, el 14 de diciembre a las 08:31 me escribiste:Even if they are always references, they behave as pass-by-value types. Also, excuse me I read struct as class for some reason earlier. (*doh!*) This error-that-should-be-warning is for both types though.Unless I'm confused, classses are ALWAYS heap (unless explicitely scoped) objects in D.Yes, and classes are always references too. But that's not even the point, the point is, the example was a struct :)[snip]struct Foo { bool opEquals(const ref Foo rhs) const { // Only signature // that compiles. return true; } } Foo getFoo() { return Foo(); } void main() { Foo foo = getFoo(); bool isEqual = foo == getFoo(); } Error: Foo.opEquals type signature should be const bool(ref const(Foo)) not const bool(Foo rhs) Will this be getting fixed witht he new operator overloading?(And please don't top quote, argh! ;))!!!
Dec 14 2009
== Quote from lws (invalid email.com)'s articleI don't know if I believe this is necesarrily bad. It's revealing some bad coding on your part. You shouldn't be doing opEquals with an rvalue of a class. Make getFoo return a reference. ref Foo getFoo() {} fixes the problem and avoids value-copying for no reason to an rvalue that's going to get garbage collected.1. This was in DFL's code, not stuff I wrote. 2. It was a small struct that was cheap to copy, not a class. 3. At any rate, the inconsistency with builtins is inexcusable.
Dec 14 2009
On 2009-12-14 07:01:47 -0800, dsimcha <dsimcha yahoo.com> said:== Quote from lws (invalid email.com)'s article1. Well, stuff like this is good warning to whomever about the code. Since D is a imperative language, it should at least give you a warning when you're doing something really inefficient that has a boilerplate way of accomplishing it that is much faster. 2. That's odd. structs DO have stack scope in D. Right? It shouldn't even warn in that case. IMHO. 3. For classes, it is consistent with the whole point of the new const stuff and the GC, and the fact that they are heap objects by definition. Classes have always been treated "differently." And I think it's good. Walter has enabled a lot of expressiveness with the syntax in D when compared to C++, and it allows nice warnings when you're doing things you probably shouldn't. Unfortunately, this isn't an error.... Maybe for some reason you REALLY want to be copying around structs and classes.I don't know if I believe this is necesarrily bad. It's revealing some bad coding on your part. You shouldn't be doing opEquals with an rvalue of a class. Make getFoo return a reference. ref Foo getFoo() {} fixes the problem and avoids value-copying for no reason to an rvalue that's going to get garbage collected.1. This was in DFL's code, not stuff I wrote. 2. It was a small struct that was cheap to copy, not a class. 3. At any rate, the inconsistency with builtins is inexcusable.
Dec 14 2009
== Quote from lws (invalid email.com)'s articleOn 2009-12-14 07:01:47 -0800, dsimcha <dsimcha yahoo.com> said:Right, but only if this warning doesn't have too many false positives that are just annoying when the programmer **does** know what he/she is doing. In this case, passing small structs by value isn't inefficient.== Quote from lws (invalid email.com)'s article1. Well, stuff like this is good warning to whomever about the code. Since D is a imperative language, it should at least give you a warning when you're doing something really inefficient that has a boilerplate way of accomplishing it that is much faster.I don't know if I believe this is necesarrily bad. It's revealing some bad coding on your part. You shouldn't be doing opEquals with an rvalue of a class. Make getFoo return a reference. ref Foo getFoo() {} fixes the problem and avoids value-copying for no reason to an rvalue that's going to get garbage collected.1. This was in DFL's code, not stuff I wrote. 2. It was a small struct that was cheap to copy, not a class. 3. At any rate, the inconsistency with builtins is inexcusable.2. That's odd. structs DO have stack scope in D. Right? It shouldn't even warn in that case. IMHO.That's my whole point. The behavior is a bug, not a feature.3. For classes, it is consistent with the whole point of the new const stuff and the GC, and the fact that they are heap objects by definition. Classes have always been treated "differently." And I think it's good. Walter has enabled a lot of expressiveness with the syntax in D when compared to C++, and it allows nice warnings when you're doing things you probably shouldn't. Unfortunately, this isn't an error.... Maybe for some reason you REALLY want to be copying around structs and classes.Maybe what we need is for it to be legal to pass rvalues to functions that expect const ref params. If it's an rvalue, just place it on the caller's stack frame implicitly and be done with it.
Dec 14 2009
On Mon, 14 Dec 2009 11:44:18 -0500, lws <invalid email.com> wrote:On 2009-12-14 07:01:47 -0800, dsimcha <dsimcha yahoo.com> said:It's not faster, it's slower. Passing a reference to an integer or smaller value type is not as efficient passing the value type itself.== Quote from lws (invalid email.com)'s article1. Well, stuff like this is good warning to whomever about the code. Since D is a imperative language, it should at least give you a warning when you're doing something really inefficient that has a boilerplate way of accomplishing it that is much faster.I don't know if I believe this is necesarrily bad. It's revealing some bad coding on your part. You shouldn't be doing opEquals with an rvalue of a class. Make getFoo return a reference. ref Foo getFoo() {} fixes the problem and avoids value-copying for no reason to an rvalue that's going to get garbage collected.1. This was in DFL's code, not stuff I wrote. 2. It was a small struct that was cheap to copy, not a class. 3. At any rate, the inconsistency with builtins is inexcusable.2. That's odd. structs DO have stack scope in D. Right? It shouldn't even warn in that case. IMHO.The issue is that the compiler is incorrectly assuming that it *must* use a const ref form of opEquals for a member when composing an opEquals function for a struct that doesn't provide one. To this end, it always ensures any overload set of opEquals has a const ref form. The premise that const ref is always required is false in some cases, and this is the bug.3. For classes, it is consistent with the whole point of the new const stuff and the GC, and the fact that they are heap objects by definition. Classes have always been treated "differently." And I think it's good. Walter has enabled a lot of expressiveness with the syntax in D when compared to C++, and it allows nice warnings when you're doing things you probably shouldn't.Classes should be allowed to be passed as const only, no ref. Passing a reference to a class makes no sense since they are references already (Even scoped class variables are references). In fact, const ref makes absolutely no sense for a class, ever.Unfortunately, this isn't an error.... Maybe for some reason you REALLY want to be copying around structs and classes.It is an error, not a warning. The following opEquals functions should always compile: struct S1 { int x; bool opEquals(S1 s) const { return true; } } struct S2 { int *x; bool opEquals(const S2 s) const { return true; } } The following should not necessarily compile: struct Sbad { int *x; bool opEquals(Sbad s) const { return true; } } -Steve
Dec 15 2009
Steven Schveighoffer <schveiguy yahoo.com> wrote:On Mon, 14 Dec 2009 11:44:18 -0500, lws <invalid email.com> wrote:This is hardly true on modern architectures. I don't have the numbers on it, but even for ints and floats, ref is just as fast (and sometimes faster). -- SimenOn 2009-12-14 07:01:47 -0800, dsimcha <dsimcha yahoo.com> said: 1. Well, stuff like this is good warning to whomever about the code. Since D is a imperative language, it should at least give you a warning when you're doing something really inefficient that has a boilerplate way of accomplishing it that is much faster.It's not faster, it's slower. Passing a reference to an integer or smaller value type is not as efficient passing the value type itself.
Dec 15 2009
On Tue, 15 Dec 2009 18:41:30 -0500, Simen kjaeraas <simen.kjaras gmail.com> wrote:Steven Schveighoffer <schveiguy yahoo.com> wrote:I don't see how this is possible. It's a double-indirection vs. a single indirection when you look at the value. Yes, it might be inlined, making the lookup just as fast as if it were a stack variable, but I don't see how it could be faster. I guess it may be faster if you don't actually use the value in the function. Besides that point, passing ints or floats by value is not "something really inefficient" that should be considered a compiler error. -SteveOn Mon, 14 Dec 2009 11:44:18 -0500, lws <invalid email.com> wrote:This is hardly true on modern architectures. I don't have the numbers on it, but even for ints and floats, ref is just as fast (and sometimes faster).On 2009-12-14 07:01:47 -0800, dsimcha <dsimcha yahoo.com> said: 1. Well, stuff like this is good warning to whomever about the code. Since D is a imperative language, it should at least give you a warning when you're doing something really inefficient that has a boilerplate way of accomplishing it that is much faster.It's not faster, it's slower. Passing a reference to an integer or smaller value type is not as efficient passing the value type itself.
Dec 15 2009
Simen kjaeraas wrote:Steven Schveighoffer <schveiguy yahoo.com> wrote:To return a reference you must allocate the value. And to use the value you must dereference the reference. All this takes cycles no matter how modern your architecture is.On Mon, 14 Dec 2009 11:44:18 -0500, lws <invalid email.com> wrote:This is hardly true on modern architectures. I don't have the numbers on it, but even for ints and floats, ref is just as fast (and sometimes faster).On 2009-12-14 07:01:47 -0800, dsimcha <dsimcha yahoo.com> said: 1. Well, stuff like this is good warning to whomever about the code. Since D is a imperative language, it should at least give you a warning when you're doing something really inefficient that has a boilerplate way of accomplishing it that is much faster.It's not faster, it's slower. Passing a reference to an integer or smaller value type is not as efficient passing the value type itself.
Dec 15 2009