Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

None } <ins> /// This function checks if the specified expression is a built-in range literal. /// (See: `LoweringContext::lower_expr()` in `src/librustc/hir/lowering.rs`). fn is_range_literal(&self, expr: &hir::Expr) -> bool { use hir::{Path, QPath, ExprKind, TyKind}; // We support `::std::ops::Range` and `::core::ops::Range` prefixes let is_range_path = |path: &Path| { let mut segs = path.segments.iter() .map(|seg| seg.ident.as_str()); if let (Some(root), Some(std_core), Some(ops), Some(range), None) = (segs.next(), segs.next(), segs.next(), segs.next(), segs.next()) { // "{{root}}" is the equivalent of `::` prefix in Path root == "{{root}}" && (std_core == "std" || std_core == "core") && ops == "ops" && range.starts_with("Range") } else { false } }; let span_is_range_literal = |span: &Span| { // Check whether a span corresponding to a range expression // is a range literal, rather than an explicit struct or `new()` call. let source_map = self.tcx.sess.source_map(); let end_point = source_map.end_point(*span); if let Ok(end_string) = source_map.span_to_snippet(end_point) { !(end_string.ends_with("}") || end_string.ends_with(")")) } else { false } }; match expr.node { // All built-in range literals but `..=` and `..` desugar to Structs ExprKind::Struct(QPath::Resolved(None, ref path), _, _) | // `..` desugars to its struct path ExprKind::Path(QPath::Resolved(None, ref path)) => { return is_range_path(&path) && span_is_range_literal(&expr.span); } // `..=` desugars into `::std::ops::RangeInclusive::new(...)` ExprKind::Call(ref func, _) => { if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node { if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node { let call_to_new = segment.ident.as_str() == "new"; return is_range_path(&path) && span_is_range_literal(&expr.span) && call_to_new; } } } _ => {} } false } </ins> pub fn check_for_cast(&self, err: &mut DiagnosticBuilder<'tcx>, expr: &hir::Expr,


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

<ins> // run-rustfix // Regression test for changes introduced while fixing #54505 // This test uses non-literals for Ranges // (expecting no parens with borrow suggestion) use std::ops::RangeBounds; // take a reference to any built-in range fn take_range(_r: &impl RangeBounds<i8>) {} fn main() { take_range(&std::ops::Range { start: 0, end: 1 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::Range { start: 0, end: 1 } take_range(&::std::ops::Range { start: 0, end: 1 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 } take_range(&std::ops::RangeFrom { start: 1 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeFrom { start: 1 } take_range(&::std::ops::RangeFrom { start: 1 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeFrom { start: 1 } take_range(&std::ops::RangeFull {}); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeFull {} take_range(&::std::ops::RangeFull {}); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeFull {} take_range(&std::ops::RangeInclusive::new(0, 1)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1) take_range(&::std::ops::RangeInclusive::new(0, 1)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1) take_range(&std::ops::RangeTo { end: 5 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeTo { end: 5 } take_range(&::std::ops::RangeTo { end: 5 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeTo { end: 5 } take_range(&std::ops::RangeToInclusive { end: 5 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 } take_range(&::std::ops::RangeToInclusive { end: 5 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 } } </ins>


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

<ins> // run-rustfix // Regression test for changes introduced while fixing #54505 // This test uses non-literals for Ranges // (expecting no parens with borrow suggestion) use std::ops::RangeBounds; // take a reference to any built-in range fn take_range(_r: &impl RangeBounds<i8>) {} fn main() { take_range(std::ops::Range { start: 0, end: 1 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::Range { start: 0, end: 1 } take_range(::std::ops::Range { start: 0, end: 1 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 } take_range(std::ops::RangeFrom { start: 1 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeFrom { start: 1 } take_range(::std::ops::RangeFrom { start: 1 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeFrom { start: 1 } take_range(std::ops::RangeFull {}); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeFull {} take_range(::std::ops::RangeFull {}); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeFull {} take_range(std::ops::RangeInclusive::new(0, 1)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1) take_range(::std::ops::RangeInclusive::new(0, 1)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1) take_range(std::ops::RangeTo { end: 5 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeTo { end: 5 } take_range(::std::ops::RangeTo { end: 5 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeTo { end: 5 } take_range(std::ops::RangeToInclusive { end: 5 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 } take_range(::std::ops::RangeToInclusive { end: 5 }); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 } } </ins>


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

