about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-04-14 13:51:10 +0200
committerbptato <nincsnevem662@gmail.com>2024-04-14 19:00:24 +0200
commit13ada1015158d65d7a3f57a89cc21769cf879934 (patch)
tree2fc81f22a3bc5f03c5b68ecaa35f666654f51479
parent60b805115795a740ec68a65b6f13182a7bcef73c (diff)
downloadchawan-13ada1015158d65d7a3f57a89cc21769cf879934.tar.gz
utils: polyfill addr/unsafeAddr distinction in Nim 2+
I wish they didn't change this.  unsafeAddr may be a confusing name,
but it's more powerful than addr.  Merging them violates the principle
of least power.

e.g. say I get n thru a param, and shadow it

proc x(n: int) =
  var n = n + 1

a screen or two later I call

  mutates_variable_in_c(addr i)

then later I no longer need to add 1, so I remove the var line.

In Nim 1.6 the compiler refuses to compile, I can instantly find the
bug.  In 2.0 it does... whatever?? Maybe for an int it "works", for an
object it likely doesn't.  Certainly not something I'd enjoy debugging.
-rw-r--r--nim.cfg1
-rw-r--r--src/utils/myaddr.nim18
2 files changed, 19 insertions, 0 deletions
diff --git a/nim.cfg b/nim.cfg
index 8d688ac0..1dc64525 100644
--- a/nim.cfg
+++ b/nim.cfg
@@ -6,6 +6,7 @@
 --experimental:"overloadableEnums"
 --warning:Effect:off
 --mm:refc
+--include:"utils/myaddr"
 --import:"utils/eprint"
 --styleCheck:usages
 --styleCheck:hint
diff --git a/src/utils/myaddr.nim b/src/utils/myaddr.nim
new file mode 100644
index 00000000..4405e0c4
--- /dev/null
+++ b/src/utils/myaddr.nim
@@ -0,0 +1,18 @@
+# Before 2.0, `addr' only worked on mutable types, and `unsafeAddr'
+# was needed to take the address of immutable ones.
+#
+# This was changed in 2.0 for some incomprehensible reason, so now to
+# write code that compiles on both versions you have to take care that
+# you use the right overload without compiler help.
+#
+# This module fixes the above problem; it is automatically included
+# in every file by nim.cfg.
+
+when NimMajor >= 2:
+  const msg = "expression has no address; maybe use `unsafeAddr'"
+
+  template addr(x: untyped): untyped {.used, error: msg.} =
+    discard
+
+  template addr(x: var untyped): untyped {.used.} =
+    system.addr x