diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 397263c697330..140e27d19248c 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -352,7 +352,7 @@ to it. Rust supports powerful local type inference in the bodies of functions but not in their item signatures. It's forbidden to allow reasoning about types based on the item signature alone. However, for ergonomic reasons, a very restricted secondary inference algorithm called -“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely to infer +“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision acts as a shorthand for writing an item signature, while not hiding away the actual types involved as full local inference would if applied to it. diff --git a/src/doc/reference.md b/src/doc/reference.md index 0596e476d5f6c..4fbe518396760 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2474,18 +2474,19 @@ The currently implemented features of the reference compiler are: internally without imposing on callers (i.e. making them behave like function calls in terms of encapsulation). -* - `default_type_parameter_fallback` - Allows type parameter defaults to - influence type inference. -* - `stmt_expr_attributes` - Allows attributes on expressions. +* `default_type_parameter_fallback` - Allows type parameter defaults to + influence type inference. -* - `type_ascription` - Allows type ascription expressions `expr: Type`. +* `stmt_expr_attributes` - Allows attributes on expressions. -* - `abi_vectorcall` - Allows the usage of the vectorcall calling convention - (e.g. `extern "vectorcall" func fn_();`) +* `type_ascription` - Allows type ascription expressions `expr: Type`. -* - `abi_sysv64` - Allows the usage of the system V AMD64 calling convention - (e.g. `extern "sysv64" func fn_();`) +* `abi_vectorcall` - Allows the usage of the vectorcall calling convention + (e.g. `extern "vectorcall" func fn_();`) + +* `abi_sysv64` - Allows the usage of the system V AMD64 calling convention + (e.g. `extern "sysv64" func fn_();`) If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about `#![feature]` directives which enabled diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index cc56bbf4890aa..ebbfbefc21b66 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -814,6 +814,14 @@ fn test_iterator_clone() { assert!(it.clone().zip(it).all(|(x,y)| x == y)); } +#[test] +fn test_iterator_last() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.chars(); + it.next(); + assert_eq!(it.last(), Some('m')); +} + #[test] fn test_bytesator() { let s = "ศไทย中华Việt Nam"; @@ -911,6 +919,14 @@ fn test_char_indices_revator() { assert_eq!(pos, p.len()); } +#[test] +fn test_char_indices_last() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.char_indices(); + it.next(); + assert_eq!(it.last(), Some((27, 'm'))); +} + #[test] fn test_splitn_char_iterator() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 196750254af30..1bd6188f4875a 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -432,6 +432,12 @@ impl<'a> Iterator for Chars<'a> { // `isize::MAX` (that's well below `usize::MAX`). ((len + 3) / 4, Some(len)) } + + #[inline] + fn last(mut self) -> Option { + // No need to go through the entire string. + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -505,6 +511,12 @@ impl<'a> Iterator for CharIndices<'a> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<(usize, char)> { + // No need to go through the entire string. + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs index 1f4d09a92247e..e2d3a4f453749 100644 --- a/src/librustc_data_structures/unify/mod.rs +++ b/src/librustc_data_structures/unify/mod.rs @@ -344,7 +344,7 @@ impl<'tcx, K, V> UnificationTable } pub fn probe(&mut self, a_id: K) -> Option { - self.get(a_id).value.clone() + self.get(a_id).value } pub fn unsolved_variables(&mut self) -> Vec { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f08178e49fb2e..093a023291ac4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4436,19 +4436,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); if lifetimes.len() > lifetime_defs.len() { let span = lifetimes[lifetime_defs.len()].span; - span_err!(self.tcx.sess, span, E0088, - "too many lifetime parameters provided: \ - expected {}, found {}", - count(lifetime_defs.len()), - count(lifetimes.len())); - } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() { - span_err!(self.tcx.sess, span, E0090, - "too few lifetime parameters provided: \ - expected {}, found {}", - count(lifetime_defs.len()), - count(lifetimes.len())); + struct_span_err!(self.tcx.sess, span, E0088, + "too many lifetime parameters provided: \ + expected {}, found {}", + count(lifetime_defs.len()), + count(lifetimes.len())) + .span_label(span, &format!("unexpected lifetime parameter{}", + match lifetimes.len() { 1 => "", _ => "s" })) + .emit(); } + // The case where there is not enough lifetime parameters is not checked, + // because this is not possible - a function never takes lifetime parameters. + // See discussion for Pull Request 36208. + // Check provided type parameters. let type_defs = segment.map_or(&[][..], |(_, generics)| { if generics.parent.is_none() { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 44dadc4367b52..31fbcb5059f82 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2437,7 +2437,6 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, write!(w, "}}")?; } write!(w, "")?; - render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it)?; if !e.variants.is_empty() { @@ -3053,7 +3052,6 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, Some("macro"), None, None))?; - render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it) } diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 20dc5b3801ba4..1c016015b7928 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -31,7 +31,7 @@ pub enum SocketAddr { /// An IPv4 socket address which is a (ip, port) combination. #[stable(feature = "rust1", since = "1.0.0")] V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4), - /// An IPv6 socket address + /// An IPv6 socket address. #[stable(feature = "rust1", since = "1.0.0")] V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6), } @@ -48,6 +48,16 @@ pub struct SocketAddrV6 { inner: c::sockaddr_in6 } impl SocketAddr { /// Creates a new socket address from the (ip, port) pair. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// assert_eq!(socket.port(), 8080); + /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] pub fn new(ip: IpAddr, port: u16) -> SocketAddr { match ip { @@ -57,6 +67,15 @@ impl SocketAddr { } /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] pub fn ip(&self) -> IpAddr { match *self { @@ -66,6 +85,16 @@ impl SocketAddr { } /// Change the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_ip(&mut self, new_ip: IpAddr) { // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. @@ -77,6 +106,15 @@ impl SocketAddr { } /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.port(), 8080); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { match *self { @@ -86,6 +124,16 @@ impl SocketAddr { } /// Change the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_port(1025); + /// assert_eq!(socket.port(), 1025); + /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { match *self { @@ -96,6 +144,20 @@ impl SocketAddr { /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address, /// false if it's a valid IPv6 address. + /// + /// # Examples + /// + /// ``` + /// #![feature(sockaddr_checker)] + /// + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// fn main() { + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), true); + /// assert_eq!(socket.is_ipv6(), false); + /// } + /// ``` #[unstable(feature = "sockaddr_checker", issue = "36949")] pub fn is_ipv4(&self) -> bool { match *self { @@ -106,6 +168,21 @@ impl SocketAddr { /// Returns true if the IP in this `SocketAddr` is a valid IPv6 address, /// false if it's a valid IPv4 address. + /// + /// # Examples + /// + /// ``` + /// #![feature(sockaddr_checker)] + /// + /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; + /// + /// fn main() { + /// let socket = SocketAddr::new( + /// IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), false); + /// assert_eq!(socket.is_ipv6(), true); + /// } + /// ``` #[unstable(feature = "sockaddr_checker", issue = "36949")] pub fn is_ipv6(&self) -> bool { match *self { diff --git a/src/test/compile-fail/E0088.rs b/src/test/compile-fail/E0088.rs index 0b235aa240c3c..9ec0960322410 100644 --- a/src/test/compile-fail/E0088.rs +++ b/src/test/compile-fail/E0088.rs @@ -9,7 +9,12 @@ // except according to those terms. fn f() {} +fn g<'a>() {} fn main() { f::<'static>(); //~ ERROR E0088 + //~^ unexpected lifetime parameter + + g::<'static, 'static>(); //~ ERROR E0088 + //~^ unexpected lifetime parameters } diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs new file mode 100644 index 0000000000000..7a8502f7caab1 --- /dev/null +++ b/src/test/incremental/hashes/for_loops.rs @@ -0,0 +1,306 @@ +// Copyright 2016 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `for` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_body() { + let mut _x = 0; + for _ in 0..1 { + _x = 2; + break; + } +} + + + +// Change iteration variable name ---------------------------------------------- +#[cfg(cfail1)] +fn change_iteration_variable_name() { + let mut _x = 0; + for _i in 0..1 { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_iteration_variable_name() { + let mut _x = 0; + for _a in 0..1 { + _x = 1; + break; + } +} + + + +// Change iteration variable pattern ------------------------------------------- +#[cfg(cfail1)] +fn change_iteration_variable_pattern() { + let mut _x = 0; + for _i in &[0, 1, 2] { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_iteration_variable_pattern() { + let mut _x = 0; + for &_i in &[0, 1, 2] { + _x = 1; + break; + } +} + + + +// Change iterable ------------------------------------------------------------- +#[cfg(cfail1)] +fn change_iterable() { + let mut _x = 0; + for _ in &[0, 1, 2] { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_iterable() { + let mut _x = 0; + for _ in &[0, 1, 3] { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + break 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_break_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + continue 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_to_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs new file mode 100644 index 0000000000000..eaa5f68b98c4b --- /dev/null +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -0,0 +1,231 @@ +// Copyright 2016 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `loop` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_body() { + let mut _x = 0; + loop { + _x = 2; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + loop { + _x = 1; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_break() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label() { + let mut _x = 0; + 'label: loop { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: loop { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: loop { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + break 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_break_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: loop { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: loop { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + continue 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + loop { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_to_break() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs new file mode 100644 index 0000000000000..405645bd1b842 --- /dev/null +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -0,0 +1,256 @@ +// Copyright 2016 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `while let` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_body() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 2; + break; + } +} + + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_condition() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_condition() { + let mut _x = 0; + while let Some(1u32) = None { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + break 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_break_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + continue 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_to_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs new file mode 100644 index 0000000000000..f16611ee463e0 --- /dev/null +++ b/src/test/incremental/hashes/while_loops.rs @@ -0,0 +1,256 @@ +// Copyright 2016 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `while` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_body() { + let mut _x = 0; + while true { + _x = 2; + break; + } +} + + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_condition() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_condition() { + let mut _x = 0; + while false { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + while true { + _x = 1; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_break() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label() { + let mut _x = 0; + 'label: while true { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while true { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while true { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + break 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_break_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while true { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while true { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + continue 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + while true { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_to_break() { + let mut _x = 0; + while true { + _x = 1; + break; + } +}