<ins> error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:16:16 | LL |     take_range(std::ops::Range { start: 0, end: 1 }); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::Range` |                help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }` | = note: expected type `&_` found type `std::ops::Range<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:21:16 | LL |     take_range(::std::ops::Range { start: 0, end: 1 }); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::Range` |                help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }` | = note: expected type `&_` found type `std::ops::Range<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:26:16 | LL |     take_range(std::ops::RangeFrom { start: 1 }); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeFrom` |                help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }` | = note: expected type `&_` found type `std::ops::RangeFrom<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:31:16 | LL |     take_range(::std::ops::RangeFrom { start: 1 }); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeFrom` |                help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }` | = note: expected type `&_` found type `std::ops::RangeFrom<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:36:16 | LL |     take_range(std::ops::RangeFull {}); |                ^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeFull` |                help: consider borrowing here: `&std::ops::RangeFull {}` | = note: expected type `&_` found type `std::ops::RangeFull` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:41:16 | LL |     take_range(::std::ops::RangeFull {}); |                ^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeFull` |                help: consider borrowing here: `&::std::ops::RangeFull {}` | = note: expected type `&_` found type `std::ops::RangeFull` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:46:16 | LL |     take_range(std::ops::RangeInclusive::new(0, 1)); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeInclusive` |                help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)` | = note: expected type `&_` found type `std::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:51:16 | LL |     take_range(::std::ops::RangeInclusive::new(0, 1)); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeInclusive` |                help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)` | = note: expected type `&_` found type `std::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:56:16 | LL |     take_range(std::ops::RangeTo { end: 5 }); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeTo` |                help: consider borrowing here: `&std::ops::RangeTo { end: 5 }` | = note: expected type `&_` found type `std::ops::RangeTo<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:61:16 | LL |     take_range(::std::ops::RangeTo { end: 5 }); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeTo` |                help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }` | = note: expected type `&_` found type `std::ops::RangeTo<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:66:16 | LL |     take_range(std::ops::RangeToInclusive { end: 5 }); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeToInclusive` |                help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }` | = note: expected type `&_` found type `std::ops::RangeToInclusive<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-literals.rs:71:16 | LL |     take_range(::std::ops::RangeToInclusive { end: 5 }); |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |                | |                expected reference, found struct `std::ops::RangeToInclusive` |                help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }` | = note: expected type `&_` found type `std::ops::RangeToInclusive<{integer}>` error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0308`. </ins>


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

<ins> // error-pattern: `#[panic_handler]` function required, but not found // Regression test for #54505 - range borrowing suggestion had // incorrect syntax (missing parentheses). // This test doesn't use std // (so all Ranges resolve to core::ops::Range...) #![no_std] #![feature(lang_items)] use core::ops::RangeBounds; #[cfg(not(target_arch = "wasm32"))] #[lang = "eh_personality"] extern fn eh_personality() {} #[cfg(target_os = "windows")] #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} // take a reference to any built-in range fn take_range(_r: &impl RangeBounds<i8>) {} fn main() { take_range(0..1); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(0..1) take_range(1..); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(1..) take_range(..); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..) take_range(0..=1); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(0..=1) take_range(..5); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..5) take_range(..=42); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..=42) } </ins>


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

