c3c icon indicating copy to clipboard operation
c3c copied to clipboard

Conditional declaration not found

Open cbuttner opened this issue 1 year ago • 2 comments

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.

cbuttner avatar May 23 '24 18:05 cbuttner

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.

lerno avatar May 26 '24 22:05 lerno

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".

lerno avatar May 26 '24 22:05 lerno

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.

cbuttner avatar Jun 06 '24 20:06 cbuttner

Please try the latest, which should emit an error.

lerno avatar Jun 06 '24 22:06 lerno

Yes, I'm now getting the error if I go back to my original code.

cbuttner avatar Jun 07 '24 10:06 cbuttner

So then we can close this or?

lerno avatar Jun 07 '24 22:06 lerno