Conditional declaration not found
module test;
import foo;
fn void main() {}
extern fn void func() @if(foo::FOO == 0);
// ^^^
// Error: 'foo::FOO' could not be found, did you spell it right?
module foo;
const int FOO @if(env::WIN32) = 0;
const int FOO @if(env::LINUX) = 1;
const int FOO @if(env::DARWIN) = 2;
If I put module foo before module test, it compiles fine.
This is due to a fundamental issue with conditional code.
Not even this works:
module test;
fn void main() {}
extern fn void func() @if(FOO == 0);
const int FOO @if(env::WIN32) = 0;
const int FOO @if(env::LINUX) = 1;
const int FOO @if(env::DARWIN) = 2;
As soon as we start using @if we potentially have ordering issues. While it's possible to detect very simple things such as:
const int FOO @if($defined(func)) = 0;
extern fn void func() @if(FOO == 0);
The more general case may have much more subtle resolution complexities which would need to have a more advanced way of solving it.
For this reason this is highly restricted in C3, as it can lead to quite unexpected resolutions otherwise.
Instead, the recommended way is to use a compile time execution rather than conditional inclusion. Our example could be written:
module test;
import foo;
fn void main() {}
extern fn void func() @if(foo::FOO == 0);
// ---
module foo;
const int FOO = @foo_value();
macro @foo_value()
{
$switch
$case env::WIN32: return 0;
$case env::LINUX: return 1;
$case env::DARWIN: return 2;
$default: return -1;
$endswitch
}
And it's now well defined.
However, there are cases where the original example might work because of ordering. I think this is unfortunate: having @if to depend on some other @if seems very fraught with danger. So it might be that this should be disallowed entirely. That is having the rule that "while resolving an @if – evaluating a global type/function/variable that itself is guarded by @if is a compile time error".
The compile time macro is a good replacement for my use case.
I'm in favor to emit an error, otherwise it's just potentially confusing UB.
Please try the latest, which should emit an error.
Yes, I'm now getting the error if I go back to my original code.
So then we can close this or?