From dac987e355deb903493d22c0ae8a8a4fd072d1c5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 21 Nov 2016 13:22:21 -0500 Subject: [PATCH 01/19] add regression test for #36168 Fixes #36168 --- .../auxiliary/point.rs | 35 ++++++++ .../struct_point.rs | 84 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs create mode 100644 src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs new file mode 100644 index 00000000000..99ba576a137 --- /dev/null +++ b/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs @@ -0,0 +1,35 @@ +// 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. + +pub struct Point { + pub x: f32, + pub y: f32, +} + +#[cfg(rpass2)] +fn unused_helper() { +} + +fn distance_squared(this: &Point) -> f32 { + return this.x * this.x + this.y * this.y; +} + +impl Point { + pub fn distance_from_origin(&self) -> f32 { + distance_squared(self).sqrt() + } +} + +impl Point { + pub fn translate(&mut self, x: f32, y: f32) { + self.x += x; + self.y += y; + } +} diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs new file mode 100644 index 00000000000..dba7f147619 --- /dev/null +++ b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs @@ -0,0 +1,84 @@ +// 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. + +// Test where we add a private item into the root of an external. +// crate. This should not cause anything we use to be invalidated. +// Regression test for #36168. + +// revisions:rpass1 rpass2 +// compile-flags: -Z query-dep-graph +// aux-build:point.rs + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] +#![allow(dead_code)] + +#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")] + +extern crate point; + +/// A fn item that calls (public) methods on `Point` from the same impl which changed +mod fn_calls_methods_in_same_impl { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn check() { + let x = Point { x: 2.0, y: 2.0 }; + x.distance_from_origin(); + } +} + +/// A fn item that calls (public) methods on `Point` from another impl +mod fn_calls_methods_in_another_impl { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn check() { + let mut x = Point { x: 2.0, y: 2.0 }; + x.translate(3.0, 3.0); + } +} + +/// A fn item that makes an instance of `Point` but does not invoke methods +mod fn_make_struct { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn make_origin() -> Point { + Point { x: 2.0, y: 2.0 } + } +} + +/// A fn item that reads fields from `Point` but does not invoke methods +mod fn_read_field { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn get_x(p: Point) -> f32 { + p.x + } +} + +/// A fn item that writes to a field of `Point` but does not invoke methods +mod fn_write_field { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn inc_x(p: &mut Point) { + p.x += 1.0; + } +} + +fn main() { +} From 1a91fc62d3f5bf91c13f13a6620cb529dbcad518 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Nov 2016 17:19:39 +0100 Subject: [PATCH 02/19] Add missing examples for Ipv6Addr --- src/libstd/net/ip.rs | 129 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 7b7be6e2eee..4df7eeae192 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -522,6 +522,14 @@ impl Ipv6Addr { /// Creates a new IPv6 address from eight 16-bit segments. /// /// The result will represent the IP address a:b:c:d:e:f:g:h. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { @@ -538,6 +546,15 @@ impl Ipv6Addr { } /// Returns the eight 16-bit segments that make up this address. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), + /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn segments(&self) -> [u16; 8] { let arr = &self.inner.s6_addr; @@ -558,6 +575,15 @@ impl Ipv6Addr { /// This property is defined in [RFC 4291]. /// /// [RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true); + /// ``` #[stable(since = "1.7.0", feature = "ip_17")] pub fn is_unspecified(&self) -> bool { self.segments() == [0, 0, 0, 0, 0, 0, 0, 0] @@ -568,6 +594,15 @@ impl Ipv6Addr { /// This property is defined in [RFC 4291]. /// /// [RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true); + /// ``` #[stable(since = "1.7.0", feature = "ip_17")] pub fn is_loopback(&self) -> bool { self.segments() == [0, 0, 0, 0, 0, 0, 0, 1] @@ -580,6 +615,20 @@ impl Ipv6Addr { /// - the loopback address /// - link-local, site-local, and unique local unicast addresses /// - interface-, link-, realm-, admin- and site-local multicast addresses + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true); + /// } + /// ``` pub fn is_global(&self) -> bool { match self.multicast_scope() { Some(Ipv6MulticastScope::Global) => true, @@ -593,6 +642,15 @@ impl Ipv6Addr { /// This property is defined in [RFC 4193]. /// /// [RFC 4193]: https://tools.ietf.org/html/rfc4193 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); + /// ``` pub fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 } @@ -602,12 +660,32 @@ impl Ipv6Addr { /// This property is defined in [RFC 4291]. /// /// [RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(), + /// false); + /// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// ``` pub fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 } /// Returns true if this is a deprecated unicast site-local address /// (fec0::/10). + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), + /// false); + /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); + /// ``` pub fn is_unicast_site_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfec0 } @@ -618,6 +696,15 @@ impl Ipv6Addr { /// This property is defined in [RFC 3849]. /// /// [RFC 3849]: https://tools.ietf.org/html/rfc3849 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); + /// ``` pub fn is_documentation(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) } @@ -632,6 +719,15 @@ impl Ipv6Addr { /// - unique local addresses /// - the unspecified address /// - the address range reserved for documentation + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); + /// ``` pub fn is_unicast_global(&self) -> bool { !self.is_multicast() && !self.is_loopback() && !self.is_unicast_link_local() @@ -640,6 +736,16 @@ impl Ipv6Addr { } /// Returns the address's multicast scope if the address is multicast. + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; + /// + /// assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), + /// Some(Ipv6MulticastScope::Global)); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); + /// ``` pub fn multicast_scope(&self) -> Option { if self.is_multicast() { match self.segments()[0] & 0x000f { @@ -662,6 +768,14 @@ impl Ipv6Addr { /// This property is defined by [RFC 4291]. /// /// [RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false); + /// ``` #[stable(since = "1.7.0", feature = "ip_17")] pub fn is_multicast(&self) -> bool { (self.segments()[0] & 0xff00) == 0xff00 @@ -671,6 +785,14 @@ impl Ipv6Addr { /// neither IPv4-compatible or IPv4-mapped. /// /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(), + /// Some(Ipv4Addr::new(192, 10, 2, 255))); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv4(&self) -> Option { match self.segments() { @@ -683,6 +805,13 @@ impl Ipv6Addr { } /// Returns the sixteen eight-bit integers the IPv6 address consists of. + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(), + /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + /// ``` #[stable(feature = "ipv6_to_octets", since = "1.12.0")] pub fn octets(&self) -> [u8; 16] { self.inner.s6_addr From a5049f7bba1c56027618a07ffa62c3af5c7da850 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 22 Nov 2016 17:04:24 +0100 Subject: [PATCH 03/19] Add ::1 example in IPv6 to IPv4 conversion --- src/libstd/net/ip.rs | 59 +++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 4df7eeae192..40563eacf29 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -646,10 +646,15 @@ impl Ipv6Addr { /// # Examples /// /// ``` + /// #![feature(ip)] + /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); - /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), + /// false); + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); + /// } /// ``` pub fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 @@ -664,11 +669,15 @@ impl Ipv6Addr { /// # Examples /// /// ``` + /// #![feature(ip)] + /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(), - /// false); - /// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(), + /// false); + /// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// } /// ``` pub fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 @@ -680,11 +689,15 @@ impl Ipv6Addr { /// # Examples /// /// ``` + /// #![feature(ip)] + /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), - /// false); - /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), + /// false); + /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); + /// } /// ``` pub fn is_unicast_site_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfec0 @@ -700,10 +713,15 @@ impl Ipv6Addr { /// # Examples /// /// ``` + /// #![feature(ip)] + /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), + /// false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); + /// } /// ``` pub fn is_documentation(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) @@ -723,10 +741,15 @@ impl Ipv6Addr { /// # Examples /// /// ``` + /// #![feature(ip)] + /// /// use std::net::Ipv6Addr; /// - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), + /// true); + /// } /// ``` pub fn is_unicast_global(&self) -> bool { !self.is_multicast() @@ -740,11 +763,15 @@ impl Ipv6Addr { /// # Examples /// /// ``` + /// #![feature(ip)] + /// /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; /// - /// assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), - /// Some(Ipv6MulticastScope::Global)); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); + /// fn main() { + /// assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), + /// Some(Ipv6MulticastScope::Global)); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); + /// } /// ``` pub fn multicast_scope(&self) -> Option { if self.is_multicast() { @@ -792,6 +819,8 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(), /// Some(Ipv4Addr::new(192, 10, 2, 255))); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), + /// Some(Ipv4Addr::new(0, 0, 0, 1))); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv4(&self) -> Option { From ebcc6d2571aa462657ced6f1b917d2c99fcea008 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 26 Nov 2016 21:35:41 +0100 Subject: [PATCH 04/19] Add part of missing UdpSocket's urls and examples --- src/libstd/net/udp.rs | 226 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 215 insertions(+), 11 deletions(-) diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 559250adac5..b280f466dd4 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -48,8 +48,18 @@ pub struct UdpSocket(net_imp::UdpSocket); impl UdpSocket { /// Creates a UDP socket from the given address. /// - /// The address type can be any implementor of `ToSocketAddr` trait. See + /// The address type can be any implementor of [`ToSocketAddrs`] trait. See /// its documentation for concrete examples. + /// + /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn bind(addr: A) -> io::Result { super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket) @@ -57,6 +67,17 @@ impl UdpSocket { /// Receives data from the socket. On success, returns the number of bytes /// read and the address from whence the data came. + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let mut buf = [0; 10]; + /// let (number_of_bytes, src_addr) = socket.recv_from(&mut buf) + /// .expect("Didn't receive data"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.0.recv_from(buf) @@ -65,11 +86,24 @@ impl UdpSocket { /// Sends data on the socket to the given address. On success, returns the /// number of bytes written. /// - /// Address type can be any implementor of `ToSocketAddrs` trait. See its + /// Address type can be any implementor of [`ToSocketAddrs`] trait. See its /// documentation for concrete examples. + /// /// This will return an error when the IP version of the local socket - /// does not match that returned from `ToSocketAddrs` + /// does not match that returned from [`ToSocketAddrs`]. + /// /// See https://github.com/rust-lang/rust/issues/34202 for more details. + /// + /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn send_to(&self, buf: &[u8], addr: A) -> io::Result { @@ -81,6 +115,16 @@ impl UdpSocket { } /// Returns the socket address that this socket was created from. + /// + /// # Examples + /// + /// ```no_run + /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// assert_eq!(socket.local_addr().unwrap(), + /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 34254))); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn local_addr(&self) -> io::Result { self.0.socket_addr() @@ -91,6 +135,15 @@ impl UdpSocket { /// The returned `UdpSocket` is a reference to the same socket that this /// object references. Both handles will read and write the same port, and /// options set on one socket will be propagated to the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let socket_clone = socket.try_clone().expect("couldn't clone the socket"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UdpSocket) @@ -98,15 +151,30 @@ impl UdpSocket { /// Sets the read timeout to the timeout specified. /// - /// If the value specified is `None`, then `read` calls will block - /// indefinitely. It is an error to pass the zero `Duration` to this + /// If the value specified is [`None`], then [`read()`] calls will block + /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// # Note /// /// Platforms may return a different error code whenever a read times out as /// a result of setting this option. For example Unix typically returns an - /// error of the kind `WouldBlock`, but Windows may return `TimedOut`. + /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock + /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_read_timeout(None).expect("set_read_timeout call failed"); + /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { self.0.set_read_timeout(dur) @@ -114,15 +182,30 @@ impl UdpSocket { /// Sets the write timeout to the timeout specified. /// - /// If the value specified is `None`, then `write` calls will block - /// indefinitely. It is an error to pass the zero `Duration` to this + /// If the value specified is [`None`], then [`write()`] calls will block + /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// # Note /// /// Platforms may return a different error code whenever a write times out /// as a result of setting this option. For example Unix typically returns - /// an error of the kind `WouldBlock`, but Windows may return `TimedOut`. + /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock + /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_write_timeout(None).expect("set_write_timeout call failed"); + /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { self.0.set_write_timeout(dur) @@ -130,7 +213,20 @@ impl UdpSocket { /// Returns the read timeout of this socket. /// - /// If the timeout is `None`, then `read` calls will block indefinitely. + /// If the timeout is [`None`], then [`read()`] calls will block indefinitely. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_read_timeout(None).expect("set_read_timeout call failed"); + /// assert_eq!(socket.read_timeout().unwrap(), None); + /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] pub fn read_timeout(&self) -> io::Result> { self.0.read_timeout() @@ -138,7 +234,20 @@ impl UdpSocket { /// Returns the write timeout of this socket. /// - /// If the timeout is `None`, then `write` calls will block indefinitely. + /// If the timeout is [`None`], then [`write()`] calls will block indefinitely. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_write_timeout(None).expect("set_write_timeout call failed"); + /// assert_eq!(socket.write_timeout().unwrap(), None); + /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] pub fn write_timeout(&self) -> io::Result> { self.0.write_timeout() @@ -148,6 +257,15 @@ impl UdpSocket { /// /// When enabled, this socket is allowed to send packets to a broadcast /// address. + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_broadcast(false).expect("set_broadcast call failed"); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { self.0.set_broadcast(broadcast) @@ -159,6 +277,16 @@ impl UdpSocket { /// [`set_broadcast`][link]. /// /// [link]: #method.set_broadcast + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_broadcast(false).expect("set_broadcast call failed"); + /// assert_eq!(socket.broadcast().unwrap(), false); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn broadcast(&self) -> io::Result { self.0.broadcast() @@ -168,6 +296,15 @@ impl UdpSocket { /// /// If enabled, multicast packets will be looped back to the local socket. /// Note that this may not have any affect on IPv6 sockets. + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed"); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { self.0.set_multicast_loop_v4(multicast_loop_v4) @@ -179,6 +316,16 @@ impl UdpSocket { /// [`set_multicast_loop_v4`][link]. /// /// [link]: #method.set_multicast_loop_v4 + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed"); + /// assert_eq!(socket.multicast_loop_v4().unwrap(), false); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn multicast_loop_v4(&self) -> io::Result { self.0.multicast_loop_v4() @@ -191,6 +338,15 @@ impl UdpSocket { /// don't leave the local network unless explicitly requested. /// /// Note that this may not have any affect on IPv6 sockets. + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed"); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> { self.0.set_multicast_ttl_v4(multicast_ttl_v4) @@ -202,6 +358,16 @@ impl UdpSocket { /// [`set_multicast_ttl_v4`][link]. /// /// [link]: #method.set_multicast_ttl_v4 + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed"); + /// assert_eq!(socket.multicast_ttl_v4().unwrap(), 42); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn multicast_ttl_v4(&self) -> io::Result { self.0.multicast_ttl_v4() @@ -211,6 +377,15 @@ impl UdpSocket { /// /// Controls whether this socket sees the multicast packets it sends itself. /// Note that this may not have any affect on IPv4 sockets. + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed"); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { self.0.set_multicast_loop_v6(multicast_loop_v6) @@ -222,6 +397,16 @@ impl UdpSocket { /// [`set_multicast_loop_v6`][link]. /// /// [link]: #method.set_multicast_loop_v6 + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed"); + /// assert_eq!(socket.multicast_loop_v6().unwrap(), false); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn multicast_loop_v6(&self) -> io::Result { self.0.multicast_loop_v6() @@ -231,6 +416,15 @@ impl UdpSocket { /// /// This value sets the time-to-live field that is used in every packet sent /// from this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_ttl(42).expect("set_ttl call failed"); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { self.0.set_ttl(ttl) @@ -241,6 +435,16 @@ impl UdpSocket { /// For more information about this option, see [`set_ttl`][link]. /// /// [link]: #method.set_ttl + /// + /// # Examples + /// + /// ```no_run + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.set_ttl(42).expect("set_ttl call failed"); + /// assert_eq!(socket.ttl().unwrap(), 42); + /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn ttl(&self) -> io::Result { self.0.ttl() From 0bcb05cf50624fc54162823f998df40658e158b1 Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Sun, 27 Nov 2016 15:34:32 +0100 Subject: [PATCH 05/19] Finishing d2f8fb0a0a9dd from @jseyfried --- src/grammar/verify.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index 48be58f731c..482f3f7d839 100644 --- a/src/grammar/verify.rs +++ b/src/grammar/verify.rs @@ -37,6 +37,8 @@ use syntax::parse::token::{self, BinOpToken, DelimToken, Lit, Token}; use syntax::parse::lexer::TokenAndSpan; use syntax_pos::Pos; +use syntax::symbol::Symbol; + fn parse_token_list(file: &str) -> HashMap { fn id() -> token::Token { Token::Ident(ast::Ident::with_empty_ctxt(Name(0))) @@ -158,7 +160,7 @@ fn fix(mut lit: &str) -> ast::Name { let leading_hashes = count(lit); // +1/-1 to adjust for single quotes - parse::token::intern(&lit[leading_hashes + 1..lit.len() - leading_hashes - 1]) + Symbol::intern(&lit[leading_hashes + 1..lit.len() - leading_hashes - 1]) } /// Assuming a char/byte literal, strip the 'b' prefix and the single quotes. @@ -168,7 +170,7 @@ fn fixchar(mut lit: &str) -> ast::Name { lit = &lit[1..]; } - parse::token::intern(&lit[1..lit.len() - 1]) + Symbol::intern(&lit[1..lit.len() - 1]) } fn count(lit: &str) -> usize { @@ -196,7 +198,7 @@ fn parse_antlr_token(s: &str, tokens: &HashMap, surrogate_ let not_found = format!("didn't find token {:?} in the map", toknum); let proto_tok = tokens.get(toknum).expect(¬_found[..]); - let nm = parse::token::intern(content); + let nm = Symbol::intern(content); debug!("What we got: content (`{}`), proto: {:?}", content, proto_tok); From 2dc3fdf2bd6153ad640544776abb62ad17d6b6be Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Sun, 27 Nov 2016 16:45:09 +0100 Subject: [PATCH 06/19] Resolve visibility issues use syntax::ast::Name; is a reexport of syntax::symbol::Symbol(u32); --- src/grammar/verify.rs | 26 ++++++++++++-------------- src/libsyntax/symbol.rs | 4 ++++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index 482f3f7d839..1903c9125e4 100644 --- a/src/grammar/verify.rs +++ b/src/grammar/verify.rs @@ -23,7 +23,6 @@ use std::fs::File; use std::io::{BufRead, Read}; use std::path::Path; -use syntax::parse; use syntax::parse::lexer; use rustc::dep_graph::DepGraph; use rustc::session::{self, config}; @@ -31,7 +30,6 @@ use rustc::middle::cstore::DummyCrateStore; use std::rc::Rc; use syntax::ast; -use syntax::ast::Name; use syntax::codemap; use syntax::parse::token::{self, BinOpToken, DelimToken, Lit, Token}; use syntax::parse::lexer::TokenAndSpan; @@ -41,7 +39,7 @@ use syntax::symbol::Symbol; fn parse_token_list(file: &str) -> HashMap { fn id() -> token::Token { - Token::Ident(ast::Ident::with_empty_ctxt(Name(0))) + Token::Ident(ast::Ident::with_empty_ctxt(Symbol::invalid())) } let mut res = HashMap::new(); @@ -67,7 +65,7 @@ fn parse_token_list(file: &str) -> HashMap { "SHL" => Token::BinOp(BinOpToken::Shl), "LBRACE" => Token::OpenDelim(DelimToken::Brace), "RARROW" => Token::RArrow, - "LIT_STR" => Token::Literal(Lit::Str_(Name(0)), None), + "LIT_STR" => Token::Literal(Lit::Str_(Symbol::invalid()), None), "DOTDOT" => Token::DotDot, "MOD_SEP" => Token::ModSep, "DOTDOTDOT" => Token::DotDotDot, @@ -77,21 +75,21 @@ fn parse_token_list(file: &str) -> HashMap { "ANDAND" => Token::AndAnd, "AT" => Token::At, "LBRACKET" => Token::OpenDelim(DelimToken::Bracket), - "LIT_STR_RAW" => Token::Literal(Lit::StrRaw(Name(0), 0), None), + "LIT_STR_RAW" => Token::Literal(Lit::StrRaw(Symbol::invalid(), 0), None), "RPAREN" => Token::CloseDelim(DelimToken::Paren), "SLASH" => Token::BinOp(BinOpToken::Slash), "COMMA" => Token::Comma, - "LIFETIME" => Token::Lifetime(ast::Ident::with_empty_ctxt(Name(0))), + "LIFETIME" => Token::Lifetime(ast::Ident::with_empty_ctxt(Symbol::invalid())), "CARET" => Token::BinOp(BinOpToken::Caret), "TILDE" => Token::Tilde, "IDENT" => id(), "PLUS" => Token::BinOp(BinOpToken::Plus), - "LIT_CHAR" => Token::Literal(Lit::Char(Name(0)), None), - "LIT_BYTE" => Token::Literal(Lit::Byte(Name(0)), None), + "LIT_CHAR" => Token::Literal(Lit::Char(Symbol::invalid()), None), + "LIT_BYTE" => Token::Literal(Lit::Byte(Symbol::invalid()), None), "EQ" => Token::Eq, "RBRACKET" => Token::CloseDelim(DelimToken::Bracket), "COMMENT" => Token::Comment, - "DOC_COMMENT" => Token::DocComment(Name(0)), + "DOC_COMMENT" => Token::DocComment(Symbol::invalid()), "DOT" => Token::Dot, "EQEQ" => Token::EqEq, "NE" => Token::Ne, @@ -101,9 +99,9 @@ fn parse_token_list(file: &str) -> HashMap { "BINOP" => Token::BinOp(BinOpToken::Plus), "POUND" => Token::Pound, "OROR" => Token::OrOr, - "LIT_INTEGER" => Token::Literal(Lit::Integer(Name(0)), None), + "LIT_INTEGER" => Token::Literal(Lit::Integer(Symbol::invalid()), None), "BINOPEQ" => Token::BinOpEq(BinOpToken::Plus), - "LIT_FLOAT" => Token::Literal(Lit::Float(Name(0)), None), + "LIT_FLOAT" => Token::Literal(Lit::Float(Symbol::invalid()), None), "WHITESPACE" => Token::Whitespace, "UNDERSCORE" => Token::Underscore, "MINUS" => Token::BinOp(BinOpToken::Minus), @@ -113,10 +111,10 @@ fn parse_token_list(file: &str) -> HashMap { "OR" => Token::BinOp(BinOpToken::Or), "GT" => Token::Gt, "LE" => Token::Le, - "LIT_BINARY" => Token::Literal(Lit::ByteStr(Name(0)), None), - "LIT_BINARY_RAW" => Token::Literal(Lit::ByteStrRaw(Name(0), 0), None), + "LIT_BINARY" => Token::Literal(Lit::ByteStr(Symbol::invalid()), None), + "LIT_BINARY_RAW" => Token::Literal(Lit::ByteStrRaw(Symbol::invalid(), 0), None), "QUESTION" => Token::Question, - "SHEBANG" => Token::Shebang(Name(0)), + "SHEBANG" => Token::Shebang(Symbol::invalid()), _ => continue, }; diff --git a/src/libsyntax/symbol.rs b/src/libsyntax/symbol.rs index fe9a176179c..e2dcc240932 100644 --- a/src/libsyntax/symbol.rs +++ b/src/libsyntax/symbol.rs @@ -35,6 +35,10 @@ impl Symbol { with_interner(|interner| interner.gensym(string)) } + pub fn invalid() -> Self { + Symbol(0u32) + } + pub fn as_str(self) -> InternedString { with_interner(|interner| unsafe { InternedString { From 28b64dc1b955afd6e89b21499dfa1fd1d452e31c Mon Sep 17 00:00:00 2001 From: Stefan Schindler Date: Sun, 27 Nov 2016 17:59:36 +0100 Subject: [PATCH 07/19] Use keywords::Invalid --- src/grammar/verify.rs | 28 +++++++++++++++------------- src/libsyntax/symbol.rs | 4 ---- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs index 1903c9125e4..919fc98e438 100644 --- a/src/grammar/verify.rs +++ b/src/grammar/verify.rs @@ -35,11 +35,11 @@ use syntax::parse::token::{self, BinOpToken, DelimToken, Lit, Token}; use syntax::parse::lexer::TokenAndSpan; use syntax_pos::Pos; -use syntax::symbol::Symbol; +use syntax::symbol::{Symbol, keywords}; fn parse_token_list(file: &str) -> HashMap { fn id() -> token::Token { - Token::Ident(ast::Ident::with_empty_ctxt(Symbol::invalid())) + Token::Ident(ast::Ident::with_empty_ctxt(keywords::Invalid.name())) } let mut res = HashMap::new(); @@ -65,7 +65,7 @@ fn parse_token_list(file: &str) -> HashMap { "SHL" => Token::BinOp(BinOpToken::Shl), "LBRACE" => Token::OpenDelim(DelimToken::Brace), "RARROW" => Token::RArrow, - "LIT_STR" => Token::Literal(Lit::Str_(Symbol::invalid()), None), + "LIT_STR" => Token::Literal(Lit::Str_(keywords::Invalid.name()), None), "DOTDOT" => Token::DotDot, "MOD_SEP" => Token::ModSep, "DOTDOTDOT" => Token::DotDotDot, @@ -75,21 +75,22 @@ fn parse_token_list(file: &str) -> HashMap { "ANDAND" => Token::AndAnd, "AT" => Token::At, "LBRACKET" => Token::OpenDelim(DelimToken::Bracket), - "LIT_STR_RAW" => Token::Literal(Lit::StrRaw(Symbol::invalid(), 0), None), + "LIT_STR_RAW" => Token::Literal(Lit::StrRaw(keywords::Invalid.name(), 0), None), "RPAREN" => Token::CloseDelim(DelimToken::Paren), "SLASH" => Token::BinOp(BinOpToken::Slash), "COMMA" => Token::Comma, - "LIFETIME" => Token::Lifetime(ast::Ident::with_empty_ctxt(Symbol::invalid())), + "LIFETIME" => Token::Lifetime( + ast::Ident::with_empty_ctxt(keywords::Invalid.name())), "CARET" => Token::BinOp(BinOpToken::Caret), "TILDE" => Token::Tilde, "IDENT" => id(), "PLUS" => Token::BinOp(BinOpToken::Plus), - "LIT_CHAR" => Token::Literal(Lit::Char(Symbol::invalid()), None), - "LIT_BYTE" => Token::Literal(Lit::Byte(Symbol::invalid()), None), + "LIT_CHAR" => Token::Literal(Lit::Char(keywords::Invalid.name()), None), + "LIT_BYTE" => Token::Literal(Lit::Byte(keywords::Invalid.name()), None), "EQ" => Token::Eq, "RBRACKET" => Token::CloseDelim(DelimToken::Bracket), "COMMENT" => Token::Comment, - "DOC_COMMENT" => Token::DocComment(Symbol::invalid()), + "DOC_COMMENT" => Token::DocComment(keywords::Invalid.name()), "DOT" => Token::Dot, "EQEQ" => Token::EqEq, "NE" => Token::Ne, @@ -99,9 +100,9 @@ fn parse_token_list(file: &str) -> HashMap { "BINOP" => Token::BinOp(BinOpToken::Plus), "POUND" => Token::Pound, "OROR" => Token::OrOr, - "LIT_INTEGER" => Token::Literal(Lit::Integer(Symbol::invalid()), None), + "LIT_INTEGER" => Token::Literal(Lit::Integer(keywords::Invalid.name()), None), "BINOPEQ" => Token::BinOpEq(BinOpToken::Plus), - "LIT_FLOAT" => Token::Literal(Lit::Float(Symbol::invalid()), None), + "LIT_FLOAT" => Token::Literal(Lit::Float(keywords::Invalid.name()), None), "WHITESPACE" => Token::Whitespace, "UNDERSCORE" => Token::Underscore, "MINUS" => Token::BinOp(BinOpToken::Minus), @@ -111,10 +112,11 @@ fn parse_token_list(file: &str) -> HashMap { "OR" => Token::BinOp(BinOpToken::Or), "GT" => Token::Gt, "LE" => Token::Le, - "LIT_BINARY" => Token::Literal(Lit::ByteStr(Symbol::invalid()), None), - "LIT_BINARY_RAW" => Token::Literal(Lit::ByteStrRaw(Symbol::invalid(), 0), None), + "LIT_BINARY" => Token::Literal(Lit::ByteStr(keywords::Invalid.name()), None), + "LIT_BINARY_RAW" => Token::Literal( + Lit::ByteStrRaw(keywords::Invalid.name(), 0), None), "QUESTION" => Token::Question, - "SHEBANG" => Token::Shebang(Symbol::invalid()), + "SHEBANG" => Token::Shebang(keywords::Invalid.name()), _ => continue, }; diff --git a/src/libsyntax/symbol.rs b/src/libsyntax/symbol.rs index e2dcc240932..fe9a176179c 100644 --- a/src/libsyntax/symbol.rs +++ b/src/libsyntax/symbol.rs @@ -35,10 +35,6 @@ impl Symbol { with_interner(|interner| interner.gensym(string)) } - pub fn invalid() -> Self { - Symbol(0u32) - } - pub fn as_str(self) -> InternedString { with_interner(|interner| unsafe { InternedString { From 72fbf9f0fee1af2f918d3a9a4e377605ae158f2a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 28 Nov 2016 17:06:10 -0500 Subject: [PATCH 08/19] fixup test cases --- .../auxiliary/point.rs | 9 +-------- .../add_private_fn_at_krate_root_cc/struct_point.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs index 99ba576a137..adc2b23441e 100644 --- a/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs +++ b/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs @@ -17,7 +17,7 @@ pub struct Point { fn unused_helper() { } -fn distance_squared(this: &Point) -> f32 { +pub fn distance_squared(this: &Point) -> f32 { return this.x * this.x + this.y * this.y; } @@ -26,10 +26,3 @@ impl Point { distance_squared(self).sqrt() } } - -impl Point { - pub fn translate(&mut self, x: f32, y: f32) { - self.x += x; - self.y += y; - } -} diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs index dba7f147619..489427ba1c1 100644 --- a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs +++ b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs @@ -21,14 +21,14 @@ #![allow(dead_code)] #![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")] -#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_calls_free_fn", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")] extern crate point; -/// A fn item that calls (public) methods on `Point` from the same impl which changed +/// A fn item that calls (public) methods on `Point` from the same impl mod fn_calls_methods_in_same_impl { use point::Point; @@ -40,13 +40,13 @@ mod fn_calls_methods_in_same_impl { } /// A fn item that calls (public) methods on `Point` from another impl -mod fn_calls_methods_in_another_impl { - use point::Point; +mod fn_calls_free_fn { + use point::{self, Point}; #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] pub fn check() { - let mut x = Point { x: 2.0, y: 2.0 }; - x.translate(3.0, 3.0); + let x = Point { x: 2.0, y: 2.0 }; + point::distance_squared(&x); } } From 4226930ddf54c4567b2eacc226d4eb897277afab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 28 Nov 2016 17:53:59 -0800 Subject: [PATCH 09/19] Show `Trait` instead of `` in E0323 For a given file ``` trait Foo { fn bar(&self); } pub struct FooConstForMethod; impl Foo for FooConstForMethod { const bar: u64 = 1; } ``` show ``` error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo` ``` instead of ``` error[E0323]: item `bar` is an associated const, which doesn't match its trait `` ``` --- src/librustc_typeck/check/mod.rs | 6 +++--- src/test/ui/span/impl-wrong-item-for-trait.stderr | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2babb81bc40..3c3f7e66e93 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1090,7 +1090,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } else { let mut err = struct_span_err!(tcx.sess, impl_item.span, E0323, "item `{}` is an associated const, \ - which doesn't match its trait `{:?}`", + which doesn't match its trait `{}`", ty_impl_item.name, impl_trait_ref); err.span_label(impl_item.span, &format!("does not match trait")); @@ -1128,7 +1128,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } else { let mut err = struct_span_err!(tcx.sess, impl_item.span, E0324, "item `{}` is an associated method, \ - which doesn't match its trait `{:?}`", + which doesn't match its trait `{}`", ty_impl_item.name, impl_trait_ref); err.span_label(impl_item.span, &format!("does not match trait")); @@ -1146,7 +1146,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } else { let mut err = struct_span_err!(tcx.sess, impl_item.span, E0325, "item `{}` is an associated type, \ - which doesn't match its trait `{:?}`", + which doesn't match its trait `{}`", ty_impl_item.name, impl_trait_ref); err.span_label(impl_item.span, &format!("does not match trait")); diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr index 244285e3584..ff6b75cd40a 100644 --- a/src/test/ui/span/impl-wrong-item-for-trait.stderr +++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr @@ -1,4 +1,4 @@ -error[E0323]: item `bar` is an associated const, which doesn't match its trait `` +error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo` --> $DIR/impl-wrong-item-for-trait.rs:25:5 | 16 | fn bar(&self); @@ -16,7 +16,7 @@ error[E0046]: not all trait items implemented, missing: `bar` 22 | impl Foo for FooConstForMethod { | ^ missing `bar` in implementation -error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `` +error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `Foo` --> $DIR/impl-wrong-item-for-trait.rs:37:5 | 17 | const MY_CONST: u32; @@ -34,7 +34,7 @@ error[E0046]: not all trait items implemented, missing: `MY_CONST` 33 | impl Foo for FooMethodForConst { | ^ missing `MY_CONST` in implementation -error[E0325]: item `bar` is an associated type, which doesn't match its trait `` +error[E0325]: item `bar` is an associated type, which doesn't match its trait `Foo` --> $DIR/impl-wrong-item-for-trait.rs:47:5 | 16 | fn bar(&self); From ffcdc191782bbb23b5a7669f4e4f7e3054893878 Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Tue, 29 Nov 2016 13:14:37 -0600 Subject: [PATCH 10/19] bootstrap/README: fix small typo --- src/bootstrap/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index f73f41ffae2..24d716c1195 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -32,7 +32,7 @@ The script accepts commands, flags, and filters to determine what to do: # build the whole compiler ./x.py build - # build the stage1 compier + # build the stage1 compiler ./x.py build --stage 1 # build stage0 libstd From 336e5dd33de28830410e0ffcda9339af619c2f9b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 29 Nov 2016 14:28:16 -0800 Subject: [PATCH 11/19] Add missing examples for IpAddr enum --- src/libstd/net/ip.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 7b7be6e2eee..edeea12ec00 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -79,8 +79,18 @@ pub enum Ipv6MulticastScope { impl IpAddr { /// Returns true for the special 'unspecified' address ([IPv4], [IPv6]). + /// /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true); + /// ``` #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_unspecified(&self) -> bool { match *self { @@ -90,8 +100,18 @@ impl IpAddr { } /// Returns true if this is a loopback address ([IPv4], [IPv6]). + /// /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true); + /// ``` #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_loopback(&self) -> bool { match *self { @@ -101,8 +121,23 @@ impl IpAddr { } /// Returns true if the address appears to be globally routable ([IPv4], [IPv6]). + /// /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// fn main() { + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), + /// true); + /// } + /// ``` pub fn is_global(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_global(), @@ -111,8 +146,18 @@ impl IpAddr { } /// Returns true if this is a multicast address ([IPv4], [IPv6]). + /// /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true); + /// ``` #[stable(feature = "ip_shared", since = "1.12.0")] pub fn is_multicast(&self) -> bool { match *self { @@ -122,8 +167,23 @@ impl IpAddr { } /// Returns true if this address is in a range designated for documentation ([IPv4], [IPv6]). + /// /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// fn main() { + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)) + /// .is_documentation(), true); + /// } + /// ``` pub fn is_documentation(&self) -> bool { match *self { IpAddr::V4(ref a) => a.is_documentation(), @@ -132,6 +192,20 @@ impl IpAddr { } /// Returns true if this address is a valid IPv4 address, false if it's a valid IPv6 address. + /// + /// # Examples + /// + /// ``` + /// #![feature(ipaddr_checker)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// fn main() { + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), + /// false); + /// } + /// ``` #[unstable(feature = "ipaddr_checker", issue = "36949")] pub fn is_ipv4(&self) -> bool { match *self { @@ -141,6 +215,20 @@ impl IpAddr { } /// Returns true if this address is a valid IPv6 address, false if it's a valid IPv4 address. + /// + /// # Examples + /// + /// ``` + /// #![feature(ipaddr_checker)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// fn main() { + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), + /// true); + /// } + /// ``` #[unstable(feature = "ipaddr_checker", issue = "36949")] pub fn is_ipv6(&self) -> bool { match *self { From d21861dd89e2df8c567c97756d9cc18e39a5283f Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Sun, 27 Nov 2016 06:54:50 -0700 Subject: [PATCH 12/19] Refactor one_bound_for_assoc_type to take an Iterator instead of Vec. --- src/librustc_typeck/astconv.rs | 66 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 032ad6efe1f..96088db9d8e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -884,10 +884,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // those that do. self.ensure_super_predicates(binding.span, trait_ref.def_id())?; - let candidates: Vec = + let candidates = traits::supertraits(tcx, trait_ref.clone()) - .filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name)) - .collect(); + .filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name)); let candidate = self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(), @@ -1191,10 +1190,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Check that there is exactly one way to find an associated type with the // correct name. - let suitable_bounds: Vec<_> = + let suitable_bounds = traits::transitive_bounds(tcx, &bounds) - .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name)) - .collect(); + .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name)); self.one_bound_for_assoc_type(suitable_bounds, &ty_param_name.as_str(), @@ -1205,31 +1203,29 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Checks that bounds contains exactly one element and reports appropriate // errors otherwise. - fn one_bound_for_assoc_type(&self, - bounds: Vec>, + fn one_bound_for_assoc_type(&self, + mut bounds: I, ty_param_name: &str, assoc_name: &str, span: Span) -> Result, ErrorReported> + where I: Iterator> { - if bounds.is_empty() { - struct_span_err!(self.tcx().sess, span, E0220, - "associated type `{}` not found for `{}`", - assoc_name, - ty_param_name) - .span_label(span, &format!("associated type `{}` not found", assoc_name)) - .emit(); - return Err(ErrorReported); - } - - if bounds.len() > 1 { - let spans = bounds.iter().map(|b| { - self.tcx().associated_items(b.def_id()).find(|item| { - item.kind == ty::AssociatedKind::Type && item.name == assoc_name - }) - .and_then(|item| self.tcx().map.span_if_local(item.def_id)) - }); + let bound = match bounds.next() { + Some(bound) => bound, + None => { + struct_span_err!(self.tcx().sess, span, E0220, + "associated type `{}` not found for `{}`", + assoc_name, + ty_param_name) + .span_label(span, &format!("associated type `{}` not found", assoc_name)) + .emit(); + return Err(ErrorReported); + } + }; + if let Some(bound2) = bounds.next() { + let bounds = iter::once(bound).chain(iter::once(bound2)).chain(bounds); let mut err = struct_span_err!( self.tcx().sess, span, E0221, "ambiguous associated type `{}` in bounds of `{}`", @@ -1237,22 +1233,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty_param_name); err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name)); - for span_and_bound in spans.zip(&bounds) { - if let Some(span) = span_and_bound.0 { + for bound in bounds { + let bound_span = self.tcx().associated_items(bound.def_id()).find(|item| { + item.kind == ty::AssociatedKind::Type && item.name == assoc_name + }) + .and_then(|item| self.tcx().map.span_if_local(item.def_id)); + + if let Some(span) = bound_span { err.span_label(span, &format!("ambiguous `{}` from `{}`", assoc_name, - span_and_bound.1)); + bound)); } else { span_note!(&mut err, span, "associated type `{}` could derive from `{}`", ty_param_name, - span_and_bound.1); + bound); } } err.emit(); } - Ok(bounds[0].clone()) + return Ok(bound); } // Create a type from a path to an associated type. @@ -1293,11 +1294,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { return (tcx.types.err, Def::Err); } - let candidates: Vec = + let candidates = traits::supertraits(tcx, ty::Binder(trait_ref)) .filter(|r| self.trait_defines_associated_type_named(r.def_id(), - assoc_name)) - .collect(); + assoc_name)); match self.one_bound_for_assoc_type(candidates, "Self", From a15d2dbef6d9a370c3048c8c3f620399e9090a5f Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 30 Nov 2016 12:17:38 -0500 Subject: [PATCH 13/19] debuginfo: Ignore macro-stepping test on aarch64 --- src/test/debuginfo/macro-stepping.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/debuginfo/macro-stepping.rs b/src/test/debuginfo/macro-stepping.rs index 52a2a58ed7d..37355ed377b 100644 --- a/src/test/debuginfo/macro-stepping.rs +++ b/src/test/debuginfo/macro-stepping.rs @@ -10,6 +10,7 @@ // ignore-windows // ignore-android +// ignore-aarch64 // min-lldb-version: 310 // aux-build:macro-stepping.rs From 8e6ae19bb51c6248384889670830fc7838617c33 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 30 Nov 2016 09:44:33 -0800 Subject: [PATCH 14/19] Add cloned example for Option --- src/libcore/option.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 607e16887a8..8871e1fa840 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -659,6 +659,16 @@ impl Option { impl<'a, T: Clone> Option<&'a T> { /// Maps an `Option<&T>` to an `Option` by cloning the contents of the /// option. + /// + /// # Examples + /// + /// ``` + /// let x = 12; + /// let opt_x = Some(&x); + /// assert_eq!(opt_x, Some(&12)); + /// let cloned = opt_x.cloned(); + /// assert_eq!(cloned, Some(12)); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn cloned(self) -> Option { self.map(|t| t.clone()) From 29a6ffa4010d965a6c587c9ffd1ce88bbea164c9 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 30 Nov 2016 17:33:52 -0500 Subject: [PATCH 15/19] incr.comp.: Add more output to -Z incremental-info. --- .../persist/file_format.rs | 16 +++++++++- src/librustc_incremental/persist/fs.rs | 4 +-- src/librustc_incremental/persist/hash.rs | 2 +- src/librustc_incremental/persist/load.rs | 32 ++++++++++++------- src/librustc_trans/base.rs | 5 +++ 5 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs index 7c2b69e762b..b67caa6750a 100644 --- a/src/librustc_incremental/persist/file_format.rs +++ b/src/librustc_incremental/persist/file_format.rs @@ -24,6 +24,7 @@ use std::path::Path; use std::fs::File; use std::env; +use rustc::session::Session; use rustc::session::config::nightly_options; /// The first few bytes of files generated by incremental compilation @@ -59,7 +60,7 @@ pub fn write_file_header(stream: &mut W) -> io::Result<()> { /// incompatible version of the compiler. /// - Returns `Err(..)` if some kind of IO error occurred while reading the /// file. -pub fn read_file(path: &Path) -> io::Result>> { +pub fn read_file(sess: &Session, path: &Path) -> io::Result>> { if !path.exists() { return Ok(None); } @@ -72,6 +73,7 @@ pub fn read_file(path: &Path) -> io::Result>> { let mut file_magic = [0u8; 4]; file.read_exact(&mut file_magic)?; if file_magic != FILE_MAGIC { + report_format_mismatch(sess, path, "Wrong FILE_MAGIC"); return Ok(None) } } @@ -85,6 +87,7 @@ pub fn read_file(path: &Path) -> io::Result>> { ((header_format_version[1] as u16) << 8); if header_format_version != HEADER_FORMAT_VERSION { + report_format_mismatch(sess, path, "Wrong HEADER_FORMAT_VERSION"); return Ok(None) } } @@ -99,6 +102,7 @@ pub fn read_file(path: &Path) -> io::Result>> { file.read_exact(&mut buffer[..])?; if &buffer[..] != rustc_version().as_bytes() { + report_format_mismatch(sess, path, "Different compiler version"); return Ok(None); } } @@ -109,6 +113,16 @@ pub fn read_file(path: &Path) -> io::Result>> { Ok(Some(data)) } +fn report_format_mismatch(sess: &Session, file: &Path, message: &str) { + debug!("read_file: {}", message); + + if sess.opts.debugging_opts.incremental_info { + println!("incremental: ignoring cache artifact `{}`: {}", + file.file_name().unwrap().to_string_lossy(), + message); + } +} + fn rustc_version() -> String { if nightly_options::is_nightly_build() { if let Some(val) = env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 26181dbaf50..2ad37e98c70 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -435,8 +435,8 @@ fn copy_files(target_dir: &Path, } if print_stats_on_success { - println!("incr. comp. session directory: {} files hard-linked", files_linked); - println!("incr. comp. session directory: {} files copied", files_copied); + println!("incremental: session directory: {} files hard-linked", files_linked); + println!("incremental: session directory: {} files copied", files_copied); } Ok(files_linked > 0 || files_copied == 0) diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 562efa4b0d2..e5203ea02b4 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -156,7 +156,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { let hashes_file_path = metadata_hash_import_path(&session_dir); - match file_format::read_file(&hashes_file_path) + match file_format::read_file(self.tcx.sess, &hashes_file_path) { Ok(Some(data)) => { match self.load_from_data(cnum, &data, svh) { diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 12bf74c9511..ec7e0bf2cf7 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -93,7 +93,7 @@ fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn load_data(sess: &Session, path: &Path) -> Option> { - match file_format::read_file(path) { + match file_format::read_file(sess, path) { Ok(Some(data)) => return Some(data), Ok(None) => { // The file either didn't exist or was produced by an incompatible @@ -132,6 +132,10 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let prev_commandline_args_hash = u64::decode(&mut dep_graph_decoder)?; if prev_commandline_args_hash != tcx.sess.opts.dep_tracking_hash() { + if tcx.sess.opts.debugging_opts.incremental_info { + println!("incremental: completely ignoring cache because of \ + differing commandline arguments"); + } // We can't reuse the cache, purge it. debug!("decode_dep_graph: differing commandline arg hashes"); for swp in work_products { @@ -192,7 +196,8 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if tcx.sess.opts.debugging_opts.incremental_info { // It'd be nice to pretty-print these paths better than just // using the `Debug` impls, but wev. - println!("module {:?} is dirty because {:?} changed or was removed", + println!("incremental: module {:?} is dirty because {:?} \ + changed or was removed", target_node, raw_source_node.map_def(|&index| { Some(directory.def_path_string(tcx, index)) @@ -277,14 +282,19 @@ fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("reconcile_work_products: dep-node for {:?} is dirty", swp); delete_dirty_work_product(tcx, swp); } else { - let all_files_exist = - swp.work_product - .saved_files - .iter() - .all(|&(_, ref file_name)| { - let path = in_incr_comp_dir_sess(tcx.sess, &file_name); - path.exists() - }); + let mut all_files_exist = true; + for &(_, ref file_name) in swp.work_product.saved_files.iter() { + let path = in_incr_comp_dir_sess(tcx.sess, file_name); + if !path.exists() { + all_files_exist = false; + + if tcx.sess.opts.debugging_opts.incremental_info { + println!("incremental: could not find file for up-to-date work product: {}", + path.display()); + } + } + } + if all_files_exist { debug!("reconcile_work_products: all files for {:?} exist", swp); tcx.dep_graph.insert_previous_work_product(&swp.id, swp.work_product); @@ -331,7 +341,7 @@ fn load_prev_metadata_hashes(tcx: TyCtxt, debug!("load_prev_metadata_hashes() - File: {}", file_path.display()); - let data = match file_format::read_file(&file_path) { + let data = match file_format::read_file(tcx.sess, &file_path) { Ok(Some(data)) => data, Ok(None) => { debug!("load_prev_metadata_hashes() - File produced by incompatible \ diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index f1126e6fd25..259ef2a780c 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1981,6 +1981,11 @@ fn trans_reuse_previous_work_products(tcx: TyCtxt, debug!("trans_reuse_previous_work_products: reusing {:?}", work_product); return Some(work_product); } else { + if tcx.sess.opts.debugging_opts.incremental_info { + println!("incremental: CGU `{}` invalidated because of \ + changed partitioning hash.", + cgu.name()); + } debug!("trans_reuse_previous_work_products: \ not reusing {:?} because hash changed to {:?}", work_product, hash); From d950ca175ab5e7a9827353f9fb7d9d6e3f6e7658 Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Thu, 1 Dec 2016 16:30:34 +0000 Subject: [PATCH 16/19] Minor fix to testing concurrency section --- src/doc/book/testing.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/book/testing.md b/src/doc/book/testing.md index 14a05102b9a..ebeb9923197 100644 --- a/src/doc/book/testing.md +++ b/src/doc/book/testing.md @@ -589,11 +589,11 @@ please see the [Documentation chapter](documentation.html). # Testing and concurrency -One thing that is important to note when writing tests are run concurrently -using threads. For this reason you should take care that your tests are written -in such a way as to not depend on each-other, or on any shared state. "Shared -state" can also include the environment, such as the current working directory, -or environment variables. +One thing that is important to note when writing tests is that they may be run +concurrently using threads. For this reason you should take care that your tests +are written in such a way as to not depend on each-other, or on any shared +state. "Shared state" can also include the environment, such as the current +working directory, or environment variables. If this is an issue it is possible to control this concurrency, either by setting the environment variable `RUST_TEST_THREADS`, or by passing the argument From 57ffda6158b6b6a119fa8f59b19f321cae9d0850 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 1 Dec 2016 12:29:28 -0500 Subject: [PATCH 17/19] add a `-Z incremental-dump-hash` flag This causes us to dump a bunch of has information to stdout that can be useful in tracking down incremental compilation invalidations, particularly across crates. --- src/librustc/session/config.rs | 2 ++ src/librustc_incremental/persist/load.rs | 13 +++++++++++++ src/librustc_incremental/persist/save.rs | 15 +++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 26dafed7019..0052fe25b05 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -885,6 +885,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "enable incremental compilation (experimental)"), incremental_info: bool = (false, parse_bool, [UNTRACKED], "print high-level information about incremental reuse (or the lack thereof)"), + incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED], + "dump hash information in textual format to stdout"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 12bf74c9511..ead353512c7 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -250,11 +250,24 @@ fn dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, current_hash); continue; } + + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("node {:?} is dirty as hash is {:?} was {:?}", + dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), + current_hash, + hash.hash); + } + debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}", dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), current_hash, hash.hash); } else { + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("node {:?} is dirty as it was removed", + hash.dep_node); + } + debug!("initial_dirty_nodes: {:?} is dirty as it was removed", hash.dep_node); } diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 05e21aa19b1..1ce4bf7f033 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -159,6 +159,12 @@ pub fn encode_dep_graph(preds: &Predecessors, } } + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + for (dep_node, hash) in &preds.hashes { + println!("HIR hash for {:?} is {}", dep_node, hash); + } + } + // Create the serialized dep-graph. let graph = SerializedDepGraph { edges: edges, @@ -248,6 +254,15 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, let hash = state.finish(); debug!("save: metadata hash for {:?} is {}", def_id, hash); + + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("metadata hash for {:?} is {}", def_id, hash); + for dep_node in sources { + println!("metadata hash for {:?} depends on {:?} with hash {}", + def_id, dep_node, preds.hashes[dep_node]); + } + } + serialized_hashes.hashes.push(SerializedMetadataHash { def_index: def_id.index, hash: hash, From ecf6f1b96aae615698ce3283750f442a18130138 Mon Sep 17 00:00:00 2001 From: jethrogb Date: Fri, 2 Dec 2016 09:19:38 -0800 Subject: [PATCH 18/19] Update items section in reference Make clear that items must be definitions, and add missing extern block --- src/doc/reference.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 4fbe5183967..8655bab4b21 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -740,13 +740,14 @@ There are several kinds of item: * [`extern crate` declarations](#extern-crate-declarations) * [`use` declarations](#use-declarations) * [modules](#modules) -* [functions](#functions) +* [function definitions](#functions) +* [`extern` blocks](#external-blocks) * [type definitions](grammar.html#type-definitions) -* [structs](#structs) -* [enumerations](#enumerations) +* [struct definitions](#structs) +* [enumeration definitions](#enumerations) * [constant items](#constant-items) * [static items](#static-items) -* [traits](#traits) +* [trait definitions](#traits) * [implementations](#implementations) Some items form an implicit scope for the declaration of sub-items. In other From 60d1660748b30e2f3c69738e068d252271715268 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 2 Dec 2016 20:16:12 -0800 Subject: [PATCH 19/19] Add Component examples --- src/libstd/path.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index d215f368d1e..d13baea40a9 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -457,7 +457,17 @@ pub enum Component<'a> { } impl<'a> Component<'a> { - /// Extracts the underlying `OsStr` slice + /// Extracts the underlying `OsStr` slice. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("./tmp/foo/bar.txt"); + /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect(); + /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn as_os_str(self) -> &'a OsStr { match self {