-
Notifications
You must be signed in to change notification settings - Fork 56
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
boolean and arithmetic expressions #18
Comments
I personally almost always use parens, even if not strictly needed:
It's easier than trying to remember specific precedence rules. |
I agree with @steveklabnik, but I think parenthesizing around uses of the exact same operator is over the top. |
@solson once you use both right and left associative operators that aren't necessarily commutative.... I agree that it's a bit overly conservative though. I have scars. |
I was thinking of specifically making the point that Rust has few or possibly no right-associative operators at all, but I'm not sure if that's true. The reference doesn't seem to make any mention. Here are a few of my other thoughts on the matter: // I don't write (x * y) + z because I learned this precedence
// repeatedly in primary/secondary school
x * y + z
// I only learned this precedence in post-secondary, so I don't
// expect it to be widely known and I parenthesize
(x && y) || z
(x & y) | z
// When it comes to the full set of bitops, I don't trust myself or
// people reading my code to get it right, so I parenthesize
(x ^ y) | ((z & w) << 8)
// When it comes to mixing ops from different "families" I parenthesize
// for the same reason
x * (y | 8)
// Special case of the above: I don't write x == (y + z) because
// everyone knows this precedence
x == y + z It may be a bit complex, but I think it's worth having fine-grained rules for operator parentheses in rustfmt. The last case makes me think that even a simple paren-heavy rule will need a number of special cases. |
I don't think it does, but I mean that this is something that's come out of using multiple languages: I can't remember if Rust does or not. So to be safe, I (possibly-over) use parens. I do think that your rules seem reasonable. |
I tend to parenthesize any subexpression that uses a different operator than the next expression up in the parse tree. I do rely on associativity, though, with chains of the same operator. I don't think rustfmt should handle whether or not you use parentheses, though. (rustc potentially should have warnings about cases that should use parentheses, such as commonly confused operator precedences.) This issue should, though, discuss how to format such expressions with spaces and newlines. General principles I'd tend to follow (some of which the style guide already covers, but I've included them to paint a complete picture):
Since function calls can appear in expressions, and expressions can appear in the arguments of function calls, the rules for expressions and function calls will interact. |
I mostly agree with @solson, except that I would probably parenthesise
Could you give some examples of this? Presumably you don't mean
Why does the linebreak make a difference?
I prefer breaking after the binop, I'm having a hard time justifying why though - perhaps uniformity with commas and semicolons? I find that indentation rule works well for 'top-level' expressions, but perhaps not for nested ones. Maybe we should punt on some of the details (e.g., to control flow and function call RFCs), but for example:
I assume that we should try and fit as many sub-expression on a line as posisble, e.g.,
I suppose also that we should prefer breaking at parens rather than inside parens. |
Rustfmt currently does change parenthesisation, but only in some cases, I think. In particular, it removes parens in control flow statements where unnecessary and I think that is the right thing to do. In general, I view parens as significant whitespace - they don't show up in the AST (although technically this is not true in Rust), and so Rustfmt should be free to mess with them. Are there concrete examples of where we wouldn't want that to happen? And are such cases common enough that that should be the default behaviour? |
That sentence appeared specifically in a point talking about the range operator ( |
Thanks for the explanation, that makes sense, I think. I probably wouldn't use parens for |
See also #34 (comment) and discussion leading up to it. |
Given we came to favour block indent for expressions elsewhere, I think this issue is ready for FCP. Most rules are given in #18 (comment), with a few others scattered around in other comments. The only remaining open questions are: whether Rustfmt should insert or remove parens (Josh thinks not, see previous link, I think we should, see #18 (comment), but it should be rare in any case (i.e., Rustfmt only makes such a change in extreme cases, not as a matter of course)). And, if we do split a line at a binop, should the operator go before or after the linebreak. (See also #34 (comment)) |
We've changed our process: rather than requiring a full RFC, a PR to close this issue only requires making the changes discussed here to the style guide. You can see more details about the process in the readme for this repo. If you'd like to help with this work, let me know, I'd be very happy to help you help us. |
This was discussed in issue #34 (#34 (comment)), but I'll copy it here because it's relevant to binops in general: Commas and semicolons should both fade into the background as simple terminators. Regarding other binops: I find that putting a binop at the end of the previous line makes it easier to get lost, and harder to construct the tree in your head, especially when you break an expression in multiple places. If I look at something like this: if really_complicated_expression
|| another_complicated_expression
|| yet_another_complicated_expression (where the complicated expressions themselves have piles of operators and calls in them), having the Typically, a comma or semicolon has importance because of its presence or absence, but for most binary operators, I need to know which operator (such as |
Including parenthesised expressions.
The text was updated successfully, but these errors were encountered: