rust-lang/rustfmt

Add option to break after = in assignment

chrisbouchard opened this issue · 5 comments

I would like to see an option in rustfmt to break after the = in an assignment when the right-hand-side is "complex". I admit I don't know what "complex" is — possibly if the right-hand-side is subject to block/visual formatting. Here are a couple examples:

let var1 = if condition {
    true_part
} else {
    false_part
};

let var2 = some_value
    .chained()
    .method()
    .calls();

To me, it would be nicer to see this as:

let var1 =
    if condition {
        true_part
    } else {
        false_part
    };

let var2 =
    some_value
        .chained()
        .method()
        .calls();

In both cases, it seems more readable to me to keep the block together at the same indent level, especially when the variable name gets long.

let it_gets_harder_to_see_them_together = if condition {
    true_part
} else {
    false_part
};

let some_value_winds_up_in_right_field = some_value
    .chained()
    .method()
    .calls();

Compare

let it_gets_harder_to_see_them_together =
    if condition {
        true_part
    } else {
        false_part
    };

let some_value_winds_up_in_right_field =
    some_value
        .chained()
        .method()
        .calls();

You can also replace long variable names with patterns or reasonable variables with type hints.

let GetsHarder { to_see: them_together } = if condition {
    true_part
} else {
    false_part
};

let var1: GetsHarder<ToSee, ThemTogether> = if condition {
    true_part
} else {
    false_part
};

To be clear, I want to keep block formatting. I just would like the option to have the block start indented on the next line.

PS. I didn't want to include this as a motivating example, because it's hardly rustfmt's fault, but editors like IntelliJ will insert "smart" type hints inline automatically. This pads out the line length in a way that rustfmt can't see, and it's why I don't suggest basing this on line length, but rather on whether the right-hand-side is "complex", block-formatted, or something like that.

Indeed, I was surprised when trying to customize my rustfmt.toml that there were close to no customization when it comes to assignments. Then again, looking at how everyone code, I think I am the oddball with my

let a = {
    fct()
        .foo()
        .bar()
};

I'm also looking for an option to prevent the following line-break after a long expression assignment (once it reaches past the 80-character line-width rule):

mod tests {
     #[test]
     fn test1() {
         let principal =
             Principal::new(ID::new_v4(), RoleDiscriminants::Consumer);
     }
}

I would rather enforce this style with block indentation:

mod tests {
     #[test]
     fn test1() {
         let principal = Principal::new(
             ID::new_v4(), 
             RoleDiscriminants::Consumer
         );
     }
}

Is it possible to enforce arguments are placed on newlines instead of the entire expression put onto a new line?

+1 for this. Sometimes, async and lambdas need to be differentiated from simple multi-line allocations

For example:

let logic_invoked_immediately/* sometimes-great-IDE-supported-long-inlay-hint-inserted-here */ = if let Some(something) = do_something {
    something
}else {
    fallback
};
let logic_run_later/* sometimes-great-IDE-supported-long-inlay-hint-inserted-here */ = |param_1| {
    do_ops_with(&param_1);
    param_1.do_something_else();
    param_1
};

let this_one_differentiates_from_immediately_invoked_logics =
    |param_1|  {
        do_ops_with(&param_1);
        param_1.do_something_else();
        param_1
    };

let this_might_be_executed_later_either =  
   async move {
      do_some_async_calc().await
   };

CLion rust plugin formatter is much more permissive on these kind of line breaks, IMO it helps me a lot to improve readability and reduce confusions from any logic's execution points.

image

Would be nice for my usecase because currently VSCode-inserted type signatures make my code constantly reflow

+1 on this, although I want to use this option to prevent precisely the "nicer" way you suggested (I dislike it).