digitalmars.D.learn - Linker anomalies
- Luh (43/43) Nov 07 2019 Hey there,
- =?UTF-8?Q?Ali_=c3=87ehreli?= (33/74) Nov 07 2019 That's an important warning where the programmer can get surprising
- Luh (6/20) Nov 07 2019 It would be clever to show the correct error message :)
- user5678 (3/46) Nov 07 2019 The diagnostic might be bad but at least the compiler doesn't
Hey there, I figured out some strange behavior ; It seems that the linker doesn't check for the function declared twice first. Instead, it says: "Error: class app.Child use of app.Parent.foo() is hidden by Child; use alias foo = Parent.foo; to introduce base class overload set" but when we call it ( p.foo() ), then it returns the correct error message. The template update() compiles fine until we call it. Bizarre, isn't it ? code: --- void main() { auto p = new Parent(); // Shows the wrong error message until uncommented //p.foo(); // Compiles when commented //update(p); } class Child : Parent { override void foo() { } } class Parent { void foo() { } void foo() { } } void update(T)(T object) if(is(T == Parent)) { static if (is(T == Parent)) { // Shouldn't compile ObjectThatDoesntExists.bar(T); } } --- Is this a bug ?
Nov 07 2019
On 11/07/2019 04:14 AM, Luh wrote:Hey there, I figured out some strange behavior ; It seems that the linker doesn't check for the function declared twice first.It's not the linker but the "compiler" that is concerned about these things.Instead, it says: "Error: class app.Child use of app.Parent.foo() is hidden by Child; use alias foo = Parent.foo; to introduce base class overload set"That's an important warning where the programmer can get surprising results depending on whether the object is used through the Parent interface or the Child interface.but when we call it ( p.foo() ), then it returns the correct errormessage. It indicates to me that the compiler is performing certain checks lazily likely for performance reasons.The template update() compiles fine until we call it.That's common for templates: As long as it's syntactically correct, some errors are delayed until instantiation time.Bizarre, isn't it ?I've seen worse. :)code: --- void main() { auto p = new Parent(); // Shows the wrong error message until uncommented //p.foo(); // Compiles when commented //update(p); } class Child : Parent { override void foo() { } } class Parent { void foo() { } void foo() { }Apparently, the compiler does not check whether an overload set has ambiguities until actual use. I suspect the opposite would slow dow compilation and cause frustration in some cases.} void update(T)(T object) if(is(T == Parent)) { static if (is(T == Parent)) { // Shouldn't compile ObjectThatDoesntExists.bar(T); } } --- Is this a bug ?It should compile because ObjectThatDoesntExists may actually be present when T==Parent depending on other conditions in the program. A simple example: // Called only in some case: version (X) update(p); // And that case happens to introduce ObjectThatDoesntExists: version (X) { class O { void bar() { } } O ObjectThatDoesntExists; // <-- Now the code will compile } // version Remember that ObjectThatDoesntExists may even be introduced by another module, which may be compiled separately with e.g. different compilation options (e.g. --version=X). So, it's not possible for the compiler to detect such cases. It's an error only if the template is actually instantiated. Ali
Nov 07 2019
On Thursday, 7 November 2019 at 18:45:21 UTC, Ali Çehreli wrote:On 11/07/2019 04:14 AM, Luh wrote: It's not the linker but the "compiler" that is concerned about these things. [...]Oops :oThat's an important warning where the programmer can get surprising results depending on whether the object is used through the Parent interface or the Child interface.It would be clever to show the correct error message :) (I spend 1 hour to find what was the problem haha. I hope the others newbies won't make the same mistake)[...]error message. [...]Apparently, the compiler does not check whether an overload set has ambiguities until actual use. I suspect the opposite would slow dow compilation and cause frustration in some cases. [...]Thanks for the tips.
Nov 07 2019
On Thursday, 7 November 2019 at 12:14:43 UTC, Luh wrote:Hey there, I figured out some strange behavior ; It seems that the linker doesn't check for the function declared twice first. Instead, it says: "Error: class app.Child use of app.Parent.foo() is hidden by Child; use alias foo = Parent.foo; to introduce base class overload set" but when we call it ( p.foo() ), then it returns the correct error message. The template update() compiles fine until we call it. Bizarre, isn't it ? code: --- void main() { auto p = new Parent(); // Shows the wrong error message until uncommented //p.foo(); // Compiles when commented //update(p); } class Child : Parent { override void foo() { } } class Parent { void foo() { } void foo() { } } void update(T)(T object) if(is(T == Parent)) { static if (is(T == Parent)) { // Shouldn't compile ObjectThatDoesntExists.bar(T); } } --- Is this a bug ?The diagnostic might be bad but at least the compiler doesn't crash, yay, woohoo !
Nov 07 2019