Open timotheecour opened 3 years ago
but this goes against the spec
This part of the spec is highly controversial anyway.
more code that works at RT can now work at CT without needing patching
So code that uses global variables which most likely was written in a hurry (cannot call this code from a func
then) "can now work at CT"? What a bold claim. More likely: "The code now compiles". But I still don't long for a language where everything compiles, I want error detection.
This is how the spec used to be:
A global var that are accessed via a compile-time mechanism needs to be annotated via
.compileTime
. To use a.compileTime
var at runtime, convert it to a aconst
orlet
helper variable.
One big problem was when to turn it into this helper variable. It needs to be done after the full compilation. This is hard to implement properly but we require the same mechanism for IC and "method" code generation so there is no way around it. So since conversion from .compileTime vars to runtime vars is hard to do with const
, we can say that a compileTime
variable can be used at runtime and it's initial value is that after the full compilation. And maybe in order to use a .compleTime variable at runtime you need a special accessing mode like runtime(ctVar)
so that it's clear what happens.
One big problem was when to turn it into this helper variable. It needs to be done after the full compilation. This is hard to implement properly but we require the same mechanism for IC and "method" code generation so there is no way around it. So since conversion from .compileTime vars to runtime vars is hard to do with const, we can say that a compileTime variable can be used at runtime and it's initial value is that after the full compilation
@araq you're missing an important part of this RFC:
there is no cross-over between CT at RT, consistently with how {.threadvar.} and {.global.} at proc scope work
there is no cross-over, both RT and CT see a fresh default initialized value, so that:
var a: int
static: a = 1
doAssert a == 0 # succeeds
This is the default correct behavior; it's as if a (CT) and a(RT) lived in different namespaces.
When you want cross-over (and don't want to use const
), is where things get more complicated, and annotation (eg {.compileTime.} or other) must be used, this is out of scope for this RFC (but we can discuss this here too if needed).
This is the default correct behavior; it's as if a (CT) and a(RT) lived in different namespaces.
Really? The correct behavior? Seems much too subtle for my taste.
This RFC is stale because it has been open for 1095 days with no activity. Contribute a fix or comment on the issue, or it will be closed in 30 days.
this works:
prints: at CT: 0 1 at RT: 0 1
this doesn't, giving:
Error: cannot evaluate at compile time: a1
proposal
make {.threadvar.} and {.global.} at module level work at CT, just like {.threadvar.} and {.global.} at proc scope.
benefits
workarounds
var a {.threadvar, compileTime.}: int
andvar a {.global, compileTime.}: int
seem to work, as doesvar a {.compileTime.}: int
which IIRC is same asvar a {.global, compileTime.}: int
, but this goes against the spec:furthermore, as this RFC suggests,
compileTime
shouldn't even be needed in the 1st place, for consistency with both global/threadvar at proc scope, as well as for sake of making RT code work at CT without needing patching.the workarounds without
{.compileTime.}
are quite bad, and made even worse because of https://github.com/nim-lang/Nim/issues/14674notes
var a: int
is implicitly{.global.}
, so the rules would apply to that too (making it available at CT)will be: at CT: (0, "before") (10, "after") at RT: (0, "before") (10, "after")
instead of: (10, "before") (20, "after")
const