On Thursday, 10 February 2022 at 22:06:30 UTC, Dave P. wrote:
>I think it would be interesting to combine a compiler and a linker into a single executable. Not necessarily for speed reasons, but for better diagnostics and the possibility of type checking external symbols. Linker errors can sometimes be hard to understand in the presence of inlining and optimizations. The linker will report references to symbols not present in your code or present in completely different places.
For example:
extern(D) int some_func(int x);
pragma(inline, true)
private int foo(int x){
return some_func(x);
}
pragma(inline, true)
private int bar(int x){
return foo(x);
}
pragma(inline, true)
private int baz(int x){
return bar(x);
}
pragma(inline, true)
private int qux(int x){
return baz(x);
}
int main(){
return qux(2);
}
When you go to compile it:
Undefined symbols for architecture arm64:
"__D7example9some_funcFiZi", referenced from:
__D7example3fooFiZi in example.o
__D7example3barFiZi in example.o
__D7example3bazFiZi in example.o
__D7example3quxFiZi in example.o
__Dmain in example.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: /usr/bin/cc failed with status: 1
The linker sees references to the extern function in places where I never wrote that in my source code. In a nontrivial project this can be quite confusing if you’re not used to this quirk of the linking process.
If the compiler is invoking the linker for you anyway, why can’t it read the object files and libraries and tell you exactly what is missing and where in your code you reference it?
Yeah, error messages could ALWAYS be better in any compiler (even rustc) at any time. This design would make it even easier to do like you explained. Thank you!