Skip to content

Commit a6885cb

Browse files
committed
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.
2 parents 9acc333 + 97692af commit a6885cb

File tree

4 files changed

+255
-56
lines changed

4 files changed

+255
-56
lines changed

src/librustc/hir/def_id.rs

+17-24
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,23 @@ use serialize::{self, Encoder, Decoder};
1616
use std::fmt;
1717
use std::u32;
1818

19-
#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, Hash, Debug)]
20-
pub struct CrateNum(u32);
21-
22-
impl Idx for CrateNum {
23-
fn new(value: usize) -> Self {
24-
assert!(value < (u32::MAX) as usize);
25-
CrateNum(value as u32)
26-
}
27-
28-
fn index(self) -> usize {
29-
self.0 as usize
30-
}
31-
}
32-
33-
/// Item definitions in the currently-compiled crate would have the CrateNum
34-
/// LOCAL_CRATE in their DefId.
35-
pub const LOCAL_CRATE: CrateNum = CrateNum(0);
36-
37-
/// Virtual crate for builtin macros
38-
// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get `CrateNum`s.
39-
pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(u32::MAX);
40-
41-
/// A CrateNum value that indicates that something is wrong.
42-
pub const INVALID_CRATE: CrateNum = CrateNum(u32::MAX - 1);
19+
newtype_index!(CrateNum
20+
{
21+
derive[Debug]
22+
ENCODABLE = custom
23+
24+
/// Item definitions in the currently-compiled crate would have the CrateNum
25+
/// LOCAL_CRATE in their DefId.
26+
const LOCAL_CRATE = 0,
27+
28+
/// Virtual crate for builtin macros
29+
// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
30+
// `CrateNum`s.
31+
const BUILTIN_MACROS_CRATE = u32::MAX,
32+
33+
/// A CrateNum value that indicates that something is wrong.
34+
const INVALID_CRATE = u32::MAX - 1,
35+
});
4336

4437
impl CrateNum {
4538
pub fn new(x: usize) -> CrateNum {

src/librustc/middle/region.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ pub struct BlockRemainder {
158158

159159
newtype_index!(FirstStatementIndex
160160
{
161-
DEBUG_FORMAT = "{}",
162-
MAX = SCOPE_DATA_REMAINDER_MAX,
161+
pub idx
162+
MAX = SCOPE_DATA_REMAINDER_MAX
163163
});
164164

165165
impl From<ScopeData> for Scope {

src/librustc/mir/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,7 @@ pub struct Constant<'tcx> {
15521552

15531553
newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" });
15541554

1555+
15551556
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
15561557
pub enum Literal<'tcx> {
15571558
Value {

src/librustc_data_structures/indexed_vec.rs

+235-30
Original file line numberDiff line numberDiff line change
@@ -45,77 +45,282 @@ macro_rules! newtype_index {
4545
// Use default constants
4646
($name:ident) => (
4747
newtype_index!(
48-
@type[$name]
49-
@max[::std::u32::MAX]
50-
@debug_format["{}"]);
48+
// Leave out derives marker so we can use its absence to ensure it comes first
49+
@type [$name]
50+
@max [::std::u32::MAX]
51+
@debug_format ["{}"]);
5152
);
5253

5354
// Define any constants
5455
($name:ident { $($tokens:tt)+ }) => (
5556
newtype_index!(
56-
@type[$name]
57-
@max[::std::u32::MAX]
58-
@debug_format["{}"]
59-
$($tokens)+);
57+
// Leave out derives marker so we can use its absence to ensure it comes first
58+
@type [$name]
59+
@max [::std::u32::MAX]
60+
@debug_format ["{}"]
61+
$($tokens)+);
6062
);
6163

6264
// ---- private rules ----
6365

6466
// Base case, user-defined constants (if any) have already been defined
65-
(@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]) => (
66-
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
67-
RustcEncodable, RustcDecodable)]
68-
pub struct $type(pub u32);
67+
(@derives [$($derives:ident,)*]
68+
@pub [$($pub:tt)*]
69+
@type [$type:ident]
70+
@max [$max:expr]
71+
@debug_format [$debug_format:expr]) => (
72+
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)]
73+
pub struct $type($($pub)* u32);
6974

7075
impl Idx for $type {
7176
fn new(value: usize) -> Self {
7277
assert!(value < ($max) as usize);
7378
$type(value as u32)
7479
}
80+
7581
fn index(self) -> usize {
7682
self.0 as usize
7783
}
7884
}
7985

86+
newtype_index!(
87+
@handle_debug
88+
@derives [$($derives,)*]
89+
@type [$type]
90+
@debug_format [$debug_format]);
91+
);
92+
93+
// base case for handle_debug where format is custom. No Debug implementation is emitted.
94+
(@handle_debug
95+
@derives [$($_derives:ident,)*]
96+
@type [$type:ident]
97+
@debug_format [custom]) => ();
98+
99+
// base case for handle_debug, no debug overrides found, so use default
100+
(@handle_debug
101+
@derives []
102+
@type [$type:ident]
103+
@debug_format [$debug_format:expr]) => (
80104
impl ::std::fmt::Debug for $type {
81105
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
82106
write!(fmt, $debug_format, self.0)
83107
}
84108
}
85109
);
86110

