digitalmars.D - Spec: can a class method change the type of the object (vtable) ?
- Johan (33/33) Mar 17 Hi all,
- Nick Treleaven (9/17) Mar 18 With dmd v2.108.0-rc.1 I get:
- kinke (9/26) Mar 18 Yeah, IIRC, this was only allowed in v2.105.0 and v2.105.1, then
- Johan (5/9) Mar 18 Any extern(C++) method is not safe, because C++ allows placement
- Dukc (17/25) Mar 18 This wouldn't accomplish anything if it was allowed. Remember,
Hi all, I am looking for a (legal D) counterexample where a class method alters the vtable of the object it is called on. In other words, a counterexample where the following transformation is invalid: ``` class A { void foo(); ... } void g() { A a = new A(); a.foo(); a.foo(); } ---Transformed into ---> void g() { A a = new A(); a.A.foo(); // devirtualized a.A.foo(); // devirtualized because `A.foo(a)` may not change the type of `a`. } ``` Although accepted by the compiler currently, I believe this is forbidden by the spec (can't find it, if it is not in the spec it should be added): ``` void foo() { this = new B(); // illegal D code } ``` Thanks, Johan
Mar 17
On Sunday, 17 March 2024 at 12:47:49 UTC, Johan wrote:Although accepted by the compiler currently, I believe this is forbidden by the spec (can't find it, if it is not in the spec it should be added): ``` void foo() { this = new B(); // illegal D code } ```With dmd v2.108.0-rc.1 I get: ``` thislval.d(7): Error: cannot modify expression `this` because it is not an lvalue ``` `this` was changed to be an lvalue for a few releases recently, see: https://issues.dlang.org/show_bug.cgi?id=24157
Mar 18
On Monday, 18 March 2024 at 12:44:46 UTC, Nick Treleaven wrote:On Sunday, 17 March 2024 at 12:47:49 UTC, Johan wrote:Yeah, IIRC, this was only allowed in v2.105.0 and v2.105.1, then reverted in v2.105.2. But it never changed the vptr, it just made `this` point to another object after the assignment (not affecting the callER though). I think the assumption/optimization should be safe. The only exception might be `extern(C++)` ctors in the future, if we really made those C++-compatible - they set the vptr (base ctors first to their vptr, then derived ctors overriding it later).Although accepted by the compiler currently, I believe this is forbidden by the spec (can't find it, if it is not in the spec it should be added): ``` void foo() { this = new B(); // illegal D code } ```With dmd v2.108.0-rc.1 I get: ``` thislval.d(7): Error: cannot modify expression `this` because it is not an lvalue ``` `this` was changed to be an lvalue for a few releases recently, see: https://issues.dlang.org/show_bug.cgi?id=24157
Mar 18
On Monday, 18 March 2024 at 13:50:59 UTC, kinke wrote:The only exception might be `extern(C++)` ctors in the future, if we really made those C++-compatible - they set the vptr (base ctors first to their vptr, then derived ctors overriding it later).Any extern(C++) method is not safe, because C++ allows placement new on `this` (a known issue for devirtualizing in C++). And indeed during construction things are particularly tricky in C++. -Johan
Mar 18
On Sunday, 17 March 2024 at 12:47:49 UTC, Johan wrote:Although accepted by the compiler currently, I believe this is forbidden by the spec (can't find it, if it is not in the spec it should be added): ``` void foo() { this = new B(); // illegal D code } ```This wouldn't accomplish anything if it was allowed. Remember, `foo` is ```D void foo(A this) { this = new B; } ``` under the hood. You aren't modifying the existing instance of the class with this, you're only allocating a new instance and then not doing anything neither with the old nor the new instance. I believe you meant ```D void foo() { import core.lifetime; this.destroy(false); emplace(cast(B) cast(void*) this); } ```
Mar 18