Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions library/proc_macro/src/bridge/ident.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::{fmt, hash};

#[derive(Copy, Clone)]
pub struct Ident<Span, Symbol> {
pub sym: Symbol,
pub is_raw: bool,
pub span: Span,
}

impl<Span, Symbol: fmt::Display, T> PartialEq<T> for Ident<Span, Symbol>
where
Symbol: PartialEq<str>,
T: AsRef<str> + ?Sized,
{
fn eq(&self, other: &T) -> bool {
Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

self.to_string() == other.as_ref()
}
}

impl<Span, Symbol: hash::Hash> hash::Hash for Ident<Span, Symbol> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.sym.hash(state);
self.is_raw.hash(state);
}
}

/// Prints the identifier as a string that should be losslessly convertible back
/// into the same identifier.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl<Span, Symbol: fmt::Display> fmt::Display for Ident<Span, Symbol> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_raw {
f.write_str("r#")?;
}
fmt::Display::fmt(&self.sym, f)
}
}
9 changes: 2 additions & 7 deletions library/proc_macro/src/bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ mod closure;
mod fxhash;
#[forbid(unsafe_code)]
mod handle;
mod ident;
#[macro_use]
#[forbid(unsafe_code)]
mod rpc;
Expand All @@ -162,6 +163,7 @@ pub mod server;
mod symbol;

use buffer::Buffer;
pub use ident::Ident;
pub use rpc::PanicMessage;
use rpc::{Decode, DecodeMut, Encode, Reader, Writer};

Expand Down Expand Up @@ -471,13 +473,6 @@ pub struct Punct<Span> {

compound_traits!(struct Punct<Span> { ch, joint, span });

#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Ident<Span, Symbol> {
pub sym: Symbol,
pub is_raw: bool,
pub span: Span,
}

compound_traits!(struct Ident<Span, Symbol> { sym, is_raw, span });

#[derive(Clone, Eq, PartialEq)]
Expand Down
36 changes: 34 additions & 2 deletions library/proc_macro/src/bridge/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@

use std::cell::RefCell;
use std::num::NonZero;
use std::str;
use std::{cmp, str};

use super::*;

/// Handle for a symbol string stored within the Interner.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Copy, Clone)]
pub struct Symbol(NonZero<u32>);

impl !Send for Symbol {}
Expand Down Expand Up @@ -97,6 +97,38 @@ impl fmt::Display for Symbol {
}
}

impl PartialEq<Self> for Symbol {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}

impl PartialEq<str> for Symbol {
fn eq(&self, other: &str) -> bool {
self.with(|s| s == other)
}
}

impl Eq for Symbol {}

impl Hash for Symbol {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}

impl PartialOrd for Symbol {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Symbol {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.with(|s| other.with(|o| s.cmp(o)))
}
}

impl<S> Encode<S> for Symbol {
fn encode(self, w: &mut Writer, s: &mut S) {
self.with(|sym| sym.encode(w, s))
Expand Down
14 changes: 9 additions & 5 deletions library/proc_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ impl PartialEq<Punct> for char {
}

/// An identifier (`ident`).
#[derive(Clone)]
#[derive(Clone, Hash)]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub struct Ident(bridge::Ident<bridge::client::Span, bridge::client::Symbol>);

Expand Down Expand Up @@ -1083,10 +1083,7 @@ impl Ident {
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.0.is_raw {
f.write_str("r#")?;
}
fmt::Display::fmt(&self.0.sym, f)
self.0.fmt(f)
}
}

Expand All @@ -1100,6 +1097,13 @@ impl fmt::Debug for Ident {
}
}

#[stable(feature = "proc_macro_ident_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T: AsRef<str> + ?Sized> PartialEq<T> for Ident {
fn eq(&self, other: &T) -> bool {
self.0 == other
}
}

/// A literal string (`"hello"`), byte string (`b"hello"`), C string (`c"hello"`),
/// character (`'a'`), byte character (`b'a'`), an integer or floating point number
/// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ impl Expander {
} else if let TT::Punct(p) = &input.tt
&& p.as_char() == '!'
&& let TT::Ident(name) = &tt
&& name.to_string() == "inline"
&& *name == "inline"
{
let g = expect_tt(
input.iter.next(),
Expand Down
Loading