111+
// Debug is requested for derive, don't generate any Debug implementation.
112+
(@handle_debug
113+
@derives [Debug, $($derives:ident,)*]
114+
@type [$type:ident]
115+
@debug_format [$debug_format:expr]) => ();
116+
117+
// It's not Debug, so just pop it off the front of the derives stack and check the rest.
118+
(@handle_debug
119+
@derives [$_derive:ident, $($derives:ident,)*]
120+
@type [$type:ident]
121+
@debug_format [$debug_format:expr]) => (
122+
newtype_index!(
123+
@handle_debug
124+
@derives [$($derives,)*]
125+
@type [$type]
126+
@debug_format [$debug_format]);
127+
);
128+
129+
// Handle the case where someone wants to make the internal field public
130+
(@type [$type:ident]
131+
@max [$max:expr]
132+
@debug_format [$debug_format:expr]
133+
pub idx
134+
$($tokens:tt)*) => (
135+
newtype_index!(
136+
@pub [pub]
137+
@type [$type]
138+
@max [$max]
139+
@debug_format [$debug_format]
140+
$($tokens)*);
141+
);
142+
143+
// The default case is that the internal field is private
144+
(@type [$type:ident]
145+
@max [$max:expr]
146+
@debug_format [$debug_format:expr]
147+
$($tokens:tt)*) => (
148+
newtype_index!(
149+
@pub []
150+
@type [$type]
151+
@max [$max]
152+
@debug_format [$debug_format]
153+
$($tokens)*);
154+
);
155+
156+
// Append comma to end of derives list if it's missing
157+
(@pub [$($pub:tt)*]
158+
@type [$type:ident]
159+
@max [$max:expr]
160+
@debug_format [$debug_format:expr]
161+
derive [$($derives:ident),*]
162+
$($tokens:tt)*) => (
163+
newtype_index!(
164+
@pub [$($pub)*]
165+
@type [$type]
166+
@max [$max]
167+
@debug_format [$debug_format]
168+
derive [$($derives,)*]
169+
$($tokens)*);
170+
);
171+
172+
// By not including the @derives marker in this list nor in the default args, we can force it
173+
// to come first if it exists. When encodable is custom, just use the derives list as-is.
174+
(@pub [$($pub:tt)*]
175+
@type [$type:ident]
176+
@max [$max:expr]
177+
@debug_format [$debug_format:expr]
178+
derive [$($derives:ident,)+]
179+
ENCODABLE = custom
180+
$($tokens:tt)*) => (
181+
newtype_index!(
182+
@derives [$($derives,)+]
183+
@pub [$($pub)*]
184+
@type [$type]
185+
@max [$max]
186+
@debug_format [$debug_format]
187+
$($tokens)*);
188+
);
189+
190+
// By not including the @derives marker in this list nor in the default args, we can force it
191+
// to come first if it exists. When encodable isn't custom, add serialization traits by default.
192+
(@pub [$($pub:tt)*]
193+
@type [$type:ident]
194+
@max [$max:expr]
195+
@debug_format [$debug_format:expr]
196+
derive [$($derives:ident,)+]
197+
$($tokens:tt)*) => (
198+
newtype_index!(
199+
@derives [$($derives,)+ RustcDecodable, RustcEncodable,]
200+
@pub [$($pub)*]
201+
@type [$type]
202+
@max [$max]
203+
@debug_format [$debug_format]
204+
$($tokens)*);
205+
);
206+
207+
// The case where no derives are added, but encodable is overriden. Don't
208+
// derive serialization traits
209+
(@pub [$($pub:tt)*]
210+
@type [$type:ident]
211+
@max [$max:expr]
212+
@debug_format [$debug_format:expr]
213+
ENCODABLE = custom
214+
$($tokens:tt)*) => (
215+
newtype_index!(
216+
@derives []
217+
@pub [$($pub)*]
218+
@type [$type]
219+
@max [$max]
220+
@debug_format [$debug_format]
221+
$($tokens)*);
222+
);
223+
224+
// The case where no derives are added, add serialization derives by default
225+
(@pub [$($pub:tt)*]
226+
@type [$type:ident]
227+
@max [$max:expr]
228+
@debug_format [$debug_format:expr]
229+
$($tokens:tt)*) => (
230+
newtype_index!(
231+
@derives [RustcDecodable, RustcEncodable,]
232+
@pub [$($pub)*]
233+
@type [$type]
234+
@max [$max]
235+
@debug_format [$debug_format]
236+
$($tokens)*);
237+
);
238+
87239
// Rewrite final without comma to one that includes comma
88-
(@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]
89-
$name:ident = $constant:expr) => (
90-
newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $name = $constant,);
240+
(@derives [$($derives:ident,)*]
241+
@pub [$($pub:tt)*]
242+
@type [$type:ident]
243+
@max [$max:expr]
244+
@debug_format [$debug_format:expr]
245+
$name:ident = $constant:expr) => (
246+
newtype_index!(
247+
@derives [$($derives,)*]
248+
@pub [$($pub)*]
249+
@type [$type]
250+
@max [$max]
251+
@debug_format [$debug_format]
252+
$name = $constant,);
91253
);
92254

