"force_multiline_blocks = true" is non-idempotent
Open
Nobody has claimed this yet.
A-matches
C-bug
only-with-option
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 1.1k
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 24
Description
To reproduce, start with this code:
use std::convert::TryFrom;
use std::env;
use std::ffi::{OsStr, OsString};
use std::io::ErrorKind;
use rustc_data_structures::fx::FxHashMap;
use rustc_mir::interpret::Pointer;
use rustc_target::abi::{LayoutOf, Size};
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
#[allow(non_snake_case)]
fn GetCurrentDirectoryW(
&mut self,
size_op: &OpTy<'tcx, Tag>, // DWORD
buf_op: &OpTy<'tcx, Tag>, // LPTSTR
) -> InterpResult<'tcx, u32> {
let this = self.eval_context_mut();
this.assert_target_os("windows", "GetCurrentDirectoryW");
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("GetCurrentDirectoryW", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
return Ok(0);
}
let size = u64::from(this.read_scalar(size_op)?.to_u32()?);
let buf = this.read_scalar(buf_op)?.check_init()?;
// If we cannot get the current directory, we return 0
match env::current_dir() {
Ok(cwd) =>
return Ok(windows_check_buffer_size(this.write_path_to_wide_str(&cwd, buf, size)?)),
Err(e) => this.set_last_error_from_io_error(e.kind())?,
}
Ok(0)
}
}
and this rustfmt.toml:
version = "Two"
use_small_heuristics = "Max"
match_arm_leading_pipes = "Preserve"
force_multiline_blocks = true
Run rustfmt once. It makes the following changes:
--- env.rs 2021-07-12 14:00:23.456543583 +0200
+++ env2.rs 2021-07-12 14:00:39.268279709 +0200
@@ -29,8 +29,9 @@
// If we cannot get the current directory, we return 0
match env::current_dir() {
- Ok(cwd) =>
- return Ok(windows_check_buffer_size(this.write_path_to_wide_str(&cwd, buf, size)?)),
+ Ok(cwd) => {
+ return Ok(windows_check_buffer_size(this.write_path_to_wide_str(&cwd, buf, size)?));
+ }
Err(e) => this.set_last_error_from_io_error(e.kind())?,
}
Ok(0)
Then run it again. It makes further changes:
--- env2.rs 2021-07-12 14:00:39.268279709 +0200
+++ env3.rs 2021-07-12 14:00:47.316145404 +0200
@@ -30,7 +30,9 @@
// If we cannot get the current directory, we return 0
match env::current_dir() {
Ok(cwd) => {
- return Ok(windows_check_buffer_size(this.write_path_to_wide_str(&cwd, buf, size)?));
+ return Ok(windows_check_buffer_size(
+ this.write_path_to_wide_str(&cwd, buf, size)?,
+ ));
}
Err(e) => this.set_last_error_from_io_error(e.kind())?,
}
This is a bug, rustfmt should be idempotent (i.e., running it a 2nd time should not change anything).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with the supplied Rust snippet and rustfmt.toml, focusing on the force_multiline_blocks option and the differing first and second formatting passes. Trace the formatter entry point responsible for these changes and add a regression check showing that formatting the result again produces no further changes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100