www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Linker anomalies

reply Luh <null null.null> writes:
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
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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 error 
message. 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
parent Luh <null null.null> writes:
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 :o
 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.
 [...]
error message. [...]
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)
 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
prev sibling parent user5678 <user5678 1234.de> writes:
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