<ins> error: `#[panic_handler]` function required, but not found error[E0308]: mismatched types --> $DIR/issue-54505-no-std.rs:28:16 | LL |     take_range(0..1); |                ^^^^ |                | |                expected reference, found struct `core::ops::Range` |                help: consider borrowing here: `&(0..1)` | = note: expected type `&_` found type `core::ops::Range<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-std.rs:33:16 | LL |     take_range(1..); |                ^^^ |                | |                expected reference, found struct `core::ops::RangeFrom` |                help: consider borrowing here: `&(1..)` | = note: expected type `&_` found type `core::ops::RangeFrom<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-std.rs:38:16 | LL |     take_range(..); |                ^^ |                | |                expected reference, found struct `core::ops::RangeFull` |                help: consider borrowing here: `&(..)` | = note: expected type `&_` found type `core::ops::RangeFull` error[E0308]: mismatched types --> $DIR/issue-54505-no-std.rs:43:16 | LL |     take_range(0..=1); |                ^^^^^ |                | |                expected reference, found struct `core::ops::RangeInclusive` |                help: consider borrowing here: `&(0..=1)` | = note: expected type `&_` found type `core::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-std.rs:48:16 | LL |     take_range(..5); |                ^^^ |                | |                expected reference, found struct `core::ops::RangeTo` |                help: consider borrowing here: `&(..5)` | = note: expected type `&_` found type `core::ops::RangeTo<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505-no-std.rs:53:16 | LL |     take_range(..=42); |                ^^^^^ |                | |                expected reference, found struct `core::ops::RangeToInclusive` |                help: consider borrowing here: `&(..=42)` | = note: expected type `&_` found type `core::ops::RangeToInclusive<{integer}>` error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. </ins>


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

<ins> // run-rustfix // Regression test for #54505 - range borrowing suggestion had // incorrect syntax (missing parentheses). use std::ops::RangeBounds; // take a reference to any built-in range fn take_range(_r: &impl RangeBounds<i8>) {} fn main() { take_range(&(0..1)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(0..1) take_range(&(1..)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(1..) take_range(&(..)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..) take_range(&(0..=1)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(0..=1) take_range(&(..5)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..5) take_range(&(..=42)); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..=42) } </ins>


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

<ins> // run-rustfix // Regression test for #54505 - range borrowing suggestion had // incorrect syntax (missing parentheses). use std::ops::RangeBounds; // take a reference to any built-in range fn take_range(_r: &impl RangeBounds<i8>) {} fn main() { take_range(0..1); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(0..1) take_range(1..); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(1..) take_range(..); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..) take_range(0..=1); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(0..=1) take_range(..5); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..5) take_range(..=42); //~^ ERROR mismatched types [E0308] //~| HELP consider borrowing here //~| SUGGESTION &(..=42) } </ins>


