-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Allow modifications to local variables in pure functions #1422
Comments
You'd still not be able to make You can add more rules to handle that, but it just goes down deeper and deeper. As we found out before (there was an effect system early last year that was dumped again), you can't really do any kind of sane purity checking on a language like Rust. I would prefer going back to a system where you can simply annotate a function that you want to use as a predicate as pure (or, preferably, |
It would not be possible to add the "pure" declaration to a higher-order function's arguments? Like
|
We could make purity part of a function's type. But that still doesn't come close to solving the problem. Consider this:
Is this pure? The block passed to |
My naive defininition of "pure" is: "a pure function can do whatever it wants, unless that impureness does not escape its scope".
Does that make sense? Or simpler:
Would use state-manipulation internally, but it would not escape. |
Sure that makes sense. Formalizing that sensible definition is where the problem lies. |
There seemed to be a paper “Grafting Functional Support on Top of an Imperative Language” by Andrei Alexandrescu on D's implementation of purity, but i can not find it. Their definition of "pure" can be found here: http://www.d-programming-language.org/function.html |
Marijn -- I'm confused about this comment "I would prefer going back to a system where you can simply annotate a function that you want to use as a predicate as pure (or, preferably, pred), and give up on any checking of this purity." This is exactly what unchecked blocks do, which I added back in August or September. (I can't remember what the exact syntax we decided on was.) Or did those go away? |
We have unchecked blocks, but we also have an attempt at formal purity checking. I'm proposing we get rid of the second, since it's just annoying and broken, and just implicitly not check purity, just believing the programmer whenever he/she annotates a function as pure. |
I feel like we already discussed the "get rid of purity checking" possibility back in the summer when we were discussing these issues thoroughly -- has anything changed since then? |
What was the conclusion of that discussion? |
The conclusion was that it's important to give the programmer the freedom to choose to write their typestate predicates a restricted sublanguage that is statically guaranteed to be pure, because otherwise they're not getting strong guarantees from the compiler. At the same time, they also have the freedom to use unchecked blocks to say "trust me"; leaving purity checking in doesn't take away freedom from someone who only wants to use the "unchecked block" option. They can just throw an unchecked block around all predicates. |
Would something like Haskell's ST monad help? Not necessarily explicitly using a monad of course (indeed, it would be ideal if you didn't even know this was going on under the covers!). The general idea is that each mutable value would be tagged with a specific type variable (one that's "fresh" for the given "pure" function), and every time you do something with mutable variable you just thread this type variable through everything (making sure they match). Then at the end you strip it out in the "runST" call. Since the result value's type doesn't have access to this type variable, it couldn't posssibly contain any mutable references leaking side effects. Maybe typestate could be used to do the same kind of tracking (with modifications). They key point is that anything impure is associated with a fresh "tag" introduced by the "pure" annotation, and that you ensure that nothing tagged with this "tag" can escape the function, statically. BTW, this not only means you can modify local variables on the stack, you can modify local heap allocations too. |
Assigning this to myself, but I don't think it's wise to spend time on it until we reach a clearer consensus about what we want in the long term w.r.t typestate and purity checking (if anything) -- see #2178. |
as part of the borrowing check that I am working on, I have all the capabilities to solve this in a nice way (as I already have to know which data is interior to the stack frame and what is not). |
It would be interesting to add some kind of warning about a function that's really pure not being marked as such. Then you can measure how many functions are really pure in a code base. If the pure to impure ratio on some real programs is more than, say, 50% (or even lower), maybe the modifier should be inverted so that pure is the default. |
you can now modify local state (that is, state which is uniquely tied to the current stack frame) in pure fns. there is still the question of allowing pure fns to invoke closures and so forth---I think this is best addressed by an adapted version of the Lighweight Polymorphic Effects functions, which basically allow a function to be "as pure as its argument closures are"---but that seems like a separate issue. |
Great, thanks. |
…1447) * Changed copyright check to the new standard PR 1422. * Fixed debug print. * Added doc comment. * Changed to proper doc-comment * reverted test cases * Changed generator test cases to new format. * Added check that above our license is empty or comments * Fixed merge fail * Escaped backslash. * Allowed empty 2nd line pattern discussed in rust-lang#1422 * Test case for maybe empty lines above. * Changed from list to generator.
Co-authored-by: Adrian Palacios <73246657+adpaco-aws@users.noreply.github.com>
…obzol Bump `rustc_{codegen_ssa,llvm}` `cc` to 1.2.16 to fix `x86` Windows jobs on newest Windows SDK Part of rust-lang#137733. Bump `rustc_{codegen_ssa,llvm}` `cc` to 1.2.16 which contains rust-lang/cc-rs#1425 to help with rust-lang#137733. Previously tested in rust-lang#137724. #### `cc` changelog between 1.2.13 and 1.2.16 <details> <summary>`cc` changes since 1.2.13 up to and including 1.2.16</summary> ##### [1.2.16](rust-lang/cc-rs@cc-v1.2.15...cc-v1.2.16) - 2025-02-28 ###### Fixed - force windows compiler to run in `out_dir` to prevent artifacts in cwd (rust-lang#1415) ###### Other - use `/arch:SSE2` for `x86` target arch (rust-lang#1425) - Regenerate windows-sys binding ([rust-lang#1422](rust-lang/cc-rs#1422)) - Regenerate target info ([rust-lang#1418](rust-lang/cc-rs#1418)) - Add LIB var when compiling flag_check (rust-lang#1417) - Change flag ordering ([rust-lang#1403](rust-lang/cc-rs#1403)) - Fix archiver detection for musl cross compilation ([rust-lang#1404](rust-lang/cc-rs#1404)) ##### [1.2.15](rust-lang/cc-rs@cc-v1.2.14...cc-v1.2.15) - 2025-02-21 ###### Other - Regenerate target info ([rust-lang#1406](rust-lang/cc-rs#1406)) - Always read from all `CFLAGS`-style flags ([rust-lang#1401](rust-lang/cc-rs#1401)) - Simplify the error output on failed `Command` invocation ([rust-lang#1397](rust-lang/cc-rs#1397)) ##### [1.2.14](rust-lang/cc-rs@cc-v1.2.13...cc-v1.2.14) - 2025-02-14 ###### Other - Regenerate target info ([rust-lang#1398](rust-lang/cc-rs#1398)) - Add support for setting `-gdwarf-{version}` based on RUSTFLAGS ([rust-lang#1395](rust-lang/cc-rs#1395)) - Add support for alternative network stack io-sock on QNX 7.1 aarch64 and x86_64 ([rust-lang#1312](rust-lang/cc-rs#1312)) </details> r? `@Kobzol`
Rollup merge of rust-lang#137788 - jieyouxu:bump-compiler-cc, r=lqd,Kobzol Bump `rustc_{codegen_ssa,llvm}` `cc` to 1.2.16 to fix `x86` Windows jobs on newest Windows SDK Part of rust-lang#137733. Bump `rustc_{codegen_ssa,llvm}` `cc` to 1.2.16 which contains rust-lang/cc-rs#1425 to help with rust-lang#137733. Previously tested in rust-lang#137724. #### `cc` changelog between 1.2.13 and 1.2.16 <details> <summary>`cc` changes since 1.2.13 up to and including 1.2.16</summary> ##### [1.2.16](rust-lang/cc-rs@cc-v1.2.15...cc-v1.2.16) - 2025-02-28 ###### Fixed - force windows compiler to run in `out_dir` to prevent artifacts in cwd (rust-lang#1415) ###### Other - use `/arch:SSE2` for `x86` target arch (rust-lang#1425) - Regenerate windows-sys binding ([rust-lang#1422](rust-lang/cc-rs#1422)) - Regenerate target info ([rust-lang#1418](rust-lang/cc-rs#1418)) - Add LIB var when compiling flag_check (rust-lang#1417) - Change flag ordering ([rust-lang#1403](rust-lang/cc-rs#1403)) - Fix archiver detection for musl cross compilation ([rust-lang#1404](rust-lang/cc-rs#1404)) ##### [1.2.15](rust-lang/cc-rs@cc-v1.2.14...cc-v1.2.15) - 2025-02-21 ###### Other - Regenerate target info ([rust-lang#1406](rust-lang/cc-rs#1406)) - Always read from all `CFLAGS`-style flags ([rust-lang#1401](rust-lang/cc-rs#1401)) - Simplify the error output on failed `Command` invocation ([rust-lang#1397](rust-lang/cc-rs#1397)) ##### [1.2.14](rust-lang/cc-rs@cc-v1.2.13...cc-v1.2.14) - 2025-02-14 ###### Other - Regenerate target info ([rust-lang#1398](rust-lang/cc-rs#1398)) - Add support for setting `-gdwarf-{version}` based on RUSTFLAGS ([rust-lang#1395](rust-lang/cc-rs#1395)) - Add support for alternative network stack io-sock on QNX 7.1 aarch64 and x86_64 ([rust-lang#1312](rust-lang/cc-rs#1312)) </details> r? `@Kobzol`
I know this issue is on someone's plate, but i could not find a related issue.
Currently we can not iterate over strings, vectors, lists etc using pure functions. That means that functions like
str::is_whitespace()
can not be declared pure either, even though logically they are.The text was updated successfully, but these errors were encountered: