diff options
author | bors <bors@rust-lang.org> | 2017-11-04 10:24:20 +0000 |
---|---|---|
committer | bors <bors@rust-lang.org> | 2017-11-04 10:24:20 +0000 |
commit | a6885cb853390fc79a8ff0b223ea1471e261d60e (patch) | |
tree | 732a966af0d57b74a079ae60311e7f81d02cea2a | |
parent | 9acc3331e187d329d29a70c788c44e25a79edf45 (diff) | |
parent | 97692afda9e493db65c833b931a6971fb58352b2 (diff) | |
download | rust-a6885cb853390fc79a8ff0b223ea1471e261d60e.tar.gz |
Auto merge of #45605 - Nashenas88:derive-newtype, r=nikomatsakis
Add derive and doc comment capabilities to newtype_index macro
This moves `RustcDecodable` and `RustcEncodable` out of the macro definition and into the macro uses. They were conflicting with `CrateNum`'s impls of `serialize::UseSpecializedEncodable` and `serialize::UseSpecializedDecodable`, and now it's not :). `CrateNum` is now defined with the `newtype_index` macro. I also added support for doc comments on constant definitions and allowed a type to remove the pub specification on the tuple param (otherwise a LOT of code would refuse to compile for `CrateNum`). I was getting dozens of errors like this if `CrateNum` was defined as `pub struct CrateNum(pub u32)`:
```
error[E0530]: match bindings cannot shadow tuple structs
--> src/librustc/dep_graph/dep_node.rs:624:25
|
63 | use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
| -------- a tuple struct `CrateNum` is imported here
...
624 | [] MissingLangItems(CrateNum),
| ^^^^^^^^ cannot be named the same as a tuple struct
```
I also cleaned up the formatting of the macro bodies as they were getting impossibly long. Should I go back and fix the matching rules to this style too?
I also want to see what the test results look like because `CrateNum` used to just derive `Debug`, but the `newtype_index` macro has a custom implementation. This might require further pushes.
Feel free to bikeshed on the macro language, I have no preference here.
-rw-r--r-- | src/librustc/hir/def_id.rs | 41 | ||||
-rw-r--r-- | src/librustc/middle/region.rs | 4 | ||||
-rw-r--r-- | src/librustc/mir/mod.rs | 1 | ||||
-rw-r--r-- | src/librustc_data_structures/indexed_vec.rs | 265 |
4 files changed, 255 insertions, 56 deletions
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 69d23504cda..cc30fdfaca6 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -16,30 +16,23 @@ use serialize::{self, Encoder, Decoder}; use std::fmt; use std::u32; -#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, Hash, Debug)] -pub struct CrateNum(u32); - -impl Idx for CrateNum { - fn new(value: usize) -> Self { - assert!(value < (u32::MAX) as usize); - CrateNum(value as u32) - } - - fn index(self) -> usize { - self.0 as usize - } -} - -/// Item definitions in the currently-compiled crate would have the CrateNum -/// LOCAL_CRATE in their DefId. -pub const LOCAL_CRATE: CrateNum = CrateNum(0); - -/// Virtual crate for builtin macros -// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get `CrateNum`s. -pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(u32::MAX); - -/// A CrateNum value that indicates that something is wrong. -pub const INVALID_CRATE: CrateNum = CrateNum(u32::MAX - 1); +newtype_index!(CrateNum + { + derive[Debug] + ENCODABLE = custom + + /// Item definitions in the currently-compiled crate would have the CrateNum + /// LOCAL_CRATE in their DefId. + const LOCAL_CRATE = 0, + + /// Virtual crate for builtin macros + // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get + // `CrateNum`s. + const BUILTIN_MACROS_CRATE = u32::MAX, + + /// A CrateNum value that indicates that something is wrong. + const INVALID_CRATE = u32::MAX - 1, + }); impl CrateNum { pub fn new(x: usize) -> CrateNum { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index e725592ff99..89707839144 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -158,8 +158,8 @@ pub struct BlockRemainder { newtype_index!(FirstStatementIndex { - DEBUG_FORMAT = "{}", - MAX = SCOPE_DATA_REMAINDER_MAX, + pub idx + MAX = SCOPE_DATA_REMAINDER_MAX }); impl From<ScopeData> for Scope { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 8f86d1b9d78..2fc27de137f 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1552,6 +1552,7 @@ pub struct Constant<'tcx> { newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" }); + #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum Literal<'tcx> { Value { diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 0660cd96a4a..dc169c67a76 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -45,38 +45,62 @@ macro_rules! newtype_index { // Use default constants ($name:ident) => ( newtype_index!( - @type[$name] - @max[::std::u32::MAX] - @debug_format["{}"]); + // Leave out derives marker so we can use its absence to ensure it comes first + @type [$name] + @max [::std::u32::MAX] + @debug_format ["{}"]); ); // Define any constants ($name:ident { $($tokens:tt)+ }) => ( newtype_index!( - @type[$name] - @max[::std::u32::MAX] - @debug_format["{}"] - $($tokens)+); + // Leave out derives marker so we can use its absence to ensure it comes first + @type [$name] + @max [::std::u32::MAX] + @debug_format ["{}"] + $($tokens)+); ); // ---- private rules ---- // Base case, user-defined constants (if any) have already been defined - (@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]) => ( - #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, - RustcEncodable, RustcDecodable)] - pub struct $type(pub u32); + (@derives [$($derives:ident,)*] + @pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr]) => ( + #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)] + pub struct $type($($pub)* u32); impl Idx for $type { fn new(value: usize) -> Self { assert!(value < ($max) as usize); $type(value as u32) } + fn index(self) -> usize { self.0 as usize } } + newtype_index!( + @handle_debug + @derives [$($derives,)*] + @type [$type] + @debug_format [$debug_format]); + ); + + // base case for handle_debug where format is custom. No Debug implementation is emitted. + (@handle_debug + @derives [$($_derives:ident,)*] + @type [$type:ident] + @debug_format [custom]) => (); + + // base case for handle_debug, no debug overrides found, so use default + (@handle_debug + @derives [] + @type [$type:ident] + @debug_format [$debug_format:expr]) => ( impl ::std::fmt::Debug for $type { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(fmt, $debug_format, self.0) @@ -84,38 +108,219 @@ macro_rules! newtype_index { } ); + // Debug is requested for derive, don't generate any Debug implementation. + (@handle_debug + @derives [Debug, $($derives:ident,)*] + @type [$type:ident] + @debug_format [$debug_format:expr]) => (); + + // It's not Debug, so just pop it off the front of the derives stack and check the rest. + (@handle_debug + @derives [$_derive:ident, $($derives:ident,)*] + @type [$type:ident] + @debug_format [$debug_format:expr]) => ( + newtype_index!( + @handle_debug + @derives [$($derives,)*] + @type [$type] + @debug_format [$debug_format]); + ); + + // Handle the case where someone wants to make the internal field public + (@type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + pub idx + $($tokens:tt)*) => ( + newtype_index!( + @pub [pub] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); + ); + + // The default case is that the internal field is private + (@type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + $($tokens:tt)*) => ( + newtype_index!( + @pub [] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); + ); + + // Append comma to end of derives list if it's missing + (@pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + derive [$($derives:ident),*] + $($tokens:tt)*) => ( + newtype_index!( + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + derive [$($derives,)*] + $($tokens)*); + ); + + // By not including the @derives marker in this list nor in the default args, we can force it + // to come first if it exists. When encodable is custom, just use the derives list as-is. + (@pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + derive [$($derives:ident,)+] + ENCODABLE = custom + $($tokens:tt)*) => ( + newtype_index!( + @derives [$($derives,)+] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); + ); + + // By not including the @derives marker in this list nor in the default args, we can force it + // to come first if it exists. When encodable isn't custom, add serialization traits by default. + (@pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + derive [$($derives:ident,)+] + $($tokens:tt)*) => ( + newtype_index!( + @derives [$($derives,)+ RustcDecodable, RustcEncodable,] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); + ); + + // The case where no derives are added, but encodable is overriden. Don't + // derive serialization traits + (@pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + ENCODABLE = custom + $($tokens:tt)*) => ( + newtype_index!( + @derives [] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); + ); + + // The case where no derives are added, add serialization derives by default + (@pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + $($tokens:tt)*) => ( + newtype_index!( + @derives [RustcDecodable, RustcEncodable,] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); + ); + // Rewrite final without comma to one that includes comma - (@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr] - $name:ident = $constant:expr) => ( - newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $name = $constant,); + (@derives [$($derives:ident,)*] + @pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + $name:ident = $constant:expr) => ( + newtype_index!( + @derives [$($derives,)*] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $name = $constant,); ); // Rewrite final const without comma to one that includes comma - (@type[$type:ident] @max[$_max:expr] @debug_format[$debug_format:expr] - const $name:ident = $constant:expr) => ( - newtype_index!(@type[$type] - @max[$max] - @debug_format[$debug_format] - const $name = $constant,); + (@derives [$($derives:ident,)*] + @pub [$($pub:tt)*] + @type [$type:ident] + @max [$_max:expr] + @debug_format [$debug_format:expr] + $(#[doc = $doc:expr])* + const $name:ident = $constant:expr) => ( + newtype_index!( + @derives [$($derives,)*] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $(#[doc = $doc])* const $name = $constant,); ); // Replace existing default for max - (@type[$type:ident] @max[$_max:expr] @debug_format[$debug_format:expr] - MAX = $max:expr, $($tokens:tt)*) => ( - newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*); + (@derives [$($derives:ident,)*] + @pub [$($pub:tt)*] + @type [$type:ident] + @max [$_max:expr] + @debug_format [$debug_format:expr] + MAX = $max:expr, + $($tokens:tt)*) => ( + newtype_index!( + @derives [$($derives,)*] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); ); // Replace existing default for debug_format - (@type[$type:ident] @max[$max:expr] @debug_format[$_debug_format:expr] - DEBUG_FORMAT = $debug_format:expr, $($tokens:tt)*) => ( - newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*); + (@derives [$($derives:ident,)*] + @pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$_debug_format:expr] + DEBUG_FORMAT = $debug_format:expr, + $($tokens:tt)*) => ( + newtype_index!( + @derives [$($derives,)*] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); ); - // Assign a user-defined constant (as final param) - (@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr] - const $name:ident = $constant:expr, $($tokens:tt)*) => ( + // Assign a user-defined constant + (@derives [$($derives:ident,)*] + @pub [$($pub:tt)*] + @type [$type:ident] + @max [$max:expr] + @debug_format [$debug_format:expr] + $(#[doc = $doc:expr])* + const $name:ident = $constant:expr, + $($tokens:tt)*) => ( + $(#[doc = $doc])* pub const $name: $type = $type($constant); - newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*); + newtype_index!( + @derives [$($derives,)*] + @pub [$($pub)*] + @type [$type] + @max [$max] + @debug_format [$debug_format] + $($tokens)*); ); } |