93255
// Rewrite final const without comma to one that includes comma
94-
(@type[$type:ident] @max[$_max:expr] @debug_format[$debug_format:expr]
95-
const $name:ident = $constant:expr) => (
96-
newtype_index!(@type[$type]
97-
@max[$max]
98-
@debug_format[$debug_format]
99-
const $name = $constant,);
256+
(@derives [$($derives:ident,)*]
257+
@pub [$($pub:tt)*]
258+
@type [$type:ident]
259+
@max [$_max:expr]
260+
@debug_format [$debug_format:expr]
261+
$(#[doc = $doc:expr])*
262+
const $name:ident = $constant:expr) => (
263+
newtype_index!(
264+
@derives [$($derives,)*]
265+
@pub [$($pub)*]
266+
@type [$type]
267+
@max [$max]
268+
@debug_format [$debug_format]
269+
$(#[doc = $doc])* const $name = $constant,);
100270
);
101271

102272
// Replace existing default for max
103-
(@type[$type:ident] @max[$_max:expr] @debug_format[$debug_format:expr]
104-
MAX = $max:expr, $($tokens:tt)*) => (
105-
newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
273+
(@derives [$($derives:ident,)*]
274+
@pub [$($pub:tt)*]
275+
@type [$type:ident]
276+
@max [$_max:expr]
277+
@debug_format [$debug_format:expr]
278+
MAX = $max:expr,
279+
$($tokens:tt)*) => (
280+
newtype_index!(
281+
@derives [$($derives,)*]
282+
@pub [$($pub)*]
283+
@type [$type]
284+
@max [$max]
285+
@debug_format [$debug_format]
286+
$($tokens)*);
106287
);
107288

108289
// Replace existing default for debug_format
109-
(@type[$type:ident] @max[$max:expr] @debug_format[$_debug_format:expr]
110-
DEBUG_FORMAT = $debug_format:expr, $($tokens:tt)*) => (
111-
newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
290+
(@derives [$($derives:ident,)*]
291+
@pub [$($pub:tt)*]
292+
@type [$type:ident]
293+
@max [$max:expr]
294+
@debug_format [$_debug_format:expr]
295+
DEBUG_FORMAT = $debug_format:expr,
296+
$($tokens:tt)*) => (
297+
newtype_index!(
298+
@derives [$($derives,)*]
299+
@pub [$($pub)*]
300+
@type [$type]
301+
@max [$max]
302+
@debug_format [$debug_format]
303+
$($tokens)*);
112304
);
113305

114-
// Assign a user-defined constant (as final param)
115-
(@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]
116-
const $name:ident = $constant:expr, $($tokens:tt)*) => (
306+
// Assign a user-defined constant
307+
(@derives [$($derives:ident,)*]
308+
@pub [$($pub:tt)*]
309+
@type [$type:ident]
310+
@max [$max:expr]
311+
@debug_format [$debug_format:expr]
312+
$(#[doc = $doc:expr])*
313+
const $name:ident = $constant:expr,
314+
$($tokens:tt)*) => (
315+
$(#[doc = $doc])*
117316
pub const $name: $type = $type($constant);
118-
newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
317+
newtype_index!(
318+
@derives [$($derives,)*]
319+
@pub [$($pub)*]
320+
@type [$type]
321+
@max [$max]
322+
@debug_format [$debug_format]
323+
$($tokens)*);
119324
);
120325
}
121326

0 commit comments

Comments
 (0)