-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restricted file writes in const fn
#25
Comments
One further idea how to restrict this even more is #[const_write = "foo.man"]
const _: &[u8] = b"foomp"; // or some actual const eval which dumps the bytes of a constant with that attribute to the given file (but the file is created in e.g. |
I'd be careful with additions like this. There are opportunities for unsafe code to exploit the fact that e.g. a Pure writes could be permitted, but Controlling the write declaratively instead of imperatively, as proposed by @oli-obk, would fix this concern. |
During a discussion @Centril and I found a few points that I should write down here: Why an attribute?The attribute on constant scheme is better than a Permitted typesTo start out with we could just allow While we could allow types other than Filenamesfor simplicity we'd only allow output filenames of the following regex: When to do thisWhile such a feature is not that hard to implement, it is pretty useless right now, since we have no loops, |
"Precedent"There's some precedent for this. On wasm, the |
@eddyb threw #[emit_artifact = "foo.man"]
const _: &[u8] = b"foomp"; |
@Centril and I briefly discussed a similar concept -- largely, my/our discussion centered around something like this being possible. We noted that @Centril was (rightfully) concerned about people depending on the implicit ordering, and I suggested a couple of mitigations: intentional shuffling of the order (sort of obvious, and not great due to non-determinism, even if we shuffle at run time, not compile time). I had the idea of saying that we only allow access via a sort function that would be #[collection]
const PLACES: &[Line];
fn foo() {
const!(PLACES.add(line!()); // at line 3
}
fn bar() {
const!(PLACES.add(line!()); // at line 10
}
fn main() {
assert_eq!(PLACES, &[3, 10]);
} |
const fn
const fn
@Mark-Simulacrum that sounds similar to the ideas that came up around custom test harnesses, where you would have something more like this: // Syntax (extremely) subject to bikeshed.
const PLACES: &[Line] = &gather_from!(places);
fn foo() {
#[gather_into(places)]
const _: Line = line!(); // at line 3
}
fn bar() {
#[gather_into(places)]
const _: Line = line!(); // at line 10
}
fn main() {
assert_eq!(PLACES, &[3, 10]);
} One advantage is that the sorted list/set design problem can be (partially) sidestepped by having an AST-driven order, as opposed to CTFE being involved at all. cc @petrochenkov @Manishearth (although it's somewhat offtopic IMO) |
somewhat related discussion -- idea for allowing writing to (interior-)mutable statics in const-eval: |
Hi! 👋
During Oxidizeconf's impl days @oli-obk and I talked about adding a very restricted version of disk writes to
const fn
contexts. This is an issue to continue that conversation.Motivation
For the CLI WG we want to generate files during compilation such as shell completions, and man pages.
Currently the best way to achieve this is by creating a
build.rs
file, and making sure the right structs are exported. This is not great, because it's easy to mess up, the use ofbuild.rs
triggers a double compilation, and certain dependencies also need to be required in as both[dependencies]
and[dev-dependencies]
.Instead it would be a lot nicer if there was a way to generate output during compilation that wouldn't require any additional setup beyond the usual flow of using crates.
Current Proposal
The idea we discussed was to add a limited form of writing files to
const fn
. The reasoning for limited filesystem access, rather than full access is to prevent people from writing output in a prior compile, and reading it back in during a next compile, causing problems for reproducibility.What we discussed was something akin to
read_bytes!
/const fs::read
, but for writing output to a special folder somewhere intarget/
that gets removed at the start of each build to ensure no data from a prior build persists.Thanks! ✨
The text was updated successfully, but these errors were encountered: