From d9769ec3834b62318da892925dc24c8883bb1635 Mon Sep 17 00:00:00 2001 From: P1start Date: Tue, 23 Dec 2014 13:13:49 +1300 Subject: [PATCH] Parse fully-qualified associated types in generics without whitespace This breaks code that looks like this: let x = foo as bar << 13; Change such code to look like this: let x = (foo as bar) << 13; Closes #17362. [breaking-change] --- src/libcollections/bit.rs | 12 ++--- src/libcore/hash/sip.rs | 16 +++---- src/librand/lib.rs | 2 +- src/libstd/io/net/ip.rs | 4 +- src/libstd/sys/common/net.rs | 8 ++-- src/libsyntax/parse/parser.rs | 44 +++++-------------- src/libtime/lib.rs | 4 +- src/libunicode/u_str.rs | 2 +- src/test/bench/shootout-reverse-complement.rs | 2 +- src/test/run-pass/parse-assoc-type-lt.rs | 18 ++++++++ 10 files changed, 53 insertions(+), 59 deletions(-) create mode 100644 src/test/run-pass/parse-assoc-type-lt.rs diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 430d7210bf69b..c3e9d91b7edc6 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -314,17 +314,17 @@ impl Bitv { for i in range(0, complete_words) { bitv.storage.push( - (reverse_bits(bytes[i * 4 + 0]) as u32 << 0) | - (reverse_bits(bytes[i * 4 + 1]) as u32 << 8) | - (reverse_bits(bytes[i * 4 + 2]) as u32 << 16) | - (reverse_bits(bytes[i * 4 + 3]) as u32 << 24) + ((reverse_bits(bytes[i * 4 + 0]) as u32) << 0) | + ((reverse_bits(bytes[i * 4 + 1]) as u32) << 8) | + ((reverse_bits(bytes[i * 4 + 2]) as u32) << 16) | + ((reverse_bits(bytes[i * 4 + 3]) as u32) << 24) ); } if extra_bytes > 0 { let mut last_word = 0u32; for (i, &byte) in bytes[complete_words*4..].iter().enumerate() { - last_word |= reverse_bits(byte) as u32 << (i * 8); + last_word |= (reverse_bits(byte) as u32) << (i * 8); } bitv.storage.push(last_word); } @@ -645,7 +645,7 @@ impl Bitv { if offset >= bitv.nbits { 0 } else { - bitv[offset] as u8 << (7 - bit) + (bitv[offset] as u8) << (7 - bit) } } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index ab6b0986c686d..2501037107a22 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -50,19 +50,19 @@ pub struct SipState { macro_rules! u8to64_le { ($buf:expr, $i:expr) => ($buf[0+$i] as u64 | - $buf[1+$i] as u64 << 8 | - $buf[2+$i] as u64 << 16 | - $buf[3+$i] as u64 << 24 | - $buf[4+$i] as u64 << 32 | - $buf[5+$i] as u64 << 40 | - $buf[6+$i] as u64 << 48 | - $buf[7+$i] as u64 << 56); + ($buf[1+$i] as u64) << 8 | + ($buf[2+$i] as u64) << 16 | + ($buf[3+$i] as u64) << 24 | + ($buf[4+$i] as u64) << 32 | + ($buf[5+$i] as u64) << 40 | + ($buf[6+$i] as u64) << 48 | + ($buf[7+$i] as u64) << 56); ($buf:expr, $i:expr, $len:expr) => ({ let mut t = 0; let mut out = 0u64; while t < $len { - out |= $buf[t+$i] as u64 << t*8; + out |= ($buf[t+$i] as u64) << t*8; t += 1; } out diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 514ff81da518e..0faf43fc2ef64 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -74,7 +74,7 @@ pub trait Rng { /// these two methods. Similarly to `next_u32`, this rarely needs /// to be called directly, prefer `r.gen()` to `r.next_u64()`. fn next_u64(&mut self) -> u64 { - (self.next_u32() as u64 << 32) | (self.next_u32() as u64) + ((self.next_u32() as u64) << 32) | (self.next_u32() as u64) } /// Return the next random f32 selected from the half-open diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index add986387daf7..83be9574f78b6 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -267,8 +267,8 @@ impl<'a> Parser<'a> { }); match ipv4 { Some(Ipv4Addr(a, b, c, d)) => { - groups[i + 0] = (a as u16 << 8) | (b as u16); - groups[i + 1] = (c as u16 << 8) | (d as u16); + groups[i + 0] = ((a as u16) << 8) | (b as u16); + groups[i + 1] = ((c as u16) << 8) | (d as u16); return (i + 2, true); } _ => {} diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 382f6875b281d..1e8246dabc5e4 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -55,10 +55,10 @@ pub enum InAddr { pub fn ip_to_inaddr(ip: IpAddr) -> InAddr { match ip { Ipv4Addr(a, b, c, d) => { - let ip = (a as u32 << 24) | - (b as u32 << 16) | - (c as u32 << 8) | - (d as u32 << 0); + let ip = ((a as u32) << 24) | + ((b as u32) << 16) | + ((c as u32) << 8) | + ((d as u32) << 0); In4Addr(libc::in_addr { s_addr: Int::from_be(ip) }) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 94b61ba56d2e5..b3dc8c3a61a10 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -669,45 +669,22 @@ impl<'a> Parser<'a> { /// `<` and continue. If a `<` is not seen, return false. /// /// This is meant to be used when parsing generics on a path to get the - /// starting token. The `force` parameter is used to forcefully break up a - /// `<<` token. If `force` is false, then `<<` is only broken when a lifetime - /// shows up next. For example, consider the expression: - /// - /// foo as bar << test - /// - /// The parser needs to know if `bar <<` is the start of a generic path or if - /// it's a left-shift token. If `test` were a lifetime, then it's impossible - /// for the token to be a left-shift, but if it's not a lifetime, then it's - /// considered a left-shift. - /// - /// The reason for this is that the only current ambiguity with `<<` is when - /// parsing closure types: - /// - /// foo::<<'a> ||>(); - /// impl Foo<<'a> ||>() { ... } - fn eat_lt(&mut self, force: bool) -> bool { + /// starting token. + fn eat_lt(&mut self) -> bool { match self.token { token::Lt => { self.bump(); true } token::BinOp(token::Shl) => { - let next_lifetime = self.look_ahead(1, |t| match *t { - token::Lifetime(..) => true, - _ => false, - }); - if force || next_lifetime { - let span = self.span; - let lo = span.lo + BytePos(1); - self.replace_token(token::Lt, lo, span.hi); - true - } else { - false - } + let span = self.span; + let lo = span.lo + BytePos(1); + self.replace_token(token::Lt, lo, span.hi); + true } _ => false, } } fn expect_lt(&mut self) { - if !self.eat_lt(true) { + if !self.eat_lt() { let found_token = self.this_token_to_string(); let token_str = Parser::token_to_string(&token::Lt); self.fatal(format!("expected `{}`, found `{}`", @@ -1582,9 +1559,8 @@ impl<'a> Parser<'a> { TyTypeof(e) } else if self.eat_keyword(keywords::Proc) { self.parse_proc_type(Vec::new()) - } else if self.check(&token::Lt) { + } else if self.eat_lt() { // QUALIFIED PATH `::item` - self.bump(); let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); let trait_ref = self.parse_trait_ref(); @@ -1870,7 +1846,7 @@ impl<'a> Parser<'a> { let identifier = self.parse_ident(); // Parse types, optionally. - let parameters = if self.eat_lt(false) { + let parameters = if self.eat_lt() { let (lifetimes, types, bindings) = self.parse_generic_values_after_lt(); ast::AngleBracketedParameters(ast::AngleBracketedParameterData { @@ -1931,7 +1907,7 @@ impl<'a> Parser<'a> { } // Check for a type segment. - if self.eat_lt(false) { + if self.eat_lt() { // Consumed `a::b::<`, go look for types let (lifetimes, types, bindings) = self.parse_generic_values_after_lt(); segments.push(ast::PathSegment { diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index e58a0229d6962..ec41904fd19c0 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -149,8 +149,8 @@ pub fn get_time() -> Timespec { // A FILETIME contains a 64-bit value representing the number of // hectonanosecond (100-nanosecond) intervals since 1601-01-01T00:00:00Z. // http://support.microsoft.com/kb/167296/en-us - let ns_since_1601 = ((time.dwHighDateTime as u64 << 32) | - (time.dwLowDateTime as u64 << 0)) / 10; + let ns_since_1601 = (((time.dwHighDateTime as u64) << 32) | + ((time.dwLowDateTime as u64) << 0)) / 10; let ns_since_1970 = ns_since_1601 - NANOSECONDS_FROM_1601_TO_1970; ((ns_since_1970 / 1000000) as i64, diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index a3d4dd057d002..9a09c13c1ab20 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -459,7 +459,7 @@ impl<'a> Iterator for Utf16Items<'a> { } // all ok, so lets decode it. - let c = ((u - 0xD800) as u32 << 10 | (u2 - 0xDC00) as u32) + 0x1_0000; + let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000; Some(Utf16Item::ScalarValue(unsafe {mem::transmute(c)})) } } diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index d746ec1dbabd5..e0939dcb43b8d 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -62,7 +62,7 @@ impl Tables { } let mut table16 = [0;1 << 16]; for (i, v) in table16.iter_mut().enumerate() { - *v = table8[i & 255] as u16 << 8 | + *v = (table8[i & 255] as u16) << 8 | table8[i >> 8] as u16; } Tables { table8: table8, table16: table16 } diff --git a/src/test/run-pass/parse-assoc-type-lt.rs b/src/test/run-pass/parse-assoc-type-lt.rs new file mode 100644 index 0000000000000..8a68711a769fc --- /dev/null +++ b/src/test/run-pass/parse-assoc-type-lt.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_types)] + +trait Foo { + type T; + fn foo() -> Box<::T>; +} + +fn main() {}