Name clash with `free`
nikswamy opened this issue · 7 comments
$ cat Free.fst Free.fsti
module Free
let free (x:bool) = not x
let test (x:bool) = free x
module Free
val test : bool -> bool
$ cat Free.c
/*
This file was generated by KaRaMeL <https://github.com/FStarLang/karamel>
KaRaMeL invocation: /home/nswamy/everest/karamel/krml prims.krml FStar_Pervasives_Native.krml FStar_Pervasives.krml Free.krml
F* version: 46cbaf03
KaRaMeL version: 70084646
*/
#include "Free.h"
static bool free(bool x)
{
return !x;
}
bool Free_test(bool x)
{
return free(x);
}
produces
✘ [CC,./Free.c] (use -verbose to see the output)
./Free.c:12:13: error: conflicting types for ‘free’
12 | static bool free(bool x)
| ^~~~
In file included from /home/nswamy/everest/karamel/include/krml/internal/target.h:7,
from /home/nswamy/everest/karamel/include/krmllib.h:19,
from ./Free.h:11,
from ./Free.c:8:
/usr/include/stdlib.h:565:13: note: previous declaration of ‘free’ was here
565 | extern void free (void *__ptr) __THROW;
| ^~~~
cc1: error: unrecognized command line option ‘-Wno-unknown-warning-option’ [-Werror]
cc1: all warnings being treated as errors
Warning 3: run_or_warn: the following command failed:
gcc-9 -I /home/nswamy/everest/karamel/krmllib/dist/minimal -I /home/nswamy/everest/karamel/krmllib -I /home/nswamy/everest/karamel/include -I . -Wall -Werror -Wno-unused-variable -Wno-unknown-warning-option -Wno-unused-but-set-variable -Wno-unused-function -g -fwrapv -D_BSD_SOURCE -D_DEFAULT_SOURCE -Wno-parentheses -std=c11 -c ./Free.c -o ./Free.o
Warning 3 is fatal, exiting.
make: *** [Makefile:7: all] Error 255
copy-pasting what I wrote on Teams: there's not much I can do since there's potentially an unbounded amount of external definitions in system headers, whatever is defined in headers you pass to -add-include
, etc.
note that you would have the same problem if you defined free
in your own C file without prefixing it suitably (and note that C compilers don't give you a warning saying "your free
function collides with a name from the standard library")
krml has a mechanism for dealing with these name collisions, which is to prefix everything; if you use -no-prefix, there you must handle name collisions yourself
the one thing I can do is add a note to the -no-prefix
option saying that you might run into this problem if you elect to use -no-prefix
I didn't use -no-prefix in this case. Is it on by default or something?
From what I understood, krml strips (or skips) such prefixes from static functions (here, free
does not appear in the interface of module Free
)
Ugh! I thought you had used no-prefix but I was wrong about that. Sorry.
Tahina: you are correct, this is the prefix that gets kicked from static functions for readability. This was a big readability improvement for HACL* and a long-standing request from many of our downstream consumers. This is also in line with standard C practices: no need to prefix a static inline function which does not generate an external symbol.
I'm not sure what can be done in a principled way... I see two not-so-great fixes:
- make this behavior optional (at the expense of verbosity)
- try to add a list of "common" names and avoid colliding with them, although it'll always be brittle because I can't maintain an up-to-date list of what's exported by system headers... it's also tricky because some of the libc functions are treated as compiler builtins and I think I've seen some C compiler allow shadowing something like "sin" or "cos" (or maybe something else).
The other fix is of course to do nothing, although that's a sub-par user experience.
I would be happy if there was a way to make this behavior optional.
Another option might be to support a "--with-prefix=(val)" option, which overrides the default and adds a user-provided namespace/prefix to every function static or otherwise.