-
Notifications
You must be signed in to change notification settings - Fork 900
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
match_arm_blocks behavior does not match documentation #4840
Comments
Thanks for the report. Could you share a reproducible snippet that contains the entire match expression with the same levels of indentation where you are seeing this? Similar to the cascading formatting failures in chains, there's some cases where rustfmt bails on the entire match if it encounters any issues formatting any of the arms or bodies contained within, so it's possible rustfmt isn't formatting any part of the match at all. There could certainly be a bug with the config option as well. |
Here's an example snippet: use std::iter;
use log::trace;
use rustc_apfloat::{Float, Round};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::{mir, mir::BinOp, ty, ty::FloatTy};
use rustc_target::abi::{Align, Integer, LayoutOf};
use crate::*;
use helpers::check_arg_count;
pub enum AtomicOp {
MirOp(mir::BinOp, bool),
Max,
Min,
}
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
fn call_intrinsic(
&mut self,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
if this.emulate_intrinsic(instance, args, ret)? {
return Ok(());
}
// All supported intrinsics have a return place.
let intrinsic_name = &*this.tcx.item_name(instance.def_id()).as_str();
let (dest, ret) = match ret {
None => throw_unsup_format!("unimplemented (diverging) intrinsic: {}", intrinsic_name),
Some(p) => p,
};
// Then handle terminating intrinsics.
match intrinsic_name {
"atomic_cxchgweak" => this.atomic_compare_exchange_weak(
args,
dest,
AtomicRwOp::SeqCst,
AtomicReadOp::SeqCst,
)?,
"atomic_umax_acq" => this.atomic_op(args, dest, AtomicOp::Max, AtomicRwOp::Acquire)?,
"atomic_umax_rel" => this.atomic_op(args, dest, AtomicOp::Max, AtomicRwOp::Release)?,
"atomic_umax_acqrel" => {
this.atomic_op(args, dest, AtomicOp::Max, AtomicRwOp::AcqRel)?
}
"atomic_umax_relaxed" => {
this.atomic_op(args, dest, AtomicOp::Max, AtomicRwOp::Relaxed)?
}
name => throw_unsup_format!("unimplemented intrinsic: {}", name),
}
trace!("{:?}", this.dump_place(**dest));
this.go_to_block(ret);
Ok(())
}
} When I change the formatting, rustfmt resets it to this -- so it doesn't look to me like it is giving up entirely (but I might be misinterpreting what that means). The
|
Thanks that's helpful!
Nope you've got it right. There's a few cases, such as comments between arms, within patterns, preceding guards, etc. which makes rustfmt barf on the entire match expression, so it just spits back out whatever was in the corresponding span originally. Unfortunately that happens silently by default, and if the original formatting was close/identical to the way rustfmt would've formatted it successfully it's hard for developers to know that happened. We've ruled that out though which is good. My guess is that the check for:
is only looking at the length of the first line of the formatted body and not whether the body was multilined itself, but will have to dig into it |
I am not sure if that's right; |
Yep, you're right. Sorry for the confusion, did some drive by labeling without really digging into it. This actually runs into one of the additional caveats in the Style Guide prescriptions for match expressions and circles back to #4004 However, the point about the documentation being mismatched (or at least incomplete) is fair. It's really more of a I suspect we will need a new config option to incorporate a |
Having an option that truly implements what is currently documented might also be useful though -- i.e., ensuring that multi-line (not "multi-statement" or whatever it currently is) arms always have braces around them (but still keeping single-line arms brace-free). I'd prefer that over the current default any day, though that's probably just my personal taste (see #4004) ;) Of course I can simulate that with |
Indeed. Converting an option from a boolean to an enum opens up a lot of formatting opportunities, and I suspect there will be plenty here |
Once again optimism about a quick implementation has proven to be unfounded 😄 I've updated the docs for the option to be more explicit about the narrow slice of cases where the option is actually applicable and have opened #4896 to track the implementation of the new, more powerful opt. Going to go ahead and close as there's not much else to do here, and we can always continue to iterate on the docs of for the current opt if need be. |
The docs for
match_arm_blocks
sayHowever, even with
match_arm_blocks = true
, I am seeing formatting like this:Clearly this match arm does not fit on the same line as the pattern. Ergo, according to the docs, it should be wrapped in a block. But it is not. So either the docs are wrong or the implementation is buggy -- or am I missing something?
FWIW I'd actually prefer having this wrapped in a block, so my preferred solution here is to make the implementation match the docs. :)
The text was updated successfully, but these errors were encountered: