-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Fn unboxed closures can incorrectly mutate upvars #17780
Comments
This looks like the unboxed closure version of #17403. The comment by @nikomatsakis there suggests that the correct fix is a bit deeper than just requiring the upvars to be aliasable. |
I think there may be multiple issues. Right now unboxed closures permit the moral equivalent of mutating through an |
@bkoropoff I meant that after your proposed fix there might be other soundness problems with unboxed closures, based on the fact that the inferred regions seem incorrect, but playing around for a bit I can't get any of them to happen. |
The following presently builds: #![feature(unboxed_closures, overloaded_calls)]
fn main() {
let mut x = 0u;
let _f = |&:| x = 42;
} However, this is equivalent to writing: struct F<'a> {
x: &'a mut uint
}
impl<'a> Fn<(),()> for F<'a> {
#[rust_call_abi_hack]
fn call(&self, _: ()) {
*self.x = 42; // error: cannot assign to data in a `&` reference
}
}
fn main() {
let mut x = 0u;
let _f = F { x: &mut x };
} The key is that My patch fixes this, but it does not address the region issue. I'll retitle the bug to make it clear that it only covers this unboxed-closure-specific issue. |
A variation of this example causes an ICE: #17786 |
This causes borrowck to correctly reject mutation or mutable borrows of upvars in `Fn` unboxed closures since the closure environment is aliasable. This also tracks the responsible closure in the aliasability information returned and uses it to give a helpful diagnostic. Closes issue rust-lang#17780
This fixes a soundness problem where `Fn` unboxed closures can mutate free variables in the environment. The following presently builds: ```rust #![feature(unboxed_closures, overloaded_calls)] fn main() { let mut x = 0u; let _f = |&:| x = 42; } ``` However, this is equivalent to writing the following, which borrowck rightly rejects: ```rust struct F<'a> { x: &'a mut uint } impl<'a> Fn<(),()> for F<'a> { #[rust_call_abi_hack] fn call(&self, _: ()) { *self.x = 42; // error: cannot assign to data in a `&` reference } } fn main() { let mut x = 0u; let _f = F { x: &mut x }; } ``` This problem is unique to unboxed closures; boxed closures cannot be invoked through an immutable reference and are not subject to it. This change marks upvars of `Fn` unboxed closures as freely aliasable in mem_categorization, which causes borrowck to reject attempts to mutate or mutably borrow them. @zwarich pointed out that even with this change, there are remaining soundness issues related to regionck (issue #17403). This region issue affects boxed closures as well. Closes issue #17780
#17784 is merged, so this is fixed. |
…eykril feat: Suggest name in completion for let_stmt and fn_param fix rust-lang#17780 1. Refactor: move `ide_assist::utils::suggest_name` to `ide-db::syntax_helpers::suggest_name` for reuse. 2. When completing `IdentPat`, detecte if the current node is a `let_stmt` or `fn_param`, and suggesting a new name based on the context.
The following program will write to freed memory:
Borrowck needs to consider upvars in capture-by-ref, self-by-ref unboxed closures to be aliasable so that mutation and mutable borrows are rejected. I'm working on a patch to do this.
The text was updated successfully, but these errors were encountered: