about summary refs log tree commit diff
diff options
context:
space:
mode:
authorpierwill <pierwill@users.noreply.github.com>2022-02-26 14:44:09 -0600
committerpierwill <pierwill@users.noreply.github.com>2022-03-03 11:52:40 -0600
commitc08a9a4f1d03f48ae38dba885fce96fad785a2de (patch)
tree830156801abe64b6e00ad29ca58d67a51907790c
parent45660949132222ba7ec0905649b2affd68e0e13c (diff)
downloadrust-c08a9a4f1d03f48ae38dba885fce96fad785a2de.tar.gz
rust-c08a9a4f1d03f48ae38dba885fce96fad785a2de.zip
Make `Ord`, `PartialOrd` opt-out in `newtype_index`
Also remove `step` impl if `ORD_IMPL = off`
-rw-r--r--compiler/rustc_macros/src/newtype.rs70
1 files changed, 46 insertions, 24 deletions
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs
index f284e5cdd5c..f5968a8a7ea 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_macros/src/newtype.rs
@@ -10,6 +10,7 @@ mod kw {
     syn::custom_keyword!(MAX);
     syn::custom_keyword!(ENCODABLE);
     syn::custom_keyword!(custom);
+    syn::custom_keyword!(ORD_IMPL);
 }
 
 #[derive(Debug)]
@@ -42,6 +43,7 @@ impl Parse for Newtype {
         let mut max = None;
         let mut consts = Vec::new();
         let mut encodable = true;
+        let mut ord = true;
 
         // Parse an optional trailing comma
         let try_comma = || -> Result<()> {
@@ -99,13 +101,20 @@ impl Parse for Newtype {
                     encodable = false;
                     continue;
                 }
+                if body.lookahead1().peek(kw::ORD_IMPL) {
+                    body.parse::<kw::ORD_IMPL>()?;
+                    body.parse::<Token![=]>()?;
+                    body.parse::<kw::custom>()?;
+                    ord = false;
+                    continue;
+                }
 
                 // We've parsed everything that the user provided, so we're done
                 if body.is_empty() {
                     break;
                 }
 
-                // Otherwise, we are parsng a user-defined constant
+                // Otherwise, we are parsing a user-defined constant
                 let const_attrs = body.call(Attribute::parse_outer)?;
                 body.parse::<Token![const]>()?;
                 let const_name: Ident = body.parse()?;
@@ -137,6 +146,40 @@ impl Parse for Newtype {
             quote! {}
         };
 
+        if ord {
+            derive_paths.push(parse_quote!(Ord));
+            derive_paths.push(parse_quote!(PartialOrd));
+        }
+
+        let step = if ord {
+            quote! {
+                impl ::std::iter::Step for #name {
+                    #[inline]
+                    fn steps_between(start: &Self, end: &Self) -> Option<usize> {
+                        <usize as ::std::iter::Step>::steps_between(
+                            &Self::index(*start),
+                            &Self::index(*end),
+                        )
+                    }
+
+                    #[inline]
+                    fn forward_checked(start: Self, u: usize) -> Option<Self> {
+                        Self::index(start).checked_add(u).map(Self::from_usize)
+                    }
+
+                    #[inline]
+                    fn backward_checked(start: Self, u: usize) -> Option<Self> {
+                        Self::index(start).checked_sub(u).map(Self::from_usize)
+                    }
+                }
+
+                // Safety: The implementation of `Step` upholds all invariants.
+                unsafe impl ::std::iter::TrustedStep for #name {}
+            }
+        } else {
+            quote! {}
+        };
+
         let debug_impl = match debug_format {
             DebugFormat::Custom => quote! {},
             DebugFormat::Format(format) => {
@@ -152,7 +195,7 @@ impl Parse for Newtype {
 
         Ok(Self(quote! {
             #(#attrs)*
-            #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, #(#derive_paths),*)]
+            #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)]
             #[rustc_layout_scalar_valid_range_end(#max)]
             #vis struct #name {
                 private: u32,
@@ -247,28 +290,7 @@ impl Parse for Newtype {
                 }
             }
 
-            impl ::std::iter::Step for #name {
-                #[inline]
-                fn steps_between(start: &Self, end: &Self) -> Option<usize> {
-                    <usize as ::std::iter::Step>::steps_between(
-                        &Self::index(*start),
-                        &Self::index(*end),
-                    )
-                }
-
-                #[inline]
-                fn forward_checked(start: Self, u: usize) -> Option<Self> {
-                    Self::index(start).checked_add(u).map(Self::from_usize)
-                }
-
-                #[inline]
-                fn backward_checked(start: Self, u: usize) -> Option<Self> {
-                    Self::index(start).checked_sub(u).map(Self::from_usize)
-                }
-            }
-
-            // Safety: The implementation of `Step` upholds all invariants.
-            unsafe impl ::std::iter::TrustedStep for #name {}
+            #step
 
             impl From<#name> for u32 {
                 #[inline]