Question:
is an incorrect suggestion because has higher precedence than . It should suggest .
If someone wants to tackle this issue, it should be straightforward to fix. In: there should be another branch for , where the path of the call is . This code is a good reference: This issue affects the other range syntaxes too, so those should also be fixed (although these are not — look at for clues).
Hi I'd like to tackle this and take the plunge into the Rust compiler code :)
great! Let me know if you hit any snags or need any more tips. You'll want to add tests for these (in ). The is a good place for general information about the compiler. When you're done, include in the pull request and I'll review it!
you've anticipated most of my newbie questions already :) Thanks for that info, very useful! I'm now in the process of stressing my PC with lots of compiling to actually get started. Skimming the test code I'm really impressed by how easy it is to add "UI" tests for these sorts of things (compile this, expect this error on this line). Snazzy! That's all great, but do you anticipate I should also add "deeper" tests? I guess I'm trying to understand if the scope of this is just pure UI or do I need to touch some syntax parsing/immediate representations, since you mentioned code in . Because the compiler is emitting a syntax suggestion, we might want to assert that the suggestion is correct syntax in the first place. I don't know if that's how deep the rabbit hole goes and if there's a facility to help out, but my hunch is that since we have all of the compiler at hand, why not use it to validate the suggestion syntax? EDIT: OK, reading up on adding new tests to the compiler I encountered mention of , and it seems to be sort-of what I was after.
The issue here is just a diagnostic issue, so checking that we're getting the updated hint is enough. The code in is just helpful to see what ranges like and are desugared into, so you can catch them in — you shouldn't need to modify anything (apart from the test) outside of . It would technically be possible to do something like this, but it would probably be more trouble than it's worth. (I'm not aware of a facility to do this easily already.) I think manually going through the possible s and checking that the parenthesisation behaviour is correct in each case would be a lot simpler: if we handle the different s in an exhaustive now (it's likely that if the ranges were handled incorrectly, there could be some others that are also missed at the moment), then this should be a one-time fix and the tests should prevent it regressing. A simple UI test should be sufficient here: will generate the output files, which will include all the relevant notes.
There was a similar problem with the suggestions, and it was fixed in . Further use of the operator precedence list can be seen in (which introduced the error fixed in the other PR).
Thanks for your guidance and much appreciated. I have dug into HIR and built-in ranges a bit more. Decided to check all the built-in range types and concluded they are all indeed affected by this problem. The following test I came up with demonstrates my intended fix (fails with nightly as well as stage 1 compiled from master): None of the fix suggestions, when applied, constitute valid syntax. My test checks for syntax I believe should be suggested by the compiler. I'm keen to tackle all of the range types at once in the scope of this issue. The problem I see though is just how wildly different each of the range types is represented in HIR. Adding a call just above this line: Revealed the following: for isfor isfor isfor isfor isfor is I'm quite bewildered by this non-uniformity and I guess I need some help unifying all of these into a elegant condition to tell "is this a built-in range?". I could probably brute-force it in a with explicit checks for , but maybe we can do better. Thanks in advance! EDIT realized that this non-uniformity was actually mentioned in the second comment from , but my plea still stands. Thanks for your patience.
I think you can match on all of these with something along the lines of (pseudocode):
Right, that's what I had in mind, but was also wondering if something like a check for  trait would work better. I guess we want to match against built-in range literals though, and explicitly. Here's how I rationalize it: because they are parsed and desugared by the compiler, the check needs to be explicit and hardcode all paths to builtin ranges. Handle a special case with a special case.
Yes, this is where the lowering code comes in handy, because you can see exactly how the different syntax is desugared differently, to make sure you really are catching all the cases. Yes, I agree. It'd be nice if there was a more uniform way to handle them, but it's not convenient at the moment. You could include a reference back to in a comment to where the desugaring takes place, which will provide some motivation for matching in .
All clear now, thanks. I have succeeded in matching all range types and getting the test to pass. Needs some cleanups, but hopefully should be ready for PR soon. I have a few more questions before that though :smile: I have noticed that most of my code would actually be irrelevant if I re-used functions and constants defined in , e.g.: Can't deny that I have used these as inspiration / guideline (albeit I did not do a stupid copy-paste). What's the policy on using clippy code (clippy is a submodule of main repo)? This is purely in the interest of pursuing . The diff is not that big (52 new lines to , fairly specific to matching paths) -- but still, my clean code sense tingles because of possible DRY violation. Another conundrum I have is whether we should address and paths (and if so, how to work out we're not using at compile time)?
Unfortunately, there's not much sharing from clippy to rustc. I wouldn't worry about it. If you can encapsulate it easily, it's possible that clippy could make use of the code in rustc instead. The function in picks the correct path for / — you should be able to use that.
Thanks for the suggestion for , unfortunately I can't really make the association of and . It seems to me they are disjoint -- in : lowering happens in , whereas typechecking happens in . in takes : The it uses needs an awful lot of things to be instantiated. Not sure if I can get the hold of it all in . Another problem I encountered while writing tests is that the changes I have made will affect suggestions for code like this: With my changes, the suggestion would be . I believe the correct suggestion would not involve the needless parentheses. This is due to not differentiating between "de-sugared" form coming from and between these de-sugared forms being supplied explicitly as input source code. With this in mind, I think current code is not PR worthy just yet. If of interest, here's the branch:
Left a couple of comments on possible approaches on that commit. The code looks fine.

<ins> error[E0308]: mismatched types --> $DIR/issue-54505.rs:14:16 | LL |     take_range(0..1); |                ^^^^ |                | |                expected reference, found struct `std::ops::Range` |                help: consider borrowing here: `&(0..1)` | = note: expected type `&_` found type `std::ops::Range<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505.rs:19:16 | LL |     take_range(1..); |                ^^^ |                | |                expected reference, found struct `std::ops::RangeFrom` |                help: consider borrowing here: `&(1..)` | = note: expected type `&_` found type `std::ops::RangeFrom<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505.rs:24:16 | LL |     take_range(..); |                ^^ |                | |                expected reference, found struct `std::ops::RangeFull` |                help: consider borrowing here: `&(..)` | = note: expected type `&_` found type `std::ops::RangeFull` error[E0308]: mismatched types --> $DIR/issue-54505.rs:29:16 | LL |     take_range(0..=1); |                ^^^^^ |                | |                expected reference, found struct `std::ops::RangeInclusive` |                help: consider borrowing here: `&(0..=1)` | = note: expected type `&_` found type `std::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505.rs:34:16 | LL |     take_range(..5); |                ^^^ |                | |                expected reference, found struct `std::ops::RangeTo` |                help: consider borrowing here: `&(..5)` | = note: expected type `&_` found type `std::ops::RangeTo<{integer}>` error[E0308]: mismatched types --> $DIR/issue-54505.rs:39:16 | LL |     take_range(..=42); |                ^^^^^ |                | |                expected reference, found struct `std::ops::RangeToInclusive` |                help: consider borrowing here: `&(..=42)` | = note: expected type `&_` found type `std::ops::RangeToInclusive<{integer}>` error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`. </ins>


Question:
The following code emits an unsquelchable warning. This warning should be a part of .
empty trait list in should have a lint name ... and that name is .
Does not appear to squelch the warning for me...
It seems eminently reasonable to me to include in since it is an attribute applied with no effect; so let's kick off fcp for that. merge
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [x] [x] [x] [x] [x] [ ] [x] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
Implementing this as part of the existing would be complicated by , but it might also be possible to implement where the existing "empty trait list" warning is issued (possibly as a ).
I need to make a buffered early lint for the same thing with .
Seems reasonable. And a macro that might end up with an empty derive list should have no problem turning off locally.
reviewed I certainly agree with moving warnings to lints.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete.

match attr.parse_list(cx.parse_sess, |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) { <del> Ok(ref traits) if traits.is_empty() => { cx.span_warn(attr.span, "empty trait list in `derive`"); false } </del> Ok(traits) => { result.extend(traits); true


Question:
The following code emits an unsquelchable warning. This warning should be a part of .
empty trait list in should have a lint name ... and that name is .
Does not appear to squelch the warning for me...
It seems eminently reasonable to me to include in since it is an attribute applied with no effect; so let's kick off fcp for that. merge
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [x] [x] [x] [x] [x] [ ] [x] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
Implementing this as part of the existing would be complicated by , but it might also be possible to implement where the existing "empty trait list" warning is issued (possibly as a ).
I need to make a buffered early lint for the same thing with .
Seems reasonable. And a macro that might end up with an empty derive list should have no problem turning off locally.
reviewed I certainly agree with moving warnings to lints.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete.

<del> // compile-pass </del> <ins> #![deny(unused)] </ins> <del> #[derive()] //~ WARNING empty trait list in `derive` struct Bar; </del> <ins> #[derive()] //~ ERROR unused attribute struct _Bar; </ins> pub fn main() {}


Question:
The following code emits an unsquelchable warning. This warning should be a part of .
empty trait list in should have a lint name ... and that name is .
Does not appear to squelch the warning for me...
It seems eminently reasonable to me to include in since it is an attribute applied with no effect; so let's kick off fcp for that. merge
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [x] [x] [x] [x] [x] [ ] [x] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
Implementing this as part of the existing would be complicated by , but it might also be possible to implement where the existing "empty trait list" warning is issued (possibly as a ).
I need to make a buffered early lint for the same thing with .
Seems reasonable. And a macro that might end up with an empty derive list should have no problem turning off locally.
reviewed I certainly agree with moving warnings to lints.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete.

<del> warning: empty trait list in `derive` </del> <ins> error: unused attribute </ins> --> $DIR/deriving-meta-empty-trait-list.rs:3:1 | LL | #[derive()] | ^^^^^^^^^^^ <ins> | note: lint level defined here --> $DIR/deriving-meta-empty-trait-list.rs:1:9 | LL | #![deny(unused)] |         ^^^^^^ = note: #[deny(unused_attributes)] implied by #[deny(unused)] error: aborting due to previous error </ins>


Question:
The following code emits an unsquelchable warning. This warning should be a part of .
empty trait list in should have a lint name ... and that name is .
Does not appear to squelch the warning for me...
It seems eminently reasonable to me to include in since it is an attribute applied with no effect; so let's kick off fcp for that. merge
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [x] [x] [x] [x] [x] [ ] [x] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
Implementing this as part of the existing would be complicated by , but it might also be possible to implement where the existing "empty trait list" warning is issued (possibly as a ).
I need to make a buffered early lint for the same thing with .
Seems reasonable. And a macro that might end up with an empty derive list should have no problem turning off locally.
reviewed I certainly agree with moving warnings to lints.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete.

#[derive(Copy="bad")] //~ ERROR expected one of `)`, `,`, or `::`, found `=` struct Test2; <del> #[derive()] //~ WARNING empty trait list struct Test3; </del> #[derive] //~ ERROR malformed `derive` attribute input struct Test4;


Question:
The following code emits an unsquelchable warning. This warning should be a part of .
empty trait list in should have a lint name ... and that name is .
Does not appear to squelch the warning for me...
It seems eminently reasonable to me to include in since it is an attribute applied with no effect; so let's kick off fcp for that. merge
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [x] [x] [x] [x] [x] [ ] [x] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
Implementing this as part of the existing would be complicated by , but it might also be possible to implement where the existing "empty trait list" warning is issued (possibly as a ).
I need to make a buffered early lint for the same thing with .
Seems reasonable. And a macro that might end up with an empty derive list should have no problem turning off locally.
reviewed I certainly agree with moving warnings to lints.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete.

LL | #[derive(Copy="bad")] |              ^ expected one of `)`, `,`, or `::` here <del> warning: empty trait list in `derive` --> $DIR/malformed-derive-entry.rs:7:1 | LL | #[derive()] | ^^^^^^^^^^^ </del> error: malformed `derive` attribute input <del> --> $DIR/malformed-derive-entry.rs:10:1 </del> <ins> --> $DIR/malformed-derive-entry.rs:7:1 </ins> | LL | #[derive] | ^^^^^^^^^ help: missing traits to be derived: `#[derive(Trait1, Trait2, ...)]`


Question:
The documentation for with say "no re-ordering of reads and writes across this point is allowed". As I understand it, for a single thread doesn't give anything more than . E.g., a store before the fence could be moved past a load after then fence. Is that correct? cc
Hmm, that's a good point, though the details are a little subtle. From the : I think what this translates into is that guarantees that: no subsequent operations can be moved before this operation if it is a load, and no operations can be moved after this operation if it is a store. The italic parts there aren't present in the current documentation, so that should probably be rectified. I think some annotated source code would really help here!
It actually depends on the other operation, does it not? stores after the fence can be moved up, but stores cannot. TBH I have a hard time thinking in terms of reorderings; I usually think in terms of what actually happens in the underlying memory model. Some of these models can be fully characterized by the allowed reorderings, but not all of them can (as far as we know). And anyway, SC fences are broken in the C11 memory model and probably going to change in the next version, so...^^ On top of that, all are in a total order, and that is the entire point of . (The website says it but you left it away in your quote. Just making sure nobody thinks that a load is the same as an load. It is not.)
I'm actually not entirely sure about that. Another store to the same memory location shouldn't be ordered before, but I don't see from the reference text why an unrelated store with couldn't be. I'd be happy for this to be rephrased this in terms of the memory model, but I'm not entirely sure how we'd even do that. Proposals welcome. I think talking about what can and cannot happen, with examples, is probably the most understandable way to present what the different orderings do. I left off the total order part because it didn't seem directly related to the original question. But you're right that it's a vital part of that shouldn't get lost in the docs!
It says The sequentially-consistent ordering consists of all operation, across all locations, and the order in which they are observed must be consistent across all threads. In particular, if one thread performs two operations (i.e., they are ordered by program-order), then the order in which it does them must match the order in which every other thread observes them. That rules out reordering them. This is the sole justification for the existence of .
Yes, good point. So how about we move the bullet point to bottom and change it to say

/// An atomic fence. /// <del> /// Depending on the specified order, a fence prevents the compiler and CPU from /// reordering certain types of memory operations around it. /// That creates synchronizes-with relationships between it and atomic operations /// or fences in other threads. </del> <ins> /// Fences create synchronization between themselves and atomic operations or fences in other /// threads. To achieve this, a fence prevents the compiler and CPU from reordering certain types of /// memory operations around it. </ins> /// /// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes /// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there


Question:
The documentation for with say "no re-ordering of reads and writes across this point is allowed". As I understand it, for a single thread doesn't give anything more than . E.g., a store before the fence could be moved past a load after then fence. Is that correct? cc
Hmm, that's a good point, though the details are a little subtle. From the : I think what this translates into is that guarantees that: no subsequent operations can be moved before this operation if it is a load, and no operations can be moved after this operation if it is a store. The italic parts there aren't present in the current documentation, so that should probably be rectified. I think some annotated source code would really help here!
It actually depends on the other operation, does it not? stores after the fence can be moved up, but stores cannot. TBH I have a hard time thinking in terms of reorderings; I usually think in terms of what actually happens in the underlying memory model. Some of these models can be fully characterized by the allowed reorderings, but not all of them can (as far as we know). And anyway, SC fences are broken in the C11 memory model and probably going to change in the next version, so...^^ On top of that, all are in a total order, and that is the entire point of . (The website says it but you left it away in your quote. Just making sure nobody thinks that a load is the same as an load. It is not.)
I'm actually not entirely sure about that. Another store to the same memory location shouldn't be ordered before, but I don't see from the reference text why an unrelated store with couldn't be. I'd be happy for this to be rephrased this in terms of the memory model, but I'm not entirely sure how we'd even do that. Proposals welcome. I think talking about what can and cannot happen, with examples, is probably the most understandable way to present what the different orderings do. I left off the total order part because it didn't seem directly related to the original question. But you're right that it's a vital part of that shouldn't get lost in the docs!
It says The sequentially-consistent ordering consists of all operation, across all locations, and the order in which they are observed must be consistent across all threads. In particular, if one thread performs two operations (i.e., they are ordered by program-order), then the order in which it does them must match the order in which every other thread observes them. That rules out reordering them. This is the sole justification for the existence of .
Yes, good point. So how about we move the bullet point to bottom and change it to say

///                                                  } /// ``` /// <ins> /// Note that in the example above, it is crucial that the accesses to `x` are atomic. Fences cannot /// be used to establish synchronization among non-atomic accesses in different threads. However, /// thanks to the happens-before relationship between A and B, any non-atomic accesses that /// happen-before A are now also properly synchronized with any non-atomic accesses that /// happen-after B. /// </ins> /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize /// with a fence. ///