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.
This commit is contained in:
commit
a6885cb853
|
@ -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);
|
||||
newtype_index!(CrateNum
|
||||
{
|
||||
derive[Debug]
|
||||
ENCODABLE = custom
|
||||
|
||||
impl Idx for CrateNum {
|
||||
fn new(value: usize) -> Self {
|
||||
assert!(value < (u32::MAX) as usize);
|
||||
CrateNum(value as u32)
|
||||
}
|
||||
/// Item definitions in the currently-compiled crate would have the CrateNum
|
||||
/// LOCAL_CRATE in their DefId.
|
||||
const LOCAL_CRATE = 0,
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0 as usize
|
||||
}
|
||||
}
|
||||
/// 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,
|
||||
|
||||
/// 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);
|
||||
/// A CrateNum value that indicates that something is wrong.
|
||||
const INVALID_CRATE = u32::MAX - 1,
|
||||
});
|
||||
|
||||
impl CrateNum {
|
||||
pub fn new(x: usize) -> CrateNum {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)*);
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue