Skip to content

Commit

Permalink
librustc: Always parse macro!()/macro![] as expressions if not
Browse files Browse the repository at this point in the history
followed by a semicolon.

This allows code like `vec![1i, 2, 3].len();` to work.

This breaks code that uses macros as statements without putting
semicolons after them, such as:

    fn main() {
        ...
        assert!(a == b)
        assert!(c == d)
        println(...);
    }

It also breaks code that uses macros as items without semicolons:

    local_data_key!(foo)

    fn main() {
        println("hello world")
    }

Add semicolons to fix this code. Those two examples can be fixed as
follows:

    fn main() {
        ...
        assert!(a == b);
        assert!(c == d);
        println(...);
    }

    local_data_key!(foo);

    fn main() {
        println("hello world")
    }

RFC rust-lang#378.

Closes rust-lang#18635.

[breaking-change]
  • Loading branch information
pcwalton committed Nov 19, 2014
1 parent e09d986 commit 6a855f6
Show file tree
Hide file tree
Showing 226 changed files with 2,301 additions and 2,023 deletions.
34 changes: 17 additions & 17 deletions src/doc/guide-macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ macro_rules! early_return(
_ => {}
}
);
)
);
// ...
early_return!(input_1 T::SpecialA);
// ...
Expand Down Expand Up @@ -179,8 +179,8 @@ macro_rules! early_return(
)+
_ => {}
}
);
)
)
);
// ...
early_return!(input_1, [T::SpecialA|T::SpecialC|T::SpecialD]);
// ...
Expand Down Expand Up @@ -275,17 +275,17 @@ macro_rules! biased_match (
_ => { $err }
};
)
)
);
# enum T1 { Good1(T2, uint), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(uint), Bad2}
# fn f(x: T1) -> uint {
biased_match!((x) ~ (T1::Good1(g1, val)) else { return 0 };
binds g1, val )
binds g1, val );
biased_match!((g1.body) ~ (T3::Good2(result) )
else { panic!("Didn't get good_2") };
binds result )
binds result );
// complicated stuff goes here
return result + val;
# }
Expand All @@ -303,7 +303,7 @@ pattern we want is clear:
( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
binds $( $bind_res:ident ),*
)
# => (0))
# => (0));
~~~~

However, it's not possible to directly expand to nested match statements. But
Expand All @@ -323,7 +323,7 @@ input patterns:
# #![feature(macro_rules)]
# macro_rules! b(
( binds $( $bind_res:ident ),* )
# => (0))
# => (0));
# fn main() {}
~~~~

Expand All @@ -337,7 +337,7 @@ input patterns:
$( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
binds $( $bind_res:ident ),*
)
# => (0))
# => (0));
~~~~

The resulting macro looks like this. Note that the separation into
Expand Down Expand Up @@ -366,7 +366,7 @@ macro_rules! biased_match_rec (
);
// Produce the requested values
( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
)
);
// Wrap the whole thing in a `let`.
macro_rules! biased_match (
Expand All @@ -388,7 +388,7 @@ macro_rules! biased_match (
binds $( $bind_res ),*
);
)
)
);
# enum T1 { Good1(T2, uint), Bad1}
Expand All @@ -398,7 +398,7 @@ macro_rules! biased_match (
biased_match!(
(x) ~ (T1::Good1(g1, val)) else { return 0 };
(g1.body) ~ (T3::Good2(result) ) else { panic!("Didn't get Good2") };
binds val, result )
binds val, result );
// complicated stuff goes here
return result + val;
# }
Expand Down Expand Up @@ -444,7 +444,7 @@ macro_rules! loop_x (
$e
}
);
)
);
fn main() {
'x: loop {
Expand Down Expand Up @@ -482,30 +482,30 @@ An example:

```rust
# #![feature(macro_rules)]
macro_rules! m1 (() => (()))
macro_rules! m1 (() => (()));

// visible here: m1

mod foo {
// visible here: m1

#[macro_export]
macro_rules! m2 (() => (()))
macro_rules! m2 (() => (()));

// visible here: m1, m2
}

// visible here: m1

macro_rules! m3 (() => (()))
macro_rules! m3 (() => (()));

// visible here: m1, m3

#[macro_escape]
mod bar {
// visible here: m1, m3

macro_rules! m4 (() => (()))
macro_rules! m4 (() => (()));

// visible here: m1, m3, m4
}
Expand Down
2 changes: 1 addition & 1 deletion src/etc/regex-match-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def read_tests(f):
def test_tostr(t):
lineno, pat, text, groups = t
options = map(group_tostr, groups)
return 'mat!(match_%s, r"%s", r"%s", %s)' \
return 'mat!{match_%s, r"%s", r"%s", %s}' \
% (lineno, pat, '' if text == "NULL" else text, ', '.join(options))


Expand Down
18 changes: 9 additions & 9 deletions src/libcollections/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2073,7 +2073,7 @@ mod tests {
let bools = vec![true, false, true, true];
let bitv: Bitv = bools.iter().map(|n| *n).collect();

assert_eq!(bitv.iter().collect::<Vec<bool>>(), bools)
assert_eq!(bitv.iter().collect::<Vec<bool>>(), bools);

let long = Vec::from_fn(10000, |i| i % 2 == 0);
let bitv: Bitv = long.iter().map(|n| *n).collect();
Expand Down Expand Up @@ -2102,8 +2102,8 @@ mod tests {
for &b in bools.iter() {
for &l in lengths.iter() {
let bitset = BitvSet::from_bitv(Bitv::with_capacity(l, b));
assert_eq!(bitset.contains(&1u), b)
assert_eq!(bitset.contains(&(l-1u)), b)
assert_eq!(bitset.contains(&1u), b);
assert_eq!(bitset.contains(&(l-1u)), b);
assert!(!bitset.contains(&l))
}
}
Expand Down Expand Up @@ -2311,12 +2311,12 @@ mod tests {
assert!(!a.is_disjoint(&d));
assert!(!d.is_disjoint(&a));

assert!(a.is_disjoint(&b))
assert!(a.is_disjoint(&c))
assert!(b.is_disjoint(&a))
assert!(b.is_disjoint(&c))
assert!(c.is_disjoint(&a))
assert!(c.is_disjoint(&b))
assert!(a.is_disjoint(&b));
assert!(a.is_disjoint(&c));
assert!(b.is_disjoint(&a));
assert!(b.is_disjoint(&c));
assert!(c.is_disjoint(&a));
assert!(c.is_disjoint(&b));
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ impl<K, V> Node<K, V> {
/// Take all the values from right, separated by the given key and value
fn absorb(&mut self, key: K, val: V, right: Node<K, V>) {
// Just as a sanity check, make sure we can fit this guy in
debug_assert!(self.len() + right.len() <= self.capacity())
debug_assert!(self.len() + right.len() <= self.capacity());

self.keys.push(key);
self.vals.push(val);
Expand Down
26 changes: 13 additions & 13 deletions src/libcollections/enum_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ mod test {

assert!(e1.is_subset(&e2));
assert!(e2.is_superset(&e1));
assert!(!e3.is_superset(&e2))
assert!(!e3.is_superset(&e2));
assert!(!e2.is_superset(&e3))
}

Expand All @@ -400,23 +400,23 @@ mod test {
let mut e1: EnumSet<Foo> = EnumSet::new();

let elems: Vec<Foo> = e1.iter().collect();
assert!(elems.is_empty())
assert!(elems.is_empty());

e1.insert(A);
let elems = e1.iter().collect();
assert_eq!(vec![A], elems)
assert_eq!(vec![A], elems);

e1.insert(C);
let elems = e1.iter().collect();
assert_eq!(vec![A,C], elems)
assert_eq!(vec![A,C], elems);

e1.insert(C);
let elems = e1.iter().collect();
assert_eq!(vec![A,C], elems)
assert_eq!(vec![A,C], elems);

e1.insert(B);
let elems = e1.iter().collect();
assert_eq!(vec![A,B,C], elems)
assert_eq!(vec![A,B,C], elems);
}

///////////////////////////////////////////////////////////////////////////
Expand All @@ -434,35 +434,35 @@ mod test {

let e_union = e1 | e2;
let elems = e_union.iter().collect();
assert_eq!(vec![A,B,C], elems)
assert_eq!(vec![A,B,C], elems);

let e_intersection = e1 & e2;
let elems = e_intersection.iter().collect();
assert_eq!(vec![C], elems)
assert_eq!(vec![C], elems);

// Another way to express intersection
let e_intersection = e1 - (e1 - e2);
let elems = e_intersection.iter().collect();
assert_eq!(vec![C], elems)
assert_eq!(vec![C], elems);

let e_subtract = e1 - e2;
let elems = e_subtract.iter().collect();
assert_eq!(vec![A], elems)
assert_eq!(vec![A], elems);

// Bitwise XOR of two sets, aka symmetric difference
let e_symmetric_diff = e1 ^ e2;
let elems = e_symmetric_diff.iter().collect();
assert_eq!(vec![A,B], elems)
assert_eq!(vec![A,B], elems);

// Another way to express symmetric difference
let e_symmetric_diff = (e1 - e2) | (e2 - e1);
let elems = e_symmetric_diff.iter().collect();
assert_eq!(vec![A,B], elems)
assert_eq!(vec![A,B], elems);

// Yet another way to express symmetric difference
let e_symmetric_diff = (e1 | e2) - (e1 & e2);
let elems = e_symmetric_diff.iter().collect();
assert_eq!(vec![A,B], elems)
assert_eq!(vec![A,B], elems);
}

#[test]
Expand Down
52 changes: 26 additions & 26 deletions src/libcollections/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,16 @@ macro_rules! impl_hash {
}
}

impl_hash!(u8, u8)
impl_hash!(u16, u16)
impl_hash!(u32, u32)
impl_hash!(u64, u64)
impl_hash!(uint, uint)
impl_hash!(i8, u8)
impl_hash!(i16, u16)
impl_hash!(i32, u32)
impl_hash!(i64, u64)
impl_hash!(int, uint)
impl_hash! { u8, u8 }
impl_hash! { u16, u16 }
impl_hash! { u32, u32 }
impl_hash! { u64, u64 }
impl_hash! { uint, uint }
impl_hash! { i8, u8 }
impl_hash! { i16, u16 }
impl_hash! { i32, u32 }
impl_hash! { i64, u64 }
impl_hash! { int, uint }

impl<S: Writer> Hash<S> for bool {
#[inline]
Expand All @@ -146,7 +146,7 @@ impl<S: Writer> Hash<S> for str {
}
}

macro_rules! impl_hash_tuple(
macro_rules! impl_hash_tuple {
() => (
impl<S: Writer> Hash<S> for () {
#[inline]
Expand All @@ -171,21 +171,21 @@ macro_rules! impl_hash_tuple(
}
}
);
)

impl_hash_tuple!()
impl_hash_tuple!(A)
impl_hash_tuple!(A B)
impl_hash_tuple!(A B C)
impl_hash_tuple!(A B C D)
impl_hash_tuple!(A B C D E)
impl_hash_tuple!(A B C D E F)
impl_hash_tuple!(A B C D E F G)
impl_hash_tuple!(A B C D E F G H)
impl_hash_tuple!(A B C D E F G H I)
impl_hash_tuple!(A B C D E F G H I J)
impl_hash_tuple!(A B C D E F G H I J K)
impl_hash_tuple!(A B C D E F G H I J K L)
}

impl_hash_tuple! {}
impl_hash_tuple! { A }
impl_hash_tuple! { A B }
impl_hash_tuple! { A B C }
impl_hash_tuple! { A B C D }
impl_hash_tuple! { A B C D E }
impl_hash_tuple! { A B C D E F }
impl_hash_tuple! { A B C D E F G }
impl_hash_tuple! { A B C D E F G H }
impl_hash_tuple! { A B C D E F G H I }
impl_hash_tuple! { A B C D E F G H I J }
impl_hash_tuple! { A B C D E F G H I J K }
impl_hash_tuple! { A B C D E F G H I J K L }

impl<S: Writer, T: Hash<S>> Hash<S> for [T] {
#[inline]
Expand Down
12 changes: 6 additions & 6 deletions src/libcollections/hash/sip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub struct SipState {
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le (
macro_rules! u8to64_le {
($buf:expr, $i:expr) =>
($buf[0+$i] as u64 |
$buf[1+$i] as u64 << 8 |
Expand All @@ -67,14 +67,14 @@ macro_rules! u8to64_le (
}
out
});
)
}

macro_rules! rotl (
macro_rules! rotl {
($x:expr, $b:expr) =>
(($x << $b) | ($x >> (64 - $b)))
)
}

macro_rules! compress (
macro_rules! compress {
($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
({
$v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
Expand All @@ -84,7 +84,7 @@ macro_rules! compress (
$v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
$v2 = rotl!($v2, 32);
})
)
}

impl SipState {
/// Creates a `SipState` that is keyed off the provided keys.
Expand Down
Loading

0 comments on commit 6a855f6

Please sign in to comment.