-   Notifications  You must be signed in to change notification settings 
- Fork 13.9k
add trait impls to proc_macro::Ident #146553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| rustbot has assigned @petrochenkov. Use  | 
55be783 to fee6f71   Compare      This comment has been minimized. 
   
 This comment has been minimized.
fee6f71 to 624c863   Compare      This comment has been minimized. 
   
 This comment has been minimized.
624c863 to 509f080   Compare      This comment has been minimized. 
   
 This comment has been minimized.
509f080 to 8bc4c57   Compare   | Some changes occurred in src/tools/clippy cc @rust-lang/clippy | 
| Clippy context: An aux crate (proc_macros.rs) was using  | 
| I suggest splitting this into one PR with (insta-stable) API changes, and then another PR with implementation optimizations. Also,  | 
| To clarify, the clippy change was to fix CI. Thanks for the context! I'd be happy to remove the  | 
| @rustbot ready | 
| 
 This was about moving the code around and providing the optimized implementation instead of just doing  The  | 
| Reminder, once the PR becomes ready for a review, use  | 
| Symbol: PartialEq<str>, | ||
| T: AsRef<str> + ?Sized, | ||
| { | ||
| fn eq(&self, other: &T) -> bool { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@petrochenkov I'm a little confused. Do you mean that this implementation should be reduced to self.to_string() == other.as_ref()? That seems to miss the point of the ACP, which was to compare Idents with Strings (and friends) without an allocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean that this implementation should be reduced to self.to_string() == other.as_ref()?
Yes.
 Allocation or not is an implementation detail, that can be changed at any later point without any process or team decisions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you push the changes?
 I still see all the unnecessary code moving and optimizations.
| @rustbot ready | 
   This comment was marked as resolved. 
   
 This comment was marked as resolved.
   This comment has been minimized. 
   
 This comment has been minimized.
| This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. | 
| @rustbot ready I think I got rid of the unnecessary code moving, but I'm not sure what you're referring to as optimizations. Let me know what, if anything, I missed. | 
| 
 Everything outside of  | 
| Anyway, I'm sending this to the libs-api team for approval. This PR adds two public APIs: 
 | 
| We took a brief look at this in today's @rust-lang/libs-api meeting. We didn't look at the  We observed that this is providing  It'd be a bit more work, but please consider implementing  | 
| 
 
 https://docs.rs/proc-macro2/1.0.101/proc_macro2/struct.Ident.html#impl-PartialEq%3CT%3E-for-Ident Since you mentioned a negative impl, I assume that you expected this would only be allowed in combination with a  The only thing it precludes is a custom PartialEq with some type that also implements AsRef<str> where you want PartialEq to be inconsistent with the standard library's AsRef-based impl, which seems fine. | 
| 
 | 
| We discussed this PR in today's standard library API team meeting. Those present were on board with adding this adjusted group of impls: 
 TransitivityWe discussed whether ident–string comparisons violate the requirement that PartialEq impls behave transitively. According to the documentation of PartialEq, by symmetry and transitivity, if: 
 then  HygieneIgnoring the absence of impl 3, one would reasonably expect that  While "do these idents resolve to the same thing" is sometimes a reasonable thing to want to know, "do these idents have the same Span" is neither that same question nor basically ever what someone would want to know in a proc macro. We discussed the scenario of idents that have the same span but end up referring to different things after name resolution, which is counterintuitive to people with an incomplete familiarity with Span. An example is: let ident = Ident::new("X", Span::call_site()); quote! { { const X: i8 = 1; print($ident); } { const X: i8 = 2; print($ident); } }Because of this kind of thing, "do these idents have the same Span" is not a workable proxy for "do these idents resolve to the same thing". The latter is not something that would be knowable during macro expansion, and it would not make sense for PartialEq comparison on Ident to be the way that we would try to surface this information. In contrast, "is this ident some specific keyword/symbol that is meaningful to the macro" is the 100% use case and it makes sense for Ident to provide affordances to make this check readable and easy. AsRef-basedThe impl currently implemented in the PR is  A subset of the team was hesitant about this generic impl for proc_macro::Ident because it rules out downstream types that could want to have both an AsRef<str> impl and a PartialEq impl based on Ident comparison, not string comparison. Hypothetically like this: pub struct MyIdent { string: String, ident: proc_macro::Ident, } impl MyIdent { pub fn new(ident: proc_macro::Ident) -> Self { MyIdent { string: ident.to_string(), ident, } } } impl AsRef<str> for MyIdent { fn as_ref(&self) -> &str { &self.string } } impl PartialEq<MyIdent> for proc_macro::Ident { fn eq(&self, other: &MyIdent) -> bool { // more efficient than `*self == other.as_ref()` *self == other.ident } }While it is difficult to imagine any procedural macro that would be bottlenecked on string comparison performance vs the faster interned identifier integer comparison, avoiding the AsRef-based generic PartialEq impl seemed like the safer route that can achieve consensus more easily. The number of concrete types that people will want to compare against in real-world code is expected to be small. HashThe proposed  Together these make Ident usable in  OrdPossible future extension: now that  | 
ACP: rust-lang/libs-team#573