D Library Breakage

Steven Schveighoffer schveiguy at yahoo.com
Fri Apr 13 23:20:13 UTC 2018


On 4/13/18 7:00 PM, Jonathan Marler wrote:

> @Steven You're just addressing the example I gave and not thinking of 
> all the other ways version (or other compiler flags) could change 
> things.  For example, you could have version code inside a template that 
> changes mangling because it is no longer inferred to be pure/safe/whatever.

Yeah, but that results in a linker error. Your solution results in a 
linker error as well. Either way, you need to adjust your build. Trying 
to make the liner spit out a nice error is an exercise in futility.

> The point is, this is a solvable problem.  All we need to do is save the 
> compiler configuration (i.e. versions/special flags that affects 
> compilation) used when compiling a library and use that information when 
> we are interpreting the module's source as as an "pre-compiled import". 
> Interpreting a module with a different version than was compiled can 
> create any error you can possibly come up with and could manifest at any 
> time (i.e. compile-time, link time, runtime).

consider:

int libraryFunction(int x)
{
     version(UseSpecializedMethod)
     {
        // do it the specialized way
        ...
     }
     else
     {
        // do it the slow way
        ...
     }
}

Do we need to penalize user code that doesn't define the library-special 
version UseSpecializedMethod? Making code not link because it didn't 
define library specific implementation details the same as the library 
isn't going to help.

> The jist is that if we don't solve this, then it's up to the 
> applications to use the same versions that were used to compile all 
> their pre-compiled D libraries...and if they don't...all bets are off.  
> They could run into any error at any time and the compiler/type system 
> can't help them.

For versions, it only makes a difference if the versions affect the 
public API (and in a silent way). I'm fine with linker errors to 
diagnose these.

Note: it's really bad form to make a library who has public API changes 
when you define different versions. It's why I'm trying to eliminate all 
of those cases for version(unittest) from phobos.

For compiler features, if you get different symbols from the exact same 
code (in other words, ALL code involved is exactly the same), then it 
may be useful to embed such a compilation linker mechanism to give a 
somewhat better linker error. For example, with dip1000, if a library 
function using dip1000 adds an attribute that normally wouldn't be 
added, you could include such a symbol, and then the linker failure 
would show that symbol missing (and hopefully clue in the user).

But even this has drawbacks -- what if you never call that function? Now 
you are having a linker error where there normally wouldn't be.

But there are actually a couple real ways to solve this, and they aren't 
simple. One is to invent our own linker/object format that allows 
embedding the stuff we want. Then you don't import source, you import 
the object (this is similar to Java).

The second is to actually spit out a specialized import file that puts 
the right attributes/definitions on the public API (and should include 
any implementation that needs to be inlined or templated).

-Steve


More information about the Digitalmars-d mailing list