c3c icon indicating copy to clipboard operation
c3c copied to clipboard

Enhancement request of symbol names resolving

Open vssukharev opened this issue 4 months ago • 4 comments

Suppose we have some code which @exports a name and immediately use it via @extern in the same module (!):

import std::io;

extern fn void f(String h) @extern("f");
fn void impl_f(String h) @export("f") => io::printfn(h); 

fn void main()
{
  f("123");
}

Here is what we have:

/nix/store/wi0nl3i48dl27dalzrrlq4n9a6mrl63y-binutils-2.44/bin/ld: build/obj/linux-x64/main.o: in function `main.main':
/home/starleks/coding/probe/c3-sandbox/main.c3:9:(.text+0x41): undefined reference to `f'
collect2: error: ld returned 1 exit status
Failed to link executable 'build/main' using command 'cc -o build/main -rdynamic -pthread build/obj/linux-x64/std_collections_list.std.os.backtrace.Backtrace.o build/obj/linux-x64/
std.core.ascii.o build/obj/linux-x64/std.core.mem.o build/obj/linux-x64/std.core.string.conv.o build/obj/linux-x64/std.core.mem.allocator.o build/obj/linux-x64/std.core.dstring.o b
uild/obj/linux-x64/std.core.types.o build/obj/linux-x64/std.core.string.o build/obj/linux-x64/std.core.builtin.o build/obj/linux-x64/std.io.file.o build/obj/linux-x64/std.io.os.o b
uild/obj/linux-x64/std.io.o build/obj/linux-x64/std.atomic.o build/obj/linux-x64/std.math.o build/obj/linux-x64/std.math.math_rt.o build/obj/linux-x64/std.os.posix.o build/obj/linu
x-x64/std.os.backtrace.o build/obj/linux-x64/std.os.linux.o build/obj/linux-x64/std.os.process.o build/obj/linux-x64/libc.o build/obj/linux-x64/main.o -ldl -lm'.

And what will be if we swap the definition and declaration in order:

import std::io;

fn void impl_f(String h) @export("f") => io::printfn(h); 
extern fn void f(String h) @extern("f");

fn void main()
{
  f("123");
}

The second one works:

Program linked to executable 'build/main'.
Launching ./build/main
123
Program completed with exit code 0.

I propose to feed the both cases as correct without needing to order it properly. P.S. The issue is not present if we divide those into two different modules

vssukharev avatar Aug 10 '25 12:08 vssukharev

I understand the linker error and the proposal to make both orders work. But why would we need @extern to reference a symbol defined in the same module? Normally @extern is for importing external symbols (e.g. from C). If the implementation is already in the same module, you can just call it directly.

Supporting an order-independent same-module @extern + @export combination adds compiler complexity for a usage pattern that seems unnecessary outside of specific test scenarios.

chrischtel avatar Aug 10 '25 12:08 chrischtel

I understand the linker error and the proposal to make both orders work. But why would we need @extern to reference a symbol defined in the same module? Normally @extern is for importing external symbols (e.g. from C). If the implementation is already in the same module, you can just call it directly.

Supporting an order-independent same-module @extern + @export combination adds compiler complexity for a usage pattern that seems unnecessary outside of specific test scenarios.

It's all about consistency. We can just prohibit @extern and @export in the same module. However, it will then cut off the possibility to expand the module with the implementation. Sounds hacky but might be useful - that's why C has retrieved such a success, because of hacky stuff you can do with it (one of many reasons).

vssukharev avatar Aug 10 '25 13:08 vssukharev

Okay. We have to see what @lerno thinks.

chrischtel avatar Aug 10 '25 13:08 chrischtel

There is a related feature, @weak which should work with this but doesn't. I need to reexamine its use.

lerno avatar Aug 25 '25 10:08 lerno