The dyn header claimed a guarantee the linker does not give

test/dyn_ops.c includes the header and calls most of what it declares, so a
renamed function fails to link. It does not catch a signature that drifts
while the name stays -- C links on names, not types -- and it does not reach
flan_dyn_map_get, flan_dyn_map_set, flan_dyn_map_contains, flan_dyn_is_nil or
flan_dyn_need_not_nil at all, none of which dyn_ops.c mentions. The comment
now says that, and says which hole is closable from here.
This commit is contained in:
Joseph Ferano 2026-09-20 13:00:55 +07:00
parent 26439dc22e
commit 9eed4cbd8c

View File

@ -3,12 +3,21 @@
* This header is not compiled into a program. The build embeds the runtime's * This header is not compiled into a program. The build embeds the runtime's
* .c files as strings and hands each one to clang on its own, with no include * .c files as strings and hands each one to clang on its own, with no include
* path (see [Build.compile_c]), so runtime/flan_dyn.c declares everything it * path (see [Build.compile_c]), so runtime/flan_dyn.c declares everything it
* defines and this file declares it a second time. That second copy is not * defines and this file declares it a second time. What keeps that second
* held honest by hand the way a repeated escape table would be: it is made * copy honest is partial, and the exact shape of it is worth writing down
* mechanical, because test/dyn_ops.c includes this header and names every * rather than overclaiming: test/dyn_ops.c includes this header and calls
* function below, so a signature that drifts from the implementation is a * most of what it declares, so a name that is spelled one way here and
* link error in `dune test` rather than a surprise at someone else's call * another way in flan_dyn.c fails to link in `dune test`.
* site. *
* Two holes in that. A signature that drifts while the name stays is not
* caught at all C links on names and not on types, so a changed parameter
* or return type compiles on both sides and goes wrong at the call site
* instead of failing the build. And five of the names below are never
* referenced by dyn_ops.c [flan_dyn_map_get], [flan_dyn_map_set],
* [flan_dyn_map_contains], [flan_dyn_is_nil] and [flan_dyn_need_not_nil]
* so not even the rename check reaches them. Calling those five from
* dyn_ops.c would close the second hole; nothing available from here closes
* the first.
* *
* Who reads it: the compiler lane, which emits calls to these names, and the * Who reads it: the compiler lane, which emits calls to these names, and the
* C tests. The whole of the boundary is here. What is behind it the value * C tests. The whole of the boundary is here. What is behind it the value