![bors[bot]](/assets/img/avatar_default.png)
11184: Correctly pass through mutable parameter references when extracting a function r=Veykril a=Vannevelj Fixes https://github.com/rust-analyzer/rust-analyzer/issues/10277 I have based this investigation based on my understanding of [the Borrowing chapter](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html) but I wasn't able to debug the test runs or see it in action in an IDE. I'll try to figure out how to do that for future PRs but for now, the tests seem to confirm my understanding. I'll lay out my hypothesis below. Here we define the parameters for the to-be-generated function:7409880a07/crates/ide_assists/src/handlers/extract_function.rs (L882)
Three values in particular are important here: `requires_mut`, `is_copy` and `move_local`. These will in turn be used here to determine the kind of parameter:7409880a07/crates/ide_assists/src/handlers/extract_function.rs (L374-L381)
and then here to determine what transformation is needed for the calling argument:7409880a07/crates/ide_assists/src/handlers/extract_function.rs (L383-L390)
which then gets transformed here:7409880a07/crates/syntax/src/ast/make.rs (L381-L383)
What I believe is happening is that * `requires_mut` is `false` (it already is marked as mutable), * `is_copy` is `false` (`Foo` does not implement `Copy`), and * `move_local` is `false` (it has further usages) According to the pattern matching in `fn kind()`, that would lead to `ParamKind::SharedRef` which in turn applies a transformation that prepends `&`. However if I look at the chapter on borrowing then we only need to mark an argument as a reference if we actually own it. In this case the value is passed through as a reference parameter into the current function which means we never had ownership in the first place. By including the additional check for a reference parameter, `move_local` now becomes `true` and the resulting parameter is now `ParamKind::Value` which will avoid applying any transformations. This was further obscured by the fact that you need further usages of the variable or `move_local` would be considered `true` after all. I didn't follow it in depth but it appears this idea applies for both the generated argument and the generated parameter. There are existing tests that account for `&mut` values but they refer to local variables for which we do have ownership and as such they didn't expose this issue. Co-authored-by: Jeroen Vannevel <jer_vannevel@outlook.com>
rust-analyzer is a modular compiler frontend for the Rust language. It is a part of a larger rls-2.0 effort to create excellent IDE support for Rust.
Work on rust-analyzer is sponsored by
Quick Start
https://rust-analyzer.github.io/manual.html#installation
Documentation
If you want to contribute to rust-analyzer or are just curious about how things work under the hood, check the ./docs/dev folder.
If you want to use rust-analyzer's language server with your editor of choice, check the manual folder. It also contains some tips & tricks to help you be more productive when using rust-analyzer.
Security and Privacy
See the corresponding sections of the manual.
Communication
For usage and troubleshooting requests, please use "IDEs and Editors" category of the Rust forum:
https://users.rust-lang.org/c/ide/14
For questions about development and implementation, join rust-analyzer working group on Zulip:
https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer
Quick Links
- Website: https://rust-analyzer.github.io/
- Metrics: https://rust-analyzer.github.io/metrics/
- API docs: https://rust-analyzer.github.io/rust-analyzer/ide/
- Changelog: https://rust-analyzer.github.io/thisweek
License
Rust analyzer is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0).
See LICENSE-APACHE and LICENSE-MIT for details.