Related to the matter of linkage, I've been ruminating a bit on the
current limited support for compile-time constants.
The "items" in a rust module are currently functions, iterators, types,
and sub-modules. These are constants, in a way, but they're not the sort
a lot of people think of. In particular there are no "value-like"
constant items such as numbers, strings, vectors, records, tuples. They
can only be dynamic values. If you want to produce one of these -- even
if it's always the same value -- you have to write a function that
returns it.
This is not entirely pleasant. There is room for improvement:
- Things that *could* be compile-time constants can't be calculated
"once". We wind up putting code in the executable rather than
read-only data, and re-calculating repeatedly at runtime.
- Some values -- say, 0-ary tags -- wind up as functions even
though they'd make more sense as enum-like constant values.
- Constant-folding is left, at best, to optional compiler passes. It
might be nice to be able to guarantee a certain quantity of it to
language users, done in the front-end.
Suppose, instead, that we have an item type
'const <ty> <ident> = <const-expr>;'
and we recursively define a subset of the expr grammar as
const-ness-propagating. And we're careful to be sure we mean
*compile-time* constant, not initialization-time constant a la C. Then:
- The problems above are solved. Enum-like 0-ary tags turn into
consts. Big structured consts can be calculated at compile time
and stored read-only. Constant folding through arithmetic and such
can be guaranteed to some reasonable degree.
- A few syntactic contexts (linkage-names in native modules, say)
currently take literal values, but could be generalized to take
references to constants. This could potentially wind up as a sort
of "cheapest layer" of static metaprogramming (not getting into
actual AST-splicing or anything).
- We already have the concepts of immutability and pure functions,
it seems a bit of a shame not to permit their use at compile time
for complicated constants.
Of course, there are also reasons to be wary of this:
- Read-only memory has the problem of not being very amenable to
refcounting. We could steal a tag-bit on pointers to read-only
values, but then we would not be tracking their refcount at all,
and this would further seal the fate of crate-loading as an
irrevocable action within a given process domain (see note on this
in previous email regarding linkage; we may be going that route
anyways).
- Value-level equality needs to be preserved and/or checked somehow
between compile-time and load-time, rather than just type
compatibility. Compiling a crate with math.pi = 3.14, then finding
you linked against a recompiled crate with math.pi = 3.15, is an
unwelcome situation. We'd need some kind of scheme to guard against
this, or make users somehow aware of the risks. Possibly just
require compilation-unit UUID-identity or CHF-identity if there's
been any constant folding? Or track the constants that were folded
and check equality at runtime link time? Awkward options, all...
Any thoughts?
-Graydon
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev