From 5451b722b0d564e8e376ef89920de5d97b01eac3 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 22 Sep 2017 17:31:18 -0500 Subject: [PATCH 001/365] Expand the introduction to the ffi module. We describe the representation of C strings, and the purpose of OsString/OsStr. Part of https://github.com/rust-lang/rust/issues/29354 --- src/libstd/ffi/mod.rs | 101 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index ca1ff18f1ca..6c8ddfc3944 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -8,7 +8,106 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Utilities related to FFI bindings. +//! This module provides utilities to handle C-like strings. It is +//! mainly of use for FFI (Foreign Function Interface) bindings and +//! code that needs to exchange C-like strings with other languages. +//! +//! # Overview +//! +//! Rust represents owned strings with the [`String`] type, and +//! borrowed slices of strings with the [`str`] primitive. Both are +//! always in UTF-8 encoding, and may contain nul bytes in the middle, +//! i.e. if you look at the bytes that make up the string, there may +//! be a `0` among them. Both `String` and `str` know their length; +//! there are no nul terminators at the end of strings like in C. +//! +//! C strings are different from Rust strings: +//! +//! * **Encodings** - C strings may have different encodings. If +//! you are bringing in strings from C APIs, you should check what +//! encoding you are getting. Rust strings are always UTF-8. +//! +//! * **Character width** - C strings may use "normal" or "wide" +//! characters, i.e. `char` or `wchar_t`, respectively. The C +//! standard leaves the actual sizes of those types open to +//! interpretation, but defines different APIs for strings made up of +//! each character type. Rust strings are always UTF-8, so different +//! Unicode characters will be encoded in a variable number of bytes +//! each. The Rust type [`char`] represents a '[Unicode +//! scalar value]', which is similar to, but not the same as, a +//! '[Unicode code point]'. +//! +//! * **Nul terminators and implicit string lengths** - Often, C +//! strings are nul-terminated, i.e. they have a `0` character at the +//! end. The length of a string buffer is not known *a priori*; +//! instead, to compute the length of a string, C code must manually +//! call a function like `strlen()` for `char`-based strings, or +//! `wcslen()` for `wchar_t`-based ones. Those functions return the +//! number of characters in the string excluding the nul terminator, +//! so the buffer length is really `len+1` characters. Rust strings +//! don't have a nul terminator, and they always know their length. +//! +//! * **No nul characters in the middle of the string** - When C +//! strings have a nul terminator character, this usually means that +//! they cannot have nul characters in the middle — a nul character +//! would essentially truncate the string. Rust strings *can* have +//! nul characters in the middle, since they don't use nul +//! terminators. +//! +//! # Representations of non-Rust strings +//! +//! [`CString`] and [`CStr`] are useful when you need to transfer +//! UTF-8 strings to and from C, respectively: +//! +//! * **From Rust to C:** [`CString`] represents an owned, C-friendly +//! UTF-8 string: it is valid UTF-8, it is nul-terminated, and has no +//! nul characters in the middle. Rust code can create a `CString` +//! out of a normal string (provided that the string doesn't have nul +//! characters in the middle), and then use a variety of methods to +//! obtain a raw `*mut u8` that can then be passed as an argument to C +//! functions. +//! +//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it +//! is what you would use to wrap a raw `*const u8` that you got from +//! a C function. A `CStr` is just guaranteed to be a nul-terminated +//! array of bytes; the UTF-8 validation step only happens when you +//! request to convert it to a `&str`. +//! +//! [`OsString`] and [`OsStr`] are useful when you need to transfer +//! strings to and from operating system calls. If you need Rust +//! strings out of them, they can take care of conversion to and from +//! the operating system's preferred form for strings — of course, it +//! may not be possible to convert all valid operating system strings +//! into valid UTF-8; the `OsString` and `OsStr` functions let you know +//! when this is the case. +//! +//! * [`OsString`] represents an owned string in whatever +//! representation the operating system prefers. In the Rust standard +//! library, various APIs that transfer strings to/from the operating +//! system use `OsString` instead of plain strings. For example, +//! [`env::var_os()`] is used to query environment variables; it +//! returns an `Option`. If the environment variable exists +//! you will get a `Some(os_string)`, which you can *then* try to +//! convert to a Rust string. This yields a [`Result<>`], so that +//! your code can detect errors in case the environment variable did +//! not in fact contain valid Unicode data. +//! +//! * [`OsStr`] represents a borrowed reference to a string in a format that +//! can be passed to the operating system. It can be converted into +//! an UTF-8 Rust string slice in a similar way to `OsString`. +//! +//! [`String`]: ../string/struct.String.html +//! [`str`]: ../primitive.str.html +//! [`char`]: ../primitive.char.html +//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value +//! [Unicode code point]: http://www.unicode.org/glossary/#code_point +//! [`CString`]: struct.CString.html +//! [`CStr`]: struct.CStr.html +//! [`OsString`]: struct.OsString.html +//! [`OsStr`]: struct.OsStr.html +//! [`env::set_var()`]: ../env/fn.set_var.html +//! [`env::var_os()`]: ../env/fn.var_os.html +//! [`Result<>`]: ../result/enum.Result.html #![stable(feature = "rust1", since = "1.0.0")] From 8da694a42138ac74047d989abd3c7daf0edcbe93 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 22 Sep 2017 20:36:44 -0500 Subject: [PATCH 002/365] Overhaul the ffi::CString docs Explain the struct's reason for being, and its most common usage patterns. Add a bunch of links. Clarify the method docs a bit. Part of https://github.com/rust-lang/rust/issues/29354 --- src/libstd/ffi/c_str.rs | 146 +++++++++++++++++++++++++++++++--------- 1 file changed, 115 insertions(+), 31 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 7992aefcb42..f0a691fd668 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -23,19 +23,68 @@ use ptr; use slice; use str::{self, Utf8Error}; -/// A type representing an owned C-compatible string. +/// A type representing an owned, C-compatible, UTF-8 string. /// -/// This type serves the primary purpose of being able to safely generate a -/// C-compatible string from a Rust byte slice or vector. An instance of this +/// This type serves the purpose of being able to safely generate a +/// C-compatible UTF-8 string from a Rust byte slice or vector. An instance of this /// type is a static guarantee that the underlying bytes contain no interior 0 -/// bytes and the final byte is 0. +/// bytes ("nul characters") and that the final byte is 0 ("nul terminator"). /// -/// A `CString` is created from either a byte slice or a byte vector. A [`u8`] -/// slice can be obtained with the `as_bytes` method. Slices produced from a -/// `CString` do *not* contain the trailing nul terminator unless otherwise -/// specified. +/// `CString` is to [`CStr`] as [`String`] is to [`&str`]: the former +/// in each pair are owned strings; the latter are borrowed +/// references. /// +/// # Creating a `CString` +/// +/// A `CString` is created from either a byte slice or a byte vector, +/// or anything that implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>` (for +/// example, you can build a `CString` straight out of a [`String`] or +/// a [`&str`], since both implement that trait). +/// +/// The [`new`] method will actually check that the provided `&[u8]` +/// does not have 0 bytes in the middle, and return an error if it +/// finds one. +/// +/// # Extracting a raw pointer to the whole C string +/// +/// `CString` implements a [`as_ptr`] method through the [`Deref`] +/// trait. This method will give you a `*const c_char` which you can +/// feed directly to extern functions that expect a nul-terminated +/// string, like C's `strdup()`. +/// +/// # Extracting a slice of the whole C string +/// +/// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a +/// `CString` with the [`as_bytes`] method. Slices produced in this +/// way do *not* contain the trailing nul terminator. This is useful +/// when you will be calling an extern function that takes a `*const +/// u8` argument which is not necessarily nul-terminated, plus another +/// argument with the length of the string — like C's `strndup()`. +/// You can of course get the slice's length with its +/// [`len`][slice.len] method. +/// +/// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you +/// can use [`as_bytes_with_nul`] instead. +/// +/// Once you have the kind of slice you need (with or without a nul +/// terminator), you can call the slice's own +/// [`as_ptr`][slice.as_ptr] method to get a raw pointer to pass to +/// extern functions. See the documentation for that function for a +/// discussion on ensuring the lifetime of the raw pointer. +/// +/// [`Into`]: ../convert/trait.Into.html +/// [`Vec`]: ../vec/struct.Vec.html +/// [`String`]: ../string/struct.String.html +/// [`&str`]: ../primitive.str.html /// [`u8`]: ../primitive.u8.html +/// [`new`]: #method.new +/// [`as_bytes`]: #method.as_bytes +/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul +/// [`as_ptr`]: #method.as_ptr +/// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr +/// [slice.len]: ../primitive.slice.html#method.len +/// [`Deref`]: ../ops/trait.Deref.html +/// [`CStr`]: struct.CStr.html /// /// # Examples /// @@ -48,6 +97,8 @@ use str::{self, Utf8Error}; /// fn my_printer(s: *const c_char); /// } /// +/// // We are certain that our string doesn't have 0 bytes in the middle, +/// // so we can .unwrap() /// let c_to_print = CString::new("Hello, world!").unwrap(); /// unsafe { /// my_printer(c_to_print.as_ptr()); @@ -58,7 +109,7 @@ use str::{self, Utf8Error}; /// # Safety /// /// `CString` is intended for working with traditional C-style strings -/// (a sequence of non-null bytes terminated by a single null byte); the +/// (a sequence of non-nul bytes terminated by a single nul byte); the /// primary use case for these kinds of strings is interoperating with C-like /// code. Often you will need to transfer ownership to/from that external /// code. It is strongly recommended that you thoroughly read through the @@ -215,8 +266,11 @@ pub struct IntoStringError { impl CString { /// Creates a new C-compatible string from a container of bytes. /// - /// This method will consume the provided data and use the underlying bytes - /// to construct a new string, ensuring that there is a trailing 0 byte. + /// This method will consume the provided data and use the + /// underlying bytes to construct a new string, ensuring that + /// there is a trailing 0 byte. This trailing 0 byte will be + /// appended by this method; the provided data should *not* + /// contain any 0 bytes in it. /// /// # Examples /// @@ -234,9 +288,11 @@ impl CString { /// /// # Errors /// - /// This function will return an error if the bytes yielded contain an - /// internal 0 byte. The error returned will contain the bytes as well as + /// This function will return an error if the supplied bytes contain an + /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as /// the position of the nul byte. + /// + /// [`NulError`]: struct.NulError.html #[stable(feature = "rust1", since = "1.0.0")] pub fn new>>(t: T) -> Result { Self::_new(t.into()) @@ -249,8 +305,8 @@ impl CString { } } - /// Creates a C-compatible string from a byte vector without checking for - /// interior 0 bytes. + /// Creates a C-compatible string by consuming a byte vector, + /// without checking for interior 0 bytes. /// /// This method is equivalent to [`new`] except that no runtime assertion /// is made that `v` contains no 0 bytes, and it requires an actual @@ -275,7 +331,7 @@ impl CString { CString { inner: v.into_boxed_slice() } } - /// Retakes ownership of a `CString` that was transferred to C. + /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`]. /// /// Additionally, the length of the string will be recalculated from the pointer. /// @@ -286,7 +342,14 @@ impl CString { /// ownership of a string that was allocated by foreign code) is likely to lead /// to undefined behavior or allocator corruption. /// + /// > **Note:** If you need to borrow a string that was allocated by + /// > foreign code, use [`CStr`]. If you need to take ownership of + /// > a string that was allocated by foreign code, you will need to + /// > make your own provisions for freeing it appropriately, likely + /// > with the foreign code's API to do that. + /// /// [`into_raw`]: #method.into_raw + /// [`CStr`]: struct.CStr.html /// /// # Examples /// @@ -315,11 +378,11 @@ impl CString { CString { inner: mem::transmute(slice) } } - /// Transfers ownership of the string to a C caller. + /// Consumes the `CString` and transfers ownership of the string to a C caller. /// - /// The pointer must be returned to Rust and reconstituted using + /// The pointer which this function returns must be returned to Rust and reconstituted using /// [`from_raw`] to be properly deallocated. Specifically, one - /// should *not* use the standard C `free` function to deallocate + /// should *not* use the standard C `free()` function to deallocate /// this string. /// /// Failure to call [`from_raw`] will lead to a memory leak. @@ -356,6 +419,22 @@ impl CString { /// On failure, ownership of the original `CString` is returned. /// /// [`String`]: ../string/struct.String.html + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let valid_utf8 = vec![b'f', b'o', b'o']; + /// let cstring = CString::new(valid_utf8).unwrap(); + /// assert_eq!(cstring.into_string().unwrap(), "foo"); + /// + /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o']; + /// let cstring = CString::new(invalid_utf8).unwrap(); + /// let err = cstring.into_string().err().unwrap(); + /// assert_eq!(err.utf8_error().valid_up_to(), 1); + /// ``` + #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_string(self) -> Result { String::from_utf8(self.into_bytes()) @@ -365,10 +444,11 @@ impl CString { }) } - /// Returns the underlying byte buffer. + /// Consumes the `CString` and returns the underlying byte buffer. /// - /// The returned buffer does **not** contain the trailing nul separator and - /// it is guaranteed to not have any interior nul bytes. + /// The returned buffer does **not** contain the trailing nul + /// terminator, and it is guaranteed to not have any interior nul + /// bytes. /// /// # Examples /// @@ -388,7 +468,7 @@ impl CString { } /// Equivalent to the [`into_bytes`] function except that the returned vector - /// includes the trailing nul byte. + /// includes the trailing nul terminator. /// /// [`into_bytes`]: #method.into_bytes /// @@ -408,8 +488,12 @@ impl CString { /// Returns the contents of this `CString` as a slice of bytes. /// - /// The returned slice does **not** contain the trailing nul separator and - /// it is guaranteed to not have any interior nul bytes. + /// The returned slice does **not** contain the trailing nul + /// terminator, and it is guaranteed to not have any interior nul + /// bytes. If you need the nul terminator, use + /// [`as_bytes_with_nul`] instead. + /// + /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul /// /// # Examples /// @@ -427,7 +511,7 @@ impl CString { } /// Equivalent to the [`as_bytes`] function except that the returned slice - /// includes the trailing nul byte. + /// includes the trailing nul terminator. /// /// [`as_bytes`]: #method.as_bytes /// @@ -598,8 +682,8 @@ impl Default for Box { } impl NulError { - /// Returns the position of the nul byte in the slice that was provided to - /// [`CString::new`]. + /// Returns the position of the nul byte in the slice that caused + /// [`CString::new`] to fail. /// /// [`CString::new`]: struct.CString.html#method.new /// @@ -766,7 +850,7 @@ impl CStr { /// assert!(cstr.is_ok()); /// ``` /// - /// Creating a `CStr` without a trailing nul byte is an error: + /// Creating a `CStr` without a trailing nul terminator is an error: /// /// ``` /// use std::ffi::CStr; @@ -869,7 +953,7 @@ impl CStr { /// requires a linear amount of work to be done) and then return the /// resulting slice of `u8` elements. /// - /// The returned slice will **not** contain the trailing nul that this C + /// The returned slice will **not** contain the trailing nul terminator that this C /// string has. /// /// > **Note**: This method is currently implemented as a 0-cost cast, but @@ -894,7 +978,7 @@ impl CStr { /// Converts this C string to a byte slice containing the trailing 0 byte. /// /// This function is the equivalent of [`to_bytes`] except that it will retain - /// the trailing nul instead of chopping it off. + /// the trailing nul terminator instead of chopping it off. /// /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the From 2cb2a0606a47a3e2b7777ef099692c735d772b32 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Sun, 24 Sep 2017 20:12:51 -0500 Subject: [PATCH 003/365] Overhaul the ffi::CStr documentation. --- src/libstd/ffi/c_str.rs | 76 +++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index f0a691fd668..a10d0a4214b 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -128,17 +128,21 @@ pub struct CString { /// Representation of a borrowed C string. /// -/// This dynamically sized type is only safely constructed via a borrowed -/// version of an instance of `CString`. This type can be constructed from a raw -/// C string as well and represents a C string borrowed from another location. +/// This type represents a borrowed reference to a nul-terminated +/// array of bytes. It can be constructed safely from a `&[`[`u8`]`]` +/// slice, or unsafely from a raw `*const c_char`. It can then be +/// converted to a Rust [`&str`] by performing UTF-8 validation, or +/// into an owned [`CString`]. +/// +/// `CStr` is to [`CString`] as [`&str`] is to [`String`]: the former +/// in each pair are borrowed references; the latter are owned +/// strings. /// /// Note that this structure is **not** `repr(C)` and is not recommended to be -/// placed in the signatures of FFI functions. Instead safe wrappers of FFI +/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI /// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe /// interface to other consumers. /// -/// [`from_ptr`]: #method.from_ptr -/// /// # Examples /// /// Inspecting a foreign C string: @@ -151,7 +155,7 @@ pub struct CString { /// /// unsafe { /// let slice = CStr::from_ptr(my_string()); -/// println!("string length: {}", slice.to_bytes().len()); +/// println!("string buffer size without nul terminator: {}", slice.to_bytes().len()); /// } /// ``` /// @@ -173,8 +177,6 @@ pub struct CString { /// /// Converting a foreign C string into a Rust [`String`]: /// -/// [`String`]: ../string/struct.String.html -/// /// ```no_run /// use std::ffi::CStr; /// use std::os::raw::c_char; @@ -189,6 +191,12 @@ pub struct CString { /// /// println!("string: {}", my_string_safe()); /// ``` +/// +/// [`u8`]: ../primitive.u8.html +/// [`&str`]: ../primitive.str.html +/// [`String`]: ../string/struct.String.html +/// [`CString`]: struct.CString.html +/// [`from_ptr`]: #method.from_ptr #[derive(Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct CStr { @@ -215,8 +223,10 @@ pub struct CStr { #[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); -/// An error returned from [`CStr::from_bytes_with_nul`] to indicate that a nul -/// byte was found too early in the slice provided or one wasn't found at all. +/// An error returned from [`CStr::from_bytes_with_nul`] to indicate +/// that a nul byte was found too early in the slice provided, or one +/// wasn't found at all. The slice used to create a `CStr` must have one +/// and only one nul byte at the end of the slice. /// /// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul /// @@ -795,9 +805,9 @@ impl fmt::Display for IntoStringError { } impl CStr { - /// Casts a raw C string to a safe C string wrapper. + /// Wraps a raw C string with a safe C string wrapper. /// - /// This function will cast the provided `ptr` to the `CStr` wrapper which + /// This function will wrap the provided `ptr` with a `CStr` wrapper, which /// allows inspection and interoperation of non-owned C strings. This method /// is unsafe for a number of reasons: /// @@ -837,9 +847,9 @@ impl CStr { /// Creates a C string wrapper from a byte slice. /// - /// This function will cast the provided `bytes` to a `CStr` wrapper after - /// ensuring that it is null terminated and does not contain any interior - /// nul bytes. + /// This function will cast the provided `bytes` to a `CStr` + /// wrapper after ensuring that the byte slice is nul-terminated + /// and does not contain any interior nul bytes. /// /// # Examples /// @@ -884,7 +894,7 @@ impl CStr { /// Unsafely creates a C string wrapper from a byte slice. /// /// This function will cast the provided `bytes` to a `CStr` wrapper without - /// performing any sanity checks. The provided slice must be null terminated + /// performing any sanity checks. The provided slice **must** be nul-terminated /// and not contain any interior nul bytes. /// /// # Examples @@ -906,7 +916,7 @@ impl CStr { /// Returns the inner pointer to this C string. /// - /// The returned pointer will be valid for as long as `self` is and points + /// The returned pointer will be valid for as long as `self` is, and points /// to a contiguous region of memory terminated with a 0 byte to represent /// the end of the string. /// @@ -927,9 +937,9 @@ impl CStr { /// ``` /// /// This happens because the pointer returned by `as_ptr` does not carry any - /// lifetime information and the string is deallocated immediately after + /// lifetime information and the [`CString`] is deallocated immediately after /// the `CString::new("Hello").unwrap().as_ptr()` expression is evaluated. - /// To fix the problem, bind the string to a local variable: + /// To fix the problem, bind the `CString` to a local variable: /// /// ```no_run /// use std::ffi::{CString}; @@ -941,6 +951,11 @@ impl CStr { /// *ptr; /// } /// ``` + /// + /// This way, the lifetime of the `CString` in `hello` encompasses + /// the lifetime of `ptr` and the `unsafe` block. + /// + /// [`CString`]: struct.CString.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_ptr(&self) -> *const c_char { @@ -949,10 +964,6 @@ impl CStr { /// Converts this C string to a byte slice. /// - /// This function will calculate the length of this string (which normally - /// requires a linear amount of work to be done) and then return the - /// resulting slice of `u8` elements. - /// /// The returned slice will **not** contain the trailing nul terminator that this C /// string has. /// @@ -1002,8 +1013,9 @@ impl CStr { /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8. /// - /// This function will calculate the length of this string and check for - /// UTF-8 validity, and then return the [`&str`] if it's valid. + /// If the contents of the `CStr` are valid UTF-8 data, this + /// function will return the corresponding [`&str`] slice. Otherwise, + /// it will return an error with details of where UTF-8 validation failed. /// /// > **Note**: This method is currently implemented to check for validity /// > after a 0-cost cast, but it is planned to alter its definition in the @@ -1031,10 +1043,12 @@ impl CStr { /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`. /// - /// This function will calculate the length of this string (which normally - /// requires a linear amount of work to be done) and then return the - /// resulting slice as a [`Cow`]`<`[`str`]`>`, replacing any invalid UTF-8 sequences - /// with `U+FFFD REPLACEMENT CHARACTER`. + /// If the contents of the `CStr` are valid UTF-8 data, this + /// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)` + /// with the the corresponding [`&str`] slice. Otherwise, it will + /// replace any invalid UTF-8 sequences with `U+FFFD REPLACEMENT + /// CHARACTER` and return a [`Cow`]`::`[`Owned`]`(`[`String`]`)` + /// with the result. /// /// > **Note**: This method is currently implemented to check for validity /// > after a 0-cost cast, but it is planned to alter its definition in the @@ -1042,7 +1056,9 @@ impl CStr { /// > check whenever this method is called. /// /// [`Cow`]: ../borrow/enum.Cow.html + /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed /// [`str`]: ../primitive.str.html + /// [`String`]: ../string/struct.String.html /// /// # Examples /// From 3c5e18f322818f54cd9764031979f29b89a3e80d Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 25 Sep 2017 10:53:13 -0500 Subject: [PATCH 004/365] Point from the error structs back to the method that created them, like in iterators --- src/libstd/ffi/c_str.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index a10d0a4214b..01d2b70e423 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -208,8 +208,13 @@ pub struct CStr { } /// An error returned from [`CString::new`] to indicate that a nul byte was found -/// in the vector provided. +/// in the vector provided. While Rust strings may contain nul bytes in the middle, +/// C strings can't, as that byte would effectively truncate the string. /// +/// This `struct` is created by the [`new`][`CString::new`] method on +/// [`CString`]. See its documentation for more. +/// +/// [`CString`]: struct.CString.html /// [`CString::new`]: struct.CString.html#method.new /// /// # Examples @@ -225,9 +230,15 @@ pub struct NulError(usize, Vec); /// An error returned from [`CStr::from_bytes_with_nul`] to indicate /// that a nul byte was found too early in the slice provided, or one -/// wasn't found at all. The slice used to create a `CStr` must have one -/// and only one nul byte at the end of the slice. +/// wasn't found at all for the nul terminator. The slice used to +/// create a `CStr` must have one and only one nul byte at the end of +/// the slice. /// +/// This `struct` is created by the +/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on +/// [`CStr`]. See its documentation for more. +/// +/// [`CStr`]: struct.CStr.html /// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul /// /// # Examples @@ -262,9 +273,17 @@ impl FromBytesWithNulError { } } -/// An error returned from [`CString::into_string`] to indicate that a UTF-8 error -/// was encountered during the conversion. +/// An error returned from [`CString::into_string`] to indicate that a +/// UTF-8 error was encountered during the conversion. `CString` is +/// just a wrapper over a buffer of bytes with a nul terminator; +/// [`into_string`][`CString::into_string`] performs UTF-8 validation +/// and may return this error. /// +/// This `struct` is created by the +/// [`into_string`][`CString::into_string`] method on [`CString`]. See +/// its documentation for more. +/// +/// [`CString`]: struct.CString.html /// [`CString::into_string`]: struct.CString.html#method.into_string #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "cstring_into", since = "1.7.0")] From 155b4b1c5fff6a2a5a87de25e2fbe8c96743efb2 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 25 Sep 2017 12:51:11 -0500 Subject: [PATCH 005/365] Module overview for std::os::windows:ffi --- src/libstd/ffi/mod.rs | 2 +- src/libstd/sys/windows/ext/ffi.rs | 56 +++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 6c8ddfc3944..376e13e3b03 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -92,7 +92,7 @@ //! your code can detect errors in case the environment variable did //! not in fact contain valid Unicode data. //! -//! * [`OsStr`] represents a borrowed reference to a string in a format that +//! * [`OsStr`] represents a borrowed string slice in a format that //! can be passed to the operating system. It can be converted into //! an UTF-8 Rust string slice in a similar way to `OsString`. //! diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs index 3f6c2827a3f..d6b8896ac09 100644 --- a/src/libstd/sys/windows/ext/ffi.rs +++ b/src/libstd/sys/windows/ext/ffi.rs @@ -9,6 +9,62 @@ // except according to those terms. //! Windows-specific extensions to the primitives in the `std::ffi` module. +//! +//! # Overview +//! +//! For historical reasons, the Windows API uses a form of potentially +//! ill-formed UTF-16 encoding for strings. Specifically, the 16-bit +//! code units in Windows strings may contain [isolated surrogate code +//! points which are not paired together][ill-formed-utf-16]. The +//! Unicode standard requires that surrogate code points (those in the +//! range U+D800 to U+DFFF) always be *paired*, because in the UTF-16 +//! encoding a *surrogate code unit pair* is used to encode a single +//! character. For compatibility with code that does not enforce +//! these pairings, Windows does not enforce them, either. +//! +//! While it is not always possible to convert such a string losslessly into +//! a valid UTF-16 string (or even UTF-8), it is often desirable to be +//! able to round-trip such a string from and to Windows APIs +//! losslessly. For example, some Rust code may be "bridging" some +//! Windows APIs together, just passing `WCHAR` strings among those +//! APIs without ever really looking into the strings. +//! +//! If Rust code *does* need to look into those strings, it can +//! convert them to valid UTF-8, possibly lossily, by substituting +//! invalid sequences with U+FFFD REPLACEMENT CHARACTER, as is +//! conventionally done in other Rust APIs that deal with string +//! encodings. +//! +//! # `OsStringExt` and `OsStrExt` +//! +//! [`OsString`] is the Rust wrapper for owned strings in the +//! preferred representation of the operating system. On Windows, +//! this struct gets augmented with an implementation of the +//! [`OsStringExt`] trait, which has a [`from_wide`] method. This +//! lets you create an [`OsString`] from a `&[u16]` slice; presumably +//! you get such a slice out of a `WCHAR` Windows API. +//! +//! Similarly, [`OsStr`] is the Rust wrapper for borrowed strings from +//! preferred representation of the operating system. On Windows, the +//! [`OsStrExt`] trait provides the [`encode_wide`] method, which +//! outputs an [`EncodeWide`] iterator. You can [`collect`] this +//! iterator, for example, to obtain a `Vec`; you can later get a +//! pointer to this vector's contents and feed it to Windows APIs. +//! +//! These traits, along with [`OsString`] and [`OsStr`], work in +//! conjunction so that it is possible to **round-trip** strings from +//! Windows and back, with no loss of data, even if the strings are +//! ill-formed UTF-16. +//! +//! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16 +//! [`OsString`]: ../../../ffi/struct.OsString.html +//! [`OsStr`]: ../../../ffi/struct.OsStr.html +//! [`OsStringExt`]: trait.OsStringExt.html +//! [`OsStrExt`]: trait.OsStrExt.html +//! [`EncodeWide`]: struct.EncodeWide.html +//! [`from_wide`]: trait.OsStringExt.html#tymethod.from_wide +//! [`encode_wide`]: trait.OsStrExt.html#tymethod.encode_wide +//! [`collect`]: ../../../iter/trait.Iterator.html#method.collect #![stable(feature = "rust1", since = "1.0.0")] From 91f6445b5956aff72755b84854a19d2921009e1e Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 25 Sep 2017 13:51:28 -0500 Subject: [PATCH 006/365] Overhaul the documentation for OsString / OsStr --- src/libstd/ffi/mod.rs | 45 ++++++++++++++++++++++++++++++++--- src/libstd/ffi/os_str.rs | 51 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 376e13e3b03..1214a2406e2 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -92,13 +92,40 @@ //! your code can detect errors in case the environment variable did //! not in fact contain valid Unicode data. //! -//! * [`OsStr`] represents a borrowed string slice in a format that -//! can be passed to the operating system. It can be converted into -//! an UTF-8 Rust string slice in a similar way to `OsString`. +//! * [`OsStr`] represents a borrowed reference to a string in a +//! format that can be passed to the operating system. It can be +//! converted into an UTF-8 Rust string slice in a similar way to +//! `OsString`. +//! +//! # Conversions +//! +//! ## On Unix +//! +//! On Unix, [`OsStr`] implements the `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which +//! augments it with two methods, [`from_bytes`] and [`as_bytes`]. These do inexpensive conversions +//! from and to UTF-8 byte slices. +//! +//! Additionally, on Unix [`OsString`] implements the +//! `std::os::unix:ffi::`[`OsStringExt`][unix.OsStringExt] trait, +//! which provides [`from_vec`] and [`into_vec`] methods that consume +//! their arguments, and take or produce vectors of [`u8`]. +//! +//! ## On Windows +//! +//! On Windows, [`OsStr`] implements the `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] +//! trait, which provides an [`encode_wide`] method. This provides an iterator that can be +//! [`collect`]ed into a vector of [`u16`]. +//! +//! Additionally, on Windows [`OsString`] implements the +//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt] trait, which provides a +//! [`from_wide`] method. The result of this method is an `OsString` which can be round-tripped to +//! a Windows string losslessly. //! //! [`String`]: ../string/struct.String.html //! [`str`]: ../primitive.str.html //! [`char`]: ../primitive.char.html +//! [`u8`]: ../primitive.u8.html +//! [`u16`]: ../primitive.u16.html //! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value //! [Unicode code point]: http://www.unicode.org/glossary/#code_point //! [`CString`]: struct.CString.html @@ -108,6 +135,18 @@ //! [`env::set_var()`]: ../env/fn.set_var.html //! [`env::var_os()`]: ../env/fn.var_os.html //! [`Result<>`]: ../result/enum.Result.html +//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html +//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec +//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec +//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html +//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes +//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes +//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html +//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html +//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide +//! [`collect`]: ../iter/trait.Iterator.html#method.collect +//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html +//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index a40a9329ed9..72b0e68a9b6 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -33,18 +33,65 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust /// and platform-native string values, and in particular allowing a Rust string -/// to be converted into an "OS" string with no cost. +/// to be converted into an "OS" string with no cost if possible. +/// +/// `OsString` is to [`OsStr`] as [`String`] is to [`&str`]: the former +/// in each pair are owned strings; the latter are borrowed +/// references. +/// +/// # Creating an `OsString` +/// +/// **From a Rust string**: `OsString` implements +/// [`From`]`<`[`String`]`>`, so you can use `my_string.`[`from`] to +/// create an `OsString` from a normal Rust string. +/// +/// **From slices:** Just like you can start with an empty Rust +/// [`String`] and then [`push_str`][String.push_str] `&str` +/// sub-string slices into it, you can create an empty `OsString` with +/// the [`new`] method and then push string slices into it with the +/// [`push`] method. +/// +/// # Extracting a borrowed reference to the whole OS string +/// +/// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from +/// an `OsString`; this is effectively a borrowed reference to the +/// whole string. +/// +/// # Conversions +/// +/// See the [module's toplevel documentation about conversions][conversions] for a discussion on the traits which +/// `OsString` implements for conversions from/to native representations. /// /// [`OsStr`]: struct.OsStr.html +/// [`From`]: ../convert/trait.From.html +/// [`from`]: ../convert/trait.From.html#tymethod.from +/// [`String`]: ../string/struct.String.html +/// [`&str`]: ../primitive.str.html +/// [`u8`]: ../primitive.u8.html +/// [`u16`]: ../primitive.u16.html +/// [String.push_str]: ../string/struct.String.html#method.push_str +/// [`new`]: #struct.OsString.html#method.new +/// [`push`]: #struct.OsString.html#method.push +/// [`as_os_str`]: #struct.OsString.html#method.as_os_str #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct OsString { inner: Buf } -/// Slices into OS strings (see [`OsString`]). +/// Borrowed reference to an OS string (see [`OsString`]). +/// +/// This type represents a borrowed reference to a string in the operating system's preferred +/// representation. +/// +/// `OsStr` is to [`OsString`] as [`String`] is to [`&str`]: the former in each pair are borrowed +/// references; the latter are owned strings. +/// +/// See the [module's toplevel documentation about conversions][conversions] for a discussion on the traits which +/// `OsStr` implements for conversions from/to native representations. /// /// [`OsString`]: struct.OsString.html +/// [conversions]: index.html#conversions #[stable(feature = "rust1", since = "1.0.0")] pub struct OsStr { inner: Slice From 4143422981e5be3593d3248e99cd503442aae698 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Tue, 26 Sep 2017 08:56:44 -0500 Subject: [PATCH 007/365] os_str: Fix too-long lines --- src/libstd/ffi/os_str.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 72b0e68a9b6..b6032f7c74c 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -59,8 +59,8 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// /// # Conversions /// -/// See the [module's toplevel documentation about conversions][conversions] for a discussion on the traits which -/// `OsString` implements for conversions from/to native representations. +/// See the [module's toplevel documentation about conversions][conversions] for a discussion on +/// the traits which `OsString` implements for conversions from/to native representations. /// /// [`OsStr`]: struct.OsStr.html /// [`From`]: ../convert/trait.From.html @@ -87,8 +87,8 @@ pub struct OsString { /// `OsStr` is to [`OsString`] as [`String`] is to [`&str`]: the former in each pair are borrowed /// references; the latter are owned strings. /// -/// See the [module's toplevel documentation about conversions][conversions] for a discussion on the traits which -/// `OsStr` implements for conversions from/to native representations. +/// See the [module's toplevel documentation about conversions][conversions] for a discussion on +/// the traits which `OsStr` implements for conversions from/to native representations. /// /// [`OsString`]: struct.OsString.html /// [conversions]: index.html#conversions From edb2c2d291811f9b21ed8bd1499648a0614f6fc8 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Tue, 26 Sep 2017 21:16:59 -0400 Subject: [PATCH 008/365] Remove uses of mem::transmute in Box methods Makes use of conversions via Unique. --- src/liballoc/boxed.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 4341b0b2975..512c7194fe3 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -269,7 +269,7 @@ impl Box { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { - mem::transmute(raw) + Box(Unique::new_unchecked(raw)) } /// Consumes the `Box`, returning the wrapped raw pointer. @@ -295,7 +295,7 @@ impl Box { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Box) -> *mut T { - unsafe { mem::transmute(b) } + Box::into_unique(b).as_ptr() } /// Consumes the `Box`, returning the wrapped pointer as `Unique`. @@ -326,7 +326,9 @@ impl Box { issue = "27730")] #[inline] pub fn into_unique(b: Box) -> Unique { - unsafe { mem::transmute(b) } + let u = b.0; + mem::forget(b); + u } } From 8ef54478157adb980598104af0ce571cb6637931 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 25 Sep 2017 00:14:56 -0400 Subject: [PATCH 009/365] Migrate to eprint/eprintln macros where appropriate. --- src/bootstrap/bin/rustc.rs | 4 +--- src/librustc_driver/lib.rs | 2 +- src/librustdoc/externalfiles.rs | 9 ++------- src/librustdoc/markdown.rs | 14 +++----------- src/librustdoc/test.rs | 9 ++++----- src/libstd/process.rs | 4 +--- src/test/run-fail/mir_drop_panics.rs | 3 +-- src/test/run-fail/mir_dynamic_drops_1.rs | 5 ++--- src/test/run-fail/mir_dynamic_drops_2.rs | 5 ++--- src/test/run-fail/mir_dynamic_drops_3.rs | 5 ++--- .../run-fail/mir_trans_calls_converging_drops.rs | 6 ++---- .../run-fail/mir_trans_calls_converging_drops_2.rs | 6 ++---- .../run-fail/mir_trans_calls_diverging_drops.rs | 4 +--- src/test/run-fail/panic-set-handler.rs | 3 +-- src/test/run-fail/panic-set-unset-handler.rs | 3 +-- src/test/run-pass/backtrace-debuginfo.rs | 4 +--- src/tools/tidy/src/lib.rs | 5 ++--- src/tools/tidy/src/main.rs | 3 +-- 18 files changed, 30 insertions(+), 64 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 848b10d312c..54a3dbafe27 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -31,8 +31,6 @@ extern crate bootstrap; use std::env; use std::ffi::OsString; -use std::io; -use std::io::prelude::*; use std::str::FromStr; use std::path::PathBuf; use std::process::{Command, ExitStatus}; @@ -270,7 +268,7 @@ fn main() { } if verbose > 1 { - writeln!(&mut io::stderr(), "rustc command: {:?}", cmd).unwrap(); + eprintln!("rustc command: {:?}", cmd); } // Actually run the compiler! diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 044f4a5eaf5..29d15188500 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1307,7 +1307,7 @@ pub fn monitor(f: F) { errors::Level::Note); } - writeln!(io::stderr(), "{}", str::from_utf8(&data.lock().unwrap()).unwrap()).unwrap(); + eprintln!("{}", str::from_utf8(&data.lock().unwrap()).unwrap()); } exit_on_err(); diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 111ae4ede27..2f7bd5e39a1 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -10,7 +10,6 @@ use std::fs::File; use std::io::prelude::*; -use std::io; use std::path::Path; use std::str; use html::markdown::{Markdown, RenderType}; @@ -70,17 +69,13 @@ pub fn load_string>(file_path: P) -> Result Ok(s.to_string()), Err(_) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: not UTF-8", - file_path.display()); + eprintln!("error reading `{}`: not UTF-8", file_path.display()); Err(LoadStringError::BadUtf8) } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 57e8e88cd13..484285e91f6 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -11,7 +11,6 @@ use std::default::Default; use std::fs::File; use std::io::prelude::*; -use std::io; use std::path::{PathBuf, Path}; use getopts; @@ -75,9 +74,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, let mut out = match File::create(&output) { Err(e) => { - let _ = writeln!(&mut io::stderr(), - "rustdoc: {}: {}", - output.display(), e); + eprintln!("rustdoc: {}: {}", output.display(), e); return 4; } Ok(f) => f @@ -85,10 +82,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, let (metadata, text) = extract_leading_metadata(&input_str); if metadata.is_empty() { - let _ = writeln!( - &mut io::stderr(), - "rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`" - ); + eprintln!("rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`"); return 5; } let title = metadata[0]; @@ -138,9 +132,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, match err { Err(e) => { - let _ = writeln!(&mut io::stderr(), - "rustdoc: cannot write to `{}`: {}", - output.display(), e); + eprintln!("rustdoc: cannot write to `{}`: {}", output.display(), e); 6 } Ok(_) => 0 diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index f9cb4b84545..5f6ccb8a75e 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -479,11 +479,10 @@ impl Collector { found = entry.remove_item(&test).is_some(); } if !found { - let _ = writeln!(&mut io::stderr(), - "WARNING: {} Code block is not currently run as a test, but will \ - in future versions of rustdoc. Please ensure this code block is \ - a runnable test, or use the `ignore` directive.", - name); + eprintln!("WARNING: {} Code block is not currently run as a test, but will \ + in future versions of rustdoc. Please ensure this code block is \ + a runnable test, or use the `ignore` directive.", + name); return } } diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 1869ad3ed70..015f859b5cc 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1083,8 +1083,6 @@ impl Child { /// function and compute the exit code from its return value: /// /// ``` -/// use std::io::{self, Write}; -/// /// fn run_app() -> Result<(), ()> { /// // Application logic here /// Ok(()) @@ -1094,7 +1092,7 @@ impl Child { /// ::std::process::exit(match run_app() { /// Ok(_) => 0, /// Err(err) => { -/// writeln!(io::stderr(), "error: {:?}", err).unwrap(); +/// eprintln!("error: {:?}", err); /// 1 /// } /// }); diff --git a/src/test/run-fail/mir_drop_panics.rs b/src/test/run-fail/mir_drop_panics.rs index 98311525ad0..51191dd7087 100644 --- a/src/test/run-fail/mir_drop_panics.rs +++ b/src/test/run-fail/mir_drop_panics.rs @@ -10,7 +10,6 @@ // error-pattern:panic 1 // error-pattern:drop 2 -use std::io::{self, Write}; struct Droppable(u32); impl Drop for Droppable { @@ -18,7 +17,7 @@ impl Drop for Droppable { if self.0 == 1 { panic!("panic 1"); } else { - write!(io::stderr(), "drop {}", self.0); + eprint!("drop {}", self.0); } } } diff --git a/src/test/run-fail/mir_dynamic_drops_1.rs b/src/test/run-fail/mir_dynamic_drops_1.rs index 6cf2851d93d..69f934272b7 100644 --- a/src/test/run-fail/mir_dynamic_drops_1.rs +++ b/src/test/run-fail/mir_dynamic_drops_1.rs @@ -9,7 +9,6 @@ // except according to those terms. // error-pattern:drop 1 // error-pattern:drop 2 -use std::io::{self, Write}; /// Structure which will not allow to be dropped twice. @@ -17,10 +16,10 @@ struct Droppable<'a>(&'a mut bool, u32); impl<'a> Drop for Droppable<'a> { fn drop(&mut self) { if *self.0 { - writeln!(io::stderr(), "{} dropped twice", self.1); + eprintln!("{} dropped twice", self.1); ::std::process::exit(1); } - writeln!(io::stderr(), "drop {}", self.1); + eprintln!("drop {}", self.1); *self.0 = true; } } diff --git a/src/test/run-fail/mir_dynamic_drops_2.rs b/src/test/run-fail/mir_dynamic_drops_2.rs index 7a90298e422..d2fe50401ab 100644 --- a/src/test/run-fail/mir_dynamic_drops_2.rs +++ b/src/test/run-fail/mir_dynamic_drops_2.rs @@ -9,7 +9,6 @@ // except according to those terms. // error-pattern:drop 1 -use std::io::{self, Write}; /// Structure which will not allow to be dropped twice. @@ -17,10 +16,10 @@ struct Droppable<'a>(&'a mut bool, u32); impl<'a> Drop for Droppable<'a> { fn drop(&mut self) { if *self.0 { - writeln!(io::stderr(), "{} dropped twice", self.1); + eprintln!("{} dropped twice", self.1); ::std::process::exit(1); } - writeln!(io::stderr(), "drop {}", self.1); + eprintln!("drop {}", self.1); *self.0 = true; } } diff --git a/src/test/run-fail/mir_dynamic_drops_3.rs b/src/test/run-fail/mir_dynamic_drops_3.rs index 79ecbbb35bc..ecc35ee9b24 100644 --- a/src/test/run-fail/mir_dynamic_drops_3.rs +++ b/src/test/run-fail/mir_dynamic_drops_3.rs @@ -12,7 +12,6 @@ // error-pattern:drop 3 // error-pattern:drop 2 // error-pattern:drop 1 -use std::io::{self, Write}; /// Structure which will not allow to be dropped twice. @@ -20,10 +19,10 @@ struct Droppable<'a>(&'a mut bool, u32); impl<'a> Drop for Droppable<'a> { fn drop(&mut self) { if *self.0 { - writeln!(io::stderr(), "{} dropped twice", self.1); + eprintln!("{} dropped twice", self.1); ::std::process::exit(1); } - writeln!(io::stderr(), "drop {}", self.1); + eprintln!("drop {}", self.1); *self.0 = true; } } diff --git a/src/test/run-fail/mir_trans_calls_converging_drops.rs b/src/test/run-fail/mir_trans_calls_converging_drops.rs index 7a7526c5fc1..9c851eb7346 100644 --- a/src/test/run-fail/mir_trans_calls_converging_drops.rs +++ b/src/test/run-fail/mir_trans_calls_converging_drops.rs @@ -12,17 +12,15 @@ // error-pattern:0 dropped // error-pattern:exit -use std::io::{self, Write}; - struct Droppable(u8); impl Drop for Droppable { fn drop(&mut self) { - write!(io::stderr(), "{} dropped\n", self.0); + eprintln!("{} dropped", self.0); } } fn converging_fn() { - write!(io::stderr(), "converging_fn called\n"); + eprintln!("converging_fn called"); } fn mir(d: Droppable) { diff --git a/src/test/run-fail/mir_trans_calls_converging_drops_2.rs b/src/test/run-fail/mir_trans_calls_converging_drops_2.rs index 1301630cc85..6f105211556 100644 --- a/src/test/run-fail/mir_trans_calls_converging_drops_2.rs +++ b/src/test/run-fail/mir_trans_calls_converging_drops_2.rs @@ -12,18 +12,16 @@ // error-pattern:dropped // error-pattern:exit -use std::io::{self, Write}; - struct Droppable; impl Drop for Droppable { fn drop(&mut self) { - write!(io::stderr(), "dropped\n"); + eprintln!("dropped"); } } // return value of this function is copied into the return slot fn complex() -> u64 { - write!(io::stderr(), "complex called\n"); + eprintln!("complex called"); 42 } diff --git a/src/test/run-fail/mir_trans_calls_diverging_drops.rs b/src/test/run-fail/mir_trans_calls_diverging_drops.rs index c1918704929..f8fbe8f79cc 100644 --- a/src/test/run-fail/mir_trans_calls_diverging_drops.rs +++ b/src/test/run-fail/mir_trans_calls_diverging_drops.rs @@ -11,12 +11,10 @@ // error-pattern:diverging_fn called // error-pattern:0 dropped -use std::io::{self, Write}; - struct Droppable(u8); impl Drop for Droppable { fn drop(&mut self) { - write!(io::stderr(), "{} dropped", self.0); + eprintln!("{} dropped", self.0); } } diff --git a/src/test/run-fail/panic-set-handler.rs b/src/test/run-fail/panic-set-handler.rs index b589544ae15..68f1c4ed0bc 100644 --- a/src/test/run-fail/panic-set-handler.rs +++ b/src/test/run-fail/panic-set-handler.rs @@ -13,11 +13,10 @@ #![feature(panic_handler)] use std::panic; -use std::io::{self, Write}; fn main() { panic::set_hook(Box::new(|i| { - write!(io::stderr(), "greetings from the panic handler"); + eprint!("greetings from the panic handler"); })); panic!("foobar"); } diff --git a/src/test/run-fail/panic-set-unset-handler.rs b/src/test/run-fail/panic-set-unset-handler.rs index 6741c2d9c2c..072139a8c9b 100644 --- a/src/test/run-fail/panic-set-unset-handler.rs +++ b/src/test/run-fail/panic-set-unset-handler.rs @@ -13,11 +13,10 @@ #![feature(panic_handler)] use std::panic; -use std::io::{self, Write}; fn main() { panic::set_hook(Box::new(|i| { - write!(io::stderr(), "greetings from the panic handler"); + eprint!("greetings from the panic handler"); })); panic::take_hook(); panic!("foobar"); diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index f81352e1773..f9233026a1e 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -19,8 +19,6 @@ // ignore-pretty issue #37195 // ignore-emscripten spawning processes is not supported -use std::io; -use std::io::prelude::*; use std::env; #[path = "backtrace-debuginfo-aux.rs"] mod aux; @@ -163,7 +161,7 @@ fn main() { let args: Vec = env::args().collect(); if args.len() >= 2 { let case = args[1].parse().unwrap(); - writeln!(&mut io::stderr(), "test case {}", case).unwrap(); + eprintln!("test case {}", case); outer(case, pos!()); println!("done."); } else { diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 90bf7a5e0a6..c316ec46762 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -33,10 +33,9 @@ macro_rules! t { macro_rules! tidy_error { ($bad:expr, $fmt:expr, $($arg:tt)*) => ({ - use std::io::Write; *$bad = true; - write!(::std::io::stderr(), "tidy error: ").expect("could not write to stderr"); - writeln!(::std::io::stderr(), $fmt, $($arg)*).expect("could not write to stderr"); + eprint!("tidy error: "); + eprintln!($fmt, $($arg)*); }); } diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 433192a21ec..f6640c902bc 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -22,7 +22,6 @@ use tidy::*; use std::process; use std::path::PathBuf; use std::env; -use std::io::{self, Write}; fn main() { let path = env::args_os().skip(1).next().expect("need an argument"); @@ -44,7 +43,7 @@ fn main() { } if bad { - writeln!(io::stderr(), "some tidy checks failed").expect("could not write to stderr"); + eprintln!("some tidy checks failed"); process::exit(1); } } From 7f9e653a299209c17d0093934973fc121e972d29 Mon Sep 17 00:00:00 2001 From: leavehouse Date: Thu, 28 Sep 2017 20:09:31 -0500 Subject: [PATCH 010/365] Fix TcpStream::local_addr example code The local address's port is not 8080 in this example, that's the remote peer address port. On my machine, the local address is different every time, so I've changed `assert_eq` to only test the IP address --- src/libstd/net/tcp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index aff9af66444..2497f38f38c 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -198,8 +198,8 @@ impl TcpStream { /// /// let stream = TcpStream::connect("127.0.0.1:8080") /// .expect("Couldn't connect to the server..."); - /// assert_eq!(stream.local_addr().unwrap(), - /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080))); + /// assert_eq!(stream.local_addr().unwrap().ip(), + /// IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn local_addr(&self) -> io::Result { From 6482ee7cde565a432980036abe521e86bff432bd Mon Sep 17 00:00:00 2001 From: leavehouse Date: Thu, 28 Sep 2017 21:49:00 -0500 Subject: [PATCH 011/365] Fix imports in TcpStream::local_addr docs example Add a missing import and remove unused imports --- src/libstd/net/tcp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 2497f38f38c..cf3b354847c 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -194,7 +194,7 @@ impl TcpStream { /// # Examples /// /// ```no_run - /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpStream}; + /// use std::net::{IpAddr, Ipv4Addr, TcpStream}; /// /// let stream = TcpStream::connect("127.0.0.1:8080") /// .expect("Couldn't connect to the server..."); From 68341a91eecb830c57779cd2423733a7395258ab Mon Sep 17 00:00:00 2001 From: Joshua Lockerman Date: Fri, 29 Sep 2017 15:58:11 -0400 Subject: [PATCH 012/365] Improve performance of spsc_queue and stream. This commit makes two main changes. 1. It switches the spsc_queue node caching strategy from keeping a shared counter of the number of nodes in the cache to keeping a consumer only counter of the number of node eligible to be cached. 2. It separate the consumer and producers fields of spsc_queue and stream into a producer cache line and consumer cache line. --- src/libstd/lib.rs | 2 + src/libstd/sync/mpsc/cache_aligned.rs | 37 ++++++ src/libstd/sync/mpsc/mod.rs | 2 + src/libstd/sync/mpsc/spsc_queue.rs | 161 +++++++++++++++++--------- src/libstd/sync/mpsc/stream.rs | 103 +++++++++------- 5 files changed, 207 insertions(+), 98 deletions(-) create mode 100644 src/libstd/sync/mpsc/cache_aligned.rs diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9fc7e2c01aa..83cc9ce582e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -244,6 +244,7 @@ #![feature(allow_internal_unstable)] #![feature(align_offset)] #![feature(asm)] +#![feature(attr_literals)] #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] @@ -290,6 +291,7 @@ #![feature(prelude_import)] #![feature(rand)] #![feature(raw)] +#![feature(repr_align)] #![feature(repr_simd)] #![feature(rustc_attrs)] #![cfg_attr(not(stage0), feature(rustc_const_unstable))] diff --git a/src/libstd/sync/mpsc/cache_aligned.rs b/src/libstd/sync/mpsc/cache_aligned.rs new file mode 100644 index 00000000000..5af01262573 --- /dev/null +++ b/src/libstd/sync/mpsc/cache_aligned.rs @@ -0,0 +1,37 @@ +// Copyright 2017 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. + +use ops::{Deref, DerefMut}; + +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(align(64))] +pub(super) struct Aligner; + +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(super) struct CacheAligned(pub T, pub Aligner); + +impl Deref for CacheAligned { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for CacheAligned { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl CacheAligned { + pub(super) fn new(t: T) -> Self { + CacheAligned(t, Aligner) + } +} diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index dcd4c8dfdf5..0bfbcd2d2cd 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -297,6 +297,8 @@ mod sync; mod mpsc_queue; mod spsc_queue; +mod cache_aligned; + /// The receiving half of Rust's [`channel`][] (or [`sync_channel`]) type. /// This half can only be owned by one thread. /// diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index 1148bc66fba..3ce59270335 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -22,12 +22,15 @@ use core::cell::UnsafeCell; use sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; +use super::cache_aligned::CacheAligned; + // Node within the linked list queue of messages to send struct Node { // FIXME: this could be an uninitialized T if we're careful enough, and // that would reduce memory usage (and be a bit faster). // is it worth it? value: Option, // nullable for re-use of nodes + cached: bool, // This node goes into the node cache next: AtomicPtr>, // next node in the queue } @@ -35,37 +38,45 @@ struct Node { /// but it can be safely shared in an Arc if it is guaranteed that there /// is only one popper and one pusher touching the queue at any one point in /// time. -pub struct Queue { +pub struct Queue { // consumer fields - tail: UnsafeCell<*mut Node>, // where to pop from - tail_prev: AtomicPtr>, // where to pop from + consumer: CacheAligned>, // producer fields + producer: CacheAligned>, +} + +struct Consumer { + tail: UnsafeCell<*mut Node>, // where to pop from + tail_prev: AtomicPtr>, // where to pop from + cache_bound: usize, // maximum cache size + cached_nodes: AtomicUsize, // number of nodes marked as cachable + addition: Addition, +} + +struct Producer { head: UnsafeCell<*mut Node>, // where to push to first: UnsafeCell<*mut Node>, // where to get new nodes from tail_copy: UnsafeCell<*mut Node>, // between first/tail - - // Cache maintenance fields. Additions and subtractions are stored - // separately in order to allow them to use nonatomic addition/subtraction. - cache_bound: usize, - cache_additions: AtomicUsize, - cache_subtractions: AtomicUsize, + addition: Addition, } -unsafe impl Send for Queue { } +unsafe impl Send for Queue { } -unsafe impl Sync for Queue { } +unsafe impl Sync for Queue { } impl Node { fn new() -> *mut Node { Box::into_raw(box Node { value: None, + cached: false, next: AtomicPtr::new(ptr::null_mut::>()), }) } } impl Queue { + #[cfg(test)] /// Creates a new queue. /// /// This is unsafe as the type system doesn't enforce a single @@ -84,18 +95,60 @@ impl Queue { /// no bound. Otherwise, the cache will never grow larger than /// `bound` (although the queue itself could be much larger. pub unsafe fn new(bound: usize) -> Queue { + Self::with_additions(bound, (), ()) + } +} + +impl Queue { + + /// Creates a new queue. With given additional elements in the producer and + /// consumer portions of the queue. + /// + /// Due to the performance implications of cache-contention, + /// we wish to keep fields used mainly by the producer on a separate cache + /// line than those used by the consumer. + /// Since cache lines are usually 64 bytes, it is unreasonably expensive to + /// allocate one for small fields, so we allow users to insert additional + /// fields into the cache lines already allocated by this for the producer + /// and consumer. + /// + /// This is unsafe as the type system doesn't enforce a single + /// consumer-producer relationship. It also allows the consumer to `pop` + /// items while there is a `peek` active due to all methods having a + /// non-mutable receiver. + /// + /// # Arguments + /// + /// * `bound` - This queue implementation is implemented with a linked + /// list, and this means that a push is always a malloc. In + /// order to amortize this cost, an internal cache of nodes is + /// maintained to prevent a malloc from always being + /// necessary. This bound is the limit on the size of the + /// cache (if desired). If the value is 0, then the cache has + /// no bound. Otherwise, the cache will never grow larger than + /// `bound` (although the queue itself could be much larger. + pub unsafe fn with_additions( + bound: usize, + producer_addition: ProducerAddition, + consumer_addition: ConsumerAddition, + ) -> Self { let n1 = Node::new(); let n2 = Node::new(); (*n1).next.store(n2, Ordering::Relaxed); Queue { - tail: UnsafeCell::new(n2), - tail_prev: AtomicPtr::new(n1), - head: UnsafeCell::new(n2), - first: UnsafeCell::new(n1), - tail_copy: UnsafeCell::new(n1), - cache_bound: bound, - cache_additions: AtomicUsize::new(0), - cache_subtractions: AtomicUsize::new(0), + consumer: CacheAligned::new(Consumer { + tail: UnsafeCell::new(n2), + tail_prev: AtomicPtr::new(n1), + cache_bound: bound, + cached_nodes: AtomicUsize::new(0), + addition: consumer_addition + }), + producer: CacheAligned::new(Producer { + head: UnsafeCell::new(n2), + first: UnsafeCell::new(n1), + tail_copy: UnsafeCell::new(n1), + addition: producer_addition + }), } } @@ -109,35 +162,25 @@ impl Queue { assert!((*n).value.is_none()); (*n).value = Some(t); (*n).next.store(ptr::null_mut(), Ordering::Relaxed); - (**self.head.get()).next.store(n, Ordering::Release); - *self.head.get() = n; + (**self.producer.head.get()).next.store(n, Ordering::Release); + *(&self.producer.head).get() = n; } } unsafe fn alloc(&self) -> *mut Node { // First try to see if we can consume the 'first' node for our uses. - // We try to avoid as many atomic instructions as possible here, so - // the addition to cache_subtractions is not atomic (plus we're the - // only one subtracting from the cache). - if *self.first.get() != *self.tail_copy.get() { - if self.cache_bound > 0 { - let b = self.cache_subtractions.load(Ordering::Relaxed); - self.cache_subtractions.store(b + 1, Ordering::Relaxed); - } - let ret = *self.first.get(); - *self.first.get() = (*ret).next.load(Ordering::Relaxed); + if *self.producer.first.get() != *self.producer.tail_copy.get() { + let ret = *self.producer.first.get(); + *self.producer.0.first.get() = (*ret).next.load(Ordering::Relaxed); return ret; } // If the above fails, then update our copy of the tail and try // again. - *self.tail_copy.get() = self.tail_prev.load(Ordering::Acquire); - if *self.first.get() != *self.tail_copy.get() { - if self.cache_bound > 0 { - let b = self.cache_subtractions.load(Ordering::Relaxed); - self.cache_subtractions.store(b + 1, Ordering::Relaxed); - } - let ret = *self.first.get(); - *self.first.get() = (*ret).next.load(Ordering::Relaxed); + *self.producer.0.tail_copy.get() = + self.consumer.tail_prev.load(Ordering::Acquire); + if *self.producer.first.get() != *self.producer.tail_copy.get() { + let ret = *self.producer.first.get(); + *self.producer.0.first.get() = (*ret).next.load(Ordering::Relaxed); return ret; } // If all of that fails, then we have to allocate a new node @@ -153,27 +196,27 @@ impl Queue { // sentinel from where we should start popping from. Hence, look at // tail's next field and see if we can use it. If we do a pop, then // the current tail node is a candidate for going into the cache. - let tail = *self.tail.get(); + let tail = *self.consumer.tail.get(); let next = (*tail).next.load(Ordering::Acquire); if next.is_null() { return None } assert!((*next).value.is_some()); let ret = (*next).value.take(); - *self.tail.get() = next; - if self.cache_bound == 0 { - self.tail_prev.store(tail, Ordering::Release); + *self.consumer.0.tail.get() = next; + if self.consumer.cache_bound == 0 { + self.consumer.tail_prev.store(tail, Ordering::Release); } else { - // FIXME: this is dubious with overflow. - let additions = self.cache_additions.load(Ordering::Relaxed); - let subtractions = self.cache_subtractions.load(Ordering::Relaxed); - let size = additions - subtractions; + let cached_nodes = self.consumer.cached_nodes.load(Ordering::Relaxed); + if cached_nodes < self.consumer.cache_bound && !(*tail).cached { + self.consumer.cached_nodes.store(cached_nodes, Ordering::Relaxed); + (*tail).cached = true; + } - if size < self.cache_bound { - self.tail_prev.store(tail, Ordering::Release); - self.cache_additions.store(additions + 1, Ordering::Relaxed); + if (*tail).cached { + self.consumer.tail_prev.store(tail, Ordering::Release); } else { - (*self.tail_prev.load(Ordering::Relaxed)) - .next.store(next, Ordering::Relaxed); + (*self.consumer.tail_prev.load(Ordering::Relaxed)) + .next.store(next, Ordering::Relaxed); // We have successfully erased all references to 'tail', so // now we can safely drop it. let _: Box> = Box::from_raw(tail); @@ -194,17 +237,25 @@ impl Queue { // This is essentially the same as above with all the popping bits // stripped out. unsafe { - let tail = *self.tail.get(); + let tail = *self.consumer.tail.get(); let next = (*tail).next.load(Ordering::Acquire); if next.is_null() { None } else { (*next).value.as_mut() } } } + + pub fn producer_addition(&self) -> &ProducerAddition { + &self.producer.addition + } + + pub fn consumer_addition(&self) -> &ConsumerAddition { + &self.consumer.addition + } } -impl Drop for Queue { +impl Drop for Queue { fn drop(&mut self) { unsafe { - let mut cur = *self.first.get(); + let mut cur = *self.producer.first.get(); while !cur.is_null() { let next = (*cur).next.load(Ordering::Relaxed); let _n: Box> = Box::from_raw(cur); diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs index 47cd8977fda..d1515eba68c 100644 --- a/src/libstd/sync/mpsc/stream.rs +++ b/src/libstd/sync/mpsc/stream.rs @@ -41,15 +41,22 @@ const MAX_STEALS: isize = 5; const MAX_STEALS: isize = 1 << 20; pub struct Packet { - queue: spsc::Queue>, // internal queue for all message + // internal queue for all messages + queue: spsc::Queue, ProducerAddition, ConsumerAddition>, +} +struct ProducerAddition { cnt: AtomicIsize, // How many items are on this channel - steals: UnsafeCell, // How many times has a port received without blocking? to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up port_dropped: AtomicBool, // flag if the channel has been destroyed. } +struct ConsumerAddition { + steals: UnsafeCell, // How many times has a port received without blocking? +} + + pub enum Failure { Empty, Disconnected, @@ -78,13 +85,18 @@ enum Message { impl Packet { pub fn new() -> Packet { Packet { - queue: unsafe { spsc::Queue::new(128) }, + queue: unsafe { spsc::Queue::with_additions( + 128, + ProducerAddition { + cnt: AtomicIsize::new(0), + to_wake: AtomicUsize::new(0), - cnt: AtomicIsize::new(0), - steals: UnsafeCell::new(0), - to_wake: AtomicUsize::new(0), - - port_dropped: AtomicBool::new(false), + port_dropped: AtomicBool::new(false), + }, + ConsumerAddition { + steals: UnsafeCell::new(0), + } + )}, } } @@ -92,7 +104,7 @@ impl Packet { // If the other port has deterministically gone away, then definitely // must return the data back up the stack. Otherwise, the data is // considered as being sent. - if self.port_dropped.load(Ordering::SeqCst) { return Err(t) } + if self.queue.producer_addition().port_dropped.load(Ordering::SeqCst) { return Err(t) } match self.do_send(Data(t)) { UpSuccess | UpDisconnected => {}, @@ -104,14 +116,16 @@ impl Packet { pub fn upgrade(&self, up: Receiver) -> UpgradeResult { // If the port has gone away, then there's no need to proceed any // further. - if self.port_dropped.load(Ordering::SeqCst) { return UpDisconnected } + if self.queue.producer_addition().port_dropped.load(Ordering::SeqCst) { + return UpDisconnected + } self.do_send(GoUp(up)) } fn do_send(&self, t: Message) -> UpgradeResult { self.queue.push(t); - match self.cnt.fetch_add(1, Ordering::SeqCst) { + match self.queue.producer_addition().cnt.fetch_add(1, Ordering::SeqCst) { // As described in the mod's doc comment, -1 == wakeup -1 => UpWoke(self.take_to_wake()), // As as described before, SPSC queues must be >= -2 @@ -125,7 +139,7 @@ impl Packet { // will never remove this data. We can only have at most one item to // drain (the port drains the rest). DISCONNECTED => { - self.cnt.store(DISCONNECTED, Ordering::SeqCst); + self.queue.producer_addition().cnt.store(DISCONNECTED, Ordering::SeqCst); let first = self.queue.pop(); let second = self.queue.pop(); assert!(second.is_none()); @@ -144,8 +158,8 @@ impl Packet { // Consumes ownership of the 'to_wake' field. fn take_to_wake(&self) -> SignalToken { - let ptr = self.to_wake.load(Ordering::SeqCst); - self.to_wake.store(0, Ordering::SeqCst); + let ptr = self.queue.producer_addition().to_wake.load(Ordering::SeqCst); + self.queue.producer_addition().to_wake.store(0, Ordering::SeqCst); assert!(ptr != 0); unsafe { SignalToken::cast_from_usize(ptr) } } @@ -154,14 +168,16 @@ impl Packet { // back if it shouldn't sleep. Note that this is the location where we take // steals into account. fn decrement(&self, token: SignalToken) -> Result<(), SignalToken> { - assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); + assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); let ptr = unsafe { token.cast_to_usize() }; - self.to_wake.store(ptr, Ordering::SeqCst); + self.queue.producer_addition().to_wake.store(ptr, Ordering::SeqCst); - let steals = unsafe { ptr::replace(self.steals.get(), 0) }; + let steals = unsafe { ptr::replace(self.queue.consumer_addition().steals.get(), 0) }; - match self.cnt.fetch_sub(1 + steals, Ordering::SeqCst) { - DISCONNECTED => { self.cnt.store(DISCONNECTED, Ordering::SeqCst); } + match self.queue.producer_addition().cnt.fetch_sub(1 + steals, Ordering::SeqCst) { + DISCONNECTED => { + self.queue.producer_addition().cnt.store(DISCONNECTED, Ordering::SeqCst); + } // If we factor in our steals and notice that the channel has no // data, we successfully sleep n => { @@ -170,7 +186,7 @@ impl Packet { } } - self.to_wake.store(0, Ordering::SeqCst); + self.queue.producer_addition().to_wake.store(0, Ordering::SeqCst); Err(unsafe { SignalToken::cast_from_usize(ptr) }) } @@ -201,7 +217,7 @@ impl Packet { // "steal" factored into the channel count above). data @ Ok(..) | data @ Err(Upgraded(..)) => unsafe { - *self.steals.get() -= 1; + *self.queue.consumer_addition().steals.get() -= 1; data }, @@ -223,20 +239,21 @@ impl Packet { // down as much as possible (without going negative), and then // adding back in whatever we couldn't factor into steals. Some(data) => unsafe { - if *self.steals.get() > MAX_STEALS { - match self.cnt.swap(0, Ordering::SeqCst) { + if *self.queue.consumer_addition().steals.get() > MAX_STEALS { + match self.queue.producer_addition().cnt.swap(0, Ordering::SeqCst) { DISCONNECTED => { - self.cnt.store(DISCONNECTED, Ordering::SeqCst); + self.queue.producer_addition().cnt.store( + DISCONNECTED, Ordering::SeqCst); } n => { - let m = cmp::min(n, *self.steals.get()); - *self.steals.get() -= m; + let m = cmp::min(n, *self.queue.consumer_addition().steals.get()); + *self.queue.consumer_addition().steals.get() -= m; self.bump(n - m); } } - assert!(*self.steals.get() >= 0); + assert!(*self.queue.consumer_addition().steals.get() >= 0); } - *self.steals.get() += 1; + *self.queue.consumer_addition().steals.get() += 1; match data { Data(t) => Ok(t), GoUp(up) => Err(Upgraded(up)), @@ -244,7 +261,7 @@ impl Packet { }, None => { - match self.cnt.load(Ordering::SeqCst) { + match self.queue.producer_addition().cnt.load(Ordering::SeqCst) { n if n != DISCONNECTED => Err(Empty), // This is a little bit of a tricky case. We failed to pop @@ -273,7 +290,7 @@ impl Packet { pub fn drop_chan(&self) { // Dropping a channel is pretty simple, we just flag it as disconnected // and then wakeup a blocker if there is one. - match self.cnt.swap(DISCONNECTED, Ordering::SeqCst) { + match self.queue.producer_addition().cnt.swap(DISCONNECTED, Ordering::SeqCst) { -1 => { self.take_to_wake().signal(); } DISCONNECTED => {} n => { assert!(n >= 0); } @@ -300,7 +317,7 @@ impl Packet { // sends are gated on this flag, so we're immediately guaranteed that // there are a bounded number of active sends that we'll have to deal // with. - self.port_dropped.store(true, Ordering::SeqCst); + self.queue.producer_addition().port_dropped.store(true, Ordering::SeqCst); // Now that we're guaranteed to deal with a bounded number of senders, // we need to drain the queue. This draining process happens atomically @@ -310,9 +327,9 @@ impl Packet { // continue to fail while active senders send data while we're dropping // data, but eventually we're guaranteed to break out of this loop // (because there is a bounded number of senders). - let mut steals = unsafe { *self.steals.get() }; + let mut steals = unsafe { *self.queue.consumer_addition().steals.get() }; while { - let cnt = self.cnt.compare_and_swap( + let cnt = self.queue.producer_addition().cnt.compare_and_swap( steals, DISCONNECTED, Ordering::SeqCst); cnt != DISCONNECTED && cnt != steals } { @@ -353,9 +370,9 @@ impl Packet { // increment the count on the channel (used for selection) fn bump(&self, amt: isize) -> isize { - match self.cnt.fetch_add(amt, Ordering::SeqCst) { + match self.queue.producer_addition().cnt.fetch_add(amt, Ordering::SeqCst) { DISCONNECTED => { - self.cnt.store(DISCONNECTED, Ordering::SeqCst); + self.queue.producer_addition().cnt.store(DISCONNECTED, Ordering::SeqCst); DISCONNECTED } n => n @@ -404,8 +421,8 @@ impl Packet { // this end. This is fine because we know it's a small bounded windows // of time until the data is actually sent. if was_upgrade { - assert_eq!(unsafe { *self.steals.get() }, 0); - assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); + assert_eq!(unsafe { *self.queue.consumer_addition().steals.get() }, 0); + assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); return Ok(true) } @@ -418,7 +435,7 @@ impl Packet { // If we were previously disconnected, then we know for sure that there // is no thread in to_wake, so just keep going let has_data = if prev == DISCONNECTED { - assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); + assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); true // there is data, that data is that we're disconnected } else { let cur = prev + steals + 1; @@ -441,13 +458,13 @@ impl Packet { if prev < 0 { drop(self.take_to_wake()); } else { - while self.to_wake.load(Ordering::SeqCst) != 0 { + while self.queue.producer_addition().to_wake.load(Ordering::SeqCst) != 0 { thread::yield_now(); } } unsafe { - assert_eq!(*self.steals.get(), 0); - *self.steals.get() = steals; + assert_eq!(*self.queue.consumer_addition().steals.get(), 0); + *self.queue.consumer_addition().steals.get() = steals; } // if we were previously positive, then there's surely data to @@ -481,7 +498,7 @@ impl Drop for Packet { // disconnection, but also a proper fence before the read of // `to_wake`, so this assert cannot be removed with also removing // the `to_wake` assert. - assert_eq!(self.cnt.load(Ordering::SeqCst), DISCONNECTED); - assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); + assert_eq!(self.queue.producer_addition().cnt.load(Ordering::SeqCst), DISCONNECTED); + assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); } } From 23f5fbee45273879d185ab18b64ac2cd8c708fec Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Sun, 1 Oct 2017 21:25:48 -0500 Subject: [PATCH 013/365] document trait impls when the type appears in the trait's generics --- src/librustdoc/clean/mod.rs | 15 +++++++++++++++ src/librustdoc/html/render.rs | 27 +++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c9afa3646b2..6da0d8a8a98 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1681,6 +1681,21 @@ impl Type { _ => false } } + + pub fn generics(&self) -> Option<&[Type]> { + match *self { + ResolvedPath { ref path, .. } => { + path.segments.last().and_then(|seg| { + if let PathParameters::AngleBracketed { ref types, .. } = seg.params { + Some(&**types) + } else { + None + } + }) + } + _ => None, + } + } } impl GetDefId for Type { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 485e75443fe..56f56994f78 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1306,7 +1306,8 @@ impl DocFolder for Cache { // Figure out the id of this impl. This may map to a // primitive rather than always to a struct/enum. // Note: matching twice to restrict the lifetime of the `i` borrow. - let did = if let clean::Item { inner: clean::ImplItem(ref i), .. } = item { + let mut dids = vec![]; + if let clean::Item { inner: clean::ImplItem(ref i), .. } = item { let masked_trait = i.trait_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)); if !masked_trait { @@ -1315,23 +1316,33 @@ impl DocFolder for Cache { clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => { - Some(did) + dids.push(did); } ref t => { - t.primitive_type().and_then(|t| { + let did = t.primitive_type().and_then(|t| { self.primitive_locations.get(&t).cloned() - }) + }); + + if let Some(did) = did { + dids.push(did); + } + } + } + } + + if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { + for bound in generics { + if let Some(did) = bound.def_id() { + dids.push(did); } } - } else { - None } } else { unreachable!() }; - if let Some(did) = did { + for did in dids { self.impls.entry(did).or_insert(vec![]).push(Impl { - impl_item: item, + impl_item: item.clone(), }); } None From 1e26094bdd18c704e1c060e2cf7d2b9bfec037ed Mon Sep 17 00:00:00 2001 From: James Munns Date: Mon, 2 Oct 2017 15:42:08 +0200 Subject: [PATCH 014/365] Allow atomic operations up to 32 bits The ARMv5te platform does not have instruction-level support for atomics, however the kernel provides [user space helpers](https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt) which can be used to perform atomic operations. When linked with `libc`, the atomic symbols needed by Rust will be provided, rather than CPU level intrinsics. As this target is specifically `linux` and `gnueabi`, it is reasonable to assume the Linux Kernel and libc will be available for the target. There is a large performance penalty, as we are not using CPU level intrinsics, however this penalty is likely preferable to not having the target at all. I have used this change in a custom target (along with `xargo`) to build `std`, as well as a number of higher level crates. --- src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs b/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs index b9573721678..97397ca4962 100644 --- a/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs +++ b/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs @@ -27,8 +27,12 @@ pub fn target() -> TargetResult { options: TargetOptions { features: "+soft-float,+strict-align".to_string(), - // No atomic instructions on ARMv5 - max_atomic_width: Some(0), + + // Atomic operations provided when linked with libgcc. + // FIXME: If the following PR is merged, the atomic operations would be + // provided by compiler-builtins instead with no change of behavior: + // https://github.com/rust-lang-nursery/compiler-builtins/pull/115/files + max_atomic_width: Some(32), abi_blacklist: super::arm_base::abi_blacklist(), .. base } From 9854e836a35c3114c81b8102d3468ff9071b4141 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 2 Oct 2017 13:53:50 -0500 Subject: [PATCH 015/365] Remove the implication that CString contains UTF-8 data. --- src/libstd/ffi/c_str.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 01d2b70e423..0d0280e2586 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -23,10 +23,11 @@ use ptr; use slice; use str::{self, Utf8Error}; -/// A type representing an owned, C-compatible, UTF-8 string. +/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the +/// middle. /// /// This type serves the purpose of being able to safely generate a -/// C-compatible UTF-8 string from a Rust byte slice or vector. An instance of this +/// C-compatible string from a Rust byte slice or vector. An instance of this /// type is a static guarantee that the underlying bytes contain no interior 0 /// bytes ("nul characters") and that the final byte is 0 ("nul terminator"). /// @@ -443,7 +444,7 @@ impl CString { Box::into_raw(self.into_inner()) as *mut c_char } - /// Converts the `CString` into a [`String`] if it contains valid Unicode data. + /// Converts the `CString` into a [`String`] if it contains valid UTF-8 data. /// /// On failure, ownership of the original `CString` is returned. /// From 50505aadbd9314375a56bf397a4a97f0102180ce Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 2 Oct 2017 14:16:37 -0500 Subject: [PATCH 016/365] Clarify the ffi module's toplevel docs, per @clarcharr's comments --- src/libstd/ffi/mod.rs | 117 +++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 53 deletions(-) diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 1214a2406e2..f8a4a904fc5 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! This module provides utilities to handle C-like strings. It is -//! mainly of use for FFI (Foreign Function Interface) bindings and -//! code that needs to exchange C-like strings with other languages. +//! This module provides utilities to handle data across non-Rust +//! interfaces, like other programming languages and the underlying +//! operating system. It is mainly of use for FFI (Foreign Function +//! Interface) bindings and code that needs to exchange C-like strings +//! with other languages. //! //! # Overview //! @@ -18,68 +20,74 @@ //! borrowed slices of strings with the [`str`] primitive. Both are //! always in UTF-8 encoding, and may contain nul bytes in the middle, //! i.e. if you look at the bytes that make up the string, there may -//! be a `0` among them. Both `String` and `str` know their length; -//! there are no nul terminators at the end of strings like in C. +//! be a `\0` among them. Both `String` and `str` store their length +//! explicitly; there are no nul terminators at the end of strings +//! like in C. //! //! C strings are different from Rust strings: //! -//! * **Encodings** - C strings may have different encodings. If -//! you are bringing in strings from C APIs, you should check what -//! encoding you are getting. Rust strings are always UTF-8. +//! * **Encodings** - Rust strings are UTF-8, but C strings may use +//! other encodings. If you are using a string from C, you should +//! check its encoding explicitly, rather than just assuming that it +//! is UTF-8 like you can do in Rust. //! -//! * **Character width** - C strings may use "normal" or "wide" -//! characters, i.e. `char` or `wchar_t`, respectively. The C -//! standard leaves the actual sizes of those types open to +//! * **Character size** - C strings may use `char` or `wchar_t`-sized +//! characters; please **note** that C's `char` is different from Rust's. +//! The C standard leaves the actual sizes of those types open to //! interpretation, but defines different APIs for strings made up of //! each character type. Rust strings are always UTF-8, so different //! Unicode characters will be encoded in a variable number of bytes -//! each. The Rust type [`char`] represents a '[Unicode -//! scalar value]', which is similar to, but not the same as, a -//! '[Unicode code point]'. +//! each. The Rust type [`char`] represents a '[Unicode scalar +//! value]', which is similar to, but not the same as, a '[Unicode +//! code point]'. //! //! * **Nul terminators and implicit string lengths** - Often, C -//! strings are nul-terminated, i.e. they have a `0` character at the -//! end. The length of a string buffer is not known *a priori*; -//! instead, to compute the length of a string, C code must manually -//! call a function like `strlen()` for `char`-based strings, or -//! `wcslen()` for `wchar_t`-based ones. Those functions return the -//! number of characters in the string excluding the nul terminator, -//! so the buffer length is really `len+1` characters. Rust strings -//! don't have a nul terminator, and they always know their length. +//! strings are nul-terminated, i.e. they have a `\0` character at the +//! end. The length of a string buffer is not stored, but has to be +//! calculated; to compute the length of a string, C code must +//! manually call a function like `strlen()` for `char`-based strings, +//! or `wcslen()` for `wchar_t`-based ones. Those functions return +//! the number of characters in the string excluding the nul +//! terminator, so the buffer length is really `len+1` characters. +//! Rust strings don't have a nul terminator; their length is always +//! stored and does not need to be calculated. While in Rust +//! accessing a string's length is a O(1) operation (becasue the +//! length is stored); in C it is an O(length) operation because the +//! length needs to be computed by scanning the string for the nul +//! terminator. //! -//! * **No nul characters in the middle of the string** - When C -//! strings have a nul terminator character, this usually means that -//! they cannot have nul characters in the middle — a nul character -//! would essentially truncate the string. Rust strings *can* have -//! nul characters in the middle, since they don't use nul -//! terminators. +//! * **Internal nul characters** - When C strings have a nul +//! terminator character, this usually means that they cannot have nul +//! characters in the middle — a nul character would essentially +//! truncate the string. Rust strings *can* have nul characters in +//! the middle, because nul does not have to mark the end of the +//! string in Rust. //! //! # Representations of non-Rust strings //! //! [`CString`] and [`CStr`] are useful when you need to transfer -//! UTF-8 strings to and from C, respectively: +//! UTF-8 strings to and from languages with a C ABI, like Python. //! //! * **From Rust to C:** [`CString`] represents an owned, C-friendly -//! UTF-8 string: it is valid UTF-8, it is nul-terminated, and has no -//! nul characters in the middle. Rust code can create a `CString` -//! out of a normal string (provided that the string doesn't have nul -//! characters in the middle), and then use a variety of methods to -//! obtain a raw `*mut u8` that can then be passed as an argument to C -//! functions. +//! string: it is nul-terminated, and has no internal nul characters. +//! Rust code can create a `CString` out of a normal string (provided +//! that the string doesn't have nul characters in the middle), and +//! then use a variety of methods to obtain a raw `*mut u8` that can +//! then be passed as an argument to functions which use the C +//! conventions for strings. //! //! * **From C to Rust:** [`CStr`] represents a borrowed C string; it //! is what you would use to wrap a raw `*const u8` that you got from -//! a C function. A `CStr` is just guaranteed to be a nul-terminated -//! array of bytes; the UTF-8 validation step only happens when you -//! request to convert it to a `&str`. +//! a C function. A `CStr` is guaranteed to be a nul-terminated array +//! of bytes. Once you have a `CStr`, you can convert it to a Rust +//! `&str` if it's valid UTF-8, or lossily convert it by adding +//! replacement characters. //! //! [`OsString`] and [`OsStr`] are useful when you need to transfer -//! strings to and from operating system calls. If you need Rust -//! strings out of them, they can take care of conversion to and from -//! the operating system's preferred form for strings — of course, it -//! may not be possible to convert all valid operating system strings -//! into valid UTF-8; the `OsString` and `OsStr` functions let you know -//! when this is the case. +//! strings to and from the operating system itself, or when capturing +//! the output of external commands. Conversions between `OsString`, +//! `OsStr` and Rust strings work similarly to those for [`CString`] +//! and [`CStr`]. //! //! * [`OsString`] represents an owned string in whatever //! representation the operating system prefers. In the Rust standard @@ -101,9 +109,10 @@ //! //! ## On Unix //! -//! On Unix, [`OsStr`] implements the `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which -//! augments it with two methods, [`from_bytes`] and [`as_bytes`]. These do inexpensive conversions -//! from and to UTF-8 byte slices. +//! On Unix, [`OsStr`] implements the +//! `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which +//! augments it with two methods, [`from_bytes`] and [`as_bytes`]. +//! These do inexpensive conversions from and to UTF-8 byte slices. //! //! Additionally, on Unix [`OsString`] implements the //! `std::os::unix:ffi::`[`OsStringExt`][unix.OsStringExt] trait, @@ -112,14 +121,16 @@ //! //! ## On Windows //! -//! On Windows, [`OsStr`] implements the `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] -//! trait, which provides an [`encode_wide`] method. This provides an iterator that can be -//! [`collect`]ed into a vector of [`u16`]. +//! On Windows, [`OsStr`] implements the +//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait, +//! which provides an [`encode_wide`] method. This provides an +//! iterator that can be [`collect`]ed into a vector of [`u16`]. //! //! Additionally, on Windows [`OsString`] implements the -//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt] trait, which provides a -//! [`from_wide`] method. The result of this method is an `OsString` which can be round-tripped to -//! a Windows string losslessly. +//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt] +//! trait, which provides a [`from_wide`] method. The result of this +//! method is an `OsString` which can be round-tripped to a Windows +//! string losslessly. //! //! [`String`]: ../string/struct.String.html //! [`str`]: ../primitive.str.html From d989cd02b56524470cc8721f296add7039821777 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 2 Oct 2017 15:46:10 -0500 Subject: [PATCH 017/365] Fix broken links in documentation --- src/libstd/ffi/os_str.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index b6032f7c74c..94b6911283b 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -70,9 +70,9 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// [`u8`]: ../primitive.u8.html /// [`u16`]: ../primitive.u16.html /// [String.push_str]: ../string/struct.String.html#method.push_str -/// [`new`]: #struct.OsString.html#method.new -/// [`push`]: #struct.OsString.html#method.push -/// [`as_os_str`]: #struct.OsString.html#method.as_os_str +/// [`new`]: #method.new +/// [`push`]: #method.push +/// [`as_os_str`]: #method.as_os_str #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct OsString { From bb74c20a5d2594cab6d9416c2ed2cc8bd45fc956 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Mon, 2 Oct 2017 22:04:23 -0300 Subject: [PATCH 018/365] Inline eq_slice into str::eq It's the only use of the function. --- src/libcore/str/mod.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 0af9fcf0a3d..670c2afa66f 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1405,16 +1405,6 @@ impl<'a> DoubleEndedIterator for LinesAny<'a> { #[allow(deprecated)] impl<'a> FusedIterator for LinesAny<'a> {} -/* -Section: Comparing strings -*/ - -/// Bytewise slice equality -#[inline] -fn eq_slice(a: &str, b: &str) -> bool { - a.as_bytes() == b.as_bytes() -} - /* Section: UTF-8 validation */ @@ -1590,7 +1580,6 @@ mod traits { use cmp::Ordering; use ops; use slice::{self, SliceIndex}; - use str::eq_slice; /// Implements ordering of strings. /// @@ -1611,7 +1600,7 @@ mod traits { impl PartialEq for str { #[inline] fn eq(&self, other: &str) -> bool { - eq_slice(self, other) + self.as_bytes() == other.as_bytes() } #[inline] fn ne(&self, other: &str) -> bool { !(*self).eq(other) } From 80fe86f8c78b52f19aa36e8d9845ecdc77277e55 Mon Sep 17 00:00:00 2001 From: bgermann Date: Tue, 3 Oct 2017 14:48:39 +0200 Subject: [PATCH 019/365] Add build environment for Solaris This can be used to build rust-std. The dilos illumos distribution was chosen, because illumos is free software as opposed to Oracle Solaris and dilos is the only illumos distribution that supports x86_64 and sparcv9 at the same level. --- src/ci/docker/dist-solaris/Dockerfile | 29 +++++ src/ci/docker/dist-solaris/build-toolchain.sh | 114 ++++++++++++++++++ src/tools/build-manifest/src/main.rs | 2 + 3 files changed, 145 insertions(+) create mode 100644 src/ci/docker/dist-solaris/Dockerfile create mode 100755 src/ci/docker/dist-solaris/build-toolchain.sh diff --git a/src/ci/docker/dist-solaris/Dockerfile b/src/ci/docker/dist-solaris/Dockerfile new file mode 100644 index 00000000000..a60c9956b75 --- /dev/null +++ b/src/ci/docker/dist-solaris/Dockerfile @@ -0,0 +1,29 @@ +FROM ubuntu:16.04 + +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +RUN apt-get install -y --no-install-recommends \ + software-properties-common libgmp-dev libmpfr-dev libmpc-dev libisl-dev +RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 +RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2-testing main' + +COPY dist-solaris/build-toolchain.sh /tmp/ +RUN /tmp/build-toolchain.sh x86_64 amd64 solaris-i386 +RUN /tmp/build-toolchain.sh sparcv9 sparcv9 solaris-sparc + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV \ + AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-ar \ + CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-sysroot \ + CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-g++ \ + AR_x86_64_sun_solaris=x86_64-sun-solaris2.11-ar \ + CC_x86_64_sun_solaris=x86_64-sun-solaris2.11-sysroot \ + CXX_x86_64_sun_solaris=x86_64-sun-solaris2.11-g++ + +ENV TARGETS=sparcv9-sun-solaris,x86_64-sun-solaris + +ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended +ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-solaris/build-toolchain.sh b/src/ci/docker/dist-solaris/build-toolchain.sh new file mode 100755 index 00000000000..c0d839a5fb7 --- /dev/null +++ b/src/ci/docker/dist-solaris/build-toolchain.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# 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. + +set -ex + +ARCH=$1 +LIB_ARCH=$2 +APT_ARCH=$3 +BINUTILS=2.28.1 +GCC=6.4.0 + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} + +# First up, build binutils +mkdir binutils +cd binutils + +curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.xz | tar xJf - +mkdir binutils-build +cd binutils-build +hide_output ../binutils-$BINUTILS/configure --target=$ARCH-sun-solaris2.11 +hide_output make -j10 +hide_output make install + +cd ../.. +rm -rf binutils + +# Next, download and install the relevant solaris packages +mkdir solaris +cd solaris + +dpkg --add-architecture $APT_ARCH +apt-get update +apt-get download \ + libc:$APT_ARCH \ + libc-dev:$APT_ARCH \ + libm:$APT_ARCH \ + libm-dev:$APT_ARCH \ + libpthread:$APT_ARCH \ + libpthread-dev:$APT_ARCH \ + librt:$APT_ARCH \ + librt-dev:$APT_ARCH \ + system-crt:$APT_ARCH \ + system-header:$APT_ARCH + +for deb in *$APT_ARCH.deb; do + dpkg -x $deb . +done + +mkdir /usr/local/$ARCH-sun-solaris2.11/usr +mv usr/include /usr/local/$ARCH-sun-solaris2.11/usr/include +mv usr/lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.11/lib +mv lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.11/lib + +ln -s /usr/local/$ARCH-sun-solaris2.11/usr/include /usr/local/$ARCH-sun-solaris2.11/sys-include +ln -s /usr/local/$ARCH-sun-solaris2.11/usr/include /usr/local/$ARCH-sun-solaris2.11/include + +cd .. +rm -rf solaris + +# Finally, download and build gcc to target solaris +mkdir gcc +cd gcc + +curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | tar xJf - +cd gcc-$GCC + +mkdir ../gcc-build +cd ../gcc-build +hide_output ../gcc-$GCC/configure \ + --enable-languages=c,c++ \ + --target=$ARCH-sun-solaris2.11 \ + --with-gnu-as \ + --with-gnu-ld \ + --disable-multilib \ + --disable-nls \ + --disable-libgomp \ + --disable-libquadmath \ + --disable-libssp \ + --disable-libvtv \ + --disable-libcilkrts \ + --disable-libada \ + --disable-libsanitizer \ + --disable-libquadmath-support \ + --disable-lto \ + --with-sysroot=/usr/local/$ARCH-sun-solaris2.11 + +hide_output make -j10 +hide_output make install + +cd ../.. +rm -rf gcc diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index db957a7a0fc..daeac35a017 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -83,6 +83,7 @@ static TARGETS: &'static [&'static str] = &[ "powerpc64le-unknown-linux-gnu", "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", + "sparcv9-sun-solaris", "wasm32-unknown-emscripten", "x86_64-linux-android", "x86_64-apple-darwin", @@ -90,6 +91,7 @@ static TARGETS: &'static [&'static str] = &[ "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", "x86_64-rumprun-netbsd", + "x86_64-sun-solaris", "x86_64-unknown-freebsd", "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", From 3264c836bbbbf9d62bc088443ca844709f8746a1 Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 4 Oct 2017 00:55:57 +0800 Subject: [PATCH 020/365] Optimize comparison functions of Iterator Replaced matching on tuples which led to less performant code generation. --- src/libcore/iter/iterator.rs | 186 +++++++++++++++++++++-------------- 1 file changed, 114 insertions(+), 72 deletions(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index e9e31065cf8..79767b37601 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -2059,14 +2059,23 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return Ordering::Equal, - (None, _ ) => return Ordering::Less, - (_ , None) => return Ordering::Greater, - (Some(x), Some(y)) => match x.cmp(&y) { - Ordering::Equal => (), - non_eq => return non_eq, + let x = match self.next() { + None => if other.next().is_none() { + return Ordering::Equal + } else { + return Ordering::Less }, + Some(val) => val, + }; + + let y = match other.next() { + None => return Ordering::Greater, + Some(val) => val, + }; + + match x.cmp(&y) { + Ordering::Equal => (), + non_eq => return non_eq, } } } @@ -2082,14 +2091,23 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return Some(Ordering::Equal), - (None, _ ) => return Some(Ordering::Less), - (_ , None) => return Some(Ordering::Greater), - (Some(x), Some(y)) => match x.partial_cmp(&y) { - Some(Ordering::Equal) => (), - non_eq => return non_eq, + let x = match self.next() { + None => if other.next().is_none() { + return Some(Ordering::Equal) + } else { + return Some(Ordering::Less) }, + Some(val) => val, + }; + + let y = match other.next() { + None => return Some(Ordering::Greater), + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Equal) => (), + non_eq => return non_eq, } } } @@ -2105,11 +2123,17 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return true, - (None, _) | (_, None) => return false, - (Some(x), Some(y)) => if x != y { return false }, - } + let x = match self.next() { + None => return other.next().is_none(), + Some(val) => val, + }; + + let y = match other.next() { + None => return false, + Some(val) => val, + }; + + if x != y { return false } } } @@ -2124,11 +2148,17 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return false, - (None, _) | (_, None) => return true, - (Some(x), Some(y)) => if x.ne(&y) { return true }, - } + let x = match self.next() { + None => return other.next().is_some(), + Some(val) => val, + }; + + let y = match other.next() { + None => return true, + Some(val) => val, + }; + + if x != y { return true } } } @@ -2143,18 +2173,21 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return false, - (None, _ ) => return true, - (_ , None) => return false, - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return true, - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return false, - None => return false, - } - }, + let x = match self.next() { + None => return other.next().is_some(), + Some(val) => val, + }; + + let y = match other.next() { + None => return false, + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Less) => return true, + Some(Ordering::Equal) => (), + Some(Ordering::Greater) => return false, + None => return false, } } } @@ -2170,18 +2203,21 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return true, - (None, _ ) => return true, - (_ , None) => return false, - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return true, - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return false, - None => return false, - } - }, + let x = match self.next() { + None => { other.next(); return true; }, + Some(val) => val, + }; + + let y = match other.next() { + None => return false, + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Less) => return true, + Some(Ordering::Equal) => (), + Some(Ordering::Greater) => return false, + None => return false, } } } @@ -2197,18 +2233,21 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return false, - (None, _ ) => return false, - (_ , None) => return true, - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return false, - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return true, - None => return false, - } - } + let x = match self.next() { + None => { other.next(); return false; }, + Some(val) => val, + }; + + let y = match other.next() { + None => return true, + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Less) => return false, + Some(Ordering::Equal) => (), + Some(Ordering::Greater) => return true, + None => return false, } } } @@ -2224,18 +2263,21 @@ pub trait Iterator { let mut other = other.into_iter(); loop { - match (self.next(), other.next()) { - (None, None) => return true, - (None, _ ) => return false, - (_ , None) => return true, - (Some(x), Some(y)) => { - match x.partial_cmp(&y) { - Some(Ordering::Less) => return false, - Some(Ordering::Equal) => {} - Some(Ordering::Greater) => return true, - None => return false, - } - }, + let x = match self.next() { + None => return other.next().is_none(), + Some(val) => val, + }; + + let y = match other.next() { + None => return true, + Some(val) => val, + }; + + match x.partial_cmp(&y) { + Some(Ordering::Less) => return false, + Some(Ordering::Equal) => (), + Some(Ordering::Greater) => return true, + None => return false, } } } From 36471293e60f5750ecc728c22ade04013e962929 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 3 Oct 2017 19:49:45 -0400 Subject: [PATCH 021/365] Add -Zmutable-noalias flag --- src/librustc/session/config.rs | 2 ++ src/librustc_trans/abi.rs | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 7c1d457a6ee..7e490dc49ca 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1060,6 +1060,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print the result of the translation item collection pass"), mir_opt_level: usize = (1, parse_uint, [TRACKED], "set the MIR optimization level (0-3, default: 1)"), + mutable_noalias: bool = (false, parse_bool, [UNTRACKED], + "emit noalias metadata for mutable references"), dump_mir: Option = (None, parse_opt_string, [UNTRACKED], "dump MIR state at various points in translation"), dump_mir_dir: Option = (None, parse_opt_string, [UNTRACKED], diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 2aecc016a5c..5dc2e992972 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -760,7 +760,16 @@ impl<'a, 'tcx> FnType<'tcx> { // on memory dependencies rather than pointer equality let is_freeze = ccx.shared().type_is_freeze(mt.ty); - if mt.mutbl != hir::MutMutable && is_freeze { + let no_alias_is_safe = + if ccx.shared().tcx().sess.opts.debugging_opts.mutable_noalias { + // Mutable refrences or immutable shared references + mt.mutbl == hir::MutMutable || is_freeze + } else { + // Only immutable shared references + mt.mutbl != hir::MutMutable && is_freeze + }; + + if no_alias_is_safe { arg.attrs.set(ArgAttribute::NoAlias); } From a12cefb497fa6ebc397f7f2f2f14f2f2712b965d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 3 Oct 2017 15:34:52 +0200 Subject: [PATCH 022/365] Move E0507 diagnostic into mod borrowck_errors shared between ast- and mir-borrowck. (Had to modify signature of `report_cannot_move_out_of` slightly to satisfy requirements of newly added `fn cannot_move_out_of` method.) --- .../borrowck/gather_loans/move_error.rs | 14 +- src/librustc_borrowck/diagnostics.rs | 126 ----------------- src/librustc_mir/diagnostics.rs | 127 ++++++++++++++++++ src/librustc_mir/util/borrowck_errors.rs | 12 ++ 4 files changed, 143 insertions(+), 136 deletions(-) diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index de3f6f08325..b56e7e1d72e 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -14,6 +14,7 @@ use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::NoteClosureEnv; use rustc::middle::mem_categorization::InteriorOffsetKind as Kind; use rustc::ty; +use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; use syntax::ast; use syntax_pos; use errors::DiagnosticBuilder; @@ -134,7 +135,7 @@ fn group_errors_with_same_origin<'tcx>(errors: &Vec>) } // (keep in sync with gather_moves::check_and_get_illegal_move_origin ) -fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, +fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, move_from: mc::cmt<'tcx>) -> DiagnosticBuilder<'a> { match move_from.cat { @@ -142,16 +143,9 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, Categorization::Deref(_, mc::Implicit(..)) | Categorization::Deref(_, mc::UnsafePtr(..)) | Categorization::StaticItem => { - let mut err = struct_span_err!(bccx, move_from.span, E0507, - "cannot move out of {}", - move_from.descriptive_string(bccx.tcx)); - err.span_label( - move_from.span, - format!("cannot move out of {}", move_from.descriptive_string(bccx.tcx)) - ); - err + bccx.cannot_move_out_of( + move_from.span, &move_from.descriptive_string(bccx.tcx), Origin::Ast) } - Categorization::Interior(ref b, mc::InteriorElement(ik)) => { let type_name = match (&b.ty.sty, ik) { (&ty::TyArray(_, _), Kind::Index) => "array", diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 29c35e23d4e..8fd17943c3a 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -317,132 +317,6 @@ fn main() { ``` "##, -E0507: r##" -You tried to move out of a value which was borrowed. Erroneous code example: - -```compile_fail,E0507 -use std::cell::RefCell; - -struct TheDarkKnight; - -impl TheDarkKnight { - fn nothing_is_true(self) {} -} - -fn main() { - let x = RefCell::new(TheDarkKnight); - - x.borrow().nothing_is_true(); // error: cannot move out of borrowed content -} -``` - -Here, the `nothing_is_true` method takes the ownership of `self`. However, -`self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`, -which is a borrow of the content owned by the `RefCell`. To fix this error, -you have three choices: - -* Try to avoid moving the variable. -* Somehow reclaim the ownership. -* Implement the `Copy` trait on the type. - -Examples: - -``` -use std::cell::RefCell; - -struct TheDarkKnight; - -impl TheDarkKnight { - fn nothing_is_true(&self) {} // First case, we don't take ownership -} - -fn main() { - let x = RefCell::new(TheDarkKnight); - - x.borrow().nothing_is_true(); // ok! -} -``` - -Or: - -``` -use std::cell::RefCell; - -struct TheDarkKnight; - -impl TheDarkKnight { - fn nothing_is_true(self) {} -} - -fn main() { - let x = RefCell::new(TheDarkKnight); - let x = x.into_inner(); // we get back ownership - - x.nothing_is_true(); // ok! -} -``` - -Or: - -``` -use std::cell::RefCell; - -#[derive(Clone, Copy)] // we implement the Copy trait -struct TheDarkKnight; - -impl TheDarkKnight { - fn nothing_is_true(self) {} -} - -fn main() { - let x = RefCell::new(TheDarkKnight); - - x.borrow().nothing_is_true(); // ok! -} -``` - -Moving a member out of a mutably borrowed struct will also cause E0507 error: - -```compile_fail,E0507 -struct TheDarkKnight; - -impl TheDarkKnight { - fn nothing_is_true(self) {} -} - -struct Batcave { - knight: TheDarkKnight -} - -fn main() { - let mut cave = Batcave { - knight: TheDarkKnight - }; - let borrowed = &mut cave; - - borrowed.knight.nothing_is_true(); // E0507 -} -``` - -It is fine only if you put something back. `mem::replace` can be used for that: - -``` -# struct TheDarkKnight; -# impl TheDarkKnight { fn nothing_is_true(self) {} } -# struct Batcave { knight: TheDarkKnight } -use std::mem; - -let mut cave = Batcave { - knight: TheDarkKnight -}; -let borrowed = &mut cave; - -mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! -``` - -You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html -"##, E0508: r##" A value was moved out of a non-copy fixed-size array. diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 950bdff1d0f..69c2b27c1d7 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -999,6 +999,133 @@ fn print_fancy_ref(fancy_ref: &FancyNum){ ``` "##, +E0507: r##" +You tried to move out of a value which was borrowed. Erroneous code example: + +```compile_fail,E0507 +use std::cell::RefCell; + +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + + x.borrow().nothing_is_true(); // error: cannot move out of borrowed content +} +``` + +Here, the `nothing_is_true` method takes the ownership of `self`. However, +`self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`, +which is a borrow of the content owned by the `RefCell`. To fix this error, +you have three choices: + +* Try to avoid moving the variable. +* Somehow reclaim the ownership. +* Implement the `Copy` trait on the type. + +Examples: + +``` +use std::cell::RefCell; + +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(&self) {} // First case, we don't take ownership +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + + x.borrow().nothing_is_true(); // ok! +} +``` + +Or: + +``` +use std::cell::RefCell; + +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + let x = x.into_inner(); // we get back ownership + + x.nothing_is_true(); // ok! +} +``` + +Or: + +``` +use std::cell::RefCell; + +#[derive(Clone, Copy)] // we implement the Copy trait +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + + x.borrow().nothing_is_true(); // ok! +} +``` + +Moving a member out of a mutably borrowed struct will also cause E0507 error: + +```compile_fail,E0507 +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +struct Batcave { + knight: TheDarkKnight +} + +fn main() { + let mut cave = Batcave { + knight: TheDarkKnight + }; + let borrowed = &mut cave; + + borrowed.knight.nothing_is_true(); // E0507 +} +``` + +It is fine only if you put something back. `mem::replace` can be used for that: + +``` +# struct TheDarkKnight; +# impl TheDarkKnight { fn nothing_is_true(self) {} } +# struct Batcave { knight: TheDarkKnight } +use std::mem; + +let mut cave = Batcave { + knight: TheDarkKnight +}; +let borrowed = &mut cave; + +mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! +``` + +You can find more information about borrowing in the rust-book: +http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html +"##, + } register_diagnostics! { diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index eddcb89c344..9330a93a41c 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -191,6 +191,18 @@ pub trait BorrowckErrors { { self.cannot_assign(span, &format!("immutable static item `{}`", desc), o) } + + fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Origin) + -> DiagnosticBuilder + { + let mut err = struct_span_err!(self, move_from_span, E0507, + "cannot move out of {}{OGN}", + move_from_desc, OGN=o); + err.span_label( + move_from_span, + format!("cannot move out of {}", move_from_desc)); + err + } } impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> { From a995b56a5e7352aec0aafd4972c3faaeed94083d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 3 Oct 2017 15:54:12 +0200 Subject: [PATCH 023/365] Move E0508 diagnostic into mod borrowck_errors shared between ast- and mir-borrowck. --- .../borrowck/gather_loans/move_error.rs | 15 +------ src/librustc_borrowck/diagnostics.rs | 45 ------------------- src/librustc_mir/diagnostics.rs | 45 +++++++++++++++++++ src/librustc_mir/util/borrowck_errors.rs | 20 +++++++++ 4 files changed, 67 insertions(+), 58 deletions(-) diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index b56e7e1d72e..ef89b569a83 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -147,19 +147,8 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, move_from.span, &move_from.descriptive_string(bccx.tcx), Origin::Ast) } Categorization::Interior(ref b, mc::InteriorElement(ik)) => { - let type_name = match (&b.ty.sty, ik) { - (&ty::TyArray(_, _), Kind::Index) => "array", - (&ty::TySlice(_), _) => "slice", - _ => { - span_bug!(move_from.span, "this path should not cause illegal move"); - }, - }; - let mut err = struct_span_err!(bccx, move_from.span, E0508, - "cannot move out of type `{}`, \ - a non-copy {}", - b.ty, type_name); - err.span_label(move_from.span, "cannot move out of here"); - err + bccx.cannot_move_out_of_interior_noncopy( + move_from.span, b.ty, ik == Kind::Index, Origin::Ast) } Categorization::Downcast(ref b, _) | diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 8fd17943c3a..85e8e0e54fa 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -317,51 +317,6 @@ fn main() { ``` "##, - -E0508: r##" -A value was moved out of a non-copy fixed-size array. - -Example of erroneous code: - -```compile_fail,E0508 -struct NonCopy; - -fn main() { - let array = [NonCopy; 1]; - let _value = array[0]; // error: cannot move out of type `[NonCopy; 1]`, - // a non-copy fixed-size array -} -``` - -The first element was moved out of the array, but this is not -possible because `NonCopy` does not implement the `Copy` trait. - -Consider borrowing the element instead of moving it: - -``` -struct NonCopy; - -fn main() { - let array = [NonCopy; 1]; - let _value = &array[0]; // Borrowing is allowed, unlike moving. -} -``` - -Alternatively, if your type implements `Clone` and you need to own the value, -consider borrowing and then cloning: - -``` -#[derive(Clone)] -struct NonCopy; - -fn main() { - let array = [NonCopy; 1]; - // Now you can clone the array element. - let _value = array[0].clone(); -} -``` -"##, - E0509: r##" This error occurs when an attempt is made to move out of a value whose type implements the `Drop` trait. diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 69c2b27c1d7..a1dd89f1a9f 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -1126,6 +1126,51 @@ You can find more information about borrowing in the rust-book: http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html "##, +E0508: r##" +A value was moved out of a non-copy fixed-size array. + +Example of erroneous code: + +```compile_fail,E0508 +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + let _value = array[0]; // error: cannot move out of type `[NonCopy; 1]`, + // a non-copy fixed-size array +} +``` + +The first element was moved out of the array, but this is not +possible because `NonCopy` does not implement the `Copy` trait. + +Consider borrowing the element instead of moving it: + +``` +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + let _value = &array[0]; // Borrowing is allowed, unlike moving. +} +``` + +Alternatively, if your type implements `Clone` and you need to own the value, +consider borrowing and then cloning: + +``` +#[derive(Clone)] +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + // Now you can clone the array element. + let _value = array[0].clone(); +} +``` +"##, + + } register_diagnostics! { diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 9330a93a41c..3d9eae33ce7 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -203,6 +203,26 @@ pub trait BorrowckErrors { format!("cannot move out of {}", move_from_desc)); err } + + fn cannot_move_out_of_interior_noncopy(&self, + move_from_span: Span, + ty: ty::Ty, + is_index: bool, + o: Origin) + -> DiagnosticBuilder + { + let type_name = match (&ty.sty, is_index) { + (&ty::TyArray(_, _), true) => "array", + (&ty::TySlice(_), _) => "slice", + _ => span_bug!(move_from_span, "this path should not cause illegal move"), + }; + let mut err = struct_span_err!(self, move_from_span, E0508, + "cannot move out of type `{}`, \ + a non-copy {}{OGN}", + ty, type_name, OGN=o); + err.span_label(move_from_span, "cannot move out of here"); + err + } } impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> { From fdd7d13c246f7f82fad231babe30b3a30dac988f Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 3 Oct 2017 16:07:20 +0200 Subject: [PATCH 024/365] Move E0509 diagnostic into mod borrowck_errors shared between ast- and mir-borrowck. --- .../borrowck/gather_loans/move_error.rs | 10 +- src/librustc_borrowck/diagnostics.rs | 95 ------------------- src/librustc_mir/diagnostics.rs | 94 ++++++++++++++++++ src/librustc_mir/util/borrowck_errors.rs | 14 +++ 4 files changed, 111 insertions(+), 102 deletions(-) diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index ef89b569a83..1f2b917bdb9 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -155,13 +155,9 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, Categorization::Interior(ref b, mc::InteriorField(_)) => { match b.ty.sty { ty::TyAdt(def, _) if def.has_dtor(bccx.tcx) => { - let mut err = struct_span_err!(bccx, move_from.span, E0509, - "cannot move out of type `{}`, \ - which implements the `Drop` trait", - b.ty); - err.span_label(move_from.span, "cannot move out of here"); - err - }, + bccx.cannot_move_out_of_interior_of_drop( + move_from.span, b.ty, Origin::Ast) + } _ => { span_bug!(move_from.span, "this path should not cause illegal move"); } diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 85e8e0e54fa..031dbcb1ebb 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -317,101 +317,6 @@ fn main() { ``` "##, -E0509: r##" -This error occurs when an attempt is made to move out of a value whose type -implements the `Drop` trait. - -Example of erroneous code: - -```compile_fail,E0509 -struct FancyNum { - num: usize -} - -struct DropStruct { - fancy: FancyNum -} - -impl Drop for DropStruct { - fn drop(&mut self) { - // Destruct DropStruct, possibly using FancyNum - } -} - -fn main() { - let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; - let fancy_field = drop_struct.fancy; // Error E0509 - println!("Fancy: {}", fancy_field.num); - // implicit call to `drop_struct.drop()` as drop_struct goes out of scope -} -``` - -Here, we tried to move a field out of a struct of type `DropStruct` which -implements the `Drop` trait. However, a struct cannot be dropped if one or -more of its fields have been moved. - -Structs implementing the `Drop` trait have an implicit destructor that gets -called when they go out of scope. This destructor may use the fields of the -struct, so moving out of the struct could make it impossible to run the -destructor. Therefore, we must think of all values whose type implements the -`Drop` trait as single units whose fields cannot be moved. - -This error can be fixed by creating a reference to the fields of a struct, -enum, or tuple using the `ref` keyword: - -``` -struct FancyNum { - num: usize -} - -struct DropStruct { - fancy: FancyNum -} - -impl Drop for DropStruct { - fn drop(&mut self) { - // Destruct DropStruct, possibly using FancyNum - } -} - -fn main() { - let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; - let ref fancy_field = drop_struct.fancy; // No more errors! - println!("Fancy: {}", fancy_field.num); - // implicit call to `drop_struct.drop()` as drop_struct goes out of scope -} -``` - -Note that this technique can also be used in the arms of a match expression: - -``` -struct FancyNum { - num: usize -} - -enum DropEnum { - Fancy(FancyNum) -} - -impl Drop for DropEnum { - fn drop(&mut self) { - // Destruct DropEnum, possibly using FancyNum - } -} - -fn main() { - // Creates and enum of type `DropEnum`, which implements `Drop` - let drop_enum = DropEnum::Fancy(FancyNum{num: 10}); - match drop_enum { - // Creates a reference to the inside of `DropEnum::Fancy` - DropEnum::Fancy(ref fancy_field) => // No error! - println!("It was fancy-- {}!", fancy_field.num), - } - // implicit call to `drop_enum.drop()` as drop_enum goes out of scope -} -``` -"##, - E0595: r##" Closures cannot mutate immutable captured variables. diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index a1dd89f1a9f..645af0bff64 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -1170,6 +1170,100 @@ fn main() { ``` "##, +E0509: r##" +This error occurs when an attempt is made to move out of a value whose type +implements the `Drop` trait. + +Example of erroneous code: + +```compile_fail,E0509 +struct FancyNum { + num: usize +} + +struct DropStruct { + fancy: FancyNum +} + +impl Drop for DropStruct { + fn drop(&mut self) { + // Destruct DropStruct, possibly using FancyNum + } +} + +fn main() { + let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; + let fancy_field = drop_struct.fancy; // Error E0509 + println!("Fancy: {}", fancy_field.num); + // implicit call to `drop_struct.drop()` as drop_struct goes out of scope +} +``` + +Here, we tried to move a field out of a struct of type `DropStruct` which +implements the `Drop` trait. However, a struct cannot be dropped if one or +more of its fields have been moved. + +Structs implementing the `Drop` trait have an implicit destructor that gets +called when they go out of scope. This destructor may use the fields of the +struct, so moving out of the struct could make it impossible to run the +destructor. Therefore, we must think of all values whose type implements the +`Drop` trait as single units whose fields cannot be moved. + +This error can be fixed by creating a reference to the fields of a struct, +enum, or tuple using the `ref` keyword: + +``` +struct FancyNum { + num: usize +} + +struct DropStruct { + fancy: FancyNum +} + +impl Drop for DropStruct { + fn drop(&mut self) { + // Destruct DropStruct, possibly using FancyNum + } +} + +fn main() { + let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; + let ref fancy_field = drop_struct.fancy; // No more errors! + println!("Fancy: {}", fancy_field.num); + // implicit call to `drop_struct.drop()` as drop_struct goes out of scope +} +``` + +Note that this technique can also be used in the arms of a match expression: + +``` +struct FancyNum { + num: usize +} + +enum DropEnum { + Fancy(FancyNum) +} + +impl Drop for DropEnum { + fn drop(&mut self) { + // Destruct DropEnum, possibly using FancyNum + } +} + +fn main() { + // Creates and enum of type `DropEnum`, which implements `Drop` + let drop_enum = DropEnum::Fancy(FancyNum{num: 10}); + match drop_enum { + // Creates a reference to the inside of `DropEnum::Fancy` + DropEnum::Fancy(ref fancy_field) => // No error! + println!("It was fancy-- {}!", fancy_field.num), + } + // implicit call to `drop_enum.drop()` as drop_enum goes out of scope +} +``` +"##, } diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 3d9eae33ce7..aaf8b9414ad 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -223,6 +223,20 @@ pub trait BorrowckErrors { err.span_label(move_from_span, "cannot move out of here"); err } + + fn cannot_move_out_of_interior_of_drop(&self, + move_from_span: Span, + container_ty: ty::Ty, + o: Origin) + -> DiagnosticBuilder + { + let mut err = struct_span_err!(self, move_from_span, E0509, + "cannot move out of type `{}`, \ + which implements the `Drop` trait{OGN}", + container_ty, OGN=o); + err.span_label(move_from_span, "cannot move out of here"); + err + } } impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> { From 43fb82d2fa5152d7b1a97bbe42d26221ff068661 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 4 Oct 2017 11:02:26 +0200 Subject: [PATCH 025/365] mir-borrowck: Gather move errors during MoveData construction and report them. Currently is using DUMMY_SP as the associated span; a follow-up commit will pass in appropriate spans when constructing the errors. --- src/librustc_mir/borrow_check.rs | 29 +++++++- .../dataflow/move_paths/builder.rs | 70 +++++++++++-------- src/librustc_mir/dataflow/move_paths/mod.rs | 31 +++++++- src/librustc_mir/transform/elaborate_drops.rs | 2 +- src/librustc_mir/transform/rustc_peek.rs | 2 +- 5 files changed, 99 insertions(+), 35 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 0ad22f91855..5c45f925dd7 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -30,6 +30,7 @@ use dataflow::{MoveDataParamEnv}; use dataflow::{BitDenotation, BlockSets, DataflowResults, DataflowResultsConsumer}; use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use dataflow::{Borrows, BorrowData, BorrowIndex}; +use dataflow::move_paths::{MoveError, IllegalMoveOriginKind}; use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult}; use util::borrowck_errors::{BorrowckErrors, Origin}; @@ -59,7 +60,33 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { let param_env = tcx.param_env(def_id); tcx.infer_ctxt().enter(|_infcx| { - let move_data = MoveData::gather_moves(mir, tcx, param_env); + let move_data = match MoveData::gather_moves(mir, tcx, param_env) { + Ok(move_data) => move_data, + Err((move_data, move_errors)) => { + for move_error in move_errors { + let (span, kind): (Span, IllegalMoveOriginKind) = match move_error { + MoveError::UnionMove { .. } => + unimplemented!("dont know how to report union move errors yet."), + MoveError::IllegalMove { cannot_move_out_of: o } => (o.span, o.kind), + }; + let origin = Origin::Mir; + let mut err = match kind { + IllegalMoveOriginKind::Static => + tcx.cannot_move_out_of(span, "static item", origin), + IllegalMoveOriginKind::BorrowedContent => + tcx.cannot_move_out_of(span, "borrowed_content", origin), + IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => + tcx.cannot_move_out_of_interior_of_drop(span, ty, origin), + IllegalMoveOriginKind::InteriorOfSlice { elem_ty: ty, is_index } => + tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin), + IllegalMoveOriginKind::InteriorOfArray { elem_ty: ty, is_index } => + tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin), + }; + err.emit(); + } + move_data + } + }; let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let flow_borrows = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 86298c3b83e..572fffdf4c0 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -22,17 +22,15 @@ use std::mem; use super::abs_domain::Lift; use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex}; +use super::{MoveError}; +use super::IllegalMoveOriginKind::*; -pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> { +struct MoveDataBuilder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, data: MoveData<'tcx>, -} - -pub enum MovePathError { - IllegalMove, - UnionMove { path: MovePathIndex }, + errors: Vec>, } impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { @@ -47,6 +45,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { mir, tcx, param_env, + errors: Vec::new(), data: MoveData { moves: IndexVec::new(), loc_map: LocationMap::new(mir), @@ -94,13 +93,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { /// /// Maybe we should have separate "borrowck" and "moveck" modes. fn move_path_for(&mut self, lval: &Lvalue<'tcx>) - -> Result + -> Result> { debug!("lookup({:?})", lval); match *lval { Lvalue::Local(local) => Ok(self.data.rev_lookup.locals[local]), - // error: can't move out of a static - Lvalue::Static(..) => Err(MovePathError::IllegalMove), + Lvalue::Static(..) => Err(MoveError::cannot_move_out_of(Static)), Lvalue::Projection(ref proj) => { self.move_path_for_projection(lval, proj) } @@ -116,25 +114,32 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { fn move_path_for_projection(&mut self, lval: &Lvalue<'tcx>, proj: &LvalueProjection<'tcx>) - -> Result + -> Result> { let base = try!(self.move_path_for(&proj.base)); let lv_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); match lv_ty.sty { - // error: can't move out of borrowed content - ty::TyRef(..) | ty::TyRawPtr(..) => return Err(MovePathError::IllegalMove), - // error: can't move out of struct with destructor + ty::TyRef(..) | ty::TyRawPtr(..) => + return Err(MoveError::cannot_move_out_of(BorrowedContent)), ty::TyAdt(adt, _) if adt.has_dtor(self.tcx) && !adt.is_box() => - return Err(MovePathError::IllegalMove), + return Err(MoveError::cannot_move_out_of(InteriorOfTypeWithDestructor { + container_ty: lv_ty + })), // move out of union - always move the entire union ty::TyAdt(adt, _) if adt.is_union() => - return Err(MovePathError::UnionMove { path: base }), - // error: can't move out of a slice - ty::TySlice(..) => - return Err(MovePathError::IllegalMove), - ty::TyArray(..) => match proj.elem { - // error: can't move out of an array - ProjectionElem::Index(..) => return Err(MovePathError::IllegalMove), + return Err(MoveError::UnionMove { path: base }), + ty::TySlice(elem_ty) => + return Err(MoveError::cannot_move_out_of(InteriorOfSlice { + elem_ty, is_index: match proj.elem { + ProjectionElem::Index(..) => true, + _ => false + }, + })), + ty::TyArray(elem_ty, _num_elems) => match proj.elem { + ProjectionElem::Index(..) => + return Err(MoveError::cannot_move_out_of(InteriorOfArray { + elem_ty, is_index: true + })), _ => { // FIXME: still badly broken } @@ -156,7 +161,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } } - fn finalize(self) -> MoveData<'tcx> { + fn finalize(self) -> Result, (MoveData<'tcx>, Vec>)> { debug!("{}", { debug!("moves for {:?}:", self.mir.span); for (j, mo) in self.data.moves.iter_enumerated() { @@ -168,14 +173,20 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } "done dumping moves" }); - self.data + + if self.errors.len() > 0 { + Err((self.data, self.errors)) + } else { + Ok(self.data) + } } } pub(super) fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>) - -> MoveData<'tcx> { + -> Result, + (MoveData<'tcx>, Vec>)> { let mut builder = MoveDataBuilder::new(mir, tcx, param_env); for (bb, block) in mir.basic_blocks().iter_enumerated() { @@ -317,13 +328,10 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } let path = match self.move_path_for(lval) { - Ok(path) | Err(MovePathError::UnionMove { path }) => path, - Err(MovePathError::IllegalMove) => { - // Moving out of a bad path. Eventually, this should be a MIR - // borrowck error instead of a bug. - span_bug!(self.mir.span, - "Broken MIR: moving out of lvalue {:?}: {:?} at {:?}", - lval, lv_ty, loc); + Ok(path) | Err(MoveError::UnionMove { path }) => path, + Err(error @ MoveError::IllegalMove { .. }) => { + self.errors.push(error); + return; } }; let move_out = self.data.moves.push(MoveOut { path: path, source: loc }); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index d2d80649846..61f64e7373d 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -13,6 +13,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec}; +use syntax_pos::{DUMMY_SP, Span}; use std::fmt; use std::ops::{Index, IndexMut}; @@ -227,11 +228,39 @@ impl<'tcx> MovePathLookup<'tcx> { } } +#[derive(Debug)] +pub struct IllegalMoveOrigin<'tcx> { + pub(crate) span: Span, + pub(crate) kind: IllegalMoveOriginKind<'tcx>, +} + +#[derive(Debug)] +pub(crate) enum IllegalMoveOriginKind<'tcx> { + Static, + BorrowedContent, + InteriorOfTypeWithDestructor { container_ty: ty::Ty<'tcx> }, + InteriorOfSlice { elem_ty: ty::Ty<'tcx>, is_index: bool, }, + InteriorOfArray { elem_ty: ty::Ty<'tcx>, is_index: bool, }, +} + +#[derive(Debug)] +pub enum MoveError<'tcx> { + IllegalMove { cannot_move_out_of: IllegalMoveOrigin<'tcx> }, + UnionMove { path: MovePathIndex }, +} + +impl<'tcx> MoveError<'tcx> { + fn cannot_move_out_of(kind: IllegalMoveOriginKind<'tcx>) -> Self { + let origin = IllegalMoveOrigin { span: DUMMY_SP, kind: kind, }; + MoveError::IllegalMove { cannot_move_out_of: origin } + } +} + impl<'a, 'tcx> MoveData<'tcx> { pub fn gather_moves(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>) - -> Self { + -> Result>)> { builder::gather_moves(mir, tcx, param_env) } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index c833904adba..be1b794ecdf 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -45,7 +45,7 @@ impl MirPass for ElaborateDrops { } let id = src.item_id(); let param_env = tcx.param_env(tcx.hir.local_def_id(id)); - let move_data = MoveData::gather_moves(mir, tcx, param_env); + let move_data = MoveData::gather_moves(mir, tcx, param_env).unwrap(); let elaborate_patch = { let mir = &*mir; let env = MoveDataParamEnv { diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index ceff52409b2..8d6458d7934 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -45,7 +45,7 @@ impl MirPass for SanityCheck { let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(mir, tcx, param_env); + let move_data = MoveData::gather_moves(mir, tcx, param_env).unwrap(); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let flow_inits = From 117586e6e9c7d31a3857800742728dac91b7c4fe Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 4 Oct 2017 11:46:35 +0200 Subject: [PATCH 026/365] Add method to `Mir` that maps a `Location` to its `SourceInfo`. --- src/librustc/mir/mod.rs | 13 +++++++++++++ src/librustc_mir/borrow_check.rs | 4 +--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ba221ef6ae1..ea3504a439a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -284,6 +284,19 @@ impl<'tcx> Mir<'tcx> { debug_assert!(location.statement_index < block.statements.len()); block.statements[location.statement_index].make_nop() } + + /// Returns the source info associated with `location`. + pub fn source_info(&self, location: Location) -> &SourceInfo { + let block = &self[location.block]; + let stmts = &block.statements; + let idx = location.statement_index; + if location.statement_index < stmts.len() { + &stmts[idx].source_info + } else { + assert!(location.statement_index == stmts.len()); + &block.terminator().source_info + } + } } #[derive(Clone, Debug)] diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 5c45f925dd7..917a8009fc9 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1126,9 +1126,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> // Retrieve span of given borrow from the current MIR representation fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { - self.mir.basic_blocks()[borrow.location.block] - .statements[borrow.location.statement_index] - .source_info.span + self.mir.source_info(borrow.location).span } } From 5a16ef4936d7174df232c7b17fc92b3060e22c3a Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 4 Oct 2017 12:34:35 +0200 Subject: [PATCH 027/365] Made `move_paths::MoveError` take span param in `cannot_move_out_of` ctor. Implicitly threaded `Location` through MoveData construction via a `Gatherer` struct (so that we could look up the span corresponding to the location when we need to signal an error). --- .../dataflow/move_paths/builder.rs | 121 +++++++++++------- src/librustc_mir/dataflow/move_paths/mod.rs | 6 +- 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 572fffdf4c0..0790d937ceb 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -84,7 +84,9 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { assert_eq!(path_map_ent, move_path); move_path } +} +impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { /// This creates a MovePath for a given lvalue, returning an `MovePathError` /// if that lvalue can't be moved from. /// @@ -97,8 +99,11 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { { debug!("lookup({:?})", lval); match *lval { - Lvalue::Local(local) => Ok(self.data.rev_lookup.locals[local]), - Lvalue::Static(..) => Err(MoveError::cannot_move_out_of(Static)), + Lvalue::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]), + Lvalue::Static(..) => { + let span = self.builder.mir.source_info(self.loc).span; + Err(MoveError::cannot_move_out_of(span, Static)) + } Lvalue::Projection(ref proj) => { self.move_path_for_projection(lval, proj) } @@ -117,41 +122,49 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { -> Result> { let base = try!(self.move_path_for(&proj.base)); - let lv_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); + let mir = self.builder.mir; + let tcx = self.builder.tcx; + let lv_ty = proj.base.ty(mir, tcx).to_ty(tcx); match lv_ty.sty { ty::TyRef(..) | ty::TyRawPtr(..) => - return Err(MoveError::cannot_move_out_of(BorrowedContent)), - ty::TyAdt(adt, _) if adt.has_dtor(self.tcx) && !adt.is_box() => - return Err(MoveError::cannot_move_out_of(InteriorOfTypeWithDestructor { + return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span, + BorrowedContent)), + ty::TyAdt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => + return Err(MoveError::cannot_move_out_of(mir.source_info(self.loc).span, + InteriorOfTypeWithDestructor { container_ty: lv_ty })), // move out of union - always move the entire union ty::TyAdt(adt, _) if adt.is_union() => return Err(MoveError::UnionMove { path: base }), ty::TySlice(elem_ty) => - return Err(MoveError::cannot_move_out_of(InteriorOfSlice { - elem_ty, is_index: match proj.elem { - ProjectionElem::Index(..) => true, - _ => false - }, - })), + return Err(MoveError::cannot_move_out_of( + mir.source_info(self.loc).span, + InteriorOfSlice { + elem_ty, is_index: match proj.elem { + ProjectionElem::Index(..) => true, + _ => false + }, + })), ty::TyArray(elem_ty, _num_elems) => match proj.elem { ProjectionElem::Index(..) => - return Err(MoveError::cannot_move_out_of(InteriorOfArray { - elem_ty, is_index: true - })), + return Err(MoveError::cannot_move_out_of( + mir.source_info(self.loc).span, + InteriorOfArray { + elem_ty, is_index: true + })), _ => { // FIXME: still badly broken } }, _ => {} }; - match self.data.rev_lookup.projections.entry((base, proj.elem.lift())) { + match self.builder.data.rev_lookup.projections.entry((base, proj.elem.lift())) { Entry::Occupied(ent) => Ok(*ent.get()), Entry::Vacant(ent) => { - let path = Self::new_move_path( - &mut self.data.move_paths, - &mut self.data.path_map, + let path = MoveDataBuilder::new_move_path( + &mut self.builder.data.move_paths, + &mut self.builder.data.path_map, Some(base), lval.clone() ); @@ -160,7 +173,9 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } } } +} +impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { fn finalize(self) -> Result, (MoveData<'tcx>, Vec>)> { debug!("{}", { debug!("moves for {:?}:", self.mir.span); @@ -208,6 +223,22 @@ pub(super) fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) { debug!("gather_statement({:?}, {:?})", loc, stmt); + (Gatherer { builder: self, loc }).gather_statement(stmt); + } + + fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) { + debug!("gather_terminator({:?}, {:?})", loc, term); + (Gatherer { builder: self, loc }).gather_terminator(term); + } +} + +struct Gatherer<'b, 'a: 'b, 'tcx: 'a> { + builder: &'b mut MoveDataBuilder<'a, 'tcx>, + loc: Location, +} + +impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { + fn gather_statement(&mut self, stmt: &Statement<'tcx>) { match stmt.kind { StatementKind::Assign(ref lval, ref rval) => { self.create_move_path(lval); @@ -217,7 +248,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { // the exterior. self.create_move_path(&lval.clone().deref()); } - self.gather_rvalue(loc, rval); + self.gather_rvalue(rval); } StatementKind::StorageLive(_) | StatementKind::StorageDead(_) => {} @@ -232,22 +263,22 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } } - fn gather_rvalue(&mut self, loc: Location, rvalue: &Rvalue<'tcx>) { + fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { match *rvalue { Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::Cast(_, ref operand, _) | Rvalue::UnaryOp(_, ref operand) => { - self.gather_operand(loc, operand) + self.gather_operand(operand) } Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) | Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { - self.gather_operand(loc, lhs); - self.gather_operand(loc, rhs); + self.gather_operand(lhs); + self.gather_operand(rhs); } Rvalue::Aggregate(ref _kind, ref operands) => { for operand in operands { - self.gather_operand(loc, operand); + self.gather_operand(operand); } } Rvalue::Ref(..) | @@ -269,8 +300,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } } - fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) { - debug!("gather_terminator({:?}, {:?})", loc, term); + fn gather_terminator(&mut self, term: &Terminator<'tcx>) { match term.kind { TerminatorKind::Goto { target: _ } | TerminatorKind::Resume | @@ -278,7 +308,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { TerminatorKind::Unreachable => { } TerminatorKind::Return => { - self.gather_move(loc, &Lvalue::Local(RETURN_POINTER)); + self.gather_move(&Lvalue::Local(RETURN_POINTER)); } TerminatorKind::Assert { .. } | @@ -287,20 +317,20 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } TerminatorKind::Yield { ref value, .. } => { - self.gather_operand(loc, value); + self.gather_operand(value); } TerminatorKind::Drop { ref location, target: _, unwind: _ } => { - self.gather_move(loc, location); + self.gather_move(location); } TerminatorKind::DropAndReplace { ref location, ref value, .. } => { self.create_move_path(location); - self.gather_operand(loc, value); + self.gather_operand(value); } TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => { - self.gather_operand(loc, func); + self.gather_operand(func); for arg in args { - self.gather_operand(loc, arg); + self.gather_operand(arg); } if let Some((ref destination, _bb)) = *destination { self.create_move_path(destination); @@ -309,37 +339,38 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } } - fn gather_operand(&mut self, loc: Location, operand: &Operand<'tcx>) { + fn gather_operand(&mut self, operand: &Operand<'tcx>) { match *operand { Operand::Constant(..) => {} // not-a-move Operand::Consume(ref lval) => { // a move - self.gather_move(loc, lval); + self.gather_move(lval); } } } - fn gather_move(&mut self, loc: Location, lval: &Lvalue<'tcx>) { - debug!("gather_move({:?}, {:?})", loc, lval); + fn gather_move(&mut self, lval: &Lvalue<'tcx>) { + debug!("gather_move({:?}, {:?})", self.loc, lval); - let lv_ty = lval.ty(self.mir, self.tcx).to_ty(self.tcx); - if !lv_ty.moves_by_default(self.tcx, self.param_env, DUMMY_SP) { - debug!("gather_move({:?}, {:?}) - {:?} is Copy. skipping", loc, lval, lv_ty); + let tcx = self.builder.tcx; + let lv_ty = lval.ty(self.builder.mir, tcx).to_ty(tcx); + if !lv_ty.moves_by_default(tcx, self.builder.param_env, DUMMY_SP) { + debug!("gather_move({:?}, {:?}) - {:?} is Copy. skipping", self.loc, lval, lv_ty); return } let path = match self.move_path_for(lval) { Ok(path) | Err(MoveError::UnionMove { path }) => path, Err(error @ MoveError::IllegalMove { .. }) => { - self.errors.push(error); + self.builder.errors.push(error); return; } }; - let move_out = self.data.moves.push(MoveOut { path: path, source: loc }); + let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc }); debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}", - loc, lval, move_out, path); + self.loc, lval, move_out, path); - self.data.path_map[path].push(move_out); - self.data.loc_map[loc].push(move_out); + self.builder.data.path_map[path].push(move_out); + self.builder.data.loc_map[self.loc].push(move_out); } } diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 61f64e7373d..9369156a223 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -13,7 +13,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec}; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::{Span}; use std::fmt; use std::ops::{Index, IndexMut}; @@ -250,8 +250,8 @@ pub enum MoveError<'tcx> { } impl<'tcx> MoveError<'tcx> { - fn cannot_move_out_of(kind: IllegalMoveOriginKind<'tcx>) -> Self { - let origin = IllegalMoveOrigin { span: DUMMY_SP, kind: kind, }; + fn cannot_move_out_of(span: Span, kind: IllegalMoveOriginKind<'tcx>) -> Self { + let origin = IllegalMoveOrigin { span, kind }; MoveError::IllegalMove { cannot_move_out_of: origin } } } From 86ca5cf94241104c2a24d75f98784f65a40f7baa Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 4 Oct 2017 13:29:55 +0200 Subject: [PATCH 028/365] Unit tests for gathering and reporting move-errors from mir-borrowck. This commit tests *just* the subset of the tests that were previously ICE'ing and where now AST- and MIR-borrowck both match in terms of the errors they report. In other words: there remain *other* tests that previously ICE'd, and now no longer ICE, but their remains a divergence between the errors reported by AST-borrowck and by MIR-borrowck. --- .../borrowck/borrowck-fn-in-const-a.rs | 7 ++++++- .../borrowck/borrowck-move-in-irrefut-pat.rs | 15 ++++++++++++--- .../borrowck-move-out-of-overloaded-auto-deref.rs | 7 ++++++- .../borrowck/borrowck-move-out-of-static-item.rs | 7 ++++++- .../borrowck-move-out-of-struct-with-dtor.rs | 15 ++++++++++++--- .../borrowck/borrowck-struct-update-with-dtor.rs | 11 +++++++++-- .../move-in-static-initializer-issue-38520.rs | 11 +++++++++-- 7 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/test/compile-fail/borrowck/borrowck-fn-in-const-a.rs b/src/test/compile-fail/borrowck/borrowck-fn-in-const-a.rs index 3098807f272..fcdcf198c28 100644 --- a/src/test/compile-fail/borrowck/borrowck-fn-in-const-a.rs +++ b/src/test/compile-fail/borrowck/borrowck-fn-in-const-a.rs @@ -8,12 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + // Check that we check fns appearing in constant declarations. // Issue #22382. const MOVE: fn(&String) -> String = { fn broken(x: &String) -> String { - return *x //~ ERROR cannot move + return *x //[ast]~ ERROR cannot move out of borrowed content [E0507] + //[mir]~^ ERROR (Ast) [E0507] + //[mir]~| ERROR (Mir) [E0507] } broken }; diff --git a/src/test/compile-fail/borrowck/borrowck-move-in-irrefut-pat.rs b/src/test/compile-fail/borrowck/borrowck-move-in-irrefut-pat.rs index ec505faf885..99b5ef794c2 100644 --- a/src/test/compile-fail/borrowck/borrowck-move-in-irrefut-pat.rs +++ b/src/test/compile-fail/borrowck/borrowck-move-in-irrefut-pat.rs @@ -8,19 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + fn with(f: F) where F: FnOnce(&String) {} fn arg_item(&_x: &String) {} - //~^ ERROR cannot move out of borrowed content + //[ast]~^ ERROR cannot move out of borrowed content [E0507] + //[mir]~^^ ERROR (Ast) [E0507] + //[mir]~| ERROR (Mir) [E0507] fn arg_closure() { with(|&_x| ()) - //~^ ERROR cannot move out of borrowed content + //[ast]~^ ERROR cannot move out of borrowed content [E0507] + //[mir]~^^ ERROR (Ast) [E0507] + //[mir]~| ERROR (Mir) [E0507] } fn let_pat() { let &_x = &"hi".to_string(); - //~^ ERROR cannot move out of borrowed content + //[ast]~^ ERROR cannot move out of borrowed content [E0507] + //[mir]~^^ ERROR (Ast) [E0507] + //[mir]~| ERROR (Mir) [E0507] } pub fn main() {} diff --git a/src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs index bf4c7474136..c7e1ea1b758 100644 --- a/src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs +++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + use std::rc::Rc; pub fn main() { let _x = Rc::new(vec![1, 2]).into_iter(); - //~^ ERROR cannot move out of borrowed content + //[ast]~^ ERROR cannot move out of borrowed content [E0507] + //[mir]~^^ ERROR (Ast) [E0507] + //[mir]~| ERROR (Mir) [E0507] } diff --git a/src/test/compile-fail/borrowck/borrowck-move-out-of-static-item.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-static-item.rs index 8b83b945fd1..9e8021fd108 100644 --- a/src/test/compile-fail/borrowck/borrowck-move-out-of-static-item.rs +++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-static-item.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + // Ensure that moves out of static items is forbidden struct Foo { @@ -22,5 +25,7 @@ fn test(f: Foo) { } fn main() { - test(BAR); //~ ERROR cannot move out of static item + test(BAR); //[ast]~ ERROR cannot move out of static item [E0507] + //[mir]~^ ERROR (Ast) [E0507] + //[mir]~| ERROR (Mir) [E0507] } diff --git a/src/test/compile-fail/borrowck/borrowck-move-out-of-struct-with-dtor.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-struct-with-dtor.rs index 16302d276ce..982f31b1341 100644 --- a/src/test/compile-fail/borrowck/borrowck-move-out-of-struct-with-dtor.rs +++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-struct-with-dtor.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + struct S {f:String} impl Drop for S { fn drop(&mut self) { println!("{}", self.f); } @@ -16,17 +19,23 @@ impl Drop for S { fn move_in_match() { match (S {f:"foo".to_string()}) { S {f:_s} => {} - //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + //[ast]~^ ERROR cannot move out of type `S`, which implements the `Drop` trait [E0509] + //[mir]~^^ ERROR (Ast) [E0509] + //[mir]~| ERROR (Mir) [E0509] } } fn move_in_let() { let S {f:_s} = S {f:"foo".to_string()}; - //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + //[ast]~^ ERROR cannot move out of type `S`, which implements the `Drop` trait [E0509] + //[mir]~^^ ERROR (Ast) [E0509] + //[mir]~| ERROR (Mir) [E0509] } fn move_in_fn_arg(S {f:_s}: S) { - //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + //[ast]~^ ERROR cannot move out of type `S`, which implements the `Drop` trait [E0509] + //[mir]~^^ ERROR (Ast) [E0509] + //[mir]~| ERROR (Mir) [E0509] } fn main() {} diff --git a/src/test/compile-fail/borrowck/borrowck-struct-update-with-dtor.rs b/src/test/compile-fail/borrowck/borrowck-struct-update-with-dtor.rs index c364788a9cc..4a1828c6958 100644 --- a/src/test/compile-fail/borrowck/borrowck-struct-update-with-dtor.rs +++ b/src/test/compile-fail/borrowck/borrowck-struct-update-with-dtor.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + // Issue 4691: Ensure that functional-struct-update can only copy, not // move, when the struct implements Drop. @@ -20,12 +23,16 @@ impl Drop for T { fn drop(&mut self) { } } fn f(s0:S) { let _s2 = S{a: 2, ..s0}; - //~^ error: cannot move out of type `S`, which implements the `Drop` trait + //[ast]~^ error: cannot move out of type `S`, which implements the `Drop` trait + //[mir]~^^ ERROR (Ast) [E0509] + //[mir]~| ERROR (Mir) [E0509] } fn g(s0:T) { let _s2 = T{a: 2, ..s0}; - //~^ error: cannot move out of type `T`, which implements the `Drop` trait + //[ast]~^ error: cannot move out of type `T`, which implements the `Drop` trait + //[mir]~^^ ERROR (Ast) [E0509] + //[mir]~| ERROR (Mir) [E0509] } fn main() { } diff --git a/src/test/compile-fail/borrowck/move-in-static-initializer-issue-38520.rs b/src/test/compile-fail/borrowck/move-in-static-initializer-issue-38520.rs index 3c1980e5b36..7f3120cc83e 100644 --- a/src/test/compile-fail/borrowck/move-in-static-initializer-issue-38520.rs +++ b/src/test/compile-fail/borrowck/move-in-static-initializer-issue-38520.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + // Regression test for #38520. Check that moves of `Foo` are not // permitted as `Foo` is not copy (even in a static/const // initializer). @@ -21,8 +24,12 @@ const fn get(x: Foo) -> usize { } const X: Foo = Foo(22); -static Y: usize = get(*&X); //~ ERROR E0507 -const Z: usize = get(*&X); //~ ERROR E0507 +static Y: usize = get(*&X); //[ast]~ ERROR E0507 + //[mir]~^ ERROR (Ast) [E0507] + //[mir]~| ERROR (Mir) [E0507] +const Z: usize = get(*&X); //[ast]~ ERROR E0507 + //[mir]~^ ERROR (Ast) [E0507] + //[mir]~| ERROR (Mir) [E0507] fn main() { } From 7428806bf9a4efb1ec9ebb737fadabf882e7b255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malo=20Jaffr=C3=A9?= Date: Wed, 4 Oct 2017 15:12:01 +0200 Subject: [PATCH 029/365] Fix some E-needstest issues. Also ignore `attr-on-trait` test on stage-1 to keep `./x.py test --stage 1` successful. Fixes #30355. Fixes #33241. Fixes #36400. Fixes #37887. Fixes #44578. --- src/test/compile-fail/issue-30355.rs | 21 ++++++++++++ src/test/compile-fail/issue-33241.rs | 23 +++++++++++++ src/test/compile-fail/issue-37887.rs | 14 ++++++++ src/test/compile-fail/issue-44578.rs | 34 +++++++++++++++++++ .../proc-macro/attr-on-trait.rs | 1 + src/test/ui/issue-36400.rs | 16 +++++++++ src/test/ui/issue-36400.stderr | 10 ++++++ 7 files changed, 119 insertions(+) create mode 100644 src/test/compile-fail/issue-30355.rs create mode 100644 src/test/compile-fail/issue-33241.rs create mode 100644 src/test/compile-fail/issue-37887.rs create mode 100644 src/test/compile-fail/issue-44578.rs create mode 100644 src/test/ui/issue-36400.rs create mode 100644 src/test/ui/issue-36400.stderr diff --git a/src/test/compile-fail/issue-30355.rs b/src/test/compile-fail/issue-30355.rs new file mode 100644 index 00000000000..ee19d040318 --- /dev/null +++ b/src/test/compile-fail/issue-30355.rs @@ -0,0 +1,21 @@ +// Copyright 2017 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 X([u8]); + +pub static Y: &'static X = { + const Y: &'static [u8] = b""; + &X(*Y) + //~^ ERROR cannot move out + //~^^ ERROR cannot move a + //~^^^ ERROR cannot move a +}; + +fn main() {} diff --git a/src/test/compile-fail/issue-33241.rs b/src/test/compile-fail/issue-33241.rs new file mode 100644 index 00000000000..6a411b4c59c --- /dev/null +++ b/src/test/compile-fail/issue-33241.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +use std::fmt; + +// CoerceUnsized is not implemented for tuples. You can still create +// an unsized tuple by transmuting a trait object. +fn any() -> T { unreachable!() } + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let t: &(u8, fmt::Debug) = any(); + println!("{:?}", &t.1); +} diff --git a/src/test/compile-fail/issue-37887.rs b/src/test/compile-fail/issue-37887.rs new file mode 100644 index 00000000000..f120bbbfc9f --- /dev/null +++ b/src/test/compile-fail/issue-37887.rs @@ -0,0 +1,14 @@ +// Copyright 2017 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. + +fn main() { + extern crate libc; //~ ERROR use of unstable + use libc::*; //~ ERROR unresolved import +} diff --git a/src/test/compile-fail/issue-44578.rs b/src/test/compile-fail/issue-44578.rs new file mode 100644 index 00000000000..a6ae21c3b54 --- /dev/null +++ b/src/test/compile-fail/issue-44578.rs @@ -0,0 +1,34 @@ +// Copyright 2017 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. + +trait Foo { + const AMT: usize; +} + +enum Bar { + First(A), + Second(B), +} + +impl Foo for Bar { + const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; //~ ERROR constant evaluation +} + +impl Foo for u8 { + const AMT: usize = 1; +} + +impl Foo for u16 { + const AMT: usize = 2; +} + +fn main() { + println!("{}", as Foo>::AMT); +} diff --git a/src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs b/src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs index 8ba38875eff..52a8652e65b 100644 --- a/src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs +++ b/src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:attr-on-trait.rs +// ignore-stage1 #![feature(proc_macro)] diff --git a/src/test/ui/issue-36400.rs b/src/test/ui/issue-36400.rs new file mode 100644 index 00000000000..c0aec5b4296 --- /dev/null +++ b/src/test/ui/issue-36400.rs @@ -0,0 +1,16 @@ +// Copyright 2017 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. + +fn f(x: &mut u32) {} + +fn main() { + let x = Box::new(3); + f(&mut *x); +} diff --git a/src/test/ui/issue-36400.stderr b/src/test/ui/issue-36400.stderr new file mode 100644 index 00000000000..69e9c455f35 --- /dev/null +++ b/src/test/ui/issue-36400.stderr @@ -0,0 +1,10 @@ +error[E0596]: cannot borrow immutable `Box` content `*x` as mutable + --> $DIR/issue-36400.rs:15:12 + | +14 | let x = Box::new(3); + | - consider changing this to `mut x` +15 | f(&mut *x); + | ^^ cannot borrow as mutable + +error: aborting due to previous error + From ad9b1ed9c286d26666b7892145c5cae7f98488bc Mon Sep 17 00:00:00 2001 From: Garrett Berg Date: Mon, 2 Oct 2017 01:08:13 -0600 Subject: [PATCH 030/365] groundwork for #45009: rustc_dirty/clean enhancements --- src/librustc/dep_graph/dep_node.rs | 19 ++++++ .../persist/dirty_clean.rs | 59 +++++++++++++++---- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 7a78765365d..eef99b0eb28 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -339,6 +339,25 @@ macro_rules! define_dep_nodes { Ok(DepNode::new_no_params(kind)) } } + + /// Used in testing + pub fn has_label_string(label: &str) -> bool { + match label { + $( + stringify!($variant) => true, + )* + _ => false, + } + } + } + + /// Contains variant => str representations for constructing + /// DepNode groups for tests. + #[allow(dead_code, non_upper_case_globals)] + pub mod label_strs { + $( + pub const $variant: &'static str = stringify!($variant); + )* } ); } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index a6d39a91863..186759d6219 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -39,6 +39,8 @@ //! previous revision to compare things to. //! +use std::collections::HashSet; +use std::vec::Vec; use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; @@ -54,6 +56,8 @@ use rustc::ty::TyCtxt; const LABEL: &'static str = "label"; const CFG: &'static str = "cfg"; +type Labels = HashSet; + pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // can't add `#[rustc_dirty]` etc without opting in to this feature if !tcx.sess.features.borrow().rustc_attrs { @@ -87,25 +91,48 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> { } impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { - fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode { - let def_path_hash = self.tcx.def_path_hash(def_id); + fn labels(&self, attr: &Attribute) -> Labels { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(LABEL) { let value = expect_associated_value(self.tcx, &item); - match DepNode::from_label_string(&value.as_str(), def_path_hash) { - Ok(dep_node) => return dep_node, - Err(()) => { - self.tcx.sess.span_fatal( - item.span, - &format!("dep-node label `{}` not recognized", value)); - } - } + return self.resolve_labels(&item, value.as_str().as_ref()); } } - self.tcx.sess.span_fatal(attr.span, "no `label` found"); } + fn resolve_labels(&self, item: &NestedMetaItem, value: &str) -> Labels { + let mut out: Labels = HashSet::new(); + for label in value.split(',') { + let label = label.trim(); + if DepNode::has_label_string(label) { + if out.contains(label) { + self.tcx.sess.span_fatal( + item.span, + &format!("dep-node label `{}` is repeated", label)); + } + out.insert(label.to_string()); + } else { + self.tcx.sess.span_fatal( + item.span, + &format!("dep-node label `{}` not recognized", label)); + } + } + out + } + + fn dep_nodes(&self, labels: &Labels, def_id: DefId) -> Vec { + let mut out = Vec::with_capacity(labels.len()); + let def_path_hash = self.tcx.def_path_hash(def_id); + for label in labels.iter() { + match DepNode::from_label_string(label, def_path_hash) { + Ok(dep_node) => out.push(dep_node), + Err(()) => unreachable!(), + } + } + out + } + fn dep_node_str(&self, dep_node: &DepNode) -> String { if let Some(def_id) = dep_node.extract_def_id(self.tcx) { format!("{:?}({})", @@ -150,12 +177,18 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { if attr.check_name(ATTR_DIRTY) { if check_config(self.tcx, attr) { self.checked_attrs.insert(attr.id); - self.assert_dirty(item_span, self.dep_node(attr, def_id)); + let labels = self.labels(attr); + for dep_node in self.dep_nodes(&labels, def_id) { + self.assert_dirty(item_span, dep_node); + } } } else if attr.check_name(ATTR_CLEAN) { if check_config(self.tcx, attr) { self.checked_attrs.insert(attr.id); - self.assert_clean(item_span, self.dep_node(attr, def_id)); + let labels = self.labels(attr); + for dep_node in self.dep_nodes(&labels, def_id) { + self.assert_clean(item_span, dep_node); + } } } } From a6dea41d64a244c8f7671dd0eeb498b015c3a712 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 4 Oct 2017 17:29:37 -0400 Subject: [PATCH 031/365] Make -Cpanic=abort imply -Zmutable-noalias --- src/librustc_trans/abi.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 5dc2e992972..ee295bdf0b4 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -37,6 +37,7 @@ use type_of; use rustc::hir; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, Layout, LayoutTyper, TyLayout, Size}; +use rustc_back::PanicStrategy; use libc::c_uint; use std::cmp; @@ -761,7 +762,8 @@ impl<'a, 'tcx> FnType<'tcx> { let is_freeze = ccx.shared().type_is_freeze(mt.ty); let no_alias_is_safe = - if ccx.shared().tcx().sess.opts.debugging_opts.mutable_noalias { + if ccx.shared().tcx().sess.opts.debugging_opts.mutable_noalias || + ccx.shared().tcx().sess.panic_strategy() == PanicStrategy::Abort { // Mutable refrences or immutable shared references mt.mutbl == hir::MutMutable || is_freeze } else { From ac25a4ac329a083a9693fe5d9d1600024db9b35c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 5 Oct 2017 01:02:25 +0300 Subject: [PATCH 032/365] rustc_trans: do not set NoCapture for anonymous lifetime &T arguments. --- src/librustc_trans/abi.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 2aecc016a5c..1f72ae849e6 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -750,9 +750,7 @@ impl<'a, 'tcx> FnType<'tcx> { Some(ty.boxed_ty()) } - ty::TyRef(b, mt) => { - use rustc::ty::{BrAnon, ReLateBound}; - + ty::TyRef(_, mt) => { // `&mut` pointer parameters never alias other parameters, or mutable global data // // `&T` where `T` contains no `UnsafeCell` is immutable, and can be marked as @@ -768,13 +766,6 @@ impl<'a, 'tcx> FnType<'tcx> { arg.attrs.set(ArgAttribute::ReadOnly); } - // When a reference in an argument has no named lifetime, it's - // impossible for that reference to escape this function - // (returned or stored beyond the call by a closure). - if let ReLateBound(_, BrAnon(_)) = *b { - arg.attrs.set(ArgAttribute::NoCapture); - } - Some(mt.ty) } _ => None From 17a2a766ac61762fdec7e89c80ce9f8ac97bf654 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Wed, 4 Oct 2017 14:08:53 -0700 Subject: [PATCH 033/365] zircon: the type of zx_handle_t is now unsigned This is a kernel ABI change that landed today. I noticed some other ABI issues and have left a note to cleanup once they are better defined. --- src/libstd/sys/unix/process/zircon.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index b5ec11b40fd..8d0ad30f9c8 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -17,11 +17,16 @@ use u64; use libc::{c_int, c_void}; -pub type zx_handle_t = i32; +pub type zx_handle_t = u32; pub type zx_vaddr_t = usize; pub type zx_rights_t = u32; pub type zx_status_t = i32; +// TODO(raggi): zx_size_t was removed from Zircon. various syscall API docs use size_t here, but +// don't define that well at the ABI level yet, as the C spec definition of size_t isn't what is +// meant. In the future Zirocn will define size_t more strictly for it's ABI. At that time, +// zx_size_t should be removed here, and replaced with an appropriately sized type with a +// sufficiently strict definition. pub type zx_size_t = usize; pub const ZX_HANDLE_INVALID: zx_handle_t = 0; From a82891ab5cca30515807fb799f9d9f08fa998d08 Mon Sep 17 00:00:00 2001 From: bgermann Date: Thu, 5 Oct 2017 00:40:36 +0200 Subject: [PATCH 034/365] Rename dist-fuchsia builder to cross2 --- src/ci/docker/{dist-fuchsia => cross2}/Dockerfile | 0 .../build-toolchain.sh => cross2/build-fuchsia-toolchain.sh} | 0 src/ci/docker/{dist-fuchsia => cross2}/shared.sh | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/ci/docker/{dist-fuchsia => cross2}/Dockerfile (100%) rename src/ci/docker/{dist-fuchsia/build-toolchain.sh => cross2/build-fuchsia-toolchain.sh} (100%) rename src/ci/docker/{dist-fuchsia => cross2}/shared.sh (100%) diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/cross2/Dockerfile similarity index 100% rename from src/ci/docker/dist-fuchsia/Dockerfile rename to src/ci/docker/cross2/Dockerfile diff --git a/src/ci/docker/dist-fuchsia/build-toolchain.sh b/src/ci/docker/cross2/build-fuchsia-toolchain.sh similarity index 100% rename from src/ci/docker/dist-fuchsia/build-toolchain.sh rename to src/ci/docker/cross2/build-fuchsia-toolchain.sh diff --git a/src/ci/docker/dist-fuchsia/shared.sh b/src/ci/docker/cross2/shared.sh similarity index 100% rename from src/ci/docker/dist-fuchsia/shared.sh rename to src/ci/docker/cross2/shared.sh From fb03bb72b9c5e46d98726ba520ba08fe8ba2082f Mon Sep 17 00:00:00 2001 From: James Tucker Date: Wed, 4 Oct 2017 15:29:01 -0700 Subject: [PATCH 035/365] zircon: update some more zx and lp constants * Use size_t where size_t is used, while it's not critical on our specifically supported architectures, this is more accurate. * Update HND_SPECIAL_COUNT to the correct value, and give it the size that enum is likely to be. --- .../sys/unix/process/process_fuchsia.rs | 10 +++---- src/libstd/sys/unix/process/zircon.rs | 28 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index 5d34da04446..a7a67ed36e8 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -9,7 +9,7 @@ // except according to those terms. use io; -use libc; +use libc::{self, size_t}; use mem; use ptr; @@ -148,8 +148,8 @@ impl Process { use sys::process::zircon::*; let mut proc_info: zx_info_process_t = Default::default(); - let mut actual: zx_size_t = 0; - let mut avail: zx_size_t = 0; + let mut actual: size_t = 0; + let mut avail: size_t = 0; unsafe { zx_cvt(zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED, @@ -171,8 +171,8 @@ impl Process { use sys::process::zircon::*; let mut proc_info: zx_info_process_t = Default::default(); - let mut actual: zx_size_t = 0; - let mut avail: zx_size_t = 0; + let mut actual: size_t = 0; + let mut avail: size_t = 0; unsafe { let status = zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED, diff --git a/src/libstd/sys/unix/process/zircon.rs b/src/libstd/sys/unix/process/zircon.rs index 8d0ad30f9c8..90864e6ef3f 100644 --- a/src/libstd/sys/unix/process/zircon.rs +++ b/src/libstd/sys/unix/process/zircon.rs @@ -15,20 +15,13 @@ use io; use os::raw::c_char; use u64; -use libc::{c_int, c_void}; +use libc::{c_int, c_void, size_t}; pub type zx_handle_t = u32; pub type zx_vaddr_t = usize; pub type zx_rights_t = u32; pub type zx_status_t = i32; -// TODO(raggi): zx_size_t was removed from Zircon. various syscall API docs use size_t here, but -// don't define that well at the ABI level yet, as the C spec definition of size_t isn't what is -// meant. In the future Zirocn will define size_t more strictly for it's ABI. At that time, -// zx_size_t should be removed here, and replaced with an appropriately sized type with a -// sufficiently strict definition. -pub type zx_size_t = usize; - pub const ZX_HANDLE_INVALID: zx_handle_t = 0; pub type zx_time_t = u64; @@ -120,36 +113,37 @@ extern { pending: *mut zx_signals_t) -> zx_status_t; pub fn zx_object_get_info(handle: zx_handle_t, topic: u32, buffer: *mut c_void, - buffer_size: zx_size_t, actual_size: *mut zx_size_t, - avail: *mut zx_size_t) -> zx_status_t; + buffer_size: size_t, actual_size: *mut size_t, + avail: *mut size_t) -> zx_status_t; } // From `enum special_handles` in system/ulib/launchpad/launchpad.c // HND_LOADER_SVC = 0 // HND_EXEC_VMO = 1 -pub const HND_SPECIAL_COUNT: usize = 2; +// HND_SEGMENTS_VMAR = 2 +const HND_SPECIAL_COUNT: c_int = 3; #[repr(C)] pub struct launchpad_t { argc: u32, envc: u32, args: *const c_char, - args_len: usize, + args_len: size_t, env: *const c_char, - env_len: usize, + env_len: size_t, handles: *mut zx_handle_t, handles_info: *mut u32, - handle_count: usize, - handle_alloc: usize, + handle_count: size_t, + handle_alloc: size_t, entry: zx_vaddr_t, base: zx_vaddr_t, vdso_base: zx_vaddr_t, - stack_size: usize, + stack_size: size_t, - special_handles: [zx_handle_t; HND_SPECIAL_COUNT], + special_handles: [zx_handle_t; HND_SPECIAL_COUNT as usize], loader_message: bool, } From a70c5cb68f84e576b16fbca86453240290e7cc22 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Oct 2017 16:21:38 -0700 Subject: [PATCH 036/365] rustc: Don't create empty codegen units This'll end up just creating a bunch of object files that otherwise wouldn't exist, so skip that extra work if possible. --- src/librustc_trans/base.rs | 3 --- src/librustc_trans/partitioning.rs | 9 --------- 2 files changed, 12 deletions(-) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 0568bd2f3ca..94e1d238c64 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1178,9 +1178,6 @@ fn collect_and_partition_translation_items<'a, 'tcx>( .collect::>() }); - assert!(tcx.sess.opts.codegen_units == codegen_units.len() || - tcx.sess.opts.debugging_opts.incremental.is_some()); - let translation_items: DefIdSet = items.iter().filter_map(|trans_item| { match *trans_item { TransItem::Fn(ref instance) => Some(instance.def_id()), diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 7c29186f465..a84bfd15402 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -407,15 +407,6 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning< for (index, cgu) in codegen_units.iter_mut().enumerate() { cgu.set_name(numbered_codegen_unit_name(crate_name, index)); } - - // If the initial partitioning contained less than target_cgu_count to begin - // with, we won't have enough codegen units here, so add a empty units until - // we reach the target count - while codegen_units.len() < target_cgu_count { - let index = codegen_units.len(); - let name = numbered_codegen_unit_name(crate_name, index); - codegen_units.push(CodegenUnit::new(name)); - } } fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartitioning<'tcx>, From 4e69d2e3eb66ed3c5c68c22561015052df1293cb Mon Sep 17 00:00:00 2001 From: bgermann Date: Thu, 5 Oct 2017 01:22:30 +0200 Subject: [PATCH 037/365] Merge dist-solaris with cross2 builder --- .travis.yml | 4 +- src/ci/docker/cross2/Dockerfile | 43 ++++++++++++------- .../build-solaris-toolchain.sh} | 17 +------- src/ci/docker/dist-solaris/Dockerfile | 29 ------------- 4 files changed, 30 insertions(+), 63 deletions(-) rename src/ci/docker/{dist-solaris/build-toolchain.sh => cross2/build-solaris-toolchain.sh} (89%) delete mode 100644 src/ci/docker/dist-solaris/Dockerfile diff --git a/.travis.yml b/.travis.yml index 9e3225a103a..139f06ec570 100644 --- a/.travis.yml +++ b/.travis.yml @@ -115,6 +115,8 @@ matrix: if: branch = auto - env: IMAGE=cross DEPLOY=1 if: branch = auto + - env: IMAGE=cross2 DEPLOY=1 + if: branch = auto - env: IMAGE=dist-aarch64-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-android DEPLOY=1 @@ -125,8 +127,6 @@ matrix: if: branch = auto - env: IMAGE=dist-armv7-linux DEPLOY=1 if: branch = auto - - env: IMAGE=dist-fuchsia DEPLOY=1 - if: branch = auto - env: IMAGE=dist-i586-gnu-i686-musl DEPLOY=1 if: branch = auto - env: IMAGE=dist-i686-freebsd DEPLOY=1 diff --git a/src/ci/docker/cross2/Dockerfile b/src/ci/docker/cross2/Dockerfile index bcd95924b42..6f854197191 100644 --- a/src/ci/docker/cross2/Dockerfile +++ b/src/ci/docker/cross2/Dockerfile @@ -1,27 +1,30 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y \ +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +RUN apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \ build-essential \ - bzip2 \ - ca-certificates \ - cmake \ - curl \ - file \ - g++ \ - gdb \ - git \ libedit-dev \ - make \ + libgmp-dev \ + libisl-dev \ + libmpc-dev \ + libmpfr-dev \ ninja-build \ nodejs \ python2.7-dev \ - sudo \ - xz-utils \ + software-properties-common \ unzip +RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 +RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2-testing main' + WORKDIR /tmp -COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh /tmp/ -RUN /tmp/build-toolchain.sh +COPY cross2/shared.sh cross2/build-fuchsia-toolchain.sh /tmp/ +COPY cross2/build-solaris-toolchain.sh /tmp/ +RUN /tmp/build-fuchsia-toolchain.sh +RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 +RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh @@ -32,10 +35,18 @@ ENV \ CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \ AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \ CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \ - CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ + CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ \ + AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-ar \ + CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-sysroot \ + CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-g++ \ + AR_x86_64_sun_solaris=x86_64-sun-solaris2.11-ar \ + CC_x86_64_sun_solaris=x86_64-sun-solaris2.11-sysroot \ + CXX_x86_64_sun_solaris=x86_64-sun-solaris2.11-g++ ENV TARGETS=x86_64-unknown-fuchsia ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia +ENV TARGETS=$TARGETS,sparcv9-sun-solaris +ENV TARGETS=$TARGETS,x86_64-sun-solaris ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended -ENV SCRIPT python2.7 ../x.py dist --target $TARGETS \ No newline at end of file +ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/ci/docker/dist-solaris/build-toolchain.sh b/src/ci/docker/cross2/build-solaris-toolchain.sh similarity index 89% rename from src/ci/docker/dist-solaris/build-toolchain.sh rename to src/ci/docker/cross2/build-solaris-toolchain.sh index c0d839a5fb7..4ff26b5dfab 100755 --- a/src/ci/docker/dist-solaris/build-toolchain.sh +++ b/src/ci/docker/cross2/build-solaris-toolchain.sh @@ -10,6 +10,7 @@ # except according to those terms. set -ex +source shared.sh ARCH=$1 LIB_ARCH=$2 @@ -17,22 +18,6 @@ APT_ARCH=$3 BINUTILS=2.28.1 GCC=6.4.0 -hide_output() { - set +x - on_err=" -echo ERROR: An error was encountered with the build. -cat /tmp/build.log -exit 1 -" - trap "$on_err" ERR - bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & - PING_LOOP_PID=$! - $@ &> /tmp/build.log - trap - ERR - kill $PING_LOOP_PID - set -x -} - # First up, build binutils mkdir binutils cd binutils diff --git a/src/ci/docker/dist-solaris/Dockerfile b/src/ci/docker/dist-solaris/Dockerfile deleted file mode 100644 index a60c9956b75..00000000000 --- a/src/ci/docker/dist-solaris/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM ubuntu:16.04 - -COPY scripts/cross-apt-packages.sh /scripts/ -RUN sh /scripts/cross-apt-packages.sh - -RUN apt-get install -y --no-install-recommends \ - software-properties-common libgmp-dev libmpfr-dev libmpc-dev libisl-dev -RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 -RUN add-apt-repository -y 'deb http://apt.dilos.org/dilos dilos2-testing main' - -COPY dist-solaris/build-toolchain.sh /tmp/ -RUN /tmp/build-toolchain.sh x86_64 amd64 solaris-i386 -RUN /tmp/build-toolchain.sh sparcv9 sparcv9 solaris-sparc - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV \ - AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-ar \ - CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-sysroot \ - CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-g++ \ - AR_x86_64_sun_solaris=x86_64-sun-solaris2.11-ar \ - CC_x86_64_sun_solaris=x86_64-sun-solaris2.11-sysroot \ - CXX_x86_64_sun_solaris=x86_64-sun-solaris2.11-g++ - -ENV TARGETS=sparcv9-sun-solaris,x86_64-sun-solaris - -ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended -ENV SCRIPT python2.7 ../x.py dist --target $TARGETS From 6f7dd654cdf5aeec714914ec0848fb711662fa11 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 5 Oct 2017 05:01:02 +0200 Subject: [PATCH 038/365] Remove nacl from librustc_llvm --- src/librustc_llvm/build.rs | 2 +- src/librustc_llvm/lib.rs | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index dde7a38efc7..12d57e78c69 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -88,7 +88,7 @@ fn main() { let is_crossed = target != host; let mut optional_components = - vec!["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", + vec!["x86", "arm", "aarch64", "mips", "powerpc", "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx"]; let mut version_cmd = Command::new(&llvm_config); diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 9be5f5b5486..98172bca177 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -346,10 +346,6 @@ pub fn initialize_available_targets() { LLVMInitializePowerPCTargetMC, LLVMInitializePowerPCAsmPrinter, LLVMInitializePowerPCAsmParser); - init_target!(llvm_component = "pnacl", - LLVMInitializePNaClTargetInfo, - LLVMInitializePNaClTarget, - LLVMInitializePNaClTargetMC); init_target!(llvm_component = "systemz", LLVMInitializeSystemZTargetInfo, LLVMInitializeSystemZTarget, From b8fad2d21961307ec908ced9d3e2a64595eb5deb Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 5 Oct 2017 05:01:19 +0200 Subject: [PATCH 039/365] Remove nacl from librustc_back --- src/librustc_back/target/le32_unknown_nacl.rs | 51 ------------------- src/librustc_back/target/mod.rs | 1 - 2 files changed, 52 deletions(-) delete mode 100644 src/librustc_back/target/le32_unknown_nacl.rs diff --git a/src/librustc_back/target/le32_unknown_nacl.rs b/src/librustc_back/target/le32_unknown_nacl.rs deleted file mode 100644 index 9af4606f1f1..00000000000 --- a/src/librustc_back/target/le32_unknown_nacl.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 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. - -use LinkerFlavor; -use super::{LinkArgs, Target, TargetOptions, TargetResult}; - -pub fn target() -> TargetResult { - let mut pre_link_args = LinkArgs::new(); - pre_link_args.insert(LinkerFlavor::Gcc, - vec!["--pnacl-exceptions=sjlj".to_string(), - "--target=le32-unknown-nacl".to_string(), - "-Wl,--start-group".to_string()]); - let mut post_link_args = LinkArgs::new(); - post_link_args.insert(LinkerFlavor::Gcc, - vec!["-Wl,--end-group".to_string()]); - - let opts = TargetOptions { - linker: "pnacl-clang".to_string(), - ar: "pnacl-ar".to_string(), - - pre_link_args, - post_link_args, - dynamic_linking: false, - executables: true, - exe_suffix: ".pexe".to_string(), - linker_is_gnu: true, - allow_asm: false, - max_atomic_width: Some(32), - .. Default::default() - }; - Ok(Target { - llvm_target: "le32-unknown-nacl".to_string(), - target_endian: "little".to_string(), - target_pointer_width: "32".to_string(), - target_c_int_width: "32".to_string(), - target_os: "nacl".to_string(), - target_env: "newlib".to_string(), - target_vendor: "unknown".to_string(), - data_layout: "e-i64:64:64-p:32:32:32-v128:32:32".to_string(), - arch: "le32".to_string(), - linker_flavor: LinkerFlavor::Gcc, - options: opts, - }) -} diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index b1b208d2de4..039e0153656 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -215,7 +215,6 @@ supported_targets! { ("i686-pc-windows-msvc", i686_pc_windows_msvc), ("i586-pc-windows-msvc", i586_pc_windows_msvc), - ("le32-unknown-nacl", le32_unknown_nacl), ("asmjs-unknown-emscripten", asmjs_unknown_emscripten), ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-experimental-emscripten", wasm32_experimental_emscripten), From aad1c998c7a08dd06719845dd5b3b962dfcb0be7 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 5 Oct 2017 05:01:41 +0200 Subject: [PATCH 040/365] Remove nacl from libstd --- src/libstd/os/mod.rs | 1 - src/libstd/os/nacl/fs.rs | 128 ------------------ src/libstd/os/nacl/mod.rs | 16 --- src/libstd/os/nacl/raw.rs | 56 -------- src/libstd/sys/unix/env.rs | 21 --- src/libstd/sys/unix/mod.rs | 5 +- src/libstd/sys/unix/os.rs | 2 - src/libstd/sys/unix/process/process_common.rs | 1 - src/libstd/sys/unix/process/process_unix.rs | 4 +- src/libstd/sys_common/backtrace.rs | 2 - 10 files changed, 4 insertions(+), 232 deletions(-) delete mode 100644 src/libstd/os/nacl/fs.rs delete mode 100644 src/libstd/os/nacl/mod.rs delete mode 100644 src/libstd/os/nacl/raw.rs diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index b460bd90f17..122f15d1d4c 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -38,7 +38,6 @@ pub mod linux; #[cfg(all(not(dox), target_os = "haiku"))] pub mod haiku; #[cfg(all(not(dox), target_os = "ios"))] pub mod ios; #[cfg(all(not(dox), target_os = "macos"))] pub mod macos; -#[cfg(all(not(dox), target_os = "nacl"))] pub mod nacl; #[cfg(all(not(dox), target_os = "netbsd"))] pub mod netbsd; #[cfg(all(not(dox), target_os = "openbsd"))] pub mod openbsd; #[cfg(all(not(dox), target_os = "solaris"))] pub mod solaris; diff --git a/src/libstd/os/nacl/fs.rs b/src/libstd/os/nacl/fs.rs deleted file mode 100644 index 3e0fb44b01e..00000000000 --- a/src/libstd/os/nacl/fs.rs +++ /dev/null @@ -1,128 +0,0 @@ -// 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. - -#![stable(feature = "metadata_ext", since = "1.1.0")] - -use libc; - -use fs::Metadata; -use sys_common::AsInner; - -#[allow(deprecated)] -use os::nacl::raw; - -/// OS-specific extension methods for `fs::Metadata` -#[stable(feature = "metadata_ext", since = "1.1.0")] -pub trait MetadataExt { - /// Gain a reference to the underlying `stat` structure which contains - /// the raw information returned by the OS. - /// - /// The contents of the returned `stat` are **not** consistent across - /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the - /// cross-Unix abstractions contained within the raw stat. - #[stable(feature = "metadata_ext", since = "1.1.0")] - #[rustc_deprecated(since = "1.8.0", - reason = "deprecated in favor of the accessor \ - methods of this trait")] - #[allow(deprecated)] - fn as_raw_stat(&self) -> &raw::stat; - - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_dev(&self) -> u64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_ino(&self) -> u64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_mode(&self) -> u32; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_nlink(&self) -> u64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_uid(&self) -> u32; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_gid(&self) -> u32; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_rdev(&self) -> u64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_size(&self) -> u64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_atime(&self) -> i64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_atime_nsec(&self) -> i64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_mtime(&self) -> i64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_mtime_nsec(&self) -> i64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_ctime(&self) -> i64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_ctime_nsec(&self) -> i64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_blksize(&self) -> u64; - #[stable(feature = "metadata_ext2", since = "1.8.0")] - fn st_blocks(&self) -> u64; -} - -#[stable(feature = "metadata_ext", since = "1.1.0")] -impl MetadataExt for Metadata { - #[allow(deprecated)] - fn as_raw_stat(&self) -> &raw::stat { - unsafe { - &*(self.as_inner().as_inner() as *const libc::stat64 - as *const raw::stat) - } - } - fn st_dev(&self) -> u64 { - self.as_inner().as_inner().st_dev as u64 - } - fn st_ino(&self) -> u64 { - self.as_inner().as_inner().st_ino as u64 - } - fn st_mode(&self) -> u32 { - self.as_inner().as_inner().st_mode as u32 - } - fn st_nlink(&self) -> u64 { - self.as_inner().as_inner().st_nlink as u64 - } - fn st_uid(&self) -> u32 { - self.as_inner().as_inner().st_uid as u32 - } - fn st_gid(&self) -> u32 { - self.as_inner().as_inner().st_gid as u32 - } - fn st_rdev(&self) -> u64 { - self.as_inner().as_inner().st_rdev as u64 - } - fn st_size(&self) -> u64 { - self.as_inner().as_inner().st_size as u64 - } - fn st_atime(&self) -> i64 { - self.as_inner().as_inner().st_atime as i64 - } - fn st_atime_nsec(&self) -> i64 { - self.as_inner().as_inner().st_atime_nsec as i64 - } - fn st_mtime(&self) -> i64 { - self.as_inner().as_inner().st_mtime as i64 - } - fn st_mtime_nsec(&self) -> i64 { - self.as_inner().as_inner().st_mtime_nsec as i64 - } - fn st_ctime(&self) -> i64 { - self.as_inner().as_inner().st_ctime as i64 - } - fn st_ctime_nsec(&self) -> i64 { - self.as_inner().as_inner().st_ctime_nsec as i64 - } - fn st_blksize(&self) -> u64 { - self.as_inner().as_inner().st_blksize as u64 - } - fn st_blocks(&self) -> u64 { - self.as_inner().as_inner().st_blocks as u64 - } -} diff --git a/src/libstd/os/nacl/mod.rs b/src/libstd/os/nacl/mod.rs deleted file mode 100644 index 7dfa2eabe3e..00000000000 --- a/src/libstd/os/nacl/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 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. - -//! Nacl-specific definitions - -#![stable(feature = "raw_ext", since = "1.1.0")] - -pub mod raw; -pub mod fs; diff --git a/src/libstd/os/nacl/raw.rs b/src/libstd/os/nacl/raw.rs deleted file mode 100644 index 3c3d4410a2a..00000000000 --- a/src/libstd/os/nacl/raw.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 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. - -//! Nacl-specific raw type definitions - -#![stable(feature = "raw_ext", since = "1.1.0")] -#![rustc_deprecated(since = "1.8.0", - reason = "these type aliases are no longer supported by \ - the standard library, the `libc` crate on \ - crates.io should be used instead for the correct \ - definitions")] -#![allow(deprecated)] - -#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type pid_t = i32; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type uid_t = u32; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type gid_t = u32; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u64; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64; -#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64; - -#[stable(feature = "pthread_t", since = "1.8.0")] -pub type pthread_t = usize; - -#[repr(C)] -#[derive(Copy, Clone)] -#[stable(feature = "raw_ext", since = "1.1.0")] -pub struct stat { - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_dev: dev_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ino: ino_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mode: mode_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_nlink: nlink_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_uid: uid_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_gid: gid_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_rdev: dev_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_size: off_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blksize: blksize_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_blocks: blkcnt_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime: time_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_atime_nsec: i64, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime: time_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_mtime_nsec: i64, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime: time_t, - #[stable(feature = "raw_ext", since = "1.1.0")] pub st_ctime_nsec: i64, -} diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs index 3d9a06bedd5..00cf7eca75d 100644 --- a/src/libstd/sys/unix/env.rs +++ b/src/libstd/sys/unix/env.rs @@ -118,27 +118,6 @@ pub mod os { pub const EXE_EXTENSION: &'static str = ""; } -#[cfg(all(target_os = "nacl", not(target_arch = "le32")))] -pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "nacl"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".so"; - pub const DLL_EXTENSION: &'static str = "so"; - pub const EXE_SUFFIX: &'static str = ".nexe"; - pub const EXE_EXTENSION: &'static str = "nexe"; -} -#[cfg(all(target_os = "nacl", target_arch = "le32"))] -pub mod os { - pub const FAMILY: &'static str = "unix"; - pub const OS: &'static str = "pnacl"; - pub const DLL_PREFIX: &'static str = "lib"; - pub const DLL_SUFFIX: &'static str = ".pso"; - pub const DLL_EXTENSION: &'static str = "pso"; - pub const EXE_SUFFIX: &'static str = ".pexe"; - pub const EXE_EXTENSION: &'static str = "pexe"; -} - #[cfg(target_os = "haiku")] pub mod os { pub const FAMILY: &'static str = "unix"; diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 1b3f1000b77..c2772e2e2cc 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -22,7 +22,6 @@ use libc; #[cfg(all(not(dox), target_os = "haiku"))] pub use os::haiku as platform; #[cfg(all(not(dox), target_os = "ios"))] pub use os::ios as platform; #[cfg(all(not(dox), target_os = "macos"))] pub use os::macos as platform; -#[cfg(all(not(dox), target_os = "nacl"))] pub use os::nacl as platform; #[cfg(all(not(dox), target_os = "netbsd"))] pub use os::netbsd as platform; #[cfg(all(not(dox), target_os = "openbsd"))] pub use os::openbsd as platform; #[cfg(all(not(dox), target_os = "solaris"))] pub use os::solaris as platform; @@ -77,11 +76,11 @@ pub fn init() { reset_sigpipe(); } - #[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))] + #[cfg(not(any(target_os = "emscripten", target_os="fuchsia")))] unsafe fn reset_sigpipe() { assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); } - #[cfg(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia"))] + #[cfg(any(target_os = "emscripten", target_os="fuchsia"))] unsafe fn reset_sigpipe() {} } diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 5ef98d24710..d8c30534eed 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -483,12 +483,10 @@ pub fn home_dir() -> Option { #[cfg(any(target_os = "android", target_os = "ios", - target_os = "nacl", target_os = "emscripten"))] unsafe fn fallback() -> Option { None } #[cfg(not(any(target_os = "android", target_os = "ios", - target_os = "nacl", target_os = "emscripten")))] unsafe fn fallback() -> Option { let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 689ccd78524..383434b1cd8 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -464,7 +464,6 @@ mod tests { // test from being flaky we ignore it on macOS. #[test] #[cfg_attr(target_os = "macos", ignore)] - #[cfg_attr(target_os = "nacl", ignore)] // no signals on NaCl. // When run under our current QEMU emulation test suite this test fails, // although the reason isn't very clear as to why. For now this test is // ignored there. diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 870db820027..743c458d580 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -184,8 +184,8 @@ impl Command { *sys::os::environ() = envp.as_ptr(); } - // NaCl has no signal support. - #[cfg(not(any(target_os = "nacl", target_os = "emscripten")))] + // emscripten has no signal support. + #[cfg(not(any(target_os = "emscripten")))] { use mem; // Reset signal handling so the child process starts in a diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 617218fe7a5..8f78c2e6f59 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg_attr(target_os = "nacl", allow(dead_code))] - /// Common code for printing the backtrace in the same way across the different /// supported platforms. From 329b901b50639232ca59fe839beda89cecbe1c85 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 5 Oct 2017 05:04:40 +0200 Subject: [PATCH 041/365] Remove nacl from libtest --- src/libtest/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 642eb285564..e8a1242c814 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1554,16 +1554,14 @@ impl MetricMap { /// elimination. /// /// This function is a no-op, and does not even read from `dummy`. -#[cfg(not(any(all(target_os = "nacl", target_arch = "le32"), - target_arch = "asmjs", target_arch = "wasm32")))] +#[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] pub fn black_box(dummy: T) -> T { // we need to "use" the argument in some way LLVM can't // introspect. unsafe { asm!("" : : "r"(&dummy)) } dummy } -#[cfg(any(all(target_os = "nacl", target_arch = "le32"), - target_arch = "asmjs", target_arch = "wasm32"))] +#[cfg(any(target_arch = "asmjs", target_arch = "wasm32"))] #[inline(never)] pub fn black_box(dummy: T) -> T { dummy From 327116a423c71754192945a319eef64947fd59df Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 5 Oct 2017 05:04:50 +0200 Subject: [PATCH 042/365] Remove nacl from librustdoc --- src/librustdoc/clean/cfg.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index da8c3a5cf20..e3ce403f3c1 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -337,7 +337,6 @@ impl<'a> fmt::Display for Html<'a> { "l4re" => "L4Re", "linux" => "Linux", "macos" => "macOS", - "nacl" => "NaCl", "netbsd" => "NetBSD", "openbsd" => "OpenBSD", "redox" => "Redox", @@ -886,4 +885,4 @@ mod test { only." ); } -} \ No newline at end of file +} From 54d63a0d3380758ae359995330fb64ccdd79069a Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Thu, 28 Sep 2017 00:14:34 -0400 Subject: [PATCH 043/365] Expand mir dump in order to handle NLL pass Extend `dump_mir` and functions it calls in order to allow callers to add custom information. We do this by adding an enum `PassWhere` and an extra argument of type `FnMut(PassWhere, &mut Write) -> io::Result<()>`. This callback is responsible for printing the extra information when MIR is dumped at various stages. For the "nll" pass, use the new mechanism to dump the `Region` information after the header, but before the control flow graph for every function. In the interest of keeping the output somewhat concise, implement a custom Debug impl for `Region` Open Questions: * What should we call what has been called `PassWhere` so far? --- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/transform/dump_mir.rs | 13 +++- src/librustc_mir/transform/generator.rs | 8 +- src/librustc_mir/transform/nll/mod.rs | 24 +++++- src/librustc_mir/util/liveness.rs | 2 +- src/librustc_mir/util/mod.rs | 2 +- src/librustc_mir/util/pretty.rs | 98 ++++++++++++++++--------- 7 files changed, 107 insertions(+), 44 deletions(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 46a5e5abbdd..b8bb2a40462 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -149,7 +149,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t mem::transmute::>(mir) }; - mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir); + mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) ); mir }) @@ -227,7 +227,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mem::transmute::>(mir) }; - mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir); + mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) ); mir }) diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 67a3281dba4..cea66837d9a 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -65,7 +65,18 @@ impl PassHook for DumpMir { pass_name, &Disambiguator { is_after }, source, - mir); + mir, + |_, _| Ok(()) ); + for (index, promoted_mir) in mir.promoted.iter_enumerated() { + let promoted_source = MirSource::Promoted(source.item_id(), index); + mir_util::dump_mir(tcx, + Some((suite, pass_num)), + pass_name, + &Disambiguator { is_after }, + promoted_source, + promoted_mir, + |_, _| Ok(()) ); + } } } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 729fe46ef37..7d0814b67fb 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -587,7 +587,7 @@ fn create_generator_drop_shim<'a, 'tcx>( // unrelated code from the resume part of the function simplify::remove_dead_blocks(&mut mir); - dump_mir(tcx, None, "generator_drop", &0, source, &mut mir); + dump_mir(tcx, None, "generator_drop", &0, source, &mut mir, |_, _| Ok(()) ); mir } @@ -673,7 +673,7 @@ fn create_generator_resume_function<'a, 'tcx>( // unrelated code from the drop part of the function simplify::remove_dead_blocks(mir); - dump_mir(tcx, None, "generator_resume", &0, source, mir); + dump_mir(tcx, None, "generator_resume", &0, source, mir, |_, _| Ok(()) ); } fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo { @@ -816,14 +816,14 @@ impl MirPass for StateTransform { // This is expanded to a drop ladder in `elaborate_generator_drops`. let drop_clean = insert_clean_drop(mir); - dump_mir(tcx, None, "generator_pre-elab", &0, source, mir); + dump_mir(tcx, None, "generator_pre-elab", &0, source, mir, |_, _| Ok(()) ); // Expand `drop(generator_struct)` to a drop ladder which destroys upvars. // If any upvars are moved out of, drop elaboration will handle upvar destruction. // However we need to also elaborate the code generated by `insert_clean_drop`. elaborate_generator_drops(tcx, def_id, mir); - dump_mir(tcx, None, "generator_post-transform", &0, source, mir); + dump_mir(tcx, None, "generator_post-transform", &0, source, mir, |_, _| Ok(()) ); // Create a copy of our MIR and use it to create the drop shim for the generator let drop_shim = create_generator_drop_shim(tcx, diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index d4a5354c78f..4925b1fcfed 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -19,6 +19,10 @@ use rustc::util::nodemap::FxHashSet; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use syntax_pos::DUMMY_SP; use std::collections::HashMap; +use std::fmt; + +use util as mir_util; +use self::mir_util::PassWhere; #[allow(dead_code)] struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -134,7 +138,7 @@ pub struct NLL; impl MirPass for NLL { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - _: MirSource, + source: MirSource, mir: &mut Mir<'tcx>) { if !tcx.sess.opts.debugging_opts.nll { return; @@ -145,14 +149,30 @@ impl MirPass for NLL { let mut renumbered_mir = mir.clone(); let mut visitor = NLLVisitor::new(infcx); visitor.visit_mir(&mut renumbered_mir); + mir_util::dump_mir(tcx, None, "nll", &0, source, mir, |pass_where, out| { + if let PassWhere::BeforeCFG = pass_where { + for (index, value) in visitor.regions.iter_enumerated() { + writeln!(out, "// R{:03}: {:?}", index.0, value)?; + } + } + Ok(()) + }); let _results = visitor.into_results(); }) } } -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Default, PartialEq, Eq)] struct Region { points: FxHashSet, } +impl fmt::Debug for Region { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(formatter, "{:?}", self.points) + } +} + + + newtype_index!(RegionIndex); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index e6d3a82ff9b..1424c063d73 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -232,7 +232,7 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, writeln!(w, "{} {{{}}}", prefix, live.join(", ")) }; print(w, " ", &result.ins)?; - write_basic_block(tcx, block, mir, w)?; + write_basic_block(tcx, block, mir, &mut |_, _| Ok(()), w)?; print(w, " ", &result.outs)?; if block.index() + 1 != mir.basic_blocks().len() { writeln!(w, "")?; diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs index 4b6da96824d..13c14f8920f 100644 --- a/src/librustc_mir/util/mod.rs +++ b/src/librustc_mir/util/mod.rs @@ -17,6 +17,6 @@ mod graphviz; mod pretty; pub mod liveness; -pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty}; +pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere}; pub use self::graphviz::{write_mir_graphviz}; pub use self::graphviz::write_node_label as write_graphviz_node_label; diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 9e1f05f6d2f..8a9047fb491 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -25,6 +25,22 @@ const INDENT: &'static str = " "; /// Alignment for lining up comments following MIR statements const ALIGN: usize = 40; +/// An indication of where we are in the control flow graph. Used for printing +/// extra information in `dump_mir` +pub enum PassWhere { + /// We have not started dumping the control flow graph, but we are about to. + BeforeCFG, + + /// We just finished dumping the control flow graph. This is right before EOF + AfterCFG, + + /// We are about to start dumping the given basic block. + BeforeBlock(BasicBlock), + + /// We are just about to dumpt the given statement or terminator. + InCFG(Location), +} + /// If the session is properly configured, dumps a human-readable /// representation of the mir into: /// @@ -39,12 +55,16 @@ const ALIGN: usize = 40; /// - `substring1&substring2,...` -- `&`-separated list of substrings /// that can appear in the pass-name or the `item_path_str` for the given /// node-id. If any one of the substrings match, the data is dumped out. -pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - pass_num: Option<(MirSuite, MirPassIndex)>, - pass_name: &str, - disambiguator: &Display, - source: MirSource, - mir: &Mir<'tcx>) { +pub fn dump_mir<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + pass_num: Option<(MirSuite, MirPassIndex)>, + pass_name: &str, + disambiguator: &Display, + source: MirSource, + mir: &Mir<'tcx>, + extra_data: F) +where + F: FnMut(PassWhere, &mut Write) -> io::Result<()> +{ if !dump_enabled(tcx, pass_name, source) { return; } @@ -53,12 +73,7 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.item_path_str(tcx.hir.local_def_id(source.item_id())) }); dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, - disambiguator, source, mir); - for (index, promoted_mir) in mir.promoted.iter_enumerated() { - let promoted_source = MirSource::Promoted(source.item_id(), index); - dump_matched_mir_node(tcx, pass_num, pass_name, &node_path, disambiguator, - promoted_source, promoted_mir); - } + disambiguator, source, mir, extra_data); } pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -85,13 +100,17 @@ pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // `item_path_str()` would otherwise trigger `type_of`, and this can // run while we are already attempting to evaluate `type_of`. -fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - pass_num: Option<(MirSuite, MirPassIndex)>, - pass_name: &str, - node_path: &str, - disambiguator: &Display, - source: MirSource, - mir: &Mir<'tcx>) { +fn dump_matched_mir_node<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + pass_num: Option<(MirSuite, MirPassIndex)>, + pass_name: &str, + node_path: &str, + disambiguator: &Display, + source: MirSource, + mir: &Mir<'tcx>, + mut extra_data: F) +where + F: FnMut(PassWhere, &mut Write) -> io::Result<()> +{ let promotion_id = match source { MirSource::Promoted(_, id) => format!("-{:?}", id), MirSource::GeneratorDrop(_) => format!("-drop"), @@ -125,7 +144,9 @@ fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, writeln!(file, "// generator_layout = {:?}", layout)?; } writeln!(file, "")?; - write_mir_fn(tcx, source, mir, &mut file)?; + extra_data(PassWhere::BeforeCFG, &mut file)?; + write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?; + extra_data(PassWhere::AfterCFG, &mut file)?; Ok(()) }); } @@ -152,24 +173,29 @@ pub fn write_mir_pretty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let id = tcx.hir.as_local_node_id(def_id).unwrap(); let src = MirSource::from_node(tcx, id); - write_mir_fn(tcx, src, mir, w)?; + write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?; for (i, mir) in mir.promoted.iter_enumerated() { writeln!(w, "")?; - write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w)?; + write_mir_fn(tcx, MirSource::Promoted(id, i), mir, &mut |_, _| Ok(()), w)?; } } Ok(()) } -pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, - mir: &Mir<'tcx>, - w: &mut Write) - -> io::Result<()> { +pub fn write_mir_fn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + src: MirSource, + mir: &Mir<'tcx>, + extra_data: &mut F, + w: &mut Write) + -> io::Result<()> +where + F: FnMut(PassWhere, &mut Write) -> io::Result<()> +{ write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { - write_basic_block(tcx, block, mir, w)?; + extra_data(PassWhere::BeforeBlock(block), w)?; + write_basic_block(tcx, block, mir, extra_data, w)?; if block.index() + 1 != mir.basic_blocks().len() { writeln!(w, "")?; } @@ -180,11 +206,15 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } /// Write out a human-readable textual representation for the given basic block. -pub fn write_basic_block(tcx: TyCtxt, - block: BasicBlock, - mir: &Mir, - w: &mut Write) - -> io::Result<()> { +pub fn write_basic_block(tcx: TyCtxt, + block: BasicBlock, + mir: &Mir, + extra_data: &mut F, + w: &mut Write) + -> io::Result<()> +where + F: FnMut(PassWhere, &mut Write) -> io::Result<()> +{ let data = &mir[block]; // Basic block label at the top. @@ -195,6 +225,7 @@ pub fn write_basic_block(tcx: TyCtxt, // List of statements in the middle. let mut current_location = Location { block: block, statement_index: 0 }; for statement in &data.statements { + extra_data(PassWhere::InCFG(current_location), w)?; let indented_mir = format!("{0}{0}{1:?};", INDENT, statement); writeln!(w, "{0:1$} // {2}", indented_mir, @@ -205,6 +236,7 @@ pub fn write_basic_block(tcx: TyCtxt, } // Terminator at the bottom. + extra_data(PassWhere::InCFG(current_location), w)?; let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind); writeln!(w, "{0:1$} // {2}", indented_terminator, From 276bebebb083c453bc6c8a144003e9c96751ebcc Mon Sep 17 00:00:00 2001 From: Barret Rennie Date: Wed, 4 Oct 2017 22:11:36 -0600 Subject: [PATCH 044/365] Update trait summaries for std::fmt This patch is part of #29355. --- src/libcore/fmt/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 6c251b9eb09..c1d5fd75adc 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -427,7 +427,7 @@ impl<'a> Display for Arguments<'a> { } } -/// Format trait for the `?` character. +/// `?` formatting. /// /// `Debug` should format the output in a programmer-facing, debugging context. /// @@ -593,7 +593,7 @@ pub trait Display { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `o` character. +/// `o` formatting. /// /// The `Octal` trait should format its output as a number in base-8. /// @@ -640,7 +640,7 @@ pub trait Octal { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `b` character. +/// `b` formatting. /// /// The `Binary` trait should format its output as a number in binary. /// @@ -687,7 +687,7 @@ pub trait Binary { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `x` character. +/// `x` formatting. /// /// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f` /// in lower case. @@ -735,7 +735,7 @@ pub trait LowerHex { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `X` character. +/// `X` formatting. /// /// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F` /// in upper case. @@ -783,7 +783,7 @@ pub trait UpperHex { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `p` character. +/// `p` formatting. /// /// The `Pointer` trait should format its output as a memory location. This is commonly presented /// as hexadecimal. @@ -828,7 +828,7 @@ pub trait Pointer { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `e` character. +/// `e` formatting. /// /// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`. /// @@ -871,7 +871,7 @@ pub trait LowerExp { fn fmt(&self, f: &mut Formatter) -> Result; } -/// Format trait for the `E` character. +/// `E` formatting. /// /// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`. /// From b50e8ebbba2c9f9f87ea6bc1fb47a8856999223c Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 4 Oct 2017 14:57:14 +0200 Subject: [PATCH 045/365] Fix infinite recursion in . --- src/librustc/dep_graph/dep_node.rs | 6 +++--- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/hir/def_id.rs | 4 ++-- src/librustc/hir/map/definitions.rs | 21 --------------------- src/librustc/ty/context.rs | 21 +++++++++++++++++++++ src/test/mir-opt/validate_1.rs | 4 ++-- src/test/mir-opt/validate_4.rs | 12 ++++++------ src/test/mir-opt/validate_5.rs | 4 ++-- 8 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 36236ff25b0..2b6c368a5b3 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -356,7 +356,7 @@ impl fmt::Debug for DepNode { ::ty::tls::with_opt(|opt_tcx| { if let Some(tcx) = opt_tcx { if let Some(def_id) = self.extract_def_id(tcx) { - write!(f, "{}", tcx.def_path(def_id).to_string(tcx))?; + write!(f, "{}", tcx.def_path_debug_str(def_id))?; } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) { write!(f, "{}", s)?; } else { @@ -700,8 +700,8 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, De let (def_id_0, def_id_1) = *self; format!("({}, {})", - tcx.def_path(def_id_0).to_string(tcx), - tcx.def_path(def_id_1).to_string(tcx)) + tcx.def_path_debug_str(def_id_0), + tcx.def_path_debug_str(def_id_1)) } } diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 2d2558fd815..f06e15b4c4f 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -577,7 +577,7 @@ impl DepGraph { "DepGraph::try_mark_green() - Duplicate DepNodeColor \ insertion for {:?}", dep_node); - debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node.kind); + debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node); Some(dep_node_index) } diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 8e48352007b..69d23504cda 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -197,12 +197,12 @@ pub struct DefId { impl fmt::Debug for DefId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "DefId {{ krate: {:?}, node: {:?}", + write!(f, "DefId {{ krate: {:?}, index: {:?}", self.krate, self.index)?; ty::tls::with_opt(|opt_tcx| { if let Some(tcx) = opt_tcx { - write!(f, " => {}", tcx.def_path(*self).to_string(tcx))?; + write!(f, " => {}", tcx.def_path_debug_str(*self))?; } Ok(()) })?; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index bd80b613e77..8bc7cf2faba 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -27,7 +27,6 @@ use std::hash::Hash; use syntax::ast; use syntax::ext::hygiene::Mark; use syntax::symbol::{Symbol, InternedString}; -use ty::TyCtxt; use util::nodemap::NodeMap; /// The DefPathTable maps DefIndexes to DefKeys and vice versa. @@ -296,26 +295,6 @@ impl DefPath { DefPath { data: data, krate: krate } } - pub fn to_string(&self, tcx: TyCtxt) -> String { - let mut s = String::with_capacity(self.data.len() * 16); - - s.push_str(&tcx.original_crate_name(self.krate).as_str()); - s.push_str("/"); - // Don't print the whole crate disambiguator. That's just annoying in - // debug output. - s.push_str(&tcx.crate_disambiguator(self.krate).as_str()[..7]); - - for component in &self.data { - write!(s, - "::{}[{}]", - component.data.as_interned_str(), - component.disambiguator) - .unwrap(); - } - - s - } - /// Returns a string representation of the DefPath without /// the crate-prefix. This method is useful if you don't have /// a TyCtxt available. diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 315ba622ccf..eb7458d18ea 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1219,6 +1219,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + pub fn def_path_debug_str(self, def_id: DefId) -> String { + // We are explicitly not going through queries here in order to get + // crate name and disambiguator since this code is called from debug!() + // statements within the query system and we'd run into endless + // recursion otherwise. + let (crate_name, crate_disambiguator) = if def_id.is_local() { + (self.crate_name.clone(), + self.sess.local_crate_disambiguator()) + } else { + (self.cstore.crate_name_untracked(def_id.krate), + self.cstore.crate_disambiguator_untracked(def_id.krate)) + }; + + format!("{}[{}]{}", + crate_name, + // Don't print the whole crate disambiguator. That's just + // annoying in debug output. + &(crate_disambiguator.as_str())[..4], + self.def_path(def_id).to_string_no_crate()) + } + pub fn metadata_encoding_version(self) -> Vec { self.cstore.metadata_encoding_version().to_vec() } diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index ec044225b83..d2ca65775a4 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -30,7 +30,7 @@ fn main() { // END RUST SOURCE // START rustc.node12.EraseRegions.after.mir // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:5) => validate_1/8cd878b::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:5) => validate_1/8cd878b::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[8cd8]::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[8cd8]::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]); // return; // } // END rustc.node12.EraseRegions.after.mir @@ -57,7 +57,7 @@ fn main() { // START rustc.node50.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:11) => validate_1/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:11) => validate_1/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _3 = _2; // StorageLive(_4); diff --git a/src/test/mir-opt/validate_4.rs b/src/test/mir-opt/validate_4.rs index 571ed425402..d240b51e222 100644 --- a/src/test/mir-opt/validate_4.rs +++ b/src/test/mir-opt/validate_4.rs @@ -48,8 +48,8 @@ fn main() { // START rustc.node22.EraseRegions.after.mir // fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:9) => validate_4/8cd878b::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:9) => validate_4/8cd878b::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); // StorageLive(_3); // _3 = _2; // (*_3) = const 23i32; @@ -61,8 +61,8 @@ fn main() { // START rustc.node31.EraseRegions.after.mir // fn test(_1: &ReErased mut i32) -> () { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[8cd8]::test[0] }, BrAnon(0)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[8cd8]::test[0] }, BrAnon(0)) mut i32]); // _3 = const write_42(_4) -> bb1; // } // bb1: { @@ -74,8 +74,8 @@ fn main() { // START rustc.node60.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:10) => validate_4/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:10) => validate_4/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:10) => validate_4/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:10) => validate_4/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _0 = const write_42(_4) -> bb1; // } diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index ff0c781d1e3..e1eeb2102d1 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -36,7 +36,7 @@ fn main() { // START rustc.node17.EraseRegions.after.mir // fn test(_1: &ReErased mut i32) -> () { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(0:4) => validate_5/8cd878b::test[0] }, BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_5[8cd8]::test[0] }, BrAnon(0)) mut i32]); // Validate(Release, [_3: bool, _4: *mut i32]); // _3 = const write_42(_4) -> bb1; // } @@ -45,7 +45,7 @@ fn main() { // START rustc.node46.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:9) => validate_5/8cd878b::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(1:9) => validate_5/8cd878b::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _3 = _2; // StorageLive(_4); From a78ce0738147932a2bf0e7bcf0346ac1214d7154 Mon Sep 17 00:00:00 2001 From: bgermann Date: Thu, 5 Oct 2017 13:48:34 +0200 Subject: [PATCH 046/365] Fix CC for solaris environments --- src/ci/docker/cross2/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/cross2/Dockerfile b/src/ci/docker/cross2/Dockerfile index 6f854197191..f5fc06767ce 100644 --- a/src/ci/docker/cross2/Dockerfile +++ b/src/ci/docker/cross2/Dockerfile @@ -37,10 +37,10 @@ ENV \ CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \ CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ \ AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-ar \ - CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-sysroot \ + CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-gcc \ CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-g++ \ AR_x86_64_sun_solaris=x86_64-sun-solaris2.11-ar \ - CC_x86_64_sun_solaris=x86_64-sun-solaris2.11-sysroot \ + CC_x86_64_sun_solaris=x86_64-sun-solaris2.11-gcc \ CXX_x86_64_sun_solaris=x86_64-sun-solaris2.11-g++ ENV TARGETS=x86_64-unknown-fuchsia From 9bff9e0ce908bef7167d5eb5e0a12b85ee76cd5e Mon Sep 17 00:00:00 2001 From: bgermann Date: Thu, 5 Oct 2017 17:21:28 +0200 Subject: [PATCH 047/365] delete 'if: branch = auto' for cross2 builder --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 139f06ec570..57ad3acde4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -116,7 +116,6 @@ matrix: - env: IMAGE=cross DEPLOY=1 if: branch = auto - env: IMAGE=cross2 DEPLOY=1 - if: branch = auto - env: IMAGE=dist-aarch64-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-android DEPLOY=1 From 724dd4653624a881f1399172f999347432be948c Mon Sep 17 00:00:00 2001 From: bgermann Date: Thu, 5 Oct 2017 19:05:19 +0200 Subject: [PATCH 048/365] Add libsocket and libresolv to Solaris builder --- src/ci/docker/cross2/build-solaris-toolchain.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ci/docker/cross2/build-solaris-toolchain.sh b/src/ci/docker/cross2/build-solaris-toolchain.sh index 4ff26b5dfab..ae84cc62b60 100755 --- a/src/ci/docker/cross2/build-solaris-toolchain.sh +++ b/src/ci/docker/cross2/build-solaris-toolchain.sh @@ -45,8 +45,12 @@ apt-get download \ libm-dev:$APT_ARCH \ libpthread:$APT_ARCH \ libpthread-dev:$APT_ARCH \ + libresolv:$APT_ARCH \ + libresolv-dev:$APT_ARCH \ librt:$APT_ARCH \ librt-dev:$APT_ARCH \ + libsocket:$APT_ARCH \ + libsocket-dev:$APT_ARCH \ system-crt:$APT_ARCH \ system-header:$APT_ARCH From dba52ff9cd8fa77545221d84dcef6d7ca624dd00 Mon Sep 17 00:00:00 2001 From: bgermann Date: Thu, 5 Oct 2017 20:42:27 +0200 Subject: [PATCH 049/365] restore 'if: branch = auto' for cross2 builder --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 57ad3acde4d..139f06ec570 100644 --- a/.travis.yml +++ b/.travis.yml @@ -116,6 +116,7 @@ matrix: - env: IMAGE=cross DEPLOY=1 if: branch = auto - env: IMAGE=cross2 DEPLOY=1 + if: branch = auto - env: IMAGE=dist-aarch64-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-android DEPLOY=1 From 47fc913e560709820cce22a90d4145925753ae19 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Oct 2017 12:34:52 -0700 Subject: [PATCH 050/365] Update the `jobserver` crate Brings in a bugfix to be compatible with the master branch of `make` where jobserver fds are set in nonblocking mode --- src/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 26be463f6bb..c7bee4d2c16 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -199,7 +199,7 @@ dependencies = [ "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -759,7 +759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jobserver" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1429,7 +1429,7 @@ dependencies = [ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", - "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_back 0.0.0", @@ -1756,7 +1756,7 @@ dependencies = [ "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2529,7 +2529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" -"checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133" +"checksum jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "094f87ed101b6832def8632f43db43dc204d27897eb95aca69b26ce2e4011e84" "checksum jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1acd0f9934da94466d2370f36832b9b19271b4abdfdb5e69f0bcd991ebcd515" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kuchiki 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2ea4f2f7883cd7c6772b06c14abca01a2cc1f75c426cebffcf6b3b925ef9fc" From 5e251b74eb200ba6d3b8ddaa68ef682c78be26e2 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Thu, 5 Oct 2017 16:54:56 -0400 Subject: [PATCH 051/365] Modify Rc/Arc language around mutability There are a few exceptions to the rule that Arc/Rc are immutable. Rather than dig into the details, add "generally" to hint at this difference, as it's kind of a distraction at this point in the docs. Additionally, Arc's docs were slightly different here generally, so add in both the existing language and the exception. Fixes #44105 --- src/liballoc/arc.rs | 6 ++++-- src/liballoc/rc.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 3b7dbd813cf..9481cd4e1a4 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -52,8 +52,10 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// also destroyed. /// /// Shared references in Rust disallow mutation by default, and `Arc` is no -/// exception. If you need to mutate through an `Arc`, use [`Mutex`][mutex], -/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. +/// exception: you cannot generally obtain a mutable reference to something +/// inside an `Arc`. If you need to mutate through an `Arc`, use +/// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic] +/// types. /// /// ## Thread Safety /// diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 553980d463f..2f8620cc750 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -19,7 +19,7 @@ //! given value is destroyed, the pointed-to value is also destroyed. //! //! Shared references in Rust disallow mutation by default, and [`Rc`] -//! is no exception: you cannot obtain a mutable reference to +//! is no exception: you cannot generally obtain a mutable reference to //! something inside an [`Rc`]. If you need mutability, put a [`Cell`] //! or [`RefCell`] inside the [`Rc`]; see [an example of mutability //! inside an Rc][mutability]. From 98045fdaca09133f3957b1abaebd21b56688fc0d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 5 Oct 2017 23:20:58 +0200 Subject: [PATCH 052/365] Add missing links for AtomicBool --- src/libcore/sync/atomic.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 465d31b5f49..524f4508c9b 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -119,7 +119,9 @@ pub fn hint_core_should_pause() /// A boolean type which can be safely shared between threads. /// -/// This type has the same in-memory representation as a `bool`. +/// This type has the same in-memory representation as a [`bool`]. +/// +/// [`bool`]: ../../../std/primitive.bool.html #[cfg(target_has_atomic = "8")] #[stable(feature = "rust1", since = "1.0.0")] pub struct AtomicBool { @@ -246,11 +248,13 @@ impl AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } - /// Returns a mutable reference to the underlying `bool`. + /// Returns a mutable reference to the underlying [`bool`]. /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. /// + /// [`bool`]: ../../../std/primitive.bool.html + /// /// # Examples /// /// ``` @@ -369,7 +373,7 @@ impl AtomicBool { unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 } } - /// Stores a value into the `bool` if the current value is the same as the `current` value. + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// The return value is always the previous value. If it is equal to `current`, then the value /// was updated. @@ -378,6 +382,7 @@ impl AtomicBool { /// ordering of this operation. /// /// [`Ordering`]: enum.Ordering.html + /// [`bool`]: ../../../std/primitive.bool.html /// /// # Examples /// @@ -401,7 +406,7 @@ impl AtomicBool { } } - /// Stores a value into the `bool` if the current value is the same as the `current` value. + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// The return value is a result indicating whether the new value was written and containing /// the previous value. On success this value is guaranteed to be equal to `current`. @@ -412,6 +417,7 @@ impl AtomicBool { /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must /// be equivalent or weaker than the success ordering. /// + /// [`bool`]: ../../../std/primitive.bool.html /// [`Ordering`]: enum.Ordering.html /// [`Release`]: enum.Ordering.html#variant.Release /// [`AcqRel`]: enum.Ordering.html#variant.Release @@ -452,7 +458,7 @@ impl AtomicBool { } } - /// Stores a value into the `bool` if the current value is the same as the `current` value. + /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the /// comparison succeeds, which can result in more efficient code on some platforms. The @@ -465,6 +471,7 @@ impl AtomicBool { /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or /// weaker than the success ordering. /// + /// [`bool`]: ../../../std/primitive.bool.html /// [`compare_exchange`]: #method.compare_exchange /// [`Ordering`]: enum.Ordering.html /// [`Release`]: enum.Ordering.html#variant.Release From 73ca15cc2958dc5693d4b463ce48fbbe057d75f6 Mon Sep 17 00:00:00 2001 From: Kevin Hunter Kesling Date: Thu, 5 Oct 2017 21:31:59 -0400 Subject: [PATCH 053/365] Fix typo, per #45057. --- src/librustc/middle/stability.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 89049958309..4e4fc8b3118 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -429,7 +429,7 @@ impl<'a, 'tcx> Index<'tcx> { // while maintaining the invariant that all sysroot crates are unstable // by default and are unable to be used. if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked { - let reason = "this crate is being loaded from the sysroot, and \ + let reason = "this crate is being loaded from the sysroot, an \ unstable location; did you mean to load this crate \ from crates.io via `Cargo.toml` instead?"; let stability = tcx.intern_stability(Stability { From 14c6c119042d2cfbaea0e17e47d2c160261e73ab Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 6 Oct 2017 19:16:16 +0900 Subject: [PATCH 054/365] Add a semicolon to span for ast::Local --- src/libsyntax/parse/parser.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 65dabe98a06..978e06c75dd 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3671,12 +3671,17 @@ impl<'a> Parser<'a> { None }; let init = self.parse_initializer()?; + let hi = if self.token == token::Semi { + self.span + } else { + self.prev_span + }; Ok(P(ast::Local { ty, pat, init, id: ast::DUMMY_NODE_ID, - span: lo.to(self.prev_span), + span: lo.to(hi), attrs, })) } From b81c8580caf8208215049d2b22239cb6bb678d0b Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 6 Oct 2017 15:35:03 +0200 Subject: [PATCH 055/365] incr.comp.: Bring back output of -Zincremental-info. --- src/bootstrap/bin/rustc.rs | 4 - .../persist/file_format.rs | 2 +- src/librustc_incremental/persist/fs.rs | 21 +++--- src/librustc_incremental/persist/load.rs | 4 +- src/librustc_incremental/persist/save.rs | 73 ++++++++++++++++++- src/librustc_trans/back/write.rs | 10 +-- src/tools/compiletest/src/runtest.rs | 1 - 7 files changed, 90 insertions(+), 25 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 848b10d312c..99c297e36c7 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -131,10 +131,6 @@ fn main() { // Pass down incremental directory, if any. if let Ok(dir) = env::var("RUSTC_INCREMENTAL") { cmd.arg(format!("-Zincremental={}", dir)); - - if verbose > 0 { - cmd.arg("-Zincremental-info"); - } } let crate_name = args.windows(2) diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs index 13b019af2ea..7d1400b6b95 100644 --- a/src/librustc_incremental/persist/file_format.rs +++ b/src/librustc_incremental/persist/file_format.rs @@ -117,7 +117,7 @@ fn report_format_mismatch(sess: &Session, file: &Path, message: &str) { debug!("read_file: {}", message); if sess.opts.debugging_opts.incremental_info { - eprintln!("incremental: ignoring cache artifact `{}`: {}", + println!("[incremental] ignoring cache artifact `{}`: {}", file.file_name().unwrap().to_string_lossy(), message); } diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 9b12b755581..d53ee5c804f 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -256,11 +256,12 @@ pub fn prepare_session_directory(sess: &Session, debug!("attempting to copy data from source: {}", source_directory.display()); - let print_file_copy_stats = sess.opts.debugging_opts.incremental_info; + // Try copying over all files from the source directory - if let Ok(allows_links) = copy_files(&session_dir, &source_directory, - print_file_copy_stats) { + if let Ok(allows_links) = copy_files(sess, + &session_dir, + &source_directory) { debug!("successfully copied data from: {}", source_directory.display()); @@ -390,9 +391,9 @@ pub fn delete_all_session_dir_contents(sess: &Session) -> io::Result<()> { Ok(()) } -fn copy_files(target_dir: &Path, - source_dir: &Path, - print_stats_on_success: bool) +fn copy_files(sess: &Session, + target_dir: &Path, + source_dir: &Path) -> Result { // We acquire a shared lock on the lock file of the directory, so that // nobody deletes it out from under us while we are reading from it. @@ -440,9 +441,11 @@ fn copy_files(target_dir: &Path, } } - if print_stats_on_success { - eprintln!("incremental: session directory: {} files hard-linked", files_linked); - eprintln!("incremental: session directory: {} files copied", files_copied); + if sess.opts.debugging_opts.incremental_info { + 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/load.rs b/src/librustc_incremental/persist/load.rs index cdfc9f2edc3..63cfbcac145 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -177,8 +177,8 @@ pub fn load_dep_graph(sess: &Session) -> PreviousDepGraph { if prev_commandline_args_hash != sess.opts.dep_tracking_hash() { if sess.opts.debugging_opts.incremental_info { - eprintln!("incremental: completely ignoring cache because of \ - differing commandline arguments"); + println!("[incremental] completely ignoring cache because of \ + differing commandline arguments"); } // We can't reuse the cache, purge it. debug!("load_dep_graph_new: differing commandline arg hashes"); diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 4919870fcd5..b9f73500e27 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::dep_graph::DepGraph; +use rustc::dep_graph::{DepGraph, DepKind}; use rustc::hir::def_id::DefId; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; @@ -170,6 +170,77 @@ fn encode_dep_graph(tcx: TyCtxt, // Encode the graph data. let serialized_graph = tcx.dep_graph.serialize(); + + if tcx.sess.opts.debugging_opts.incremental_info { + #[derive(Clone)] + struct Stat { + kind: DepKind, + node_counter: u64, + edge_counter: u64, + } + + let total_node_count = serialized_graph.nodes.len(); + let total_edge_count = serialized_graph.edge_list_data.len(); + + let mut counts: FxHashMap<_, Stat> = FxHashMap(); + + for (i, &(node, _)) in serialized_graph.nodes.iter_enumerated() { + let stat = counts.entry(node.kind).or_insert(Stat { + kind: node.kind, + node_counter: 0, + edge_counter: 0, + }); + + stat.node_counter += 1; + let (edge_start, edge_end) = serialized_graph.edge_list_indices[i]; + stat.edge_counter += (edge_end - edge_start) as u64; + } + + let mut counts: Vec<_> = counts.values().cloned().collect(); + counts.sort_by_key(|s| -(s.node_counter as i64)); + + let percentage_of_all_nodes: Vec = counts.iter().map(|s| { + (100.0 * (s.node_counter as f64)) / (total_node_count as f64) + }).collect(); + + let average_edges_per_kind: Vec = counts.iter().map(|s| { + (s.edge_counter as f64) / (s.node_counter as f64) + }).collect(); + + println!("[incremental]"); + println!("[incremental] DepGraph Statistics"); + + const SEPARATOR: &str = "[incremental] --------------------------------\ + ----------------------------------------------\ + ------------"; + + println!("{}", SEPARATOR); + println!("[incremental]"); + println!("[incremental] Total Node Count: {}", total_node_count); + println!("[incremental] Total Edge Count: {}", total_edge_count); + println!("[incremental]"); + println!("[incremental] {:<36}| {:<17}| {:<12}| {:<17}|", + "Node Kind", + "Node Frequency", + "Node Count", + "Avg. Edge Count"); + println!("[incremental] -------------------------------------\ + |------------------\ + |-------------\ + |------------------|"); + + for (i, stat) in counts.iter().enumerate() { + println!("[incremental] {:<36}|{:>16.1}% |{:>12} |{:>17.1} |", + format!("{:?}", stat.kind), + percentage_of_all_nodes[i], + stat.node_counter, + average_edges_per_kind[i]); + } + + println!("{}", SEPARATOR); + println!("[incremental]"); + } + serialized_graph.encode(encoder)?; Ok(()) diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index c238c68c471..20e4bbb2c5c 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1045,13 +1045,9 @@ fn produce_final_output_artifacts(sess: &Session, } pub fn dump_incremental_data(trans: &CrateTranslation) { - let mut reuse = 0; - for mtrans in trans.modules.iter() { - if mtrans.pre_existing { - reuse += 1; - } - } - eprintln!("incremental: re-using {} out of {} modules", reuse, trans.modules.len()); + println!("[incremental] Re-using {} out of {} modules", + trans.modules.iter().filter(|m| m.pre_existing).count(), + trans.modules.len()); } enum WorkItem { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 10ef326d9db..53c88307329 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2036,7 +2036,6 @@ actual:\n\ // Add an extra flag pointing at the incremental directory. let mut revision_props = self.props.clone(); revision_props.incremental_dir = Some(incremental_dir); - revision_props.compile_flags.push(String::from("-Zincremental-info")); let revision_cx = TestCx { config: self.config, From 19884470076efdeaa03af634b27f306fffc92289 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Oct 2017 07:06:30 -0700 Subject: [PATCH 056/365] rustc: Reduce default CGUs to 16 Rationale explained in the included comment as well as #44941 --- src/librustc/session/config.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 7c1d457a6ee..ca9603277a7 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1716,7 +1716,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) let codegen_units = codegen_units.unwrap_or_else(|| { match opt_level { - // If we're compiling at `-O0` then default to 32 codegen units. + // If we're compiling at `-O0` then default to 16 codegen units. // The number here shouldn't matter too too much as debug mode // builds don't rely on performance at all, meaning that lost // opportunities for inlining through multiple codegen units is @@ -1734,7 +1734,21 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) // unit takes *too* long to build we'll be guaranteed that all // cpus will finish pretty closely to one another and we should // make relatively optimal use of system resources - OptLevel::No => 32, + // + // Another note worth mentioning here, however, is that this number + // isn't *too* high. When codegen units are increased that means we + // currently have to codegen `#[inline]` functions into each codegen + // unit, which means the more codegen units we're using the more we + // may be generating. In other words, increasing codegen units may + // increase the overall work the compiler does. If we don't have + // enough cores to make up for this loss then increasing the number + // of codegen units could become an overall loss! + // + // As a result we choose a hopefully conservative value 16, which + // should be more than the number of cpus of most hardware compiling + // Rust but also not too much for 2-4 core machines to have too much + // loss of compile time. + OptLevel::No => 16, // All other optimization levels default use one codegen unit, // the historical default in Rust for a Long Time. From 8782d0fe78762db6c8cf750cc9707ede94026832 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 6 Oct 2017 23:57:00 +0900 Subject: [PATCH 057/365] Better error for missing tuple pattern in args (#44150) --- src/librustc/traits/error_reporting.rs | 94 ++++++++++++++----- .../ui/mismatched_types/closure-arg-count.rs | 2 + .../mismatched_types/closure-arg-count.stderr | 18 +++- 3 files changed, 87 insertions(+), 27 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c7c8141f4f7..372f0564726 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -718,7 +718,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return; } let expected_trait_ty = expected_trait_ref.self_ty(); - let found_span = expected_trait_ty.ty_to_def_id().and_then(|did| { + + let found_did = expected_trait_ty.ty_to_def_id(); + let found_span = found_did.and_then(|did| { self.tcx.hir.span_if_local(did) }); @@ -727,10 +729,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::TyTuple(ref tys, _) => tys.len(), _ => 1, }; - let arg_ty_count = + let (arg_tys, arg_ty_count) = match actual_trait_ref.skip_binder().substs.type_at(1).sty { - ty::TyTuple(ref tys, _) => tys.len(), - _ => 1, + ty::TyTuple(ref tys, _) => + (tys.iter().map(|t| &t.sty).collect(), tys.len()), + ref sty => (vec![sty], 1), }; if self_ty_count == arg_ty_count { self.report_closure_arg_mismatch(span, @@ -738,12 +741,45 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { expected_trait_ref, actual_trait_ref) } else { - // Expected `|| { }`, found `|x, y| { }` - // Expected `fn(x) -> ()`, found `|| { }` + let arg_tuple = if arg_ty_count == 1 { + arg_tys.first().and_then(|t| { + if let &&ty::TyTuple(ref tuptys, _) = t { + Some(tuptys.len()) + } else { + None + } + }) + } else { + None + }; + + // FIXME(#44150): Expand this to "N args expected bug a N-tuple found". + // Type of the 1st expected argument is somehow provided as type of a + // found one in that case. + // + // ``` + // [1i32, 2, 3].sort_by(|(a, b)| ..) + // // ^^^^^^^^ + // // actual_trait_ref: std::ops::FnMut<(&i32, &i32)> + // // expected_trait_ref: std::ops::FnMut<(&i32,)> + // ``` + + let closure_args_span = found_did.and_then(|did| self.tcx.hir.get_if_local(did)) + .and_then(|node| { + if let hir::map::NodeExpr( + &hir::Expr { node: hir::ExprClosure(_, _, _, span, _), .. }) = node + { + Some(span) + } else { + None + } + }); + self.report_arg_count_mismatch( span, - found_span, + closure_args_span.or(found_span), arg_ty_count, + arg_tuple, self_ty_count, expected_trait_ty.is_closure() ) @@ -771,28 +807,42 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span: Span, found_span: Option, expected: usize, + expected_tuple: Option, found: usize, is_closure: bool) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!(self.tcx.sess, span, E0593, - "{} takes {} argument{} but {} argument{} {} required", - if is_closure { "closure" } else { "function" }, - found, - if found == 1 { "" } else { "s" }, - expected, - if expected == 1 { "" } else { "s" }, - if expected == 1 { "is" } else { "are" }); + let kind = if is_closure { "closure" } else { "function" }; + + let tuple_or_args = |tuple, args| if let Some(n) = tuple { + format!("a {}-tuple", n) + } else { + format!( + "{} argument{}", + args, + if args == 1 { "" } else { "s" } + ) + }; + + let found_str = tuple_or_args(None, found); + let expected_str = tuple_or_args(expected_tuple, expected); + + let mut err = struct_span_err!(self.tcx.sess, span, E0593, + "{} takes {} but {} {} required", + kind, + found_str, + expected_str, + if expected_tuple.is_some() || expected == 1 { "is" } else { "are" }); + + err.span_label( + span, + format!("expected {} that takes {}", kind, expected_str) + ); - err.span_label(span, format!("expected {} that takes {} argument{}", - if is_closure { "closure" } else { "function" }, - expected, - if expected == 1 { "" } else { "s" })); if let Some(span) = found_span { - err.span_label(span, format!("takes {} argument{}", - found, - if found == 1 { "" } else { "s" })); + err.span_label(span, format!("takes {}", found_str)); } + err } diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index f94471a73ca..a2a31d44a49 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -16,4 +16,6 @@ fn main() { [1, 2, 3].sort_by(|tuple| panic!()); [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); f(|| panic!()); + + let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); } diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 3031a77b1e8..e59a585149b 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -2,7 +2,7 @@ error[E0593]: closure takes 0 arguments but 2 arguments are required --> $DIR/closure-arg-count.rs:15:15 | 15 | [1, 2, 3].sort_by(|| panic!()); - | ^^^^^^^ ----------- takes 0 arguments + | ^^^^^^^ -- takes 0 arguments | | | expected closure that takes 2 arguments @@ -10,7 +10,7 @@ error[E0593]: closure takes 1 argument but 2 arguments are required --> $DIR/closure-arg-count.rs:16:15 | 16 | [1, 2, 3].sort_by(|tuple| panic!()); - | ^^^^^^^ ---------------- takes 1 argument + | ^^^^^^^ ------- takes 1 argument | | | expected closure that takes 2 arguments @@ -27,7 +27,7 @@ error[E0593]: closure takes 1 argument but 2 arguments are required --> $DIR/closure-arg-count.rs:17:15 | 17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); - | ^^^^^^^ -------------------------- takes 1 argument + | ^^^^^^^ ----------------- takes 1 argument | | | expected closure that takes 2 arguments @@ -35,11 +35,19 @@ error[E0593]: closure takes 0 arguments but 1 argument is required --> $DIR/closure-arg-count.rs:18:5 | 18 | f(|| panic!()); - | ^ ----------- takes 0 arguments + | ^ -- takes 0 arguments | | | expected closure that takes 1 argument | = note: required by `f` -error: aborting due to 5 previous errors +error[E0593]: closure takes 2 arguments but a 2-tuple is required + --> $DIR/closure-arg-count.rs:20:53 + | +20 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); + | ^^^ ------ takes 2 arguments + | | + | expected closure that takes a 2-tuple + +error: aborting due to 6 previous errors From aa78919733264bfd07e49c7ed8e82f5a5a9eed11 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Mon, 2 Oct 2017 19:36:58 +0200 Subject: [PATCH 058/365] mir-borrowck: print values in error messages in the same way that the AST borrowck - Print fields with `.name` rather than `.` - Autoderef values if followed by a field or an index --- src/librustc_mir/borrow_check.rs | 101 ++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 14b6e319132..f4bf280cd25 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1053,12 +1053,12 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> // End-user visible description of `lvalue` fn describe_lvalue(&self, lvalue: &Lvalue) -> String { let mut buf = String::new(); - self.append_lvalue_to_string(lvalue, &mut buf); + self.append_lvalue_to_string(lvalue, &mut buf, None); buf } // Appends end-user visible description of `lvalue` to `buf`. - fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String) { + fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String, autoderef: Option) { match *lvalue { Lvalue::Local(local) => { let local = &self.mir.local_decls[local]; @@ -1071,15 +1071,25 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id))); } Lvalue::Projection(ref proj) => { + let mut autoderef = autoderef.unwrap_or(false); let (prefix, suffix, index_operand) = match proj.elem { - ProjectionElem::Deref => - ("(*", format!(")"), None), + ProjectionElem::Deref => { + if autoderef { + ("", format!(""), None) + } else { + ("(*", format!(")"), None) + } + }, ProjectionElem::Downcast(..) => ("", format!(""), None), // (dont emit downcast info) - ProjectionElem::Field(field, _ty) => - ("", format!(".{}", field.index()), None), // FIXME: report name of field - ProjectionElem::Index(index) => - ("", format!(""), Some(index)), + ProjectionElem::Field(field, _ty) => { + autoderef = true; + ("", format!(".{}", self.describe_field(&proj.base, field.index())), None) + }, + ProjectionElem::Index(index) => { + autoderef = true; + ("", format!(""), Some(index)) + }, ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => ("", format!("[{} of {}]", offset, min_length), None), ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => @@ -1092,10 +1102,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> ("", format!("[{}:-{}]", from, to), None), }; buf.push_str(prefix); - self.append_lvalue_to_string(&proj.base, buf); + self.append_lvalue_to_string(&proj.base, buf, Some(autoderef)); if let Some(index) = index_operand { buf.push_str("["); - self.append_lvalue_to_string(&Lvalue::Local(index), buf); + self.append_lvalue_to_string(&Lvalue::Local(index), buf, None); buf.push_str("]"); } else { buf.push_str(&suffix); @@ -1104,6 +1114,77 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> } } + // End-user visible description of the `field_index`nth field of `base` + fn describe_field(&self, base: &Lvalue, field_index: usize) -> String { + match *base { + Lvalue::Local(local) => { + let local = &self.mir.local_decls[local]; + self.describe_field_from_ty(&local.ty, field_index) + }, + Lvalue::Static(ref static_) => { + self.describe_field_from_ty(&static_.ty, field_index) + }, + Lvalue::Projection(ref proj) => { + match proj.elem { + ProjectionElem::Deref => + self.describe_field(&proj.base, field_index), + ProjectionElem::Downcast(..) => { + debug!("End-user description not implemented for field of projection {:?}", + proj); + format!("{}", field_index) + }, + ProjectionElem::Field(..) => { + debug!("End-user description not implemented for field of projection {:?}", + proj); + format!("{}", field_index) + }, + ProjectionElem::Index(..) => { + debug!("End-user description not implemented for field of projection {:?}", + proj); + format!("{}", field_index) + }, + ProjectionElem::ConstantIndex { .. } => { + debug!("End-user description not implemented for field of projection {:?}", + proj); + format!("{}", field_index) + }, + ProjectionElem::Subslice { .. } => { + debug!("End-user description not implemented for field of projection {:?}", + proj); + format!("{}", field_index) + } + } + } + } + } + + // End-user visible description of the `field_index`nth field of `ty` + fn describe_field_from_ty(&self, ty: &ty::Ty, field_index: usize) -> String { + if ty.is_box() { + // If the type is a box, the field is described from the boxed type + self.describe_field_from_ty(&ty.boxed_ty(), field_index) + } + else { + match ty.sty { + ty::TyAdt(def, _) => { + if def.is_enum() { + format!("{}", field_index) + } + else { + format!("{}", def.struct_variant().fields[field_index].name) + } + }, + ty::TyTuple(_, _) => { + format!("{}", field_index) + }, + _ => { + debug!("End-user description not implemented for field of type {:?}", ty.sty); + format!("{}", field_index) + } + } + } + } + // Retrieve span of given borrow from the current MIR representation fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { self.mir.basic_blocks()[borrow.location.block] From ff8ea69d8f52935345f74241bb524383a47bd1d7 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Mon, 2 Oct 2017 19:39:43 +0200 Subject: [PATCH 059/365] mir-borrowck: Add tests for `describe_lvalue()` --- .../borrowck/borrowck-describe-lvalue.rs | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs new file mode 100644 index 00000000000..6de8bda9276 --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -0,0 +1,166 @@ +// 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. + +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + +pub struct Foo { + x: u32 +} + +pub struct Bar(u32); + +pub enum Baz { + X(u32) +} + +union U { + a: u8, + b: u64, +} + +impl Foo { + fn x(&mut self) -> &mut u32 { &mut self.x } +} + +impl Bar { + fn x(&mut self) -> &mut u32 { &mut self.0 } +} + +impl Baz { + fn x(&mut self) -> &mut u32 { + match *self { + Baz::X(ref mut value) => value + } + } +} + +static mut sfoo : Foo = Foo{x: 23 }; +static mut sbar : Bar = Bar(23); +static mut stuple : (i32, i32) = (24, 25); +static mut senum : Baz = Baz::X(26); +static mut sunion : U = U { a: 0 }; + +fn main() { + // Local and field from struct + { + let mut f = Foo { x: 22 }; + let _x = f.x(); + f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed + //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `f.x` because it was mutably borrowed (Mir) + } + // Local and field from tuple-struct + { + let mut g = Bar(22); + let _0 = g.x(); + g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed + //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `g.0` because it was mutably borrowed (Mir) + } + // Local and field from tuple + { + let mut h = (22, 23); + let _0 = &mut h.0; + h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed + //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `h.0` because it was mutably borrowed (Mir) + } + // Local and field from enum + { + let mut e = Baz::X(2); + let _e0 = e.x(); + match e { + Baz::X(value) => value + //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `e.0` because it was mutably borrowed (Mir) + }; + } + // Local and field from union + unsafe { + let mut u = U { b: 0 }; + let _ra = &mut u.a; + u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed + //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir) + } + // Static and field from struct + unsafe { + let _x = sfoo.x(); + sfoo.x; //[mir]~ ERROR cannot use `sfoo.x` because it was mutably borrowed (Mir) + } + // Static and field from tuple-struct + unsafe { + let _0 = sbar.x(); + sbar.0; //[mir]~ ERROR cannot use `sbar.0` because it was mutably borrowed (Mir) + } + // Static and field from tuple + unsafe { + let _0 = &mut stuple.0; + stuple.0; //[mir]~ ERROR cannot use `stuple.0` because it was mutably borrowed (Mir) + } + // Static and field from enum + unsafe { + let _e0 = senum.x(); + match senum { + Baz::X(value) => value + //[mir]~^ ERROR cannot use `senum.0` because it was mutably borrowed (Mir) + }; + } + // Static and field from union + unsafe { + let _ra = &mut sunion.a; + sunion.a; //[mir]~ ERROR cannot use `sunion.a` because it was mutably borrowed (Mir) + } + // Deref and field from struct + { + let mut f = Box::new(Foo { x: 22 }); + let _x = f.x(); + f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed + //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `f.x` because it was mutably borrowed (Mir) + } + // Deref and field from tuple-struct + { + let mut g = Box::new(Bar(22)); + let _0 = g.x(); + g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed + //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `g.0` because it was mutably borrowed (Mir) + } + // Deref and field from tuple + { + let mut h = Box::new((22, 23)); + let _0 = &mut h.0; + h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed + //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `h.0` because it was mutably borrowed (Mir) + } + // Deref and field from enum + { + let mut e = Box::new(Baz::X(3)); + let _e0 = e.x(); + match *e { + Baz::X(value) => value + //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `e.0` because it was mutably borrowed (Mir) + }; + } + // Deref and field from union + unsafe { + let mut u = Box::new(U { b: 0 }); + let _ra = &mut u.a; + u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed + //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir) + } +} From 7bdf177c8fe045508eff5fe767f00be3f1fca92d Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Mon, 2 Oct 2017 19:40:08 +0200 Subject: [PATCH 060/365] mir-borrowck: Fix existing tests --- .../compile-fail/borrowck/borrowck-assign-comp.rs | 4 ++-- .../borrowck/borrowck-closures-mut-and-imm.rs | 2 +- .../compile-fail/borrowck/borrowck-union-borrow.rs | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/compile-fail/borrowck/borrowck-assign-comp.rs b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs index e63de3a3bed..548436c3ed8 100644 --- a/src/test/compile-fail/borrowck/borrowck-assign-comp.rs +++ b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs @@ -22,7 +22,7 @@ fn a() { // immutable. Otherwise the type of &_q.x (&isize) would be wrong. p.x = 5; //[ast]~ ERROR cannot assign to `p.x` //[mir]~^ ERROR cannot assign to `p.x` because it is borrowed (Ast) - //[mir]~| ERROR cannot assign to `p.0` because it is borrowed (Mir) + //[mir]~| ERROR cannot assign to `p.x` because it is borrowed (Mir) q.x; } @@ -47,7 +47,7 @@ fn d() { let q = &p.y; p.y = 5; //[ast]~ ERROR cannot assign to `p.y` //[mir]~^ ERROR cannot assign to `p.y` because it is borrowed (Ast) - //[mir]~| ERROR cannot assign to `p.1` because it is borrowed (Mir) + //[mir]~| ERROR cannot assign to `p.y` because it is borrowed (Mir) *q; } diff --git a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs index 6c003ec2d48..0b6b9bf7d48 100644 --- a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs +++ b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs @@ -82,7 +82,7 @@ fn g() { let c1 = || get(&*x.f); *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f` //[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed (Ast) - //[mir]~| ERROR cannot assign to `(*(*x).0)` because it is borrowed (Mir) + //[mir]~| ERROR cannot assign to `(*x.f)` because it is borrowed (Mir) } fn h() { diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs index 73d323ea82c..0655d2914ee 100644 --- a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs @@ -34,13 +34,13 @@ fn main() { let ra = &u.a; let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable (Ast) - //[mir]~| ERROR cannot borrow `u.0` as mutable because it is also borrowed as immutable (Mir) + //[mir]~| ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable (Mir) } { let ra = &u.a; u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed (Ast) - //[mir]~| ERROR cannot assign to `u.0` because it is borrowed (Mir) + //[mir]~| ERROR cannot assign to `u.a` because it is borrowed (Mir) } // Imm borrow, other field { @@ -68,25 +68,25 @@ fn main() { let rma = &mut u.a; let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable (Ast) - //[mir]~| ERROR cannot borrow `u.0` as immutable because it is also borrowed as mutable (Mir) + //[mir]~| ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable (Mir) } { let ra = &mut u.a; let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast) - //[mir]~| ERROR cannot use `u.0` because it was mutably borrowed (Mir) + //[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir) } { let rma = &mut u.a; let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time (Ast) - //[mir]~| ERROR cannot borrow `u.0` as mutable more than once at a time (Mir) + //[mir]~| ERROR cannot borrow `u.a` as mutable more than once at a time (Mir) } { let rma = &mut u.a; u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed (Ast) - //[mir]~| ERROR cannot assign to `u.0` because it is borrowed (Mir) + //[mir]~| ERROR cannot assign to `u.a` because it is borrowed (Mir) } // Mut borrow, other field { From 456e12ec38f669b26b08414527ee1dc35091da33 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Wed, 4 Oct 2017 18:02:36 +0200 Subject: [PATCH 061/365] mir-borrowck: Panic when trying to print a field access on a non-box type that is neither Adt nor tuple --- src/librustc_mir/borrow_check.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index f4bf280cd25..18bb78ef50f 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1178,8 +1178,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> format!("{}", field_index) }, _ => { - debug!("End-user description not implemented for field of type {:?}", ty.sty); - format!("{}", field_index) + // Might need a revision when the fields in trait RFC is implemented + // (https://github.com/rust-lang/rfcs/pull/1546) + bug!("Field access unsupported for non-box types that are neither Adt (struct, \ + enum, union) nor tuples"); } } } From ef2f42d04a4c83dd5b50cd672b8a1b0791e00f98 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Thu, 5 Oct 2017 11:03:32 +0200 Subject: [PATCH 062/365] mir-borrowck: Autoderef values followed by a constant index, and fix reported lvalue for constant index Previously the constant index was reported as `[x of y]` or `[-x of y]` where `x` was the offset and `y` the minimum length of the slice. The minus sign wasn't in the right case since for `&[_, x, .., _, _]`, the error reported was `[-1 of 4]`, and for `&[_, _, .., x, _]`, the error reported was `[2 of 4]`. This commit fixes the sign so that the indexes 1 and -2 are reported, and remove the ` of y` part of the message to make it more succinct. --- src/librustc_mir/borrow_check.rs | 12 ++++--- .../borrowck/borrowck-describe-lvalue.rs | 35 +++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 18bb78ef50f..85ecb9d6e36 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1090,10 +1090,14 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> autoderef = true; ("", format!(""), Some(index)) }, - ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => - ("", format!("[{} of {}]", offset, min_length), None), - ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => - ("", format!("[-{} of {}]", offset, min_length), None), + ProjectionElem::ConstantIndex { offset, from_end: false, .. } => { + autoderef = true; + ("", format!("[{}]", offset), None) + }, + ProjectionElem::ConstantIndex { offset, from_end: true, .. } => { + autoderef = true; + ("", format!("[-{}]", offset), None) + }, ProjectionElem::Subslice { from, to: 0 } => ("", format!("[{}:]", from), None), ProjectionElem::Subslice { from: 0, to } => diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 6de8bda9276..9d1b2b64d85 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -11,6 +11,8 @@ // revisions: ast mir //[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir +#![feature(advanced_slice_patterns)] + pub struct Foo { x: u32 } @@ -163,4 +165,37 @@ fn main() { //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast) //[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir) } + // Constant index + { + let mut v = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let _v = &mut v; + match v { + &[x, _, .., _, _] => println!("{}", x), + //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[0]` because it was mutably borrowed (Mir) + _ => panic!("other case"), + } + match v { + &[_, x, .., _, _] => println!("{}", x), + //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[1]` because it was mutably borrowed (Mir) + _ => panic!("other case"), + } + match v { + &[_, _, .., x, _] => println!("{}", x), + //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[-2]` because it was mutably borrowed (Mir) + _ => panic!("other case"), + } + match v { + &[_, _, .., _, x] => println!("{}", x), + //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[-1]` because it was mutably borrowed (Mir) + _ => panic!("other case"), + } + } } From 0241ea45b2e71e53921627bc09219653f2629c0e Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Fri, 6 Oct 2017 17:21:06 +0200 Subject: [PATCH 063/365] mir-borrowck: Replace all constant index and sublices output with `[..]` to match the AST borrowck output --- src/librustc_mir/borrow_check.rs | 17 +++----- .../borrowck/borrowck-describe-lvalue.rs | 43 +++++++++++++++++-- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 85ecb9d6e36..d57bac7c85a 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1090,20 +1090,13 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> autoderef = true; ("", format!(""), Some(index)) }, - ProjectionElem::ConstantIndex { offset, from_end: false, .. } => { + ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { autoderef = true; - ("", format!("[{}]", offset), None) + // Since it isn't possible to borrow an element on a particular index and + // then use another while the borrow is held, don't output indices details + // to avoid confusing the end-user + ("", format!("[..]"), None) }, - ProjectionElem::ConstantIndex { offset, from_end: true, .. } => { - autoderef = true; - ("", format!("[-{}]", offset), None) - }, - ProjectionElem::Subslice { from, to: 0 } => - ("", format!("[{}:]", from), None), - ProjectionElem::Subslice { from: 0, to } => - ("", format!("[:-{}]", to), None), - ProjectionElem::Subslice { from, to } => - ("", format!("[{}:-{}]", from, to), None), }; buf.push_str(prefix); self.append_lvalue_to_string(&proj.base, buf, Some(autoderef)); diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 9d1b2b64d85..088b678efb5 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength // revisions: ast mir //[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir +#![feature(slice_patterns)] #![feature(advanced_slice_patterns)] pub struct Foo { @@ -173,29 +175,62 @@ fn main() { &[x, _, .., _, _] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) - //[mir]~| ERROR cannot use `v[0]` because it was mutably borrowed (Mir) + //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir) _ => panic!("other case"), } match v { &[_, x, .., _, _] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) - //[mir]~| ERROR cannot use `v[1]` because it was mutably borrowed (Mir) + //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir) _ => panic!("other case"), } match v { &[_, _, .., x, _] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) - //[mir]~| ERROR cannot use `v[-2]` because it was mutably borrowed (Mir) + //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir) _ => panic!("other case"), } match v { &[_, _, .., _, x] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) - //[mir]~| ERROR cannot use `v[-1]` because it was mutably borrowed (Mir) + //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir) _ => panic!("other case"), } } + // Subslices + { + let mut v = &[1, 2, 3, 4, 5]; + let _v = &mut v; + match v { + &[x..] => println!("{:?}", x), + //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir) + _ => panic!("other case"), + } + match v { + &[_, x..] => println!("{:?}", x), + //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir) + _ => panic!("other case"), + } + match v { + &[x.., _] => println!("{:?}", x), + //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir) + _ => panic!("other case"), + } + match v { + &[_, x.., _] => println!("{:?}", x), + //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir) + _ => panic!("other case"), + } + } } From f35c4e3aa168e1d5d78753ae1d12e8f25cbec699 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Fri, 6 Oct 2017 17:24:23 +0200 Subject: [PATCH 064/365] mir-borrowck: Implement end-user output for field of downcast projection --- src/librustc_mir/borrow_check.rs | 7 ++----- .../borrowck/borrowck-describe-lvalue.rs | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index d57bac7c85a..62e73557b25 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1125,11 +1125,6 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> match proj.elem { ProjectionElem::Deref => self.describe_field(&proj.base, field_index), - ProjectionElem::Downcast(..) => { - debug!("End-user description not implemented for field of projection {:?}", - proj); - format!("{}", field_index) - }, ProjectionElem::Field(..) => { debug!("End-user description not implemented for field of projection {:?}", proj); @@ -1145,6 +1140,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> proj); format!("{}", field_index) }, + ProjectionElem::Downcast(def, variant_index) => + format!("{}", def.variants[variant_index].fields[field_index].name), ProjectionElem::Subslice { .. } => { debug!("End-user description not implemented for field of projection {:?}", proj); diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 088b678efb5..7ea965b07be 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -233,4 +233,24 @@ fn main() { _ => panic!("other case"), } } + // Downcasted field + { + enum E { A(X), B { x: X } } + + let mut e = E::A(3); + let _e = &mut e; + match e { + E::A(ref ax) => + //[ast]~^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable + //[mir]~^^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `e.0` as immutable because it is also borrowed as mutable (Mir) + //[mir]~| ERROR cannot use `e` because it was mutably borrowed (Mir) + println!("e.ax: {:?}", ax), + E::B { x: ref bx } => + //[ast]~^ ERROR cannot borrow `e.x` as immutable because `e` is also borrowed as mutable + //[mir]~^^ ERROR cannot borrow `e.x` as immutable because `e` is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `e.x` as immutable because it is also borrowed as mutable (Mir) + println!("e.bx: {:?}", bx), + } + } } From ce3b2e779e56b99a682086d7d9575260158f1ad1 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Fri, 6 Oct 2017 17:25:41 +0200 Subject: [PATCH 065/365] mir-borrowck: Implement end-user output for field of field projection --- src/librustc_mir/borrow_check.rs | 7 ++---- .../borrowck/borrowck-describe-lvalue.rs | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 62e73557b25..384b1fb418c 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1125,11 +1125,6 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> match proj.elem { ProjectionElem::Deref => self.describe_field(&proj.base, field_index), - ProjectionElem::Field(..) => { - debug!("End-user description not implemented for field of projection {:?}", - proj); - format!("{}", field_index) - }, ProjectionElem::Index(..) => { debug!("End-user description not implemented for field of projection {:?}", proj); @@ -1142,6 +1137,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> }, ProjectionElem::Downcast(def, variant_index) => format!("{}", def.variants[variant_index].fields[field_index].name), + ProjectionElem::Field(_, field_type) => + self.describe_field_from_ty(&field_type, field_index), ProjectionElem::Subslice { .. } => { debug!("End-user description not implemented for field of projection {:?}", proj); diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 7ea965b07be..103aad693f7 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -253,4 +253,27 @@ fn main() { println!("e.bx: {:?}", bx), } } + // Field in field + { + struct F { x: u32, y: u32 }; + struct S { x: F, y: (u32, u32), }; + let mut s = S { x: F { x: 1, y: 2}, y: (999, 998) }; + let _s = &mut s; + match s { + S { y: (ref y0, _), .. } => + //[ast]~^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable + //[mir]~^^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `s.y.0` as immutable because it is also borrowed as mutable (Mir) + println!("y0: {:?}", y0), + _ => panic!("other case"), + } + match s { + S { x: F { y: ref x0, .. }, .. } => + //[ast]~^ ERROR cannot borrow `s.x.y` as immutable because `s` is also borrowed as mutable + //[mir]~^^ ERROR cannot borrow `s.x.y` as immutable because `s` is also borrowed as mutable (Ast) + //[mir]~| ERROR cannot borrow `s.x.y` as immutable because it is also borrowed as mutable (Mir) + println!("x0: {:?}", x0), + _ => panic!("other case"), + } + } } From 9ce2f3af9379246909d3e0151b956ad428bbc175 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Fri, 6 Oct 2017 17:26:14 +0200 Subject: [PATCH 066/365] mir-borrowck: Implement end-user output for field of index projection --- src/librustc_mir/borrow_check.rs | 12 ++-------- .../borrowck/borrowck-describe-lvalue.rs | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 384b1fb418c..0d9dbfab1e8 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1125,20 +1125,12 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> match proj.elem { ProjectionElem::Deref => self.describe_field(&proj.base, field_index), - ProjectionElem::Index(..) => { - debug!("End-user description not implemented for field of projection {:?}", - proj); - format!("{}", field_index) - }, - ProjectionElem::ConstantIndex { .. } => { - debug!("End-user description not implemented for field of projection {:?}", - proj); - format!("{}", field_index) - }, ProjectionElem::Downcast(def, variant_index) => format!("{}", def.variants[variant_index].fields[field_index].name), ProjectionElem::Field(_, field_type) => self.describe_field_from_ty(&field_type, field_index), + ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } => + format!("{}", self.describe_field(&proj.base, field_index)), ProjectionElem::Subslice { .. } => { debug!("End-user description not implemented for field of projection {:?}", proj); diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 103aad693f7..7ead9032c13 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -276,4 +276,27 @@ fn main() { _ => panic!("other case"), } } + // Field of index + { + struct F {x: u32, y: u32}; + let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}]; + let _v = &mut v; + v[0].y; + //[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[..].y` because it was mutably borrowed (Ast) + //[mir]~| ERROR cannot use `v[..].y` because it was mutably borrowed (Mir) + //[mir]~| ERROR cannot use `(*v)` because it was mutably borrowed (Mir) + } + // Field of constant index + { + struct F {x: u32, y: u32}; + let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}]; + let _v = &mut v; + match v { + &[_, F {x: ref xf, ..}] => println!("{}", xf), + //[mir]~^ ERROR cannot borrow `v[..].x` as immutable because it is also borrowed as mutable (Mir) + // No errors in AST + _ => panic!("other case") + } + } } From ca5dc86c5a2e92f35c94e7a1f4592bb7fd0b271c Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Fri, 6 Oct 2017 17:26:53 +0200 Subject: [PATCH 067/365] mir-borrowck: Implement end-user output for field of reference, pointer and array --- src/librustc_mir/borrow_check.rs | 9 ++++-- .../borrowck/borrowck-describe-lvalue.rs | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 0d9dbfab1e8..eb05a815c73 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1160,11 +1160,16 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> ty::TyTuple(_, _) => { format!("{}", field_index) }, + ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => { + self.describe_field_from_ty(&tnm.ty, field_index) + }, + ty::TyArray(ty, _) => { + self.describe_field_from_ty(&ty, field_index) + } _ => { // Might need a revision when the fields in trait RFC is implemented // (https://github.com/rust-lang/rfcs/pull/1546) - bug!("Field access unsupported for non-box types that are neither Adt (struct, \ - enum, union) nor tuples"); + bug!("End-user description not implemented for field access on `{:?}`", ty.sty); } } } diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 7ead9032c13..cff913b17be 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -276,6 +276,34 @@ fn main() { _ => panic!("other case"), } } + // Field of ref + { + struct Block<'a> { + current: &'a u8, + unrelated: &'a u8, + }; + + fn bump<'a>(mut block: &mut Block<'a>) { + let x = &mut block; + let p: &'a u8 = &*block.current; + //[mir]~^ ERROR cannot borrow `(*block.current)` as immutable because it is also borrowed as mutable (Mir) + // No errors in AST because of issue rust#38899 + } + } + // Field of ptr + { + struct Block2 { + current: *const u8, + unrelated: *const u8, + } + + unsafe fn bump2(mut block: *mut Block2) { + let x = &mut block; + let p : *const u8 = &*(*block).current; + //[mir]~^ ERROR cannot borrow `(*block.current)` as immutable because it is also borrowed as mutable (Mir) + // No errors in AST because of issue rust#38899 + } + } // Field of index { struct F {x: u32, y: u32}; From 8b8cdd984aa31eebccea2a9fb5c1f7931dd01c27 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Fri, 6 Oct 2017 17:29:14 +0200 Subject: [PATCH 068/365] mir-borrowck: Append `_` or `..` depending on the context if a local variable hasn't a name --- src/librustc_mir/borrow_check.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index eb05a815c73..3546b998532 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -14,7 +14,7 @@ use rustc::hir::def_id::{DefId}; use rustc::infer::{InferCtxt}; use rustc::ty::{self, TyCtxt, ParamEnv}; use rustc::ty::maps::Providers; -use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue}; +use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue, Local}; use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind}; use rustc::mir::transform::{MirSource}; @@ -1061,11 +1061,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String, autoderef: Option) { match *lvalue { Lvalue::Local(local) => { - let local = &self.mir.local_decls[local]; - match local.name { - Some(name) => buf.push_str(&format!("{}", name)), - None => buf.push_str("_"), - } + self.append_local_to_string(local, buf, "_"); } Lvalue::Static(ref static_) => { buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id))); @@ -1102,7 +1098,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> self.append_lvalue_to_string(&proj.base, buf, Some(autoderef)); if let Some(index) = index_operand { buf.push_str("["); - self.append_lvalue_to_string(&Lvalue::Local(index), buf, None); + self.append_local_to_string(index, buf, ".."); buf.push_str("]"); } else { buf.push_str(&suffix); @@ -1111,6 +1107,16 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> } } + // Appends end-user visible description of the `local` lvalue to `buf`. If `local` doesn't have + // a name, then `none_string` is appended instead + fn append_local_to_string(&self, local_index: Local, buf: &mut String, none_string: &str) { + let local = &self.mir.local_decls[local_index]; + match local.name { + Some(name) => buf.push_str(&format!("{}", name)), + None => buf.push_str(none_string) + } + } + // End-user visible description of the `field_index`nth field of `base` fn describe_field(&self, base: &Lvalue, field_index: usize) -> String { match *base { From b6eef82c684268bd719d3ced4f4cca69b014aaff Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sat, 7 Oct 2017 00:26:41 +0900 Subject: [PATCH 069/365] Rename variables --- src/librustc/traits/error_reporting.rs | 42 +++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 372f0564726..115782ca2ad 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -711,38 +711,38 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, _) => { + OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => { + let found_trait_ref = self.resolve_type_vars_if_possible(&*found_trait_ref); let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref); - let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref); - if actual_trait_ref.self_ty().references_error() { + if expected_trait_ref.self_ty().references_error() { return; } - let expected_trait_ty = expected_trait_ref.self_ty(); + let found_trait_ty = found_trait_ref.self_ty(); - let found_did = expected_trait_ty.ty_to_def_id(); + let found_did = found_trait_ty.ty_to_def_id(); let found_span = found_did.and_then(|did| { self.tcx.hir.span_if_local(did) }); - let self_ty_count = - match expected_trait_ref.skip_binder().substs.type_at(1).sty { + let found_ty_count = + match found_trait_ref.skip_binder().substs.type_at(1).sty { ty::TyTuple(ref tys, _) => tys.len(), _ => 1, }; - let (arg_tys, arg_ty_count) = - match actual_trait_ref.skip_binder().substs.type_at(1).sty { + let (expected_tys, expected_ty_count) = + match expected_trait_ref.skip_binder().substs.type_at(1).sty { ty::TyTuple(ref tys, _) => (tys.iter().map(|t| &t.sty).collect(), tys.len()), ref sty => (vec![sty], 1), }; - if self_ty_count == arg_ty_count { + if found_ty_count == expected_ty_count { self.report_closure_arg_mismatch(span, found_span, - expected_trait_ref, - actual_trait_ref) + found_trait_ref, + expected_trait_ref) } else { - let arg_tuple = if arg_ty_count == 1 { - arg_tys.first().and_then(|t| { + let expected_tuple = if expected_ty_count == 1 { + expected_tys.first().and_then(|t| { if let &&ty::TyTuple(ref tuptys, _) = t { Some(tuptys.len()) } else { @@ -753,15 +753,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { None }; - // FIXME(#44150): Expand this to "N args expected bug a N-tuple found". + // FIXME(#44150): Expand this to "N args expected but a N-tuple found." // Type of the 1st expected argument is somehow provided as type of a // found one in that case. // // ``` // [1i32, 2, 3].sort_by(|(a, b)| ..) // // ^^^^^^^^ - // // actual_trait_ref: std::ops::FnMut<(&i32, &i32)> - // // expected_trait_ref: std::ops::FnMut<(&i32,)> + // // expected_trait_ref: std::ops::FnMut<(&i32, &i32)> + // // found_trait_ref: std::ops::FnMut<(&i32,)> // ``` let closure_args_span = found_did.and_then(|did| self.tcx.hir.get_if_local(did)) @@ -778,10 +778,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.report_arg_count_mismatch( span, closure_args_span.or(found_span), - arg_ty_count, - arg_tuple, - self_ty_count, - expected_trait_ty.is_closure() + expected_ty_count, + expected_tuple, + found_ty_count, + found_trait_ty.is_closure() ) } } From e32e81c9da5adcc77bd12192d45d2d4af54d0ee9 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Fri, 6 Oct 2017 18:23:53 +0200 Subject: [PATCH 070/365] mir-borrowck: Implement end-user output for field of subslice and slice type --- src/librustc_mir/borrow_check.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 3546b998532..14e6f597826 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1135,13 +1135,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> format!("{}", def.variants[variant_index].fields[field_index].name), ProjectionElem::Field(_, field_type) => self.describe_field_from_ty(&field_type, field_index), - ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } => + ProjectionElem::Index(..) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } => format!("{}", self.describe_field(&proj.base, field_index)), - ProjectionElem::Subslice { .. } => { - debug!("End-user description not implemented for field of projection {:?}", - proj); - format!("{}", field_index) - } } } } @@ -1169,7 +1166,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => { self.describe_field_from_ty(&tnm.ty, field_index) }, - ty::TyArray(ty, _) => { + ty::TyArray(ty, _) | ty::TySlice(ty) => { self.describe_field_from_ty(&ty, field_index) } _ => { From c3c1df582094b10f803d875f43f6e8b7e3107c5d Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 3 Oct 2017 13:28:57 -0600 Subject: [PATCH 071/365] Implement display_hint in gdb pretty printers A few pretty-printers were returning a quoted string from their to_string method. It's preferable in gdb to return a lazy string and to let gdb handle the display by having a "display_hint" method that returns "string" -- it lets gdb settings (like "set print ...") work, it handles corrupted strings a bit better, and it passes the information along to IDEs. --- src/etc/gdb_rust_pretty_printing.py | 15 +++++++++++---- src/test/debuginfo/pretty-std.rs | 4 ++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 822dc581404..0612873e281 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -248,7 +248,10 @@ class RustStringSlicePrinter(object): def to_string(self): (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val) raw_ptr = data_ptr.get_wrapped_value() - return '"%s"' % raw_ptr.string(encoding="utf-8", length=length) + return raw_ptr.lazy_string(encoding="utf-8", length=length) + + def display_hint(self): + return "string" class RustStdVecPrinter(object): @@ -278,9 +281,11 @@ class RustStdStringPrinter(object): def to_string(self): vec = self.__val.get_child_at_index(0) (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(vec) - return '"%s"' % data_ptr.get_wrapped_value().string(encoding="utf-8", - length=length) + return data_ptr.get_wrapped_value().lazy_string(encoding="utf-8", + length=length) + def display_hint(self): + return "string" class RustOsStringPrinter(object): def __init__(self, val): @@ -294,8 +299,10 @@ class RustOsStringPrinter(object): (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec( vec) - return '"%s"' % data_ptr.get_wrapped_value().string(length=length) + return data_ptr.get_wrapped_value().lazy_string(length=length) + def display_hint(self): + return "string" class RustCStyleVariantPrinter(object): def __init__(self, val): diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 9596f0287bc..2a28c895b79 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -44,6 +44,10 @@ // gdb-command: print some_string // gdb-check:$8 = Some = {"IAMA optional string!"} +// gdb-command: set print length 5 +// gdb-command: print some_string +// gdb-check:$8 = Some = {"IAMA "...} + // === LLDB TESTS ================================================================================== From 904133e1e28b690e2bbd101b719509aa897539a0 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Fri, 6 Oct 2017 16:39:01 -0400 Subject: [PATCH 072/365] Revert to using mem::transmute in Box::into_unique Seems to cause this error: "Cannot handle boxed::Box<[u8]> represented as TyLayout". --- src/liballoc/boxed.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 512c7194fe3..6b92da11079 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -326,9 +326,7 @@ impl Box { issue = "27730")] #[inline] pub fn into_unique(b: Box) -> Unique { - let u = b.0; - mem::forget(b); - u + unsafe { mem::transmute(b) } } } From 452b71a07be066432d93a93c1f9e7f10e18d7c96 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Fri, 6 Oct 2017 17:01:50 -0400 Subject: [PATCH 073/365] Revert to using mem::transmute in Box::from_raw Same reasons as commit 904133e1e28b690e2bbd101b719509aa897539a0. --- src/liballoc/boxed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6b92da11079..2e77b1b390c 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -269,7 +269,7 @@ impl Box { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { - Box(Unique::new_unchecked(raw)) + mem::transmute(raw) } /// Consumes the `Box`, returning the wrapped raw pointer. From 5ce5b2fe76802385e2974bdec8d82117fb55d0ea Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Fri, 6 Oct 2017 17:29:49 -0400 Subject: [PATCH 074/365] Create Box::from_unique function Provides a reasonable interface for Box::from_raw implementation. Does not get around the requirement of mem::transmute for converting back and forth between Unique and Box. --- src/liballoc/boxed.rs | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2e77b1b390c..53d643e7288 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -269,7 +269,34 @@ impl Box { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { - mem::transmute(raw) + Box::from_unique(Unique::new_unchecked(raw)) + } + + /// Constructs a `Box` from a `Unique` pointer. + /// + /// After calling this function, the memory is owned by a `Box` and `T` then + /// be destroyed and released upon drop. + /// + /// # Safety + /// + /// A `Unique` can be safely created via [`Unique::new`] and thus doesn't + /// necessarily own the data pointed to nor is the data guaranteed to live + /// as long as the pointer. + /// + /// [`Unique::new`]: ../../core/ptr/struct.Unique.html#method.new + /// + /// # Examples + /// + /// ``` + /// let x = Box::new(5); + /// let ptr = Box::into_unique(x); + /// let x = unsafe { Box::from_unique(ptr) }; + /// ``` + #[unstable(feature = "unique", reason = "needs an RFC to flesh out design", + issue = "27730")] + #[inline] + pub unsafe fn from_unique(u: Unique) -> Self { + mem::transmute(u) } /// Consumes the `Box`, returning the wrapped raw pointer. @@ -303,13 +330,18 @@ impl Box { /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `Box` with the [`Box::from_raw`] function. + /// proper way to do so is to either convert the `Unique` pointer: + /// + /// - Into a `Box` with the [`Box::from_unique`] function. + /// + /// - Into a raw pointer and back into a `Box` with the [`Box::from_raw`] + /// function. /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_unique(b)` instead of `b.into_unique()`. This /// is so that there is no conflict with a method on the inner type. /// + /// [`Box::from_unique`]: struct.Box.html#method.from_unique /// [`Box::from_raw`]: struct.Box.html#method.from_raw /// /// # Examples From 5af88ee9969320ef900190e1e6a8247d800b7fe6 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Fri, 6 Oct 2017 17:39:38 -0400 Subject: [PATCH 075/365] Add missing word in Box::from_unique docs --- src/liballoc/boxed.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 53d643e7288..2c14dfb1dd0 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -274,8 +274,8 @@ impl Box { /// Constructs a `Box` from a `Unique` pointer. /// - /// After calling this function, the memory is owned by a `Box` and `T` then - /// be destroyed and released upon drop. + /// After calling this function, the memory is owned by a `Box` and `T` can + /// then be destroyed and released upon drop. /// /// # Safety /// From 22298b8240d40ed9b3dbdf570bccce56dfbfcd2c Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Fri, 6 Oct 2017 19:21:22 -0400 Subject: [PATCH 076/365] Add unique feature in Box::from_unique docs --- src/liballoc/boxed.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2c14dfb1dd0..0d19b74ebae 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -288,9 +288,13 @@ impl Box { /// # Examples /// /// ``` - /// let x = Box::new(5); - /// let ptr = Box::into_unique(x); - /// let x = unsafe { Box::from_unique(ptr) }; + /// #![feature(unique)] + /// + /// fn main() { + /// let x = Box::new(5); + /// let ptr = Box::into_unique(x); + /// let x = unsafe { Box::from_unique(ptr) }; + /// } /// ``` #[unstable(feature = "unique", reason = "needs an RFC to flesh out design", issue = "27730")] From c74bda1075757cd00f72a918e2d7fdaf47f85c2d Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sat, 7 Oct 2017 15:12:56 +0900 Subject: [PATCH 077/365] Add suggestion --- src/librustc/traits/error_reporting.rs | 131 +++++++++++++----- .../ui/mismatched_types/closure-arg-count.rs | 2 + .../mismatched_types/closure-arg-count.stderr | 32 +++-- 3 files changed, 126 insertions(+), 39 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 115782ca2ad..5056876f3ad 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -764,23 +764,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // // found_trait_ref: std::ops::FnMut<(&i32,)> // ``` - let closure_args_span = found_did.and_then(|did| self.tcx.hir.get_if_local(did)) + let (closure_span, closure_args) = found_did + .and_then(|did| self.tcx.hir.get_if_local(did)) .and_then(|node| { if let hir::map::NodeExpr( - &hir::Expr { node: hir::ExprClosure(_, _, _, span, _), .. }) = node + &hir::Expr { + node: hir::ExprClosure(_, ref decl, id, span, _), + .. + }) = node { - Some(span) + let ty_snips = decl.inputs.iter() + .map(|ty| { + self.tcx.sess.codemap().span_to_snippet(ty.span).ok() + .and_then(|snip| { + // filter out dummy spans + if snip == "," || snip == "|" { + None + } else { + Some(snip) + } + }) + }) + .collect::>>(); + + let body = self.tcx.hir.body(id); + let pat_snips = body.arguments.iter() + .map(|arg| + self.tcx.sess.codemap().span_to_snippet(arg.pat.span).ok()) + .collect::>>(); + + Some((span, pat_snips, ty_snips)) } else { None } - }); + }) + .map(|(span, pat, ty)| (Some(span), Some((pat, ty)))) + .unwrap_or((None, None)); + let closure_args = closure_args.and_then(|(pat, ty)| Some((pat?, ty))); self.report_arg_count_mismatch( span, - closure_args_span.or(found_span), + closure_span.or(found_span), expected_ty_count, expected_tuple, found_ty_count, + closure_args, found_trait_ty.is_closure() ) } @@ -803,44 +831,85 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.emit(); } - fn report_arg_count_mismatch(&self, - span: Span, - found_span: Option, - expected: usize, - expected_tuple: Option, - found: usize, - is_closure: bool) - -> DiagnosticBuilder<'tcx> - { + fn report_arg_count_mismatch( + &self, + span: Span, + found_span: Option, + expected: usize, + expected_tuple: Option, + found: usize, + closure_args: Option<(Vec, Vec>)>, + is_closure: bool + ) -> DiagnosticBuilder<'tcx> { + use std::borrow::Cow; + let kind = if is_closure { "closure" } else { "function" }; - let tuple_or_args = |tuple, args| if let Some(n) = tuple { - format!("a {}-tuple", n) - } else { - format!( + let args_str = |n| format!( "{} argument{}", - args, - if args == 1 { "" } else { "s" } - ) - }; - - let found_str = tuple_or_args(None, found); - let expected_str = tuple_or_args(expected_tuple, expected); + n, + if n == 1 { "" } else { "s" } + ); let mut err = struct_span_err!(self.tcx.sess, span, E0593, - "{} takes {} but {} {} required", + "{} takes {}, but {} {} required", kind, - found_str, - expected_str, - if expected_tuple.is_some() || expected == 1 { "is" } else { "are" }); + if expected_tuple.is_some() { + Cow::from("multiple arguments") + } else { + Cow::from(args_str(found)) + }, + if expected_tuple.is_some() { + Cow::from("a tuple argument") + } else { + Cow::from(args_str(expected)) + }, + if expected == 1 { "is" } else { "are" }); err.span_label( span, - format!("expected {} that takes {}", kind, expected_str) + format!( + "expected {} that takes {}{}", + kind, + args_str(expected), + if let Some(n) = expected_tuple { + assert!(expected == 1); + Cow::from(format!(", a {}-tuple", n)) + } else { + Cow::from("") + } + ) ); if let Some(span) = found_span { - err.span_label(span, format!("takes {}", found_str)); + if let (Some(expected_tuple), Some((pats, tys))) = (expected_tuple, closure_args) { + if expected_tuple != found || pats.len() != found { + err.span_label(span, format!("takes {}", args_str(found))); + } else { + let sugg = format!( + "|({}){}|", + pats.join(", "), + + // add type annotations if available + if tys.iter().any(|ty| ty.is_some()) { + Cow::from(format!( + ": ({})", + tys.into_iter().map(|ty| if let Some(ty) = ty { + ty + } else { + "_".to_string() + }).collect::>().join(", ") + )) + } else { + Cow::from("") + }, + ); + + err.span_suggestion(span, "consider changing to", sugg); + } + } else { + err.span_label(span, format!("takes {}", args_str(found))); + } } err diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index a2a31d44a49..5d2d1d2b04c 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -18,4 +18,6 @@ fn main() { f(|| panic!()); let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); + let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i); + let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); } diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index e59a585149b..24860faf2d5 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -1,4 +1,4 @@ -error[E0593]: closure takes 0 arguments but 2 arguments are required +error[E0593]: closure takes 0 arguments, but 2 arguments are required --> $DIR/closure-arg-count.rs:15:15 | 15 | [1, 2, 3].sort_by(|| panic!()); @@ -6,7 +6,7 @@ error[E0593]: closure takes 0 arguments but 2 arguments are required | | | expected closure that takes 2 arguments -error[E0593]: closure takes 1 argument but 2 arguments are required +error[E0593]: closure takes 1 argument, but 2 arguments are required --> $DIR/closure-arg-count.rs:16:15 | 16 | [1, 2, 3].sort_by(|tuple| panic!()); @@ -23,7 +23,7 @@ error[E0308]: mismatched types = note: expected type `&{integer}` found type `(_, _)` -error[E0593]: closure takes 1 argument but 2 arguments are required +error[E0593]: closure takes 1 argument, but 2 arguments are required --> $DIR/closure-arg-count.rs:17:15 | 17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); @@ -31,7 +31,7 @@ error[E0593]: closure takes 1 argument but 2 arguments are required | | | expected closure that takes 2 arguments -error[E0593]: closure takes 0 arguments but 1 argument is required +error[E0593]: closure takes 0 arguments, but 1 argument is required --> $DIR/closure-arg-count.rs:18:5 | 18 | f(|| panic!()); @@ -41,13 +41,29 @@ error[E0593]: closure takes 0 arguments but 1 argument is required | = note: required by `f` -error[E0593]: closure takes 2 arguments but a 2-tuple is required +error[E0593]: closure takes multiple arguments, but a tuple argument is required --> $DIR/closure-arg-count.rs:20:53 | 20 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); - | ^^^ ------ takes 2 arguments + | ^^^ ------ help: consider changing to: `|(i, x)|` | | - | expected closure that takes a 2-tuple + | expected closure that takes 1 argument, a 2-tuple -error: aborting due to 6 previous errors +error[E0593]: closure takes multiple arguments, but a tuple argument is required + --> $DIR/closure-arg-count.rs:21:53 + | +21 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i); + | ^^^ ------------- help: consider changing to: `|(i, x): (usize, _)|` + | | + | expected closure that takes 1 argument, a 2-tuple + +error[E0593]: closure takes multiple arguments, but a tuple argument is required + --> $DIR/closure-arg-count.rs:22:53 + | +22 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); + | ^^^ --------- takes 3 arguments + | | + | expected closure that takes 1 argument, a 2-tuple + +error: aborting due to 8 previous errors From 45907f5caca8ea3023174b939d1fd4c052569420 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sat, 7 Oct 2017 05:32:31 -0400 Subject: [PATCH 078/365] fmt: remove unnecessary lint suppression --- src/libcore/fmt/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 6c251b9eb09..7627a2048d1 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -322,7 +322,6 @@ impl<'a> ArgumentV1<'a> { // flags available in the v1 format of format_args #[derive(Copy, Clone)] -#[allow(dead_code)] // SignMinus isn't currently used enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, } impl<'a> Arguments<'a> { From 19dcf9190ce3c28188781806135b9f9e24e771c9 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sat, 7 Oct 2017 05:31:21 -0400 Subject: [PATCH 079/365] fmt: DRY --- src/libcore/fmt/builders.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index b594c886b64..60b9eeb1283 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use fmt::{self, FlagV1}; +use fmt; struct PadAdapter<'a, 'b: 'a> { fmt: &'a mut fmt::Formatter<'b>, @@ -140,7 +140,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { } fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + self.fmt.alternate() } } @@ -233,7 +233,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { } fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + self.fmt.alternate() } } @@ -277,7 +277,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { } fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + self.fmt.alternate() } } @@ -519,6 +519,6 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { } fn is_pretty(&self) -> bool { - self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + self.fmt.alternate() } } From 41b105b6eac2f3b73cc3225d20fab8cecaabb73f Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sat, 7 Oct 2017 05:48:58 -0400 Subject: [PATCH 080/365] fmt: remove misleading comment fragment --- src/libcore/fmt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 7627a2048d1..32f1142069e 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1275,7 +1275,7 @@ impl<'a> Formatter<'a> { write(self.buf, fmt) } - /// Flags for formatting (packed version of rt::Flag) + /// Flags for formatting #[stable(feature = "rust1", since = "1.0.0")] pub fn flags(&self) -> u32 { self.flags } From 3493c62ff2628ef81f6f3a968c951252e9b57824 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 27 Sep 2017 00:43:22 +0200 Subject: [PATCH 081/365] Add names to BareFnTy --- src/librustc/hir/intravisit.rs | 2 +- src/librustc/hir/lowering.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 1755b3bca05..3130a88306e 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -574,7 +574,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyTup(ref tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } - TyBareFn(ref function_declaration) => { + TyBareFn(ref function_declaration, _) => { visitor.visit_fn_decl(&function_declaration.decl); walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1fdfbe20328..c03c9499608 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -673,7 +673,15 @@ impl<'a> LoweringContext<'a> { unsafety: self.lower_unsafety(f.unsafety), abi: f.abi, decl: self.lower_fn_decl(&f.decl), - })) + }, + decl.inputs.iter().map(|arg| { + match arg.pat.node { + PatKind::Ident(_, ident, None) => { + respan(ident.span, ident.node.name) + } + _ => respan(arg.pat.span, keywords::Invalid.name()), + } + }).collect())) } TyKind::Never => hir::TyNever, TyKind::Tup(ref tys) => { From 4ca1b19fde0c4fcdeba24a8e6135577e86c69f49 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 23 Jul 2017 08:14:38 -0700 Subject: [PATCH 082/365] rustc: Implement ThinLTO This commit is an implementation of LLVM's ThinLTO for consumption in rustc itself. Currently today LTO works by merging all relevant LLVM modules into one and then running optimization passes. "Thin" LTO operates differently by having more sharded work and allowing parallelism opportunities between optimizing codegen units. Further down the road Thin LTO also allows *incremental* LTO which should enable even faster release builds without compromising on the performance we have today. This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then also implements two forms of ThinLTO: * In one mode we'll *only* perform ThinLTO over the codegen units produced in a single compilation. That is, we won't load upstream rlibs, but we'll instead just perform ThinLTO amongst all codegen units produced by the compiler for the local crate. This is intended to emulate a desired end point where we have codegen units turned on by default for all crates and ThinLTO allows us to do this without performance loss. * In anther mode, like full LTO today, we'll optimize all upstream dependencies in "thin" mode. Unlike today, however, this LTO step is fully parallelized so should finish much more quickly. There's a good bit of comments about what the implementation is doing and where it came from, but the tl;dr; is that currently most of the support here is copied from upstream LLVM. This code duplication is done for a number of reasons: * Controlling parallelism means we can use the existing jobserver support to avoid overloading machines. * We will likely want a slightly different form of incremental caching which integrates with our own incremental strategy, but this is yet to be determined. * This buys us some flexibility about when/where we run ThinLTO, as well as having it tailored to fit our needs for the time being. * Finally this allows us to reuse some artifacts such as our `TargetMachine` creation, where all our options we used today aren't necessarily supported by upstream LLVM yet. My hope is that we can get some experience with this copy/paste in tree and then eventually upstream some work to LLVM itself to avoid the duplication while still ensuring our needs are met. Otherwise I fear that maintaining these bindings may be quite costly over the years with LLVM updates! --- src/librustc/session/config.rs | 20 +- src/librustc_llvm/build.rs | 1 + src/librustc_llvm/ffi.rs | 56 +++ src/librustc_trans/back/link.rs | 43 +- src/librustc_trans/back/lto.rs | 463 +++++++++++++++--- src/librustc_trans/back/write.rs | 88 +++- src/librustc_trans/base.rs | 15 +- src/librustc_trans/partitioning.rs | 3 +- src/librustc_trans/time_graph.rs | 152 ++++-- src/rustllvm/PassWrapper.cpp | 461 +++++++++++++++++ .../drop_in_place_intrinsic.rs | 6 +- .../item-collection/generic-drop-glue.rs | 12 +- .../instantiation-through-vtable.rs | 4 +- .../item-collection/non-generic-drop-glue.rs | 4 +- .../item-collection/transitive-drop-glue.rs | 18 +- .../item-collection/tuple-drop-glue.rs | 8 +- .../codegen-units/item-collection/unsizing.rs | 8 +- .../extra-filename-with-temp-outputs/Makefile | 2 +- src/test/run-make/sepcomp-cci-copies/Makefile | 2 +- src/test/run-make/sepcomp-inlining/Makefile | 8 +- src/test/run-make/sepcomp-separate/Makefile | 2 +- .../auxiliary/thin-lto-inlines-aux.rs | 17 + src/test/run-pass/thin-lto-inlines.rs | 39 ++ src/test/run-pass/thin-lto-inlines2.rs | 38 ++ 24 files changed, 1288 insertions(+), 182 deletions(-) create mode 100644 src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs create mode 100644 src/test/run-pass/thin-lto-inlines.rs create mode 100644 src/test/run-pass/thin-lto-inlines2.rs diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 7c1d457a6ee..6ef64ef3d96 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -409,9 +409,7 @@ impl_stable_hash_for!(struct self::OutputFilenames { outputs }); -/// Codegen unit names generated by the numbered naming scheme will contain this -/// marker right before the index of the codegen unit. -pub const NUMBERED_CODEGEN_UNIT_MARKER: &'static str = ".cgu-"; +pub const RUST_CGU_EXT: &str = "rust-cgu"; impl OutputFilenames { pub fn path(&self, flavor: OutputType) -> PathBuf { @@ -442,22 +440,14 @@ impl OutputFilenames { let mut extension = String::new(); if let Some(codegen_unit_name) = codegen_unit_name { - if codegen_unit_name.contains(NUMBERED_CODEGEN_UNIT_MARKER) { - // If we use the numbered naming scheme for modules, we don't want - // the files to look like ... - // but simply .. - let marker_offset = codegen_unit_name.rfind(NUMBERED_CODEGEN_UNIT_MARKER) - .unwrap(); - let index_offset = marker_offset + NUMBERED_CODEGEN_UNIT_MARKER.len(); - extension.push_str(&codegen_unit_name[index_offset .. ]); - } else { - extension.push_str(codegen_unit_name); - }; + extension.push_str(codegen_unit_name); } if !ext.is_empty() { if !extension.is_empty() { extension.push_str("."); + extension.push_str(RUST_CGU_EXT); + extension.push_str("."); } extension.push_str(ext); @@ -1105,6 +1095,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "run the non-lexical lifetimes MIR pass"), trans_time_graph: bool = (false, parse_bool, [UNTRACKED], "generate a graphical HTML report of time spent in trans and LLVM"), + thinlto: bool = (false, parse_bool, [TRACKED], + "enable ThinLTO when possible"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index dde7a38efc7..676bbc87b6c 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -115,6 +115,7 @@ fn main() { "linker", "asmparser", "mcjit", + "lto", "interpreter", "instrumentation"]; diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index fd4a136f50b..3399bf2acd8 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -345,6 +345,20 @@ pub enum PassKind { Module, } +/// LLVMRustThinLTOData +pub enum ThinLTOData {} + +/// LLVMRustThinLTOBuffer +pub enum ThinLTOBuffer {} + +/// LLVMRustThinLTOModule +#[repr(C)] +pub struct ThinLTOModule { + pub identifier: *const c_char, + pub data: *const u8, + pub len: usize, +} + // Opaque pointer types #[allow(missing_copy_implementations)] pub enum Module_opaque {} @@ -1271,6 +1285,9 @@ extern "C" { PM: PassManagerRef, Internalize: Bool, RunInliner: Bool); + pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( + PMB: PassManagerBuilderRef, + PM: PassManagerRef) -> bool; // Stuff that's in rustllvm/ because it's not upstream yet. @@ -1685,4 +1702,43 @@ extern "C" { pub fn LLVMRustModuleBufferLen(p: *const ModuleBuffer) -> usize; pub fn LLVMRustModuleBufferFree(p: *mut ModuleBuffer); pub fn LLVMRustModuleCost(M: ModuleRef) -> u64; + + pub fn LLVMRustThinLTOAvailable() -> bool; + pub fn LLVMRustWriteThinBitcodeToFile(PMR: PassManagerRef, + M: ModuleRef, + BC: *const c_char) -> bool; + pub fn LLVMRustThinLTOBufferCreate(M: ModuleRef) -> *mut ThinLTOBuffer; + pub fn LLVMRustThinLTOBufferFree(M: *mut ThinLTOBuffer); + pub fn LLVMRustThinLTOBufferPtr(M: *const ThinLTOBuffer) -> *const c_char; + pub fn LLVMRustThinLTOBufferLen(M: *const ThinLTOBuffer) -> size_t; + pub fn LLVMRustCreateThinLTOData( + Modules: *const ThinLTOModule, + NumModules: c_uint, + PreservedSymbols: *const *const c_char, + PreservedSymbolsLen: c_uint, + ) -> *mut ThinLTOData; + pub fn LLVMRustPrepareThinLTORename( + Data: *const ThinLTOData, + Module: ModuleRef, + ) -> bool; + pub fn LLVMRustPrepareThinLTOResolveWeak( + Data: *const ThinLTOData, + Module: ModuleRef, + ) -> bool; + pub fn LLVMRustPrepareThinLTOInternalize( + Data: *const ThinLTOData, + Module: ModuleRef, + ) -> bool; + pub fn LLVMRustPrepareThinLTOImport( + Data: *const ThinLTOData, + Module: ModuleRef, + ) -> bool; + pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData); + pub fn LLVMRustParseBitcodeForThinLTO( + Context: ContextRef, + Data: *const u8, + len: usize, + Identifier: *const c_char, + ) -> ModuleRef; + pub fn LLVMGetModuleIdentifier(M: ModuleRef, size: *mut usize) -> *const c_char; } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 3badc1b9a69..3f25c182fa2 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -16,6 +16,7 @@ use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, PrintRequest}; +use rustc::session::config::RUST_CGU_EXT; use rustc::session::filesearch; use rustc::session::search_paths::PathKind; use rustc::session::Session; @@ -45,13 +46,9 @@ use syntax::attr; /// The LLVM module name containing crate-metadata. This includes a `.` on /// purpose, so it cannot clash with the name of a user-defined module. pub const METADATA_MODULE_NAME: &'static str = "crate.metadata"; -/// The name of the crate-metadata object file the compiler generates. Must -/// match up with `METADATA_MODULE_NAME`. -pub const METADATA_OBJ_NAME: &'static str = "crate.metadata.o"; // same as for metadata above, but for allocator shim pub const ALLOCATOR_MODULE_NAME: &'static str = "crate.allocator"; -pub const ALLOCATOR_OBJ_NAME: &'static str = "crate.allocator.o"; pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_output_for_target, invalid_output_for_target, build_link_meta, out_filename, @@ -129,6 +126,14 @@ fn command_path(sess: &Session) -> OsString { env::join_paths(new_path).unwrap() } +fn metadata_obj(outputs: &OutputFilenames) -> PathBuf { + outputs.temp_path(OutputType::Object, Some(METADATA_MODULE_NAME)) +} + +fn allocator_obj(outputs: &OutputFilenames) -> PathBuf { + outputs.temp_path(OutputType::Object, Some(ALLOCATOR_MODULE_NAME)) +} + pub fn remove(sess: &Session, path: &Path) { match fs::remove_file(path) { Ok(..) => {} @@ -174,9 +179,9 @@ pub fn link_binary(sess: &Session, remove(sess, &obj.object); } } - remove(sess, &outputs.with_extension(METADATA_OBJ_NAME)); + remove(sess, &metadata_obj(outputs)); if trans.allocator_module.is_some() { - remove(sess, &outputs.with_extension(ALLOCATOR_OBJ_NAME)); + remove(sess, &allocator_obj(outputs)); } } @@ -478,7 +483,7 @@ fn link_rlib<'a>(sess: &'a Session, RlibFlavor::StaticlibBase => { if trans.allocator_module.is_some() { - ab.add_file(&outputs.with_extension(ALLOCATOR_OBJ_NAME)); + ab.add_file(&allocator_obj(outputs)); } } } @@ -908,11 +913,11 @@ fn link_args(cmd: &mut Linker, // object file, so we link that in here. if crate_type == config::CrateTypeDylib || crate_type == config::CrateTypeProcMacro { - cmd.add_object(&outputs.with_extension(METADATA_OBJ_NAME)); + cmd.add_object(&metadata_obj(outputs)); } if trans.allocator_module.is_some() { - cmd.add_object(&outputs.with_extension(ALLOCATOR_OBJ_NAME)); + cmd.add_object(&allocator_obj(outputs)); } // Try to strip as much out of the generated object by removing unused @@ -1265,11 +1270,23 @@ fn add_upstream_rust_crates(cmd: &mut Linker, let canonical = f.replace("-", "_"); let canonical_name = name.replace("-", "_"); + // Look for `.rust-cgu.o` at the end of the filename to conclude + // that this is a Rust-related object file. + fn looks_like_rust(s: &str) -> bool { + let path = Path::new(s); + let ext = path.extension().and_then(|s| s.to_str()); + if ext != Some(OutputType::Object.extension()) { + return false + } + let ext2 = path.file_stem() + .and_then(|s| Path::new(s).extension()) + .and_then(|s| s.to_str()); + ext2 == Some(RUST_CGU_EXT) + } + let is_rust_object = - canonical.starts_with(&canonical_name) && { - let num = &f[name.len()..f.len() - 2]; - num.len() > 0 && num[1..].parse::().is_ok() - }; + canonical.starts_with(&canonical_name) && + looks_like_rust(&f); // If we've been requested to skip all native object files // (those not generated by the rust compiler) then we can skip diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 8651b95b12a..8f75b891a30 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -9,23 +9,25 @@ // except according to those terms. use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION}; -use back::write; use back::symbol_export; -use rustc::session::config; +use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; +use back::write; use errors::{FatalError, Handler}; -use llvm; use llvm::archive_ro::ArchiveRO; use llvm::{ModuleRef, TargetMachineRef, True, False}; -use rustc::middle::exported_symbols::SymbolExportLevel; -use rustc::util::common::time; +use llvm; use rustc::hir::def_id::LOCAL_CRATE; -use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; -use {ModuleTranslation, ModuleKind}; +use rustc::middle::exported_symbols::SymbolExportLevel; +use rustc::session::config; +use rustc::util::common::time; +use time_graph::Timeline; +use {ModuleTranslation, ModuleLlvm, ModuleKind, ModuleSource}; use libc; use std::ffi::CString; use std::slice; +use std::sync::Arc; pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { match crate_type { @@ -45,14 +47,14 @@ pub enum LtoModuleTranslation { _serialized_bitcode: Vec, }, - // Note the lack of other entries in this enum! Ideally one day this gap is - // intended to be filled with a "Thin" LTO variant. + Thin(ThinModule), } impl LtoModuleTranslation { pub fn name(&self) -> &str { match *self { LtoModuleTranslation::Fat { .. } => "everything", + LtoModuleTranslation::Thin(ref m) => m.name(), } } @@ -62,7 +64,9 @@ impl LtoModuleTranslation { /// points to LLVM data structures owned by this `LtoModuleTranslation`. /// It's intended that the module returned is immediately code generated and /// dropped, and then this LTO module is dropped. - pub unsafe fn optimize(&mut self, cgcx: &CodegenContext) + pub unsafe fn optimize(&mut self, + cgcx: &CodegenContext, + timeline: &mut Timeline) -> Result { match *self { @@ -71,9 +75,11 @@ impl LtoModuleTranslation { let config = cgcx.config(trans.kind); let llmod = trans.llvm().unwrap().llmod; let tm = trans.llvm().unwrap().tm; - run_pass_manager(cgcx, tm, llmod, config); + run_pass_manager(cgcx, tm, llmod, config, false); + timeline.record("fat-done"); Ok(trans) } + LtoModuleTranslation::Thin(ref mut thin) => thin.optimize(cgcx, timeline), } } @@ -83,33 +89,31 @@ impl LtoModuleTranslation { match *self { // Only one module with fat LTO, so the cost doesn't matter. LtoModuleTranslation::Fat { .. } => 0, + LtoModuleTranslation::Thin(ref m) => m.cost(), } } } -pub fn run(cgcx: &CodegenContext, modules: Vec) +pub enum LTOMode { + WholeCrateGraph, + JustThisCrate, +} + +pub fn run(cgcx: &CodegenContext, + modules: Vec, + mode: LTOMode, + timeline: &mut Timeline) -> Result, FatalError> { let diag_handler = cgcx.create_diag_handler(); - if cgcx.opts.cg.prefer_dynamic { - diag_handler.struct_err("cannot prefer dynamic linking when performing LTO") - .note("only 'staticlib', 'bin', and 'cdylib' outputs are \ - supported with LTO") - .emit(); - return Err(FatalError) - } - - // Make sure we actually can run LTO - for crate_type in cgcx.crate_types.iter() { - if !crate_type_allows_lto(*crate_type) { - let e = diag_handler.fatal("lto can only be run for executables, cdylibs and \ - static library outputs"); - return Err(e) + let export_threshold = match mode { + LTOMode::WholeCrateGraph => { + symbol_export::crates_export_threshold(&cgcx.crate_types) } - } - - let export_threshold = - symbol_export::crates_export_threshold(&cgcx.crate_types); + LTOMode::JustThisCrate => { + SymbolExportLevel::Rust + } + }; let symbol_filter = &|&(ref name, _, level): &(String, _, SymbolExportLevel)| { if level.is_below_threshold(export_threshold) { @@ -121,55 +125,81 @@ pub fn run(cgcx: &CodegenContext, modules: Vec) } }; - let mut symbol_white_list: Vec = cgcx.exported_symbols[&LOCAL_CRATE] + let mut symbol_white_list = cgcx.exported_symbols[&LOCAL_CRATE] .iter() .filter_map(symbol_filter) - .collect(); - info!("{} symbols in whitelist", symbol_white_list.len()); + .collect::>(); + timeline.record("whitelist"); - // For each of our upstream dependencies, find the corresponding rlib and - // load the bitcode from the archive. Then merge it into the current LLVM - // module that we've got. + // If we're performing LTO for the entire crate graph, then for each of our + // upstream dependencies, find the corresponding rlib and load the bitcode + // from the archive. + // + // We save off all the bytecode and LLVM module ids for later processing + // with either fat or thin LTO let mut upstream_modules = Vec::new(); - for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() { - symbol_white_list.extend( - cgcx.exported_symbols[&cnum] - .iter() - .filter_map(symbol_filter)); - info!("{} symbols in whitelist after {}", symbol_white_list.len(), cnum); + if let LTOMode::WholeCrateGraph = mode { + if cgcx.opts.cg.prefer_dynamic { + diag_handler.struct_err("cannot prefer dynamic linking when performing LTO") + .note("only 'staticlib', 'bin', and 'cdylib' outputs are \ + supported with LTO") + .emit(); + return Err(FatalError) + } - let archive = ArchiveRO::open(&path).expect("wanted an rlib"); - let bytecodes = archive.iter().filter_map(|child| { - child.ok().and_then(|c| c.name().map(|name| (name, c))) - }).filter(|&(name, _)| name.ends_with(RLIB_BYTECODE_EXTENSION)); - for (name, data) in bytecodes { - info!("adding bytecode {}", name); - let bc_encoded = data.data(); + // Make sure we actually can run LTO + for crate_type in cgcx.crate_types.iter() { + if !crate_type_allows_lto(*crate_type) { + let e = diag_handler.fatal("lto can only be run for executables, cdylibs and \ + static library outputs"); + return Err(e) + } + } - let (bc, id) = time(cgcx.time_passes, &format!("decode {}", name), || { - match DecodedBytecode::new(bc_encoded) { - Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), - Err(e) => Err(diag_handler.fatal(&e)), - } - })?; - let bc = SerializedModule::FromRlib(bc); - upstream_modules.push((bc, CString::new(id).unwrap())); + for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() { + symbol_white_list.extend( + cgcx.exported_symbols[&cnum] + .iter() + .filter_map(symbol_filter)); + + let archive = ArchiveRO::open(&path).expect("wanted an rlib"); + let bytecodes = archive.iter().filter_map(|child| { + child.ok().and_then(|c| c.name().map(|name| (name, c))) + }).filter(|&(name, _)| name.ends_with(RLIB_BYTECODE_EXTENSION)); + for (name, data) in bytecodes { + info!("adding bytecode {}", name); + let bc_encoded = data.data(); + + let (bc, id) = time(cgcx.time_passes, &format!("decode {}", name), || { + match DecodedBytecode::new(bc_encoded) { + Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), + Err(e) => Err(diag_handler.fatal(&e)), + } + })?; + let bc = SerializedModule::FromRlib(bc); + upstream_modules.push((bc, CString::new(id).unwrap())); + } + timeline.record(&format!("load: {}", path.display())); } } - // Internalize everything but the exported symbols of the current module - let arr: Vec<*const libc::c_char> = symbol_white_list.iter() - .map(|c| c.as_ptr()) - .collect(); - - fat_lto(cgcx, &diag_handler, modules, upstream_modules, &arr) + let arr = symbol_white_list.iter().map(|c| c.as_ptr()).collect::>(); + match mode { + LTOMode::WholeCrateGraph if !cgcx.thinlto => { + fat_lto(cgcx, &diag_handler, modules, upstream_modules, &arr, timeline) + } + _ => { + thin_lto(&diag_handler, modules, upstream_modules, &arr, timeline) + } + } } fn fat_lto(cgcx: &CodegenContext, diag_handler: &Handler, mut modules: Vec, mut serialized_modules: Vec<(SerializedModule, CString)>, - symbol_white_list: &[*const libc::c_char]) + symbol_white_list: &[*const libc::c_char], + timeline: &mut Timeline) -> Result, FatalError> { info!("going for a fat lto"); @@ -228,6 +258,7 @@ fn fat_lto(cgcx: &CodegenContext, Err(write::llvm_err(&diag_handler, msg)) } })?; + timeline.record(&format!("link {:?}", name)); serialized_bitcode.push(bc_decoded); } cgcx.save_temp_bitcode(&module, "lto.input"); @@ -248,6 +279,7 @@ fn fat_lto(cgcx: &CodegenContext, } cgcx.save_temp_bitcode(&module, "lto.after-nounwind"); } + timeline.record("passes"); Ok(vec![LtoModuleTranslation::Fat { module: Some(module), @@ -255,11 +287,143 @@ fn fat_lto(cgcx: &CodegenContext, }]) } +/// Prepare "thin" LTO to get run on these modules. +/// +/// The general structure of ThinLTO is quite different from the structure of +/// "fat" LTO above. With "fat" LTO all LLVM modules in question are merged into +/// one giant LLVM module, and then we run more optimization passes over this +/// big module after internalizing most symbols. Thin LTO, on the other hand, +/// avoid this large bottleneck through more targeted optimization. +/// +/// At a high level Thin LTO looks like: +/// +/// 1. Prepare a "summary" of each LLVM module in question which describes +/// the values inside, cost of the values, etc. +/// 2. Merge the summaries of all modules in question into one "index" +/// 3. Perform some global analysis on this index +/// 4. For each module, use the index and analysis calculated previously to +/// perform local transformations on the module, for example inlining +/// small functions from other modules. +/// 5. Run thin-specific optimization passes over each module, and then code +/// generate everything at the end. +/// +/// The summary for each module is intended to be quite cheap, and the global +/// index is relatively quite cheap to create as well. As a result, the goal of +/// ThinLTO is to reduce the bottleneck on LTO and enable LTO to be used in more +/// situations. For example one cheap optimization is that we can parallelize +/// all codegen modules, easily making use of all the cores on a machine. +/// +/// With all that in mind, the function here is designed at specifically just +/// calculating the *index* for ThinLTO. This index will then be shared amongst +/// all of the `LtoModuleTranslation` units returned below and destroyed once +/// they all go out of scope. +fn thin_lto(diag_handler: &Handler, + modules: Vec, + serialized_modules: Vec<(SerializedModule, CString)>, + symbol_white_list: &[*const libc::c_char], + timeline: &mut Timeline) + -> Result, FatalError> +{ + unsafe { + info!("going for that thin, thin LTO"); + + let mut thin_buffers = Vec::new(); + let mut module_names = Vec::new(); + let mut thin_modules = Vec::new(); + + // FIXME: right now, like with fat LTO, we serialize all in-memory + // modules before working with them and ThinLTO. We really + // shouldn't do this, however, and instead figure out how to + // extract a summary from an in-memory module and then merge that + // into the global index. It turns out that this loop is by far + // the most expensive portion of this small bit of global + // analysis! + for (i, module) in modules.iter().enumerate() { + info!("local module: {} - {}", i, module.llmod_id); + let llvm = module.llvm().expect("can't lto pretranslated module"); + let name = CString::new(module.llmod_id.clone()).unwrap(); + let buffer = llvm::LLVMRustThinLTOBufferCreate(llvm.llmod); + let buffer = ThinBuffer(buffer); + thin_modules.push(llvm::ThinLTOModule { + identifier: name.as_ptr(), + data: buffer.data().as_ptr(), + len: buffer.data().len(), + }); + thin_buffers.push(buffer); + module_names.push(name); + timeline.record(&module.llmod_id); + } + + // FIXME: All upstream crates are deserialized internally in the + // function below to extract their summary and modules. Note that + // unlike the loop above we *must* decode and/or read something + // here as these are all just serialized files on disk. An + // improvement, however, to make here would be to store the + // module summary separately from the actual module itself. Right + // now this is store in one large bitcode file, and the entire + // file is deflate-compressed. We could try to bypass some of the + // decompression by storing the index uncompressed and only + // lazily decompressing the bytecode if necessary. + // + // Note that truly taking advantage of this optimization will + // likely be further down the road. We'd have to implement + // incremental ThinLTO first where we could actually avoid + // looking at upstream modules entirely sometimes (the contents, + // we must always unconditionally look at the index). + let mut serialized = Vec::new(); + for (module, name) in serialized_modules { + info!("foreign module {:?}", name); + thin_modules.push(llvm::ThinLTOModule { + identifier: name.as_ptr(), + data: module.data().as_ptr(), + len: module.data().len(), + }); + serialized.push(module); + module_names.push(name); + } + + // Delegate to the C++ bindings to create some data here. Once this is a + // tried-and-true interface we may wish to try to upstream some of this + // to LLVM itself, right now we reimplement a lot of what they do + // upstream... + let data = llvm::LLVMRustCreateThinLTOData( + thin_modules.as_ptr(), + thin_modules.len() as u32, + symbol_white_list.as_ptr(), + symbol_white_list.len() as u32, + ); + if data.is_null() { + let msg = format!("failed to prepare thin LTO context"); + return Err(write::llvm_err(&diag_handler, msg)) + } + let data = ThinData(data); + info!("thin LTO data created"); + timeline.record("data"); + + // Throw our data in an `Arc` as we'll be sharing it across threads. We + // also put all memory referenced by the C++ data (buffers, ids, etc) + // into the arc as well. After this we'll create a thin module + // translation per module in this data. + let shared = Arc::new(ThinShared { + data, + thin_buffers, + serialized_modules: serialized, + module_names, + }); + Ok((0..shared.module_names.len()).map(|i| { + LtoModuleTranslation::Thin(ThinModule { + shared: shared.clone(), + idx: i, + }) + }).collect()) + } +} + fn run_pass_manager(cgcx: &CodegenContext, tm: TargetMachineRef, llmod: ModuleRef, - config: &ModuleConfig) { - + config: &ModuleConfig, + thin: bool) { // Now we have one massive module inside of llmod. Time to run the // LTO-specific optimization passes that LLVM provides. // @@ -274,9 +438,15 @@ fn run_pass_manager(cgcx: &CodegenContext, llvm::LLVMRustAddPass(pm, pass); with_llvm_pmb(llmod, config, &mut |b| { - llvm::LLVMPassManagerBuilderPopulateLTOPassManager(b, pm, - /* Internalize = */ False, - /* RunInliner = */ True); + if thin { + if !llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm) { + panic!("this version of LLVM does not support ThinLTO"); + } + } else { + llvm::LLVMPassManagerBuilderPopulateLTOPassManager(b, pm, + /* Internalize = */ False, + /* RunInliner = */ True); + } }); let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); @@ -331,3 +501,158 @@ impl Drop for ModuleBuffer { unsafe { llvm::LLVMRustModuleBufferFree(self.0); } } } + +pub struct ThinModule { + shared: Arc, + idx: usize, +} + +struct ThinShared { + data: ThinData, + thin_buffers: Vec, + serialized_modules: Vec, + module_names: Vec, +} + +struct ThinData(*mut llvm::ThinLTOData); + +unsafe impl Send for ThinData {} +unsafe impl Sync for ThinData {} + +impl Drop for ThinData { + fn drop(&mut self) { + unsafe { + llvm::LLVMRustFreeThinLTOData(self.0); + } + } +} + +struct ThinBuffer(*mut llvm::ThinLTOBuffer); + +unsafe impl Send for ThinBuffer {} +unsafe impl Sync for ThinBuffer {} + +impl ThinBuffer { + fn data(&self) -> &[u8] { + unsafe { + let ptr = llvm::LLVMRustThinLTOBufferPtr(self.0) as *const _; + let len = llvm::LLVMRustThinLTOBufferLen(self.0); + slice::from_raw_parts(ptr, len) + } + } +} + +impl Drop for ThinBuffer { + fn drop(&mut self) { + unsafe { + llvm::LLVMRustThinLTOBufferFree(self.0); + } + } +} + +impl ThinModule { + fn name(&self) -> &str { + self.shared.module_names[self.idx].to_str().unwrap() + } + + fn cost(&self) -> u64 { + // Yes, that's correct, we're using the size of the bytecode as an + // indicator for how costly this codegen unit is. + self.data().len() as u64 + } + + fn data(&self) -> &[u8] { + let a = self.shared.thin_buffers.get(self.idx).map(|b| b.data()); + a.unwrap_or_else(|| { + let len = self.shared.thin_buffers.len(); + self.shared.serialized_modules[self.idx - len].data() + }) + } + + unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline) + -> Result + { + let diag_handler = cgcx.create_diag_handler(); + let tm = (cgcx.tm_factory)().map_err(|e| { + write::llvm_err(&diag_handler, e) + })?; + + // Right now the implementation we've got only works over serialized + // modules, so we create a fresh new LLVM context and parse the module + // into that context. One day, however, we may do this for upstream + // crates but for locally translated modules we may be able to reuse + // that LLVM Context and Module. + let llcx = llvm::LLVMContextCreate(); + let llmod = llvm::LLVMRustParseBitcodeForThinLTO( + llcx, + self.data().as_ptr(), + self.data().len(), + self.shared.module_names[self.idx].as_ptr(), + ); + assert!(!llmod.is_null()); + let mtrans = ModuleTranslation { + source: ModuleSource::Translated(ModuleLlvm { + llmod, + llcx, + tm, + }), + llmod_id: self.name().to_string(), + name: self.name().to_string(), + kind: ModuleKind::Regular, + }; + cgcx.save_temp_bitcode(&mtrans, "thin-lto-input"); + + // Like with "fat" LTO, get some better optimizations if landing pads + // are disabled by removing all landing pads. + if cgcx.no_landing_pads { + llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-nounwind"); + timeline.record("nounwind"); + } + + // Up next comes the per-module local analyses that we do for Thin LTO. + // Each of these functions is basically copied from the LLVM + // implementation and then tailored to suit this implementation. Ideally + // each of these would be supported by upstream LLVM but that's perhaps + // a patch for another day! + // + // You can find some more comments about these functions in the LLVM + // bindings we've got (currently `PassWrapper.cpp`) + if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) { + let msg = format!("failed to prepare thin LTO module"); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-rename"); + timeline.record("rename"); + if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) { + let msg = format!("failed to prepare thin LTO module"); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-resolve"); + timeline.record("resolve"); + if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) { + let msg = format!("failed to prepare thin LTO module"); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-internalize"); + timeline.record("internalize"); + if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) { + let msg = format!("failed to prepare thin LTO module"); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-import"); + timeline.record("import"); + + // Alright now that we've done everything related to the ThinLTO + // analysis it's time to run some optimizations! Here we use the same + // `run_pass_manager` as the "fat" LTO above except that we tell it to + // populate a thin-specific pass manager, which presumably LLVM treats a + // little differently. + info!("running thin lto passes over {}", mtrans.name); + let config = cgcx.config(mtrans.kind); + run_pass_manager(cgcx, tm, llmod, config, true); + cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-pm"); + timeline.record("thin-done"); + Ok(mtrans) + } +} diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 1988b9f76e4..b3b2384a027 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -19,7 +19,7 @@ use rustc::session::config::{self, OutputFilenames, OutputType, OutputTypes, Pas AllPasses, Sanitizer}; use rustc::session::Session; use rustc::util::nodemap::FxHashMap; -use time_graph::{self, TimeGraph}; +use time_graph::{self, TimeGraph, Timeline}; use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; use llvm::{SMDiagnosticRef, ContextRef}; @@ -303,6 +303,7 @@ pub struct CodegenContext { // Resouces needed when running LTO pub time_passes: bool, pub lto: bool, + pub thinlto: bool, pub no_landing_pads: bool, pub save_temps: bool, pub exported_symbols: Arc, @@ -315,6 +316,8 @@ pub struct CodegenContext { allocator_module_config: Arc, pub tm_factory: Arc Result + Send + Sync>, + // Number of cgus excluding the allocator/metadata modules + pub total_cgus: usize, // Handler to use for diagnostics produced during codegen. pub diag_emitter: SharedEmitter, // LLVM passes added by plugins. @@ -450,7 +453,8 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo unsafe fn optimize(cgcx: &CodegenContext, diag_handler: &Handler, mtrans: &ModuleTranslation, - config: &ModuleConfig) + config: &ModuleConfig, + timeline: &mut Timeline) -> Result<(), FatalError> { let (llmod, llcx, tm) = match mtrans.source { @@ -529,6 +533,7 @@ unsafe fn optimize(cgcx: &CodegenContext, // Finally, run the actual optimization passes time(config.time_passes, &format!("llvm function passes [{}]", module_name.unwrap()), || llvm::LLVMRustRunFunctionPassManager(fpm, llmod)); + timeline.record("fpm"); time(config.time_passes, &format!("llvm module passes [{}]", module_name.unwrap()), || llvm::LLVMRunPassManager(mpm, llmod)); @@ -543,7 +548,18 @@ fn generate_lto_work(cgcx: &CodegenContext, modules: Vec) -> Vec<(WorkItem, u64)> { - let lto_modules = lto::run(cgcx, modules).unwrap_or_else(|e| panic!(e)); + let mut timeline = cgcx.time_graph.as_ref().map(|tg| { + tg.start(TRANS_WORKER_TIMELINE, + TRANS_WORK_PACKAGE_KIND, + "generate lto") + }).unwrap_or(Timeline::noop()); + let mode = if cgcx.lto { + lto::LTOMode::WholeCrateGraph + } else { + lto::LTOMode::JustThisCrate + }; + let lto_modules = lto::run(cgcx, modules, mode, &mut timeline) + .unwrap_or_else(|e| panic!(e)); lto_modules.into_iter().map(|module| { let cost = module.cost(); @@ -554,9 +570,11 @@ fn generate_lto_work(cgcx: &CodegenContext, unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &Handler, mtrans: ModuleTranslation, - config: &ModuleConfig) + config: &ModuleConfig, + timeline: &mut Timeline) -> Result { + timeline.record("codegen"); let (llmod, llcx, tm) = match mtrans.source { ModuleSource::Translated(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm), ModuleSource::Preexisting(_) => { @@ -601,7 +619,18 @@ unsafe fn codegen(cgcx: &CodegenContext, if write_bc { let bc_out_c = path2cstr(&bc_out); - llvm::LLVMWriteBitcodeToFile(llmod, bc_out_c.as_ptr()); + if llvm::LLVMRustThinLTOAvailable() { + with_codegen(tm, llmod, config.no_builtins, |cpm| { + llvm::LLVMRustWriteThinBitcodeToFile( + cpm, + llmod, + bc_out_c.as_ptr(), + ) + }); + } else { + llvm::LLVMWriteBitcodeToFile(llmod, bc_out_c.as_ptr()); + } + timeline.record("bc"); } time(config.time_passes, &format!("codegen passes [{}]", module_name.unwrap()), @@ -644,7 +673,8 @@ unsafe fn codegen(cgcx: &CodegenContext, with_codegen(tm, llmod, config.no_builtins, |cpm| { llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); llvm::LLVMDisposePassManager(cpm); - }) + }); + timeline.record("ir"); } if config.emit_asm { @@ -665,6 +695,7 @@ unsafe fn codegen(cgcx: &CodegenContext, if config.emit_obj { llvm::LLVMDisposeModule(llmod); } + timeline.record("asm"); } if write_obj { @@ -672,6 +703,7 @@ unsafe fn codegen(cgcx: &CodegenContext, write_output_file(diag_handler, tm, cpm, llmod, &obj_out, llvm::FileType::ObjectFile) })?; + timeline.record("obj"); } Ok(()) @@ -712,7 +744,8 @@ pub fn start_async_translation(tcx: TyCtxt, time_graph: Option, link: LinkMeta, metadata: EncodedMetadata, - coordinator_receive: Receiver>) + coordinator_receive: Receiver>, + total_cgus: usize) -> OngoingCrateTranslation { let sess = tcx.sess; let crate_output = tcx.output_filenames(LOCAL_CRATE); @@ -836,6 +869,7 @@ pub fn start_async_translation(tcx: TyCtxt, shared_emitter, trans_worker_send, coordinator_receive, + total_cgus, client, time_graph.clone(), Arc::new(modules_config), @@ -1080,7 +1114,9 @@ enum WorkItemResult { NeedsLTO(ModuleTranslation), } -fn execute_work_item(cgcx: &CodegenContext, work_item: WorkItem) +fn execute_work_item(cgcx: &CodegenContext, + work_item: WorkItem, + timeline: &mut Timeline) -> Result { let diag_handler = cgcx.create_diag_handler(); @@ -1089,8 +1125,8 @@ fn execute_work_item(cgcx: &CodegenContext, work_item: WorkItem) WorkItem::Optimize(mtrans) => mtrans, WorkItem::LTO(mut lto) => { unsafe { - let module = lto.optimize(cgcx)?; - let module = codegen(cgcx, &diag_handler, module, config)?; + let module = lto.optimize(cgcx, timeline)?; + let module = codegen(cgcx, &diag_handler, module, config, timeline)?; return Ok(WorkItemResult::Compiled(module)) } } @@ -1140,9 +1176,27 @@ fn execute_work_item(cgcx: &CodegenContext, work_item: WorkItem) debug!("llvm-optimizing {:?}", module_name); unsafe { - optimize(cgcx, &diag_handler, &mtrans, config)?; - if !cgcx.lto || mtrans.kind == ModuleKind::Metadata { - let module = codegen(cgcx, &diag_handler, mtrans, config)?; + optimize(cgcx, &diag_handler, &mtrans, config, timeline)?; + + let lto = cgcx.lto; + + let auto_thin_lto = + cgcx.thinlto && + cgcx.total_cgus > 1 && + mtrans.kind != ModuleKind::Allocator; + + // If we're a metadata module we never participate in LTO. + // + // If LTO was explicitly requested on the command line, we always + // LTO everything else. + // + // If LTO *wasn't* explicitly requested and we're not a metdata + // module, then we may automatically do ThinLTO if we've got + // multiple codegen units. Note, however, that the allocator module + // doesn't participate here automatically because of linker + // shenanigans later on. + if mtrans.kind == ModuleKind::Metadata || (!lto && !auto_thin_lto) { + let module = codegen(cgcx, &diag_handler, mtrans, config, timeline)?; Ok(WorkItemResult::Compiled(module)) } else { Ok(WorkItemResult::NeedsLTO(mtrans)) @@ -1187,6 +1241,7 @@ fn start_executing_work(tcx: TyCtxt, shared_emitter: SharedEmitter, trans_worker_send: Sender, coordinator_receive: Receiver>, + total_cgus: usize, jobserver: Client, time_graph: Option, modules_config: Arc, @@ -1229,6 +1284,7 @@ fn start_executing_work(tcx: TyCtxt, crate_types: sess.crate_types.borrow().clone(), each_linked_rlib_for_lto, lto: sess.lto(), + thinlto: sess.opts.debugging_opts.thinlto, no_landing_pads: sess.no_landing_pads(), save_temps: sess.opts.cg.save_temps, opts: Arc::new(sess.opts.clone()), @@ -1246,6 +1302,7 @@ fn start_executing_work(tcx: TyCtxt, metadata_module_config: metadata_config, allocator_module_config: allocator_config, tm_factory: target_machine_factory(tcx.sess), + total_cgus, }; // This is the "main loop" of parallel work happening for parallel codegen. @@ -1743,12 +1800,13 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem) { // as a diagnostic was already sent off to the main thread - just // surface that there was an error in this worker. bomb.result = { - let _timing_guard = cgcx.time_graph.as_ref().map(|tg| { + let timeline = cgcx.time_graph.as_ref().map(|tg| { tg.start(time_graph::TimelineId(cgcx.worker), LLVM_WORK_PACKAGE_KIND, &work.name()) }); - execute_work_item(&cgcx, work).ok() + let mut timeline = timeline.unwrap_or(Timeline::noop()); + execute_work_item(&cgcx, work, &mut timeline).ok() }; }); } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 8c39f579b3e..5764b0b34d1 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -886,6 +886,11 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, check_for_rustc_errors_attr(tcx); + if tcx.sess.opts.debugging_opts.thinlto { + if unsafe { !llvm::LLVMRustThinLTOAvailable() } { + tcx.sess.fatal("this compiler's LLVM does not support ThinLTO"); + } + } let crate_hash = tcx.dep_graph .fingerprint_of(&DepNode::new_no_params(DepKind::Krate)); @@ -925,7 +930,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time_graph.clone(), link_meta, metadata, - rx); + rx, + 1); ongoing_translation.submit_pre_translated_module_to_llvm(tcx, metadata_module); ongoing_translation.translation_finished(tcx); @@ -961,7 +967,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time_graph.clone(), link_meta, metadata, - rx); + rx, + codegen_units.len()); // Translate an allocator shim, if any let allocator_module = if let Some(kind) = tcx.sess.allocator_kind.get() { @@ -1372,7 +1379,9 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // crashes if the module identifier is same as other symbols // such as a function name in the module. // 1. http://llvm.org/bugs/show_bug.cgi?id=11479 - let llmod_id = format!("{}.rs", cgu.name()); + let llmod_id = format!("{}-{}.rs", + cgu.name(), + tcx.crate_disambiguator(LOCAL_CRATE)); // Instantiate translation items without filling out definitions yet... let scx = SharedCrateContext::new(tcx); diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 7b6daa7d133..82ec1aaa413 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -108,7 +108,6 @@ use rustc::dep_graph::{DepNode, WorkProductId}; use rustc::hir::def_id::DefId; use rustc::hir::map::DefPathData; use rustc::middle::trans::{Linkage, Visibility}; -use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER; use rustc::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -627,7 +626,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString { - Symbol::intern(&format!("{}{}{}", crate_name, NUMBERED_CODEGEN_UNIT_MARKER, index)).as_str() + Symbol::intern(&format!("{}{}", crate_name, index)).as_str() } fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_trans/time_graph.rs b/src/librustc_trans/time_graph.rs index ec57af888e5..a8502682a80 100644 --- a/src/librustc_trans/time_graph.rs +++ b/src/librustc_trans/time_graph.rs @@ -9,11 +9,12 @@ // except according to those terms. use std::collections::HashMap; +use std::fs::File; +use std::io::prelude::*; use std::marker::PhantomData; +use std::mem; use std::sync::{Arc, Mutex}; use std::time::Instant; -use std::io::prelude::*; -use std::fs::File; const OUTPUT_WIDTH_IN_PX: u64 = 1000; const TIME_LINE_HEIGHT_IN_PX: u64 = 20; @@ -25,6 +26,7 @@ struct Timing { end: Instant, work_package_kind: WorkPackageKind, name: String, + events: Vec<(String, Instant)>, } #[derive(Clone, Copy, Hash, Eq, PartialEq, Debug)] @@ -44,9 +46,14 @@ pub struct TimeGraph { #[derive(Clone, Copy)] pub struct WorkPackageKind(pub &'static [&'static str]); -pub struct RaiiToken { +pub struct Timeline { + token: Option, +} + +struct RaiiToken { graph: TimeGraph, timeline: TimelineId, + events: Vec<(String, Instant)>, // The token must not be Send: _marker: PhantomData<*const ()> } @@ -54,7 +61,7 @@ pub struct RaiiToken { impl Drop for RaiiToken { fn drop(&mut self) { - self.graph.end(self.timeline); + self.graph.end(self.timeline, mem::replace(&mut self.events, Vec::new())); } } @@ -68,7 +75,7 @@ impl TimeGraph { pub fn start(&self, timeline: TimelineId, work_package_kind: WorkPackageKind, - name: &str) -> RaiiToken { + name: &str) -> Timeline { { let mut table = self.data.lock().unwrap(); @@ -81,14 +88,17 @@ impl TimeGraph { data.open_work_package = Some((Instant::now(), work_package_kind, name.to_string())); } - RaiiToken { - graph: self.clone(), - timeline, - _marker: PhantomData, + Timeline { + token: Some(RaiiToken { + graph: self.clone(), + timeline, + events: Vec::new(), + _marker: PhantomData, + }), } } - fn end(&self, timeline: TimelineId) { + fn end(&self, timeline: TimelineId, events: Vec<(String, Instant)>) { let end = Instant::now(); let mut table = self.data.lock().unwrap(); @@ -100,6 +110,7 @@ impl TimeGraph { end, work_package_kind, name, + events, }); } else { bug!("end timing without start?") @@ -113,13 +124,13 @@ impl TimeGraph { assert!(data.open_work_package.is_none()); } - let mut timelines: Vec = + let mut threads: Vec = table.values().map(|data| data.clone()).collect(); - timelines.sort_by_key(|timeline| timeline.timings[0].start); + threads.sort_by_key(|timeline| timeline.timings[0].start); - let earliest_instant = timelines[0].timings[0].start; - let latest_instant = timelines.iter() + let earliest_instant = threads[0].timings[0].start; + let latest_instant = threads.iter() .map(|timeline| timeline.timings .last() .unwrap() @@ -130,16 +141,46 @@ impl TimeGraph { let mut file = File::create(format!("{}.html", output_filename)).unwrap(); - writeln!(file, "").unwrap(); - writeln!(file, "").unwrap(); - writeln!(file, "").unwrap(); + writeln!(file, " + + + + + +
+ ", + total_height = threads.len() * TIME_LINE_HEIGHT_STRIDE_IN_PX, + width = OUTPUT_WIDTH_IN_PX, + ).unwrap(); let mut color = 0; - - for (line_index, timeline) in timelines.iter().enumerate() { + for (line_index, thread) in threads.iter().enumerate() { let line_top = line_index * TIME_LINE_HEIGHT_STRIDE_IN_PX; - for span in &timeline.timings { + for span in &thread.timings { let start = distance(earliest_instant, span.start); let end = distance(earliest_instant, span.end); @@ -148,13 +189,13 @@ impl TimeGraph { let colors = span.work_package_kind.0; - writeln!(file, "
{}
", + writeln!(file, "{}", + color, line_top, start, end - start, @@ -167,8 +208,61 @@ impl TimeGraph { } } - writeln!(file, "").unwrap(); - writeln!(file, "").unwrap(); + writeln!(file, " +
+ ").unwrap(); + + let mut idx = 0; + for thread in threads.iter() { + for timing in &thread.timings { + let colors = timing.work_package_kind.0; + let height = TIME_LINE_HEIGHT_STRIDE_IN_PX * timing.events.len(); + writeln!(file, "
", + idx, + colors[idx % colors.len()], + height).unwrap(); + idx += 1; + let max = distance(timing.start, timing.end); + for (i, &(ref event, time)) in timing.events.iter().enumerate() { + let i = i as u64; + let time = distance(timing.start, time); + let at = normalize(time, max, OUTPUT_WIDTH_IN_PX); + writeln!(file, "{}", + at, + TIME_LINE_HEIGHT_IN_PX * i, + event).unwrap(); + } + writeln!(file, "
").unwrap(); + } + } + + writeln!(file, " + + + ").unwrap(); + } +} + +impl Timeline { + pub fn noop() -> Timeline { + Timeline { token: None } + } + + /// Record an event which happened at this moment on this timeline. + /// + /// Events are displayed in the eventual HTML output where you can click on + /// a particular timeline and it'll expand to all of the events that + /// happened on that timeline. This can then be used to drill into a + /// particular timeline and see what events are happening and taking the + /// most time. + pub fn record(&mut self, name: &str) { + if let Some(ref mut token) = self.token { + token.events.push((name.to_string(), Instant::now())); + } } } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 2f966e5a1c5..e37f048dd47 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -26,7 +26,11 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #if LLVM_VERSION_GE(4, 0) +#include "llvm/Object/ModuleSummaryIndexObjectFile.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" +#include "llvm/Transforms/IPO/FunctionImport.h" +#include "llvm/Transforms/Utils/FunctionImportUtils.h" +#include "llvm/LTO/LTO.h" #endif #include "llvm-c/Transforms/PassManagerBuilder.h" @@ -102,6 +106,19 @@ extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) { PMB->add(Pass); } +extern "C" +bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager( + LLVMPassManagerBuilderRef PMBR, + LLVMPassManagerRef PMR +) { +#if LLVM_VERSION_GE(4, 0) + unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR)); + return true; +#else + return false; +#endif +} + #ifdef LLVM_COMPONENT_X86 #define SUBTARGET_X86 SUBTARGET(X86) #else @@ -740,3 +757,447 @@ extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) { unwrap(M)->setPIELevel(PIELevel::Level::Large); #endif } + +extern "C" bool +LLVMRustThinLTOAvailable() { +#if LLVM_VERSION_GE(4, 0) + return true; +#else + return false; +#endif +} + +#if LLVM_VERSION_GE(4, 0) + +// Here you'll find an implementation of ThinLTO as used by the Rust compiler +// right now. This ThinLTO support is only enabled on "recent ish" versions of +// LLVM, and otherwise it's just blanket rejected from other compilers. +// +// Most of this implementation is straight copied from LLVM. At the time of +// this writing it wasn't *quite* suitable to reuse more code from upstream +// for our purposes, but we should strive to upstream this support once it's +// ready to go! I figure we may want a bit of testing locally first before +// sending this upstream to LLVM. I hear though they're quite eager to receive +// feedback like this! +// +// If you're reading this code and wondering "what in the world" or you're +// working "good lord by LLVM upgrade is *still* failing due to these bindings" +// then fear not! (ok maybe fear a little). All code here is mostly based +// on `lib/LTO/ThinLTOCodeGenerator.cpp` in LLVM. +// +// You'll find that the general layout here roughly corresponds to the `run` +// method in that file as well as `ProcessThinLTOModule`. Functions are +// specifically commented below as well, but if you're updating this code +// or otherwise trying to understand it, the LLVM source will be useful in +// interpreting the mysteries within. +// +// Otherwise I'll apologize in advance, it probably requires a relatively +// significant investment on your part to "truly understand" what's going on +// here. Not saying I do myself, but it took me awhile staring at LLVM's source +// and various online resources about ThinLTO to make heads or tails of all +// this. + +extern "C" bool +LLVMRustWriteThinBitcodeToFile(LLVMPassManagerRef PMR, + LLVMModuleRef M, + const char *BcFile) { + llvm::legacy::PassManager *PM = unwrap(PMR); + std::error_code EC; + llvm::raw_fd_ostream bc(BcFile, EC, llvm::sys::fs::F_None); + if (EC) { + LLVMRustSetLastError(EC.message().c_str()); + return false; + } + PM->add(createWriteThinLTOBitcodePass(bc)); + PM->run(*unwrap(M)); + delete PM; + return true; +} + +// This is a shared data structure which *must* be threadsafe to share +// read-only amongst threads. This also corresponds basically to the arguments +// of the `ProcessThinLTOModule` function in the LLVM source. +struct LLVMRustThinLTOData { + // The combined index that is the global analysis over all modules we're + // performing ThinLTO for. This is mostly managed by LLVM. + ModuleSummaryIndex Index; + + // All modules we may look at, stored as in-memory serialized versions. This + // is later used when inlining to ensure we can extract any module to inline + // from. + StringMap ModuleMap; + + // A set that we manage of everything we *don't* want internalized. Note that + // this includes all transitive references right now as well, but it may not + // always! + DenseSet GUIDPreservedSymbols; + + // Not 100% sure what these are, but they impact what's internalized and + // what's inlined across modules, I believe. + StringMap ImportLists; + StringMap ExportLists; + StringMap ModuleToDefinedGVSummaries; +}; + +// Just an argument to the `LLVMRustCreateThinLTOData` function below. +struct LLVMRustThinLTOModule { + const char *identifier; + const char *data; + size_t len; +}; + +// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`, not sure what it +// does. +static const GlobalValueSummary * +getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) { + auto StrongDefForLinker = llvm::find_if( + GVSummaryList, [](const std::unique_ptr &Summary) { + auto Linkage = Summary->linkage(); + return !GlobalValue::isAvailableExternallyLinkage(Linkage) && + !GlobalValue::isWeakForLinker(Linkage); + }); + if (StrongDefForLinker != GVSummaryList.end()) + return StrongDefForLinker->get(); + + auto FirstDefForLinker = llvm::find_if( + GVSummaryList, [](const std::unique_ptr &Summary) { + auto Linkage = Summary->linkage(); + return !GlobalValue::isAvailableExternallyLinkage(Linkage); + }); + if (FirstDefForLinker == GVSummaryList.end()) + return nullptr; + return FirstDefForLinker->get(); +} + +// This is a helper function we added that isn't present in LLVM's source. +// +// The way LTO works in Rust is that we typically have a number of symbols that +// we know ahead of time need to be preserved. We want to ensure that ThinLTO +// doesn't accidentally internalize any of these and otherwise is always +// ready to keep them linking correctly. +// +// This function will recursively walk the `GUID` provided and all of its +// references, as specified in the `Index`. In other words, we're taking a +// `GUID` as input, adding it to `Preserved`, and then taking all `GUID` +// items that the input references and recursing. +static void +addPreservedGUID(const ModuleSummaryIndex &Index, + DenseSet &Preserved, + GlobalValue::GUID GUID) { + if (Preserved.count(GUID)) + return; + Preserved.insert(GUID); + + auto SummaryList = Index.findGlobalValueSummaryList(GUID); + if (SummaryList == Index.end()) + return; + for (auto &Summary : SummaryList->second) { + for (auto &Ref : Summary->refs()) { + if (Ref.isGUID()) { + addPreservedGUID(Index, Preserved, Ref.getGUID()); + } else { + auto Value = Ref.getValue(); + addPreservedGUID(Index, Preserved, Value->getGUID()); + } + } + + GlobalValueSummary *GVSummary = Summary.get(); + if (isa(GVSummary)) { + FunctionSummary *FS = cast(GVSummary); + for (auto &Call: FS->calls()) { + if (Call.first.isGUID()) { + addPreservedGUID(Index, Preserved, Call.first.getGUID()); + } else { + auto Value = Call.first.getValue(); + addPreservedGUID(Index, Preserved, Value->getGUID()); + } + } + for (auto &GUID: FS->type_tests()) { + addPreservedGUID(Index, Preserved, GUID); + } + } + } +} + +// The main entry point for creating the global ThinLTO analysis. The structure +// here is basically the same as before threads are spawned in the `run` +// function of `lib/LTO/ThinLTOCodeGenerator.cpp`. +extern "C" LLVMRustThinLTOData* +LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, + int num_modules, + const char **preserved_symbols, + int num_symbols) { + auto Ret = llvm::make_unique(); + + // Load each module's summary and merge it into one combined index + for (int i = 0; i < num_modules; i++) { + auto module = &modules[i]; + StringRef buffer(module->data, module->len); + MemoryBufferRef mem_buffer(buffer, module->identifier); + + Ret->ModuleMap[module->identifier] = mem_buffer; + + Expected> ObjOrErr = + object::ModuleSummaryIndexObjectFile::create(mem_buffer); + if (!ObjOrErr) { + LLVMRustSetLastError(toString(ObjOrErr.takeError()).c_str()); + return nullptr; + } + auto Index = (*ObjOrErr)->takeIndex(); + Ret->Index.mergeFrom(std::move(Index), i); + } + + // Collect for each module the list of function it defines (GUID -> Summary) + Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries); + + // Convert the preserved symbols set from string to GUID, this is then needed + // for internalization. We use `addPreservedGUID` to include any transitively + // used symbol as well. + for (int i = 0; i < num_symbols; i++) { + addPreservedGUID(Ret->Index, + Ret->GUIDPreservedSymbols, + GlobalValue::getGUID(preserved_symbols[i])); + } + + // Collect the import/export lists for all modules from the call-graph in the + // combined index + // + // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` + computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols); + ComputeCrossModuleImport( + Ret->Index, + Ret->ModuleToDefinedGVSummaries, + Ret->ImportLists, + Ret->ExportLists + ); + + // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it + // impacts the caching. + // + // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` + StringMap> ResolvedODR; + DenseMap PrevailingCopy; + for (auto &I : Ret->Index) { + if (I.second.size() > 1) + PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second); + } + auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) { + const auto &Prevailing = PrevailingCopy.find(GUID); + if (Prevailing == PrevailingCopy.end()) + return true; + return Prevailing->second == S; + }; + auto recordNewLinkage = [&](StringRef ModuleIdentifier, + GlobalValue::GUID GUID, + GlobalValue::LinkageTypes NewLinkage) { + ResolvedODR[ModuleIdentifier][GUID] = NewLinkage; + }; + thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage); + auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) { + const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); + return (ExportList != Ret->ExportLists.end() && + ExportList->second.count(GUID)) || + Ret->GUIDPreservedSymbols.count(GUID); + }; + thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported); + + return Ret.release(); +} + +extern "C" void +LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) { + delete Data; +} + +// Below are the various passes that happen *per module* when doing ThinLTO. +// +// In other words, these are the functions that are all run concurrently +// with one another, one per module. The passes here correspond to the analysis +// passes in `lib/LTO/ThinLTOCodeGenerator.cpp`, currently found in the +// `ProcessThinLTOModule` function. Here they're split up into separate steps +// so rustc can save off the intermediate bytecode between each step. + +extern "C" bool +LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { + Module &Mod = *unwrap(M); + if (renameModuleForThinLTO(Mod, Data->Index)) { + LLVMRustSetLastError("renameModuleForThinLTO failed"); + return false; + } + return true; +} + +extern "C" bool +LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { + Module &Mod = *unwrap(M); + const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); + thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals); + return true; +} + +extern "C" bool +LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { + Module &Mod = *unwrap(M); + const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); + thinLTOInternalizeModule(Mod, DefinedGlobals); + return true; +} + +extern "C" bool +LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { + Module &Mod = *unwrap(M); + const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier()); + auto Loader = [&](StringRef Identifier) { + const auto &Memory = Data->ModuleMap.lookup(Identifier); + auto &Context = Mod.getContext(); + return getLazyBitcodeModule(Memory, Context, true, true); + }; + FunctionImporter Importer(Data->Index, Loader); + Expected Result = Importer.importFunctions(Mod, ImportList); + if (!Result) { + LLVMRustSetLastError(toString(Result.takeError()).c_str()); + return false; + } + return true; +} + +// This struct and various functions are sort of a hack right now, but the +// problem is that we've got in-memory LLVM modules after we generate and +// optimize all codegen-units for one compilation in rustc. To be compatible +// with the LTO support above we need to serialize the modules plus their +// ThinLTO summary into memory. +// +// This structure is basically an owned version of a serialize module, with +// a ThinLTO summary attached. +struct LLVMRustThinLTOBuffer { + std::string data; +}; + +extern "C" LLVMRustThinLTOBuffer* +LLVMRustThinLTOBufferCreate(LLVMModuleRef M) { + auto Ret = llvm::make_unique(); + { + raw_string_ostream OS(Ret->data); + { + legacy::PassManager PM; + PM.add(createWriteThinLTOBitcodePass(OS)); + PM.run(*unwrap(M)); + } + } + return Ret.release(); +} + +extern "C" void +LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) { + delete Buffer; +} + +extern "C" const void* +LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) { + return Buffer->data.data(); +} + +extern "C" size_t +LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) { + return Buffer->data.length(); +} + +// This is what we used to parse upstream bitcode for actual ThinLTO +// processing. We'll call this once per module optimized through ThinLTO, and +// it'll be called concurrently on many threads. +extern "C" LLVMModuleRef +LLVMRustParseBitcodeForThinLTO(LLVMContextRef Context, + const char *data, + size_t len, + const char *identifier) { + StringRef Data(data, len); + MemoryBufferRef Buffer(Data, identifier); + unwrap(Context)->enableDebugTypeODRUniquing(); + Expected> SrcOrError = + parseBitcodeFile(Buffer, *unwrap(Context)); + if (!SrcOrError) { + LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str()); + return nullptr; + } + return wrap(std::move(*SrcOrError).release()); +} + +#else + +extern "C" bool +LLVMRustWriteThinBitcodeToFile(LLVMPassManagerRef PMR, + LLVMModuleRef M, + const char *BcFile) { + llvm_unreachable("ThinLTO not available"); +} + +struct LLVMRustThinLTOData { +}; + +struct LLVMRustThinLTOModule { +}; + +extern "C" LLVMRustThinLTOData* +LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, + int num_modules, + const char **preserved_symbols, + int num_symbols) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" bool +LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" bool +LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" bool +LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" bool +LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" void +LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) { + llvm_unreachable("ThinLTO not available"); +} + +struct LLVMRustThinLTOBuffer { +}; + +extern "C" LLVMRustThinLTOBuffer* +LLVMRustThinLTOBufferCreate(LLVMModuleRef M) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" void +LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" const void* +LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" size_t +LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) { + llvm_unreachable("ThinLTO not available"); +} + +extern "C" LLVMModuleRef +LLVMRustParseBitcodeForThinLTO(LLVMContextRef Context, + const char *data, + size_t len, + const char *identifier) { + llvm_unreachable("ThinLTO not available"); +} +#endif // LLVM_VERSION_GE(4, 0) diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs index d8e6028b799..bd1325e7501 100644 --- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -11,7 +11,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-trans-items=eager -//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ drop_in_place_intrinsic.cgu-0[Internal] +//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ drop_in_place_intrinsic0[Internal] struct StructWithDtor(u32); impl Drop for StructWithDtor { @@ -22,7 +22,7 @@ impl Drop for StructWithDtor { //~ TRANS_ITEM fn drop_in_place_intrinsic::main[0] fn main() { - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic0[Internal] let x = [StructWithDtor(0), StructWithDtor(1)]; drop_slice_in_place(&x); @@ -34,7 +34,7 @@ fn drop_slice_in_place(x: &[StructWithDtor]) { // This is the interesting thing in this test case: Normally we would // not have drop-glue for the unsized [StructWithDtor]. This has to be // generated though when the drop_in_place() intrinsic is used. - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic0[Internal] ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]); } } diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs index 06e02b10015..108a8b570de 100644 --- a/src/test/codegen-units/item-collection/generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs @@ -45,7 +45,7 @@ enum EnumNoDrop { struct NonGenericNoDrop(i32); struct NonGenericWithDrop(i32); -//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ generic_drop_glue.cgu-0[Internal] +//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ generic_drop_glue0[Internal] impl Drop for NonGenericWithDrop { //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0] @@ -54,11 +54,11 @@ impl Drop for NonGenericWithDrop { //~ TRANS_ITEM fn generic_drop_glue::main[0] fn main() { - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0] let _ = StructWithDrop { x: 0i8, y: 'a' }.x; - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]> let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y; @@ -67,17 +67,17 @@ fn main() { // This is supposed to generate drop-glue because it contains a field that // needs to be dropped. - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y; - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0] let _ = match EnumWithDrop::A::(0) { EnumWithDrop::A(x) => x, EnumWithDrop::B(x) => x as i32 }; - //~TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue.cgu-0[Internal] + //~TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] //~ TRANS_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0] let _ = match EnumWithDrop::B::(1.0) { EnumWithDrop::A(x) => x, diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index 9c6bdb6624e..875cacb3907 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -31,13 +31,13 @@ impl Trait for Struct { fn main() { let s1 = Struct { _a: 0u32 }; - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable0[Internal] //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; let s1 = Struct { _a: 0u64 }; - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable0[Internal] //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ TRANS_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs index 5f70ff396dd..a6081b2c5eb 100644 --- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs @@ -13,7 +13,7 @@ #![deny(dead_code)] -//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue.cgu-0[Internal] +//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue0[Internal] struct StructWithDrop { x: i32 } @@ -27,7 +27,7 @@ struct StructNoDrop { x: i32 } -//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue.cgu-0[Internal] +//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue0[Internal] enum EnumWithDrop { A(i32) } diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs index e41cb34eec6..8eef5f00f2a 100644 --- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs +++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs @@ -13,11 +13,11 @@ #![deny(dead_code)] -//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue.cgu-0[Internal] +//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue0[Internal] struct Root(Intermediate); -//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue.cgu-0[Internal] +//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue0[Internal] struct Intermediate(Leaf); -//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue.cgu-0[Internal] +//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue0[Internal] struct Leaf; impl Drop for Leaf { @@ -38,15 +38,15 @@ fn main() { let _ = Root(Intermediate(Leaf)); - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue.cgu-0[Internal] - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue.cgu-0[Internal] - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] //~ TRANS_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] let _ = RootGen(IntermediateGen(LeafGen(0u32))); - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue.cgu-0[Internal] - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue.cgu-0[Internal] - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] //~ TRANS_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] let _ = RootGen(IntermediateGen(LeafGen(0i16))); } diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs index 39043cf87cb..7edb1c14525 100644 --- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs +++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs @@ -13,7 +13,7 @@ #![deny(dead_code)] -//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ tuple_drop_glue.cgu-0[Internal] +//~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ tuple_drop_glue0[Internal] struct Dropped; impl Drop for Dropped { @@ -23,10 +23,10 @@ impl Drop for Dropped { //~ TRANS_ITEM fn tuple_drop_glue::main[0] fn main() { - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue0[Internal] let x = (0u32, Dropped); - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue.cgu-0[Internal] - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue0[Internal] let x = (0i16, (Dropped, true)); } diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs index de7613741b2..cf0c6643238 100644 --- a/src/test/codegen-units/item-collection/unsizing.rs +++ b/src/test/codegen-units/item-collection/unsizing.rs @@ -57,13 +57,13 @@ fn main() { // simple case let bool_sized = &true; - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] //~ TRANS_ITEM fn unsizing::{{impl}}[0]::foo[0] let _bool_unsized = bool_sized as &Trait; let char_sized = &'a'; - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] //~ TRANS_ITEM fn unsizing::{{impl}}[1]::foo[0] let _char_unsized = char_sized as &Trait; @@ -73,13 +73,13 @@ fn main() _b: 2, _c: 3.0f64 }; - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] //~ TRANS_ITEM fn unsizing::{{impl}}[2]::foo[0] let _struct_unsized = struct_sized as &Struct; // custom coercion let wrapper_sized = Wrapper(&0u32); - //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing.cgu-0[Internal] + //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] //~ TRANS_ITEM fn unsizing::{{impl}}[3]::foo[0] let _wrapper_sized = wrapper_sized as Wrapper; } diff --git a/src/test/run-make/extra-filename-with-temp-outputs/Makefile b/src/test/run-make/extra-filename-with-temp-outputs/Makefile index d33c18a6f3c..13ca397eaf2 100644 --- a/src/test/run-make/extra-filename-with-temp-outputs/Makefile +++ b/src/test/run-make/extra-filename-with-temp-outputs/Makefile @@ -2,5 +2,5 @@ all: $(RUSTC) -C extra-filename=bar foo.rs -C save-temps - rm $(TMPDIR)/foobar.0.o + rm $(TMPDIR)/foobar.foo0.rust-cgu.o rm $(TMPDIR)/$(call BIN,foobar) diff --git a/src/test/run-make/sepcomp-cci-copies/Makefile b/src/test/run-make/sepcomp-cci-copies/Makefile index 189088219d5..8324a074d6c 100644 --- a/src/test/run-make/sepcomp-cci-copies/Makefile +++ b/src/test/run-make/sepcomp-cci-copies/Makefile @@ -6,4 +6,4 @@ all: $(RUSTC) cci_lib.rs $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 - [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ .*cci_fn)" -eq "2" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ .*cci_fn)" -eq "2" ] diff --git a/src/test/run-make/sepcomp-inlining/Makefile b/src/test/run-make/sepcomp-inlining/Makefile index 720dfff2c04..6dc837b8a78 100644 --- a/src/test/run-make/sepcomp-inlining/Makefile +++ b/src/test/run-make/sepcomp-inlining/Makefile @@ -8,7 +8,7 @@ all: $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 - [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ i32\ .*inlined)" -eq "0" ] - [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "2" ] - [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ hidden\ i32\ .*normal)" -eq "1" ] - [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c declare\ hidden\ i32\ .*normal)" -eq "2" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ i32\ .*inlined)" -eq "0" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "2" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ hidden\ i32\ .*normal)" -eq "1" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c declare\ hidden\ i32\ .*normal)" -eq "2" ] diff --git a/src/test/run-make/sepcomp-separate/Makefile b/src/test/run-make/sepcomp-separate/Makefile index a475bdfd74a..5b8bdb0fad8 100644 --- a/src/test/run-make/sepcomp-separate/Makefile +++ b/src/test/run-make/sepcomp-separate/Makefile @@ -6,4 +6,4 @@ all: $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 - [ "$$(cat "$(TMPDIR)"/foo.?.ll | grep -c define\ .*magic_fn)" -eq "3" ] + [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ .*magic_fn)" -eq "3" ] diff --git a/src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs b/src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs new file mode 100644 index 00000000000..ccbb0e7a718 --- /dev/null +++ b/src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs @@ -0,0 +1,17 @@ +// Copyright 2017 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. + +// no-prefer-dynamic + +#![crate_type = "rlib"] + +pub fn bar() -> u32 { + 3 +} diff --git a/src/test/run-pass/thin-lto-inlines.rs b/src/test/run-pass/thin-lto-inlines.rs new file mode 100644 index 00000000000..3135a682d86 --- /dev/null +++ b/src/test/run-pass/thin-lto-inlines.rs @@ -0,0 +1,39 @@ +// Copyright 2017 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. + +// compile-flags: -Z thinlto -C codegen-units=8 -O +// min-llvm-version 4.0 +// ignore-emscripten + +// We want to assert here that ThinLTO will inline across codegen units. There's +// not really a great way to do that in general so we sort of hack around it by +// praying two functions go into separate codegen units and then assuming that +// if inlining *doesn't* happen the first byte of the functions will differ. + +pub fn foo() -> u32 { + bar::bar() +} + +mod bar { + pub fn bar() -> u32 { + 3 + } +} + +fn main() { + println!("{} {}", foo(), bar::bar()); + + unsafe { + let foo = foo as usize as *const u8; + let bar = bar::bar as usize as *const u8; + + assert_eq!(*foo, *bar); + } +} diff --git a/src/test/run-pass/thin-lto-inlines2.rs b/src/test/run-pass/thin-lto-inlines2.rs new file mode 100644 index 00000000000..ed899d2b115 --- /dev/null +++ b/src/test/run-pass/thin-lto-inlines2.rs @@ -0,0 +1,38 @@ +// Copyright 2017 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. + +// compile-flags: -Z thinlto -C codegen-units=8 -O -C lto +// aux-build:thin-lto-inlines-aux.rs +// min-llvm-version 4.0 +// no-prefer-dynamic +// ignore-emscripten + +// We want to assert here that ThinLTO will inline across codegen units. There's +// not really a great way to do that in general so we sort of hack around it by +// praying two functions go into separate codegen units and then assuming that +// if inlining *doesn't* happen the first byte of the functions will differ. + +extern crate thin_lto_inlines_aux as bar; + +pub fn foo() -> u32 { + bar::bar() +} + +fn main() { + println!("{} {}", foo(), bar::bar()); + + unsafe { + let foo = foo as usize as *const u8; + let bar = bar::bar as usize as *const u8; + + assert_eq!(*foo, *bar); + } +} + From fe24e815a2d0aecfd975a15a12a4b4937bb4cc37 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 27 Sep 2017 00:43:37 +0200 Subject: [PATCH 083/365] Fix invalid rustdoc rendering for FnTy args --- src/librustc/hir/intravisit.rs | 2 +- src/librustc/hir/lowering.rs | 11 ++--------- src/librustc/hir/mod.rs | 1 + src/librustc/hir/print.rs | 8 +++++--- src/librustc/ich/impls_hir.rs | 3 ++- src/librustdoc/clean/mod.rs | 2 +- src/test/rustdoc/fn-pointer-arg-name.rs | 15 +++++++++++++++ 7 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 src/test/rustdoc/fn-pointer-arg-name.rs diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 3130a88306e..1755b3bca05 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -574,7 +574,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyTup(ref tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } - TyBareFn(ref function_declaration, _) => { + TyBareFn(ref function_declaration) => { visitor.visit_fn_decl(&function_declaration.decl); walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c03c9499608..64a2ba1fa6f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -673,15 +673,8 @@ impl<'a> LoweringContext<'a> { unsafety: self.lower_unsafety(f.unsafety), abi: f.abi, decl: self.lower_fn_decl(&f.decl), - }, - decl.inputs.iter().map(|arg| { - match arg.pat.node { - PatKind::Ident(_, ident, None) => { - respan(ident.span, ident.node.name) - } - _ => respan(arg.pat.span, keywords::Invalid.name()), - } - }).collect())) + arg_names: self.lower_fn_args_to_names(&f.decl), + })) } TyKind::Never => hir::TyNever, TyKind::Tup(ref tys) => { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index dcff66dc23b..5ad0ff04c1b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1418,6 +1418,7 @@ pub struct BareFnTy { pub abi: Abi, pub lifetimes: HirVec, pub decl: P, + pub arg_names: HirVec>, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 5daffe667fd..7287e599b29 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -399,7 +399,8 @@ impl<'a> State<'a> { }, span: syntax_pos::DUMMY_SP, }; - self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics)?; + self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics, + &f.arg_names[..])?; } hir::TyPath(ref qpath) => { self.print_qpath(qpath, false)? @@ -2140,7 +2141,8 @@ impl<'a> State<'a> { unsafety: hir::Unsafety, decl: &hir::FnDecl, name: Option, - generics: &hir::Generics) + generics: &hir::Generics, + arg_names: &[Spanned]) -> io::Result<()> { self.ibox(indent_unit)?; if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { @@ -2163,7 +2165,7 @@ impl<'a> State<'a> { name, &generics, &hir::Inherited, - &[], + arg_names, None)?; self.end() } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 776f85cf5da..c0fae8bf8bd 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -274,7 +274,8 @@ impl_stable_hash_for!(struct hir::BareFnTy { unsafety, abi, lifetimes, - decl + decl, + arg_names }); impl_stable_hash_for!(enum hir::Ty_ { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c9afa3646b2..424f48a17e9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2491,7 +2491,7 @@ impl Clean for hir::BareFnTy { type_params: Vec::new(), where_predicates: Vec::new() }, - decl: (&*self.decl, &[][..]).clean(cx), + decl: (&*self.decl, &self.arg_names[..]).clean(cx), abi: self.abi, } } diff --git a/src/test/rustdoc/fn-pointer-arg-name.rs b/src/test/rustdoc/fn-pointer-arg-name.rs new file mode 100644 index 00000000000..af87f1b4669 --- /dev/null +++ b/src/test/rustdoc/fn-pointer-arg-name.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +#![crate_name = "foo"] + +// @has foo/fn.f.html +// @has - '//*[@class="rust fn"]' 'pub fn f(callback: fn(len: usize, foo: u32))' +pub fn f(callback: fn(len: usize, foo: u32)) {} From 7d1c14a32d9b09681d8050b30e35c30c7058d8b7 Mon Sep 17 00:00:00 2001 From: Robin Kruppe Date: Sat, 7 Oct 2017 18:04:23 +0200 Subject: [PATCH 084/365] Fix typo in codegen test --- src/test/codegen/float_math.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/codegen/float_math.rs b/src/test/codegen/float_math.rs index bc458d45446..6a6d6f90b2e 100644 --- a/src/test/codegen/float_math.rs +++ b/src/test/codegen/float_math.rs @@ -19,7 +19,7 @@ use std::intrinsics::{fadd_fast, fsub_fast, fmul_fast, fdiv_fast, frem_fast}; #[no_mangle] pub fn add(x: f32, y: f32) -> f32 { // CHECK: fadd float -// CHECK-NOT fast +// CHECK-NOT: fast x + y } From 691ab6c5bf597e98a4bae94b9a433f029f9ca9c1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Oct 2017 19:26:02 +0300 Subject: [PATCH 085/365] Document that `-C ar=PATH` doesn't do anything --- src/librustc/session/config.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 7c1d457a6ee..8d1ad5d7bc4 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -874,7 +874,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, build_codegen_options, "C", "codegen", CG_OPTIONS, cg_type_desc, cgsetters, ar: Option = (None, parse_opt_string, [UNTRACKED], - "tool to assemble archives with"), + "tool to assemble archives with (has no effect currently, \ + rustc doesn't use an external archiver)"), linker: Option = (None, parse_opt_string, [UNTRACKED], "system linker to link outputs with"), link_arg: Vec = (vec![], parse_string_push, [UNTRACKED], From 0cdf587ab356128d07f96e3d2dff255e1ebb5097 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sat, 16 Sep 2017 15:59:15 +0800 Subject: [PATCH 086/365] doc-test: In Markdown tests, Use all of `

` to `

` as the test name. This mainly simplifies debugging error index tests, as the error codes are `

`s in the huge document containing all codes. --- src/librustc_resolve/diagnostics.rs | 6 +-- src/librustdoc/test.rs | 74 ++++++++++++++++++----------- 2 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 9193ac0fcd6..564626ac398 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -43,7 +43,7 @@ parameter if so. "##, E0154: r##" -## Note: this error code is no longer emitted by the compiler. +#### Note: this error code is no longer emitted by the compiler. Imports (`use` statements) are not allowed after non-item statements, such as variable declarations and expression statements. @@ -79,7 +79,7 @@ https://doc.rust-lang.org/reference.html#statements "##, E0251: r##" -## Note: this error code is no longer emitted by the compiler. +#### Note: this error code is no longer emitted by the compiler. Two items of the same name cannot be imported without rebinding one of the items under a new local name. @@ -268,7 +268,7 @@ fn main() { "##, E0256: r##" -## Note: this error code is no longer emitted by the compiler. +#### Note: this error code is no longer emitted by the compiler. You can't import a type or module when the name of the item being imported is the same as another type or submodule defined in the module. diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 5ce73d38fdf..2cd1261e795 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -407,13 +407,33 @@ pub struct Collector { pub tests: Vec, // to be removed when hoedown will be definitely gone pub old_tests: HashMap>, + + // The name of the test displayed to the user, separated by `::`. + // + // In tests from Rust source, this is the path to the item + // e.g. `["std", "vec", "Vec", "push"]`. + // + // In tests from a markdown file, this is the titles of all headers (h1~h6) + // of the sections that contain the code block, e.g. if the markdown file is + // written as: + // + // ``````markdown + // # Title + // + // ## Subtitle + // + // ```rust + // assert!(true); + // ``` + // `````` + // + // the `names` vector of that test will be `["Title", "Subtitle"]`. names: Vec, + cfgs: Vec, libs: SearchPaths, externs: Externs, - cnt: usize, use_headers: bool, - current_header: Option, cratename: String, opts: TestOptions, maybe_sysroot: Option, @@ -436,9 +456,7 @@ impl Collector { cfgs, libs, externs, - cnt: 0, use_headers, - current_header: None, cratename, opts, maybe_sysroot, @@ -450,28 +468,12 @@ impl Collector { } fn generate_name(&self, line: usize, filename: &str) -> String { - if self.use_headers { - if let Some(ref header) = self.current_header { - format!("{} - {} (line {})", filename, header, line) - } else { - format!("{} - (line {})", filename, line) - } - } else { - format!("{} - {} (line {})", filename, self.names.join("::"), line) - } + format!("{} - {} (line {})", filename, self.names.join("::"), line) } // to be removed once hoedown is gone fn generate_name_beginning(&self, filename: &str) -> String { - if self.use_headers { - if let Some(ref header) = self.current_header { - format!("{} - {} (line", filename, header) - } else { - format!("{} - (line", filename) - } - } else { - format!("{} - {} (line", filename, self.names.join("::")) - } + format!("{} - {} (line", filename, self.names.join("::")) } pub fn add_old_test(&mut self, test: String, filename: String) { @@ -580,7 +582,7 @@ impl Collector { } pub fn register_header(&mut self, name: &str, level: u32) { - if self.use_headers && level == 1 { + if self.use_headers { // we use these headings as test names, so it's good if // they're valid identifiers. let name = name.chars().enumerate().map(|(i, c)| { @@ -592,9 +594,28 @@ impl Collector { } }).collect::(); - // new header => reset count. - self.cnt = 0; - self.current_header = Some(name); + // Here we try to efficiently assemble the header titles into the + // test name in the form of `h1::h2::h3::h4::h5::h6`. + // + // Suppose originally `self.names` contains `[h1, h2, h3]`... + let level = level as usize; + if level <= self.names.len() { + // ... Consider `level == 2`. All headers in the lower levels + // are irrelevant in this new level. So we should reset + // `self.names` to contain headers until

, and replace that + // slot with the new name: `[h1, name]`. + self.names.truncate(level); + self.names[level - 1] = name; + } else { + // ... On the other hand, consider `level == 5`. This means we + // need to extend `self.names` to contain five headers. We fill + // in the missing level (

) with `_`. Thus `self.names` will + // become `[h1, h2, h3, "_", name]`. + if level - 1 > self.names.len() { + self.names.resize(level - 1, "_".to_owned()); + } + self.names.push(name); + } } } } @@ -625,7 +646,6 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { attrs.collapse_doc_comments(); attrs.unindent_doc_comments(); if let Some(doc) = attrs.doc_value() { - self.collector.cnt = 0; if self.collector.render_type == RenderType::Pulldown { markdown::old_find_testable_code(doc, self.collector, attrs.span.unwrap_or(DUMMY_SP)); From 07b189977d88d1de595601e7137275e4f4ccd8a2 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 8 Oct 2017 01:39:27 +0800 Subject: [PATCH 087/365] debuginfo-test: Fix #45086. LLDB's output may be None instead of '', and that will cause type mismatch when normalize_whitespace() expects a string instead of None. This commit simply ensures we do pass '' even if the output is None. --- src/etc/lldb_batchmode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py index 4952cf4f82c..24a0ce0ac36 100644 --- a/src/etc/lldb_batchmode.py +++ b/src/etc/lldb_batchmode.py @@ -81,7 +81,7 @@ def execute_command(command_interpreter, command): if res.Succeeded(): if res.HasResult(): - print(normalize_whitespace(res.GetOutput()), end='\n') + print(normalize_whitespace(res.GetOutput() or ''), end='\n') # If the command introduced any breakpoints, make sure to register # them with the breakpoint From 2b8f190d63d07bb7dd352c050c2a1daaa5c6574e Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 7 Oct 2017 20:48:25 +0200 Subject: [PATCH 088/365] enable strict alignment (+strict-align) on ARMv6 As discovered in #44538 ARMv6 devices may or may not support unaligned memory accesses. ARMv6 Linux *seems* to have no problem with unaligned accesses but this is because the kernel is stepping in to fix each unaligned memory access -- this incurs in a performance penalty. This commit enforces aligned memory accesses on all our in-tree ARM targets that may be used with ARMv6 devices. This should improve performance of Rust programs on ARMv6 devices. For the record, clang also applies this attribute when targeting ARMv6 devices that are not running Darwin or NetBSD. --- src/librustc_back/target/arm_linux_androideabi.rs | 2 +- src/librustc_back/target/arm_unknown_linux_gnueabi.rs | 2 +- src/librustc_back/target/arm_unknown_linux_gnueabihf.rs | 2 +- src/librustc_back/target/arm_unknown_linux_musleabi.rs | 2 +- src/librustc_back/target/arm_unknown_linux_musleabihf.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_back/target/arm_linux_androideabi.rs index e93a9a788a4..ba21b1df032 100644 --- a/src/librustc_back/target/arm_linux_androideabi.rs +++ b/src/librustc_back/target/arm_linux_androideabi.rs @@ -14,7 +14,7 @@ use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { let mut base = super::android_base::opts(); // https://developer.android.com/ndk/guides/abis.html#armeabi - base.features = "+v5te".to_string(); + base.features = "+strict-align,+v5te".to_string(); base.max_atomic_width = Some(64); Ok(Target { diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs index b9f40accaeb..e630376a67d 100644 --- a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs +++ b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs @@ -27,7 +27,7 @@ pub fn target() -> TargetResult { linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+v6".to_string(), + features: "+strict-align,+v6".to_string(), abi_blacklist: super::arm_base::abi_blacklist(), .. base }, diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs index a3ea69caec6..178a948b2b9 100644 --- a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs +++ b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs @@ -27,7 +27,7 @@ pub fn target() -> TargetResult { linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+v6,+vfp2".to_string(), + features: "+strict-align,+v6,+vfp2".to_string(), abi_blacklist: super::arm_base::abi_blacklist(), .. base } diff --git a/src/librustc_back/target/arm_unknown_linux_musleabi.rs b/src/librustc_back/target/arm_unknown_linux_musleabi.rs index 598f722d9af..29720ec5efc 100644 --- a/src/librustc_back/target/arm_unknown_linux_musleabi.rs +++ b/src/librustc_back/target/arm_unknown_linux_musleabi.rs @@ -16,7 +16,7 @@ pub fn target() -> TargetResult { // Most of these settings are copied from the arm_unknown_linux_gnueabi // target. - base.features = "+v6".to_string(); + base.features = "+strict-align,+v6".to_string(); base.max_atomic_width = Some(64); Ok(Target { // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it diff --git a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs index ea0bf75b103..fc8313877f6 100644 --- a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs +++ b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs @@ -16,7 +16,7 @@ pub fn target() -> TargetResult { // Most of these settings are copied from the arm_unknown_linux_gnueabihf // target. - base.features = "+v6,+vfp2".to_string(); + base.features = "+strict-align,+v6,+vfp2".to_string(); base.max_atomic_width = Some(64); Ok(Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM From d52acbe37f69a2ebc9d161c479ed628da1cbea4e Mon Sep 17 00:00:00 2001 From: Florian Hartwig Date: Sat, 7 Oct 2017 14:49:42 +0200 Subject: [PATCH 089/365] Add read_to_end implementation to &[u8]'s Read impl The default impl for read_to_end does a bunch of bookkeeping that isn't necessary for slices and is about 4 times slower on my machine. --- src/libstd/io/impls.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index d6b41ceda43..fe1179a3b4a 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -206,6 +206,14 @@ impl<'a> Read for &'a [u8] { *self = b; Ok(()) } + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + buf.extend_from_slice(*self); + let len = self.len(); + *self = &self[len..]; + Ok(len) + } } #[stable(feature = "rust1", since = "1.0.0")] From e0ac65e669e2a59a674327f7ff2590afbc2f3442 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Sat, 7 Oct 2017 13:19:34 +0300 Subject: [PATCH 090/365] address more FIXME whose associated issues were marked as closed update FIXME(#6298) to point to open issue 15020 update FIXME(#6268) to point to RFC 811 update FIXME(#10520) to point to RFC 1751 remove FIXME for emscripten issue 4563 and include target in `test_estimate_scaling_factor` remove FIXME(#18207) since node_id isn't used for `ref` pattern analysis remove FIXME(#6308) since DST was implemented in #12938 remove FIXME(#2658) since it was decided to not reorganize module remove FIXME(#20590) since it was decided to stay conservative with projection types remove FIXME(#20297) since it was decided that solving the issue is unnecessary remove FIXME(#27086) since closures do correspond to structs now remove FIXME(#13846) and enable `function_sections` for windows remove mention of #22079 in FIXME(#22079) since this is a general FIXME remove FIXME(#5074) since the restriction on borrow were lifted --- src/libcore/tests/num/flt2dec/estimator.rs | 5 --- src/librustc/middle/dataflow.rs | 2 +- src/librustc/middle/mem_categorization.rs | 6 ++-- src/librustc/middle/region.rs | 4 +-- src/librustc/session/filesearch.rs | 2 -- src/librustc/traits/coherence.rs | 1 - src/librustc/traits/select.rs | 14 ++------ src/librustc/ty/outlives.rs | 36 ------------------- src/librustc_back/target/windows_base.rs | 3 +- src/librustc_borrowck/borrowck/README.md | 5 +-- src/librustc_borrowck/borrowck/check_loans.rs | 4 +-- .../borrowck/gather_loans/mod.rs | 5 ++- src/librustc_typeck/check/regionck.rs | 3 +- 13 files changed, 16 insertions(+), 74 deletions(-) diff --git a/src/libcore/tests/num/flt2dec/estimator.rs b/src/libcore/tests/num/flt2dec/estimator.rs index 0bca616ea9a..857aae72c8a 100644 --- a/src/libcore/tests/num/flt2dec/estimator.rs +++ b/src/libcore/tests/num/flt2dec/estimator.rs @@ -8,11 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME https://github.com/kripken/emscripten/issues/4563 -// NB we have to actually not compile this test to avoid -// an undefined symbol error -#![cfg(not(target_os = "emscripten"))] - use core::num::flt2dec::estimator::*; #[test] diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index e88678dea1d..5c86554f907 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -171,7 +171,7 @@ fn build_local_id_to_index(body: Option<&hir::Body>, -> FxHashMap> { let mut index = FxHashMap(); - // FIXME (#6298): Would it be better to fold formals from decl + // FIXME(#15020) Would it be better to fold formals from decl // into cfg itself? i.e. introduce a fn-based flow-graph in // addition to the current block-based flow-graph, rather than // have to put traversals like this here? diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c973881c980..8754316ca84 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -477,10 +477,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { fn pat_ty(&self, pat: &hir::Pat) -> McResult> { let base_ty = self.node_ty(pat.hir_id)?; - // FIXME (Issue #18207): This code detects whether we are - // looking at a `ref x`, and if so, figures out what the type - // *being borrowed* is. But ideally we would put in a more - // fundamental fix to this conflated use of the node id. + // This code detects whether we are looking at a `ref x`, + // and if so, figures out what the type *being borrowed* is. let ret_ty = match pat.node { PatKind::Binding(..) => { let bm = *self.tables diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index b909ee9f93b..635bcbf7771 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -960,7 +960,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: hir::ExprAssignOp(..) | hir::ExprIndex(..) | hir::ExprUnary(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) => { - // FIXME(#6268) Nested method calls + // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls // // The lifetimes for a call or method call look as follows: // @@ -1081,8 +1081,6 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, // Here, the expression `[...]` has an extended lifetime due to rule // A, but the inner rvalues `a()` and `b()` have an extended lifetime // due to rule C. - // - // FIXME(#6308) -- Note that `[]` patterns work more smoothly post-DST. if let Some(expr) = init { record_rvalue_scope_if_borrow_expr(visitor, &expr, blk_scope); diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs index 1004b282602..b636fc6c995 100644 --- a/src/librustc/session/filesearch.rs +++ b/src/librustc/session/filesearch.rs @@ -28,8 +28,6 @@ pub enum FileMatch { } // A module for searching for libraries -// FIXME (#2658): I'm not happy how this module turned out. Should -// probably just be folded into cstore. pub struct FileSearch<'a> { pub sysroot: &'a Path, diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index f3682f8d35d..dc5ce735324 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -252,7 +252,6 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal) fn is_type_parameter(ty: Ty) -> bool { match ty.sty { - // FIXME(#20590) straighten story about projection types ty::TyProjection(..) | ty::TyParam(..) => true, _ => false, } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 00f0672822f..cec79faff31 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1309,13 +1309,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }; if obligation.predicate.skip_binder().self_ty().is_ty_var() { - // FIXME(#20297): Self is a type variable (e.g. `_: AsRef`). + // Self is a type variable (e.g. `_: AsRef`). // // This is somewhat problematic, as the current scheme can't really // handle it turning to be a projection. This does end up as truly // ambiguous in most cases anyway. // - // Until this is fixed, take the fast path out - this also improves + // Take the fast path out - this also improves // performance by preventing assemble_candidates_from_impls from // matching every impl for this trait. return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true }); @@ -1383,8 +1383,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("assemble_candidates_for_projected_tys({:?})", obligation); - // FIXME(#20297) -- just examining the self-type is very simplistic - // before we go into the whole skolemization thing, just // quickly check if the self-type is a projection at all. match obligation.predicate.0.trait_ref.self_ty().sty { @@ -2174,14 +2172,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } ty::TyClosure(def_id, ref substs) => { - // FIXME(#27086). We are invariant w/r/t our - // func_substs, but we don't see them as - // constituent types; this seems RIGHT but also like - // something that a normal type couldn't simulate. Is - // this just a gap with the way that PhantomData and - // OIBIT interact? That is, there is no way to say - // "make me invariant with respect to this TYPE, but - // do not act as though I can reach it" substs.upvar_tys(def_id, self.tcx()).collect() } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 657ed407791..5e1dc485d42 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -73,42 +73,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // projection). match ty.sty { ty::TyClosure(def_id, ref substs) => { - // FIXME(#27086). We do not accumulate from substs, since they - // don't represent reachable data. This means that, in - // practice, some of the lifetime parameters might not - // be in scope when the body runs, so long as there is - // no reachable data with that lifetime. For better or - // worse, this is consistent with fn types, however, - // which can also encapsulate data in this fashion - // (though it's somewhat harder, and typically - // requires virtual dispatch). - // - // Note that changing this (in a naive way, at least) - // causes regressions for what appears to be perfectly - // reasonable code like this: - // - // ``` - // fn foo<'a>(p: &Data<'a>) { - // bar(|q: &mut Parser| q.read_addr()) - // } - // fn bar(p: Box) { - // } - // ``` - // - // Note that `p` (and `'a`) are not used in the - // closure at all, but to meet the requirement that - // the closure type `C: 'static` (so it can be coerced - // to the object type), we get the requirement that - // `'a: 'static` since `'a` appears in the closure - // type `C`. - // - // A smarter fix might "prune" unused `func_substs` -- - // this would avoid breaking simple examples like - // this, but would still break others (which might - // indeed be invalid, depending on your POV). Pruning - // would be a subtle process, since we have to see - // what func/type parameters are used and unused, - // taking into consideration UFCS and so forth. for upvar_ty in substs.upvar_tys(def_id, *self) { self.compute_components(upvar_ty, out); diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index e6aa745d54e..21b8c4e082e 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -64,8 +64,7 @@ pub fn opts() -> TargetOptions { ]); TargetOptions { - // FIXME(#13846) this should be enabled for windows - function_sections: false, + function_sections: true, linker: "gcc".to_string(), dynamic_linking: true, executables: true, diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index 034b7cbadd9..fb70a6c3e84 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -781,8 +781,9 @@ the base path, it will still be considered freezable. -**FIXME #10520: Restrictions against mutating the base pointer.** When -an `&mut` pointer is frozen or claimed, we currently pass along the +**FIXME(https://github.com/rust-lang/rfcs/issues/1751) +Restrictions against mutating the base pointer.** +When an `&mut` pointer is frozen or claimed, we currently pass along the restriction against MUTATE to the base pointer. I do not believe this restriction is needed. It dates from the days when we had a way to mutate that preserved the value being mutated (i.e., swap). Nowadays diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index fea662e21fa..0fc1b68b878 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -659,7 +659,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { debug!("check_if_path_is_moved(id={:?}, use_kind={:?}, lp={:?})", id, use_kind, lp); - // FIXME (22079): if you find yourself tempted to cut and paste + // FIXME: if you find yourself tempted to cut and paste // the body below and then specializing the error reporting, // consider refactoring this instead! @@ -720,7 +720,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // the path must be initialized to prevent a case of // partial reinitialization // - // FIXME (22079): could refactor via hypothetical + // FIXME: could refactor via hypothetical // generalized check_if_path_is_moved let loan_path = owned_ptr_base_path_rc(lp_base); self.move_data.each_move_of(id, &loan_path, |_, _| { diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index a58b62ba2a7..6b52d842f8b 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -406,7 +406,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { self.all_loans.push(loan); // if loan_gen_scope != borrow_id { - // FIXME(#6268) Nested method calls + // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls // // Typically, the scope of the loan includes the point at // which the loan is originated. This @@ -417,9 +417,8 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { //let restr = restrictions::compute_restrictions( // self.bccx, borrow_span, cmt, RESTR_EMPTY); //let loan = { - // let all_loans = &mut *self.all_loans; // FIXME(#5074) // Loan { - // index: all_loans.len(), + // index: self.all_loans.len(), // loan_path, // cmt, // mutbl: ConstMutability, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 609af638e97..ad7978480a6 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -815,7 +815,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { // the type of the node expr.id here *before applying // adjustments*. // - // FIXME(#6268) nested method calls requires that this rule change + // FIXME(https://github.com/rust-lang/rfcs/issues/811) + // nested method calls requires that this rule change let ty0 = self.resolve_node_type(expr.hir_id); self.type_must_outlive(infer::AddrOf(expr.span), ty0, expr_region); intravisit::walk_expr(self, expr); From 3fff2d95bf90514e66892ca9be666c35eeae9165 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sat, 7 Oct 2017 21:33:36 +0200 Subject: [PATCH 091/365] core: Ensure std::mem::Discriminant is Send + Sync `PhantomData<*const T>` has the implication of Send / Syncness following the *const T type, but the discriminant should always be Send and Sync. Use `PhantomData T>` which has the same variance in T, but is Send + Sync --- src/libcore/mem.rs | 2 +- src/libcore/tests/mem.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index e085d427b8c..680a0f5b2c0 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -836,7 +836,7 @@ pub unsafe fn transmute_copy(src: &T) -> U { /// /// See the `discriminant` function in this module for more information. #[stable(feature = "discriminant_value", since = "1.21.0")] -pub struct Discriminant(u64, PhantomData<*const T>); +pub struct Discriminant(u64, PhantomData T>); // N.B. These trait implementations cannot be derived because we don't want any bounds on T. diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index 86e59c736ba..f55a1c81463 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -121,3 +121,19 @@ fn test_transmute() { } } +#[test] +#[allow(dead_code)] +fn test_discriminant_send_sync() { + enum Regular { + A, + B(i32) + } + enum NotSendSync { + A(*const i32) + } + + fn is_send_sync() { } + + is_send_sync::>(); + is_send_sync::>(); +} From 4b2bdf7b543df0ae28ce27db700ad46d9be59eed Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Oct 2017 14:59:33 -0700 Subject: [PATCH 092/365] rustc: Don't inline in CGUs at -O0 This commit tweaks the behavior of inlining functions into multiple codegen units when rustc is compiling in debug mode. Today rustc will unconditionally treat `#[inline]` functions by translating them into all codegen units that they're needed within, marking the linkage as `internal`. This commit changes the behavior so that in debug mode (compiling at `-O0`) rustc will instead only translate `#[inline]` functions into *one* codegen unit, forcing all other codegen units to reference this one copy. The goal here is to improve debug compile times by reducing the amount of translation that happens on behalf of multiple codegen units. It was discovered in #44941 that increasing the number of codegen units had the adverse side effect of increasing the overal work done by the compiler, and the suspicion here was that the compiler was inlining, translating, and codegen'ing more functions with more codegen units (for example `String` would be basically inlined into all codegen units if used). The strategy in this commit should reduce the cost of `#[inline]` functions to being equivalent to one codegen unit, which is only translating and codegen'ing inline functions once. Collected [data] shows that this does indeed improve the situation from [before] as the overall cpu-clock time increases at a much slower rate and when pinned to one core rustc does not consume significantly more wall clock time than with one codegen unit. One caveat of this commit is that the symbol names for inlined functions that are only translated once needed some slight tweaking. These inline functions could be translated into multiple crates and we need to make sure the symbols don't collideA so the crate name/disambiguator is mixed in to the symbol name hash in these situations. [data]: https://github.com/rust-lang/rust/issues/44941#issuecomment-334880911 [before]: https://github.com/rust-lang/rust/issues/44941#issuecomment-334583384 --- src/librustc/session/config.rs | 2 + src/librustc_trans/back/symbol_names.rs | 52 +++++--- src/librustc_trans/collector.rs | 6 +- src/librustc_trans/partitioning.rs | 111 +++++++++--------- src/librustc_trans/trans_item.rs | 37 +++++- .../drop_in_place_intrinsic.rs | 1 + .../item-collection/generic-drop-glue.rs | 1 + .../instantiation-through-vtable.rs | 1 + .../item-collection/non-generic-drop-glue.rs | 1 + .../item-collection/transitive-drop-glue.rs | 1 + .../item-collection/tuple-drop-glue.rs | 1 + .../codegen-units/item-collection/unsizing.rs | 1 + .../partitioning/extern-drop-glue.rs | 1 + .../inlining-from-extern-crate.rs | 1 + .../partitioning/local-drop-glue.rs | 1 + .../local-inlining-but-not-all.rs | 54 +++++++++ .../partitioning/local-inlining.rs | 1 + .../partitioning/local-transitive-inlining.rs | 1 + .../partitioning/vtable-through-const.rs | 1 + src/test/run-make/sepcomp-cci-copies/Makefile | 3 +- src/test/run-make/sepcomp-inlining/Makefile | 3 +- 21 files changed, 200 insertions(+), 81 deletions(-) create mode 100644 src/test/codegen-units/partitioning/local-inlining-but-not-all.rs diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 6ef64ef3d96..44dc04f0895 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1097,6 +1097,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "generate a graphical HTML report of time spent in trans and LLVM"), thinlto: bool = (false, parse_bool, [TRACKED], "enable ThinLTO when possible"), + inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], + "control whether #[inline] functions are in all cgus"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 306071223fc..66a27f1c4a9 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -98,8 +98,10 @@ //! DefPaths which are much more robust in the face of changes to the code base. use monomorphize::Instance; +use trans_item::{TransItemExt, InstantiationMode}; use rustc::middle::weak_lang_items; +use rustc::middle::trans::TransItem; use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -150,7 +152,10 @@ pub fn provide(providers: &mut Providers) { fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // the DefId of the item this name is for - def_id: Option, + def_id: DefId, + + // instance this name will be for + instance: Instance<'tcx>, // type of the item, without any generic // parameters substituted; this is @@ -160,7 +165,7 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // values for generic type parameters, // if any. - substs: Option<&'tcx Substs<'tcx>>) + substs: &'tcx Substs<'tcx>) -> u64 { debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs); @@ -170,7 +175,7 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // the main symbol name is not necessarily unique; hash in the // compiler's internal def-path, guaranteeing each symbol has a // truly unique path - hasher.hash(def_id.map(|def_id| tcx.def_path_hash(def_id))); + hasher.hash(tcx.def_path_hash(def_id)); // Include the main item-type. Note that, in this case, the // assertions about `needs_subst` may not hold, but this item-type @@ -186,19 +191,36 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // also include any type parameters (for generic items) - if let Some(substs) = substs { - assert!(!substs.has_erasable_regions()); - assert!(!substs.needs_subst()); - substs.visit_with(&mut hasher); + assert!(!substs.has_erasable_regions()); + assert!(!substs.needs_subst()); + substs.visit_with(&mut hasher); - // If this is an instance of a generic function, we also hash in - // the ID of the instantiating crate. This avoids symbol conflicts - // in case the same instances is emitted in two crates of the same - // project. - if substs.types().next().is_some() { - hasher.hash(tcx.crate_name.as_str()); - hasher.hash(tcx.sess.local_crate_disambiguator().as_str()); + let mut avoid_cross_crate_conflicts = false; + + // If this is an instance of a generic function, we also hash in + // the ID of the instantiating crate. This avoids symbol conflicts + // in case the same instances is emitted in two crates of the same + // project. + if substs.types().next().is_some() { + avoid_cross_crate_conflicts = true; + } + + // If we're dealing with an instance of a function that's inlined from + // another crate but we're marking it as globally shared to our + // compliation (aka we're not making an internal copy in each of our + // codegen units) then this symbol may become an exported (but hidden + // visibility) symbol. This means that multiple crates may do the same + // and we want to be sure to avoid any symbol conflicts here. + match TransItem::Fn(instance).instantiation_mode(tcx) { + InstantiationMode::GloballyShared { may_conflict: true } => { + avoid_cross_crate_conflicts = true; } + _ => {} + } + + if avoid_cross_crate_conflicts { + hasher.hash(tcx.crate_name.as_str()); + hasher.hash(tcx.sess.local_crate_disambiguator().as_str()); } }); @@ -309,7 +331,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance // and should not matter anyhow. let instance_ty = tcx.erase_regions(&instance_ty); - let hash = get_symbol_hash(tcx, Some(def_id), instance_ty, Some(substs)); + let hash = get_symbol_hash(tcx, def_id, instance, instance_ty, substs); SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)).finish(hash) } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 73df1b45c59..9d1e36fa581 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -401,9 +401,9 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn record_accesses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - caller: TransItem<'tcx>, - callees: &[TransItem<'tcx>], - inlining_map: &mut InliningMap<'tcx>) { + caller: TransItem<'tcx>, + callees: &[TransItem<'tcx>], + inlining_map: &mut InliningMap<'tcx>) { let is_inlining_candidate = |trans_item: &TransItem<'tcx>| { trans_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy }; diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 82ec1aaa413..e4bfd994868 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -279,75 +279,74 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut internalization_candidates = FxHashSet(); for trans_item in trans_items { - let is_root = trans_item.instantiation_mode(tcx) == InstantiationMode::GloballyShared; + match trans_item.instantiation_mode(tcx) { + InstantiationMode::GloballyShared { .. } => {} + InstantiationMode::LocalCopy => continue, + } - if is_root { - let characteristic_def_id = characteristic_def_id_of_trans_item(tcx, trans_item); - let is_volatile = is_incremental_build && - trans_item.is_generic_fn(); + let characteristic_def_id = characteristic_def_id_of_trans_item(tcx, trans_item); + let is_volatile = is_incremental_build && + trans_item.is_generic_fn(); - let codegen_unit_name = match characteristic_def_id { - Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile), - None => Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str(), - }; + let codegen_unit_name = match characteristic_def_id { + Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile), + None => Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str(), + }; - let make_codegen_unit = || { - CodegenUnit::new(codegen_unit_name.clone()) - }; + let make_codegen_unit = || { + CodegenUnit::new(codegen_unit_name.clone()) + }; - let codegen_unit = codegen_units.entry(codegen_unit_name.clone()) - .or_insert_with(make_codegen_unit); + let codegen_unit = codegen_units.entry(codegen_unit_name.clone()) + .or_insert_with(make_codegen_unit); - let (linkage, visibility) = match trans_item.explicit_linkage(tcx) { - Some(explicit_linkage) => (explicit_linkage, Visibility::Default), - None => { - match trans_item { - TransItem::Fn(ref instance) => { - let visibility = match instance.def { - InstanceDef::Item(def_id) => { - if def_id.is_local() { - if tcx.is_exported_symbol(def_id) { - Visibility::Default - } else { - internalization_candidates.insert(trans_item); - Visibility::Hidden - } + let (linkage, visibility) = match trans_item.explicit_linkage(tcx) { + Some(explicit_linkage) => (explicit_linkage, Visibility::Default), + None => { + match trans_item { + TransItem::Fn(ref instance) => { + let visibility = match instance.def { + InstanceDef::Item(def_id) => { + if def_id.is_local() { + if tcx.is_exported_symbol(def_id) { + Visibility::Default } else { - internalization_candidates.insert(trans_item); Visibility::Hidden } + } else { + Visibility::Hidden } - InstanceDef::FnPtrShim(..) | - InstanceDef::Virtual(..) | - InstanceDef::Intrinsic(..) | - InstanceDef::ClosureOnceShim { .. } | - InstanceDef::DropGlue(..) | - InstanceDef::CloneShim(..) => { - bug!("partitioning: Encountered unexpected - root translation item: {:?}", - trans_item) - } - }; - (Linkage::External, visibility) - } - TransItem::Static(node_id) | - TransItem::GlobalAsm(node_id) => { - let def_id = tcx.hir.local_def_id(node_id); - let visibility = if tcx.is_exported_symbol(def_id) { - Visibility::Default - } else { - internalization_candidates.insert(trans_item); + } + InstanceDef::FnPtrShim(..) | + InstanceDef::Virtual(..) | + InstanceDef::Intrinsic(..) | + InstanceDef::ClosureOnceShim { .. } | + InstanceDef::DropGlue(..) | + InstanceDef::CloneShim(..) => { Visibility::Hidden - }; - (Linkage::External, visibility) - } + } + }; + (Linkage::External, visibility) + } + TransItem::Static(node_id) | + TransItem::GlobalAsm(node_id) => { + let def_id = tcx.hir.local_def_id(node_id); + let visibility = if tcx.is_exported_symbol(def_id) { + Visibility::Default + } else { + Visibility::Hidden + }; + (Linkage::External, visibility) } } - }; - - codegen_unit.items_mut().insert(trans_item, (linkage, visibility)); - roots.insert(trans_item); + } + }; + if visibility == Visibility::Hidden { + internalization_candidates.insert(trans_item); } + + codegen_unit.items_mut().insert(trans_item, (linkage, visibility)); + roots.insert(trans_item); } // always ensure we have at least one CGU; otherwise, if we have a diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 526b61303e1..e40b1617d0a 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -26,6 +26,7 @@ use monomorphize::Instance; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::trans::{Linkage, Visibility}; +use rustc::session::config::OptLevel; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; @@ -44,7 +45,20 @@ pub use rustc::middle::trans::TransItem; pub enum InstantiationMode { /// There will be exactly one instance of the given TransItem. It will have /// external linkage so that it can be linked to from other codegen units. - GloballyShared, + GloballyShared { + /// In some compilation scenarios we may decide to take functions that + /// are typically `LocalCopy` and instead move them to `GloballyShared` + /// to avoid translating them a bunch of times. In this situation, + /// however, our local copy may conflict with other crates also + /// inlining the same function. + /// + /// This flag indicates that this situation is occuring, and informs + /// symbol name calculation that some extra mangling is needed to + /// avoid conflicts. Note that this may eventually go away entirely if + /// ThinLTO enables us to *always* have a globally shared instance of a + /// function within one crate's compilation. + may_conflict: bool, + }, /// Each codegen unit containing a reference to the given TransItem will /// have its own private copy of the function (with internal linkage). @@ -154,18 +168,31 @@ pub trait TransItemExt<'a, 'tcx>: fmt::Debug { fn instantiation_mode(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> InstantiationMode { + let inline_in_all_cgus = + tcx.sess.opts.debugging_opts.inline_in_all_cgus.unwrap_or_else(|| { + tcx.sess.opts.optimize != OptLevel::No + }); + match *self.as_trans_item() { TransItem::Fn(ref instance) => { if self.explicit_linkage(tcx).is_none() && common::requests_inline(tcx, instance) { - InstantiationMode::LocalCopy + if inline_in_all_cgus { + InstantiationMode::LocalCopy + } else { + InstantiationMode::GloballyShared { may_conflict: true } + } } else { - InstantiationMode::GloballyShared + InstantiationMode::GloballyShared { may_conflict: false } } } - TransItem::Static(..) => InstantiationMode::GloballyShared, - TransItem::GlobalAsm(..) => InstantiationMode::GloballyShared, + TransItem::Static(..) => { + InstantiationMode::GloballyShared { may_conflict: false } + } + TransItem::GlobalAsm(..) => { + InstantiationMode::GloballyShared { may_conflict: false } + } } } diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs index bd1325e7501..b8033b88fb7 100644 --- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-trans-items=eager +// compile-flags:-Zinline-in-all-cgus //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0] @@ drop_in_place_intrinsic0[Internal] struct StructWithDtor(u32); diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs index 108a8b570de..65936d12e31 100644 --- a/src/test/codegen-units/item-collection/generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-trans-items=eager +// compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index 875cacb3907..e32366d15c3 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-trans-items=eager +// compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs index a6081b2c5eb..5765f230e8b 100644 --- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-trans-items=eager +// compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs index 8eef5f00f2a..be560690e51 100644 --- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs +++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-trans-items=eager +// compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs index 7edb1c14525..ad1475a73f7 100644 --- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs +++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-trans-items=eager +// compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs index cf0c6643238..d7e457cde8a 100644 --- a/src/test/codegen-units/item-collection/unsizing.rs +++ b/src/test/codegen-units/item-collection/unsizing.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength // compile-flags:-Zprint-trans-items=eager +// compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] #![feature(coerce_unsized)] diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs index 4e6ae167024..29528644ed0 100644 --- a/src/test/codegen-units/partitioning/extern-drop-glue.rs +++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs @@ -13,6 +13,7 @@ // We specify -Z incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/extern-drop-glue +// compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs index 20920c9ebe4..4bfd35b59bc 100644 --- a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs +++ b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs @@ -12,6 +12,7 @@ // We specify -Z incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/inlining-from-extern-crate +// compile-flags:-Zinline-in-all-cgus #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs index d2ce847e108..65e91343ccf 100644 --- a/src/test/codegen-units/partitioning/local-drop-glue.rs +++ b/src/test/codegen-units/partitioning/local-drop-glue.rs @@ -12,6 +12,7 @@ // We specify -Z incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/local-drop-glue +// compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs new file mode 100644 index 00000000000..ccc8f03a40f --- /dev/null +++ b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs @@ -0,0 +1,54 @@ +// 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. + +// ignore-tidy-linelength +// We specify -Z incremental here because we want to test the partitioning for +// incremental compilation +// compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/local-inlining-but-not-all +// compile-flags:-Zinline-in-all-cgus=no + +#![allow(dead_code)] +#![crate_type="lib"] + +mod inline { + + //~ TRANS_ITEM fn local_inlining_but_not_all::inline[0]::inlined_function[0] @@ local_inlining_but_not_all-inline[External] + #[inline(always)] + pub fn inlined_function() + { + + } +} + +mod user1 { + use super::inline; + + //~ TRANS_ITEM fn local_inlining_but_not_all::user1[0]::foo[0] @@ local_inlining_but_not_all-user1[Internal] + fn foo() { + inline::inlined_function(); + } +} + +mod user2 { + use super::inline; + + //~ TRANS_ITEM fn local_inlining_but_not_all::user2[0]::bar[0] @@ local_inlining_but_not_all-user2[Internal] + fn bar() { + inline::inlined_function(); + } +} + +mod non_user { + + //~ TRANS_ITEM fn local_inlining_but_not_all::non_user[0]::baz[0] @@ local_inlining_but_not_all-non_user[Internal] + fn baz() { + + } +} diff --git a/src/test/codegen-units/partitioning/local-inlining.rs b/src/test/codegen-units/partitioning/local-inlining.rs index a4d9e60d228..f3176191241 100644 --- a/src/test/codegen-units/partitioning/local-inlining.rs +++ b/src/test/codegen-units/partitioning/local-inlining.rs @@ -12,6 +12,7 @@ // We specify -Z incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/local-inlining +// compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/local-transitive-inlining.rs b/src/test/codegen-units/partitioning/local-transitive-inlining.rs index 1beaa186d9e..bda76a8789f 100644 --- a/src/test/codegen-units/partitioning/local-transitive-inlining.rs +++ b/src/test/codegen-units/partitioning/local-transitive-inlining.rs @@ -12,6 +12,7 @@ // We specify -Z incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/local-transitive-inlining +// compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs index 74f2f843567..302f9312b57 100644 --- a/src/test/codegen-units/partitioning/vtable-through-const.rs +++ b/src/test/codegen-units/partitioning/vtable-through-const.rs @@ -13,6 +13,7 @@ // We specify -Z incremental here because we want to test the partitioning for // incremental compilation // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/vtable-through-const +// compile-flags:-Zinline-in-all-cgus // This test case makes sure, that references made through constants are // recorded properly in the InliningMap. diff --git a/src/test/run-make/sepcomp-cci-copies/Makefile b/src/test/run-make/sepcomp-cci-copies/Makefile index 8324a074d6c..ccd4e1b0e71 100644 --- a/src/test/run-make/sepcomp-cci-copies/Makefile +++ b/src/test/run-make/sepcomp-cci-copies/Makefile @@ -5,5 +5,6 @@ all: $(RUSTC) cci_lib.rs - $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 + $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 \ + -Z inline-in-all-cgus [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ .*cci_fn)" -eq "2" ] diff --git a/src/test/run-make/sepcomp-inlining/Makefile b/src/test/run-make/sepcomp-inlining/Makefile index 6dc837b8a78..1d20d940000 100644 --- a/src/test/run-make/sepcomp-inlining/Makefile +++ b/src/test/run-make/sepcomp-inlining/Makefile @@ -7,7 +7,8 @@ # in only one compilation unit. all: - $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 + $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 \ + -Z inline-in-all-cgus [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ i32\ .*inlined)" -eq "0" ] [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "2" ] [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ hidden\ i32\ .*normal)" -eq "1" ] From 6f4e942ef96f92e61f40c0d1bd889e66b0de3cfd Mon Sep 17 00:00:00 2001 From: Michael Hewson Date: Sat, 7 Oct 2017 23:51:43 -0400 Subject: [PATCH 093/365] update comments referring to old check_method_self_type - function has been renamed to check_method_receiver --- src/librustc_typeck/astconv.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index af8cc2c806a..6b7a5b3af96 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1464,7 +1464,7 @@ impl<'tcx> ExplicitSelf<'tcx> { /// declaration like `self: SomeType` into either `self`, /// `&self`, `&mut self`, or `Box`. We do this here /// by some simple pattern matching. A more precise check - /// is done later in `check_method_self_type()`. + /// is done later in `check_method_receiver()`. /// /// Examples: /// @@ -1475,7 +1475,7 @@ impl<'tcx> ExplicitSelf<'tcx> { /// fn method2(self: &T); // ExplicitSelf::ByValue /// fn method3(self: Box<&T>); // ExplicitSelf::ByBox /// - /// // Invalid cases will be caught later by `check_method_self_type`: + /// // Invalid cases will be caught later by `check_method_receiver`: /// fn method_err1(self: &mut T); // ExplicitSelf::ByReference /// } /// ``` From f108fce21cd025ead58ced8c21a8156fe339e26f Mon Sep 17 00:00:00 2001 From: Chris Wong Date: Sun, 8 Oct 2017 21:42:33 +1300 Subject: [PATCH 094/365] Make the result of `Literal::string()` more readable Closes #45076 --- src/libproc_macro/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index e6307f10c13..cf30966fa89 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -488,7 +488,7 @@ impl Literal { pub fn string(string: &str) -> Literal { let mut escaped = String::new(); for ch in string.chars() { - escaped.extend(ch.escape_unicode()); + escaped.extend(ch.escape_debug()); } Literal(token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None)) } From 9b0480bec63fb1d096fd9017604a861f80ea7df1 Mon Sep 17 00:00:00 2001 From: Wonwoo Choi Date: Tue, 26 Sep 2017 00:36:08 +0900 Subject: [PATCH 095/365] Name higher-ranked lifetimes properly while displaying Now they don't shadow other lifetimes. --- src/librustc/ty/context.rs | 6 + src/librustc/util/ppaux.rs | 90 ++++++++++---- .../ui/anonymous-higher-ranked-lifetime.rs | 40 +++++++ .../anonymous-higher-ranked-lifetime.stderr | 112 ++++++++++++++++++ .../regions-fn-subtyping-return-static.stderr | 2 +- 5 files changed, 229 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/anonymous-higher-ranked-lifetime.rs create mode 100644 src/test/ui/anonymous-higher-ranked-lifetime.stderr diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 740299b91f1..a7eacc3744d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -915,6 +915,10 @@ pub struct GlobalCtxt<'tcx> { /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime. pub rvalue_promotable_to_static: RefCell>, + pub display_used_late_bound_region_names: RefCell>>, + + pub display_late_bound_region_index: Cell, + /// The definite name of the current crate after taking into account /// attributes, commandline parameters, etc. pub crate_name: Symbol, @@ -1189,6 +1193,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), rvalue_promotable_to_static: RefCell::new(NodeMap()), + display_used_late_bound_region_names: RefCell::new(None), + display_late_bound_region_index: Cell::new(0), crate_name: Symbol::intern(crate_name), data_layout, layout_interner: RefCell::new(FxHashSet()), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 214973e3085..a6fb7a0f25c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -20,6 +20,7 @@ use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; use ty::{TyClosure, TyGenerator, TyProjection, TyAnon}; use ty::{TyDynamic, TyInt, TyUint, TyInfer}; use ty::{self, Ty, TyCtxt, TypeFoldable}; +use util::nodemap::FxHashSet; use std::cell::Cell; use std::fmt; @@ -259,12 +260,34 @@ pub fn parameterized(f: &mut fmt::Formatter, Ok(()) } +struct LateBoundRegionNameCollector(FxHashSet); + +impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + match *r { + ty::ReLateBound(_, ty::BrNamed(_, name)) => { + self.0.insert(name); + }, + _ => {}, + } + r.super_visit_with(self) + } +} + fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, tcx: TyCtxt<'a, 'gcx, 'tcx>, original: &ty::Binder, lifted: Option>) -> fmt::Result where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx> { + fn name_by_region_index(index: usize) -> Symbol { + match index { + 0 => Symbol::intern("'r"), + 1 => Symbol::intern("'s"), + i => Symbol::intern(&format!("'t{}", i-2)), + } + } + // Replace any anonymous late-bound regions with named // variants, using gensym'd identifiers, so that we can // clearly differentiate between named and unnamed regions in @@ -286,27 +309,54 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, } }; - let new_value = tcx.replace_late_bound_regions(&value, |br| { - let _ = start_or_continue(f, "for<", ", "); - let br = match br { - ty::BrNamed(_, name) => { - let _ = write!(f, "{}", name); - br - } - ty::BrAnon(_) | - ty::BrFresh(_) | - ty::BrEnv => { - let name = Symbol::intern("'r"); - let _ = write!(f, "{}", name); - ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID), - name) - } - }; - tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br)) - }).0; + // If displaying is just started, collect named late-bound regions. + let display_just_started = tcx.display_used_late_bound_region_names.borrow().is_none(); + if display_just_started { + let mut collector = LateBoundRegionNameCollector(FxHashSet()); + value.visit_with(&mut collector); + *tcx.display_used_late_bound_region_names.borrow_mut() = Some(collector.0); + } + let old_region_index = tcx.display_late_bound_region_index.get(); + let mut region_index = old_region_index; + let new_value = { + let used_region_names = tcx.display_used_late_bound_region_names.borrow(); + let used_region_names = used_region_names.as_ref().unwrap(); + tcx.replace_late_bound_regions(&value, |br| { + let _ = start_or_continue(f, "for<", ", "); + let br = match br { + ty::BrNamed(_, name) => { + let _ = write!(f, "{}", name); + br + } + ty::BrAnon(_) | + ty::BrFresh(_) | + ty::BrEnv => { + let name = loop { + let name = name_by_region_index(region_index); + region_index += 1; + if !used_region_names.contains(&name) { + break name; + } + }; + let _ = write!(f, "{}", name); + ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID), + name) + } + }; + tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br)) + }).0 + }; start_or_continue(f, "", "> ")?; - write!(f, "{}", new_value) + + // Push current state to gcx, and restore after writing new_value. + tcx.display_late_bound_region_index.set(region_index); + write!(f, "{}", new_value)?; + tcx.display_late_bound_region_index.set(old_region_index); + if display_just_started { + *tcx.display_used_late_bound_region_names.borrow_mut() = None; + } + Ok(()) } impl<'tcx> fmt::Display for &'tcx ty::Slice> { @@ -782,7 +832,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { write!(f, "}}") } TyFnPtr(ref bare_fn) => { - write!(f, "{}", bare_fn.0) + write!(f, "{}", bare_fn) } TyInfer(infer_ty) => write!(f, "{}", infer_ty), TyError => write!(f, "[type error]"), diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.rs b/src/test/ui/anonymous-higher-ranked-lifetime.rs new file mode 100644 index 00000000000..f2d04c16d99 --- /dev/null +++ b/src/test/ui/anonymous-higher-ranked-lifetime.rs @@ -0,0 +1,40 @@ +// Copyright 2015 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. + +fn main() { + f1(|_: (), _: ()| {}); + f2(|_: (), _: ()| {}); + f3(|_: (), _: ()| {}); + f4(|_: (), _: ()| {}); + f5(|_: (), _: ()| {}); + g1(|_: (), _: ()| {}); + g2(|_: (), _: ()| {}); + g3(|_: (), _: ()| {}); + g4(|_: (), _: ()| {}); + h1(|_: (), _: (), _: (), _: ()| {}); + h2(|_: (), _: (), _: (), _: ()| {}); +} + +// Basic +fn f1(_: F) where F: Fn(&(), &()) {} +fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} +fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} +fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} +fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} + +// Nested +fn g1(_: F) where F: Fn(&(), Box) {} +fn g2(_: F) where F: Fn(&(), fn(&())) {} +fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} +fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} + +// Mixed +fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} +fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr new file mode 100644 index 00000000000..f962b772203 --- /dev/null +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -0,0 +1,112 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + | +12 | f1(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _` + | + = note: required by `f1` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:13:5 + | +13 | f2(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _` + | + = note: required by `f2` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 + | +14 | f3(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'r> fn(&(), &'r ()) -> _` + | + = note: required by `f3` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:15:5 + | +15 | f4(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _` + | + = note: required by `f4` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 + | +16 | f5(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'r> fn(&'r (), &'r ()) -> _` + | + = note: required by `f5` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:17:5 + | +17 | g1(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'r> fn(&'r (), std::boxed::Box std::ops::Fn(&'s ()) + 'static>) -> _` + | + = note: required by `g1` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 + | +18 | g2(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _` + | + = note: required by `g2` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:19:5 + | +19 | g3(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'s> fn(&'s (), std::boxed::Box std::ops::Fn(&'r ()) + 'static>) -> _` + | + = note: required by `g3` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 + | +20 | g4(|_: (), _: ()| {}); + | ^^ ----------------- found signature of `fn((), ()) -> _` + | | + | expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _` + | + = note: required by `g4` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:21:5 + | +21 | h1(|_: (), _: (), _: (), _: ()| {}); + | ^^ ------------------------------- found signature of `fn((), (), (), ()) -> _` + | | + | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box std::ops::Fn(&'t0 ()) + 'static>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _` + | + = note: required by `h1` + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 + | +22 | h2(|_: (), _: (), _: (), _: ()| {}); + | ^^ ------------------------------- found signature of `fn((), (), (), ()) -> _` + | | + | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box std::ops::Fn(&'s ()) + 'static>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _` + | + = note: required by `h2` + +error: aborting due to 11 previous errors + diff --git a/src/test/ui/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions-fn-subtyping-return-static.stderr index 1598a8a40d2..0c88c63edeb 100644 --- a/src/test/ui/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types 51 | want_F(bar); //~ ERROR E0308 | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx | - = note: expected type `fn(&'cx S) -> &'cx S` + = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` found type `fn(&'a S) -> &S {bar::<'_>}` error: aborting due to previous error From cbc6e902889bec9ee96e8e8520ed65aa342d418f Mon Sep 17 00:00:00 2001 From: Wonwoo Choi Date: Mon, 2 Oct 2017 02:12:08 +0900 Subject: [PATCH 096/365] Introduce `Print` trait for displaying types --- src/librustc/ty/context.rs | 6 - src/librustc/util/ppaux.rs | 1949 ++++++++++++++++++++---------------- 2 files changed, 1060 insertions(+), 895 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a7eacc3744d..740299b91f1 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -915,10 +915,6 @@ pub struct GlobalCtxt<'tcx> { /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime. pub rvalue_promotable_to_static: RefCell>, - pub display_used_late_bound_region_names: RefCell>>, - - pub display_late_bound_region_index: Cell, - /// The definite name of the current crate after taking into account /// attributes, commandline parameters, etc. pub crate_name: Symbol, @@ -1193,8 +1189,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), rvalue_promotable_to_static: RefCell::new(NodeMap()), - display_used_late_bound_region_names: RefCell::new(None), - display_late_bound_region_index: Cell::new(0), crate_name: Symbol::intern(crate_name), data_layout, layout_interner: RefCell::new(FxHashSet()), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a6fb7a0f25c..0eb2c19fe44 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -33,235 +33,104 @@ use syntax::ast::CRATE_NODE_ID; use syntax::symbol::Symbol; use hir; -pub fn verbose() -> bool { - ty::tls::with(|tcx| tcx.sess.verbose()) -} - -pub fn identify_regions() -> bool { - ty::tls::with(|tcx| tcx.sess.opts.debugging_opts.identify_regions) -} - -fn fn_sig(f: &mut fmt::Formatter, - inputs: &[Ty], - variadic: bool, - output: Ty) - -> fmt::Result { - write!(f, "(")?; - let mut inputs = inputs.iter(); - if let Some(&ty) = inputs.next() { - write!(f, "{}", ty)?; - for &ty in inputs { - write!(f, ", {}", ty)?; - } - if variadic { - write!(f, ", ...")?; - } - } - write!(f, ")")?; - if !output.is_nil() { - write!(f, " -> {}", output)?; - } - - Ok(()) -} - -pub fn parameterized(f: &mut fmt::Formatter, - substs: &subst::Substs, - mut did: DefId, - projections: &[ty::ProjectionPredicate]) - -> fmt::Result { - let key = ty::tls::with(|tcx| tcx.def_key(did)); - let mut item_name = if let Some(name) = key.disambiguated_data.data.get_opt_name() { - Some(name) - } else { - did.index = key.parent.unwrap_or_else( - || bug!("finding type for {:?}, encountered def-id {:?} with no parent", - did, did)); - parameterized(f, substs, did, projections)?; - return write!(f, "::{}", key.disambiguated_data.data.as_interned_str()); - }; - - let mut verbose = false; - let mut num_supplied_defaults = 0; - let mut has_self = false; - let mut num_regions = 0; - let mut num_types = 0; - let mut is_value_path = false; - let fn_trait_kind = ty::tls::with(|tcx| { - // Unfortunately, some kinds of items (e.g., closures) don't have - // generics. So walk back up the find the closest parent that DOES - // have them. - let mut item_def_id = did; - loop { - let key = tcx.def_key(item_def_id); - match key.disambiguated_data.data { - DefPathData::TypeNs(_) => { - break; - } - DefPathData::ValueNs(_) | DefPathData::EnumVariant(_) => { - is_value_path = true; - break; - } - _ => { - // if we're making a symbol for something, there ought - // to be a value or type-def or something in there - // *somewhere* - item_def_id.index = key.parent.unwrap_or_else(|| { - bug!("finding type for {:?}, encountered def-id {:?} with no \ - parent", did, item_def_id); - }); - } - } - } - let mut generics = tcx.generics_of(item_def_id); - let mut path_def_id = did; - verbose = tcx.sess.verbose(); - has_self = generics.has_self; - - let mut child_types = 0; - if let Some(def_id) = generics.parent { - // Methods. - assert!(is_value_path); - child_types = generics.types.len(); - generics = tcx.generics_of(def_id); - num_regions = generics.regions.len(); - num_types = generics.types.len(); - - if has_self { - write!(f, "<{} as ", substs.type_at(0))?; - } - - path_def_id = def_id; - } else { - item_name = None; - - if is_value_path { - // Functions. - assert_eq!(has_self, false); - } else { - // Types and traits. - num_regions = generics.regions.len(); - num_types = generics.types.len(); - } - } - - if !verbose { - if generics.types.last().map_or(false, |def| def.has_default) { - if let Some(substs) = tcx.lift(&substs) { - let tps = substs.types().rev().skip(child_types); - for (def, actual) in generics.types.iter().rev().zip(tps) { - if !def.has_default { - break; - } - if tcx.type_of(def.def_id).subst(tcx, substs) != actual { - break; - } - num_supplied_defaults += 1; - } - } - } - } - - write!(f, "{}", tcx.item_path_str(path_def_id))?; - Ok(tcx.lang_items().fn_trait_kind(path_def_id)) - })?; - - if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { - let projection_ty = projections[0].ty; - if let TyTuple(ref args, _) = substs.type_at(1).sty { - return fn_sig(f, args, false, projection_ty); - } - } - - let empty = Cell::new(true); - let start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| { - if empty.get() { - empty.set(false); - write!(f, "{}", start) - } else { - write!(f, "{}", cont) +macro_rules! gen_display_debug_body { + ( $with:path ) => { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut cx = PrintContext::new(); + $with(self, f, &mut cx) } }; - - let print_regions = |f: &mut fmt::Formatter, start: &str, skip, count| { - // Don't print any regions if they're all erased. - let regions = || substs.regions().skip(skip).take(count); - if regions().all(|r: ty::Region| *r == ty::ReErased) { - return Ok(()); +} +macro_rules! gen_display_debug { + ( ($($x:tt)+) $target:ty, display yes ) => { + impl<$($x)+> fmt::Display for $target { + gen_display_debug_body! { Print::print_display } } - - for region in regions() { - let region: ty::Region = region; - start_or_continue(f, start, ", ")?; - if verbose { - write!(f, "{:?}", region)?; - } else { - let s = region.to_string(); - if s.is_empty() { - // This happens when the value of the region - // parameter is not easily serialized. This may be - // because the user omitted it in the first place, - // or because it refers to some block in the code, - // etc. I'm not sure how best to serialize this. - write!(f, "'_")?; - } else { - write!(f, "{}", s)?; - } + }; + ( () $target:ty, display yes ) => { + impl fmt::Display for $target { + gen_display_debug_body! { Print::print_display } + } + }; + ( ($($x:tt)+) $target:ty, debug yes ) => { + impl<$($x)+> fmt::Debug for $target { + gen_display_debug_body! { Print::print_debug } + } + }; + ( () $target:ty, debug yes ) => { + impl fmt::Debug for $target { + gen_display_debug_body! { Print::print_debug } + } + }; + ( $generic:tt $target:ty, $t:ident no ) => {}; +} +macro_rules! gen_print_impl { + ( ($($x:tt)+) $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { + impl<$($x)+> Print for $target { + fn print(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result { + if $cx.is_debug $dbg + else $disp } } - - Ok(()) }; - - print_regions(f, "<", 0, num_regions)?; - - let tps = substs.types().take(num_types - num_supplied_defaults) - .skip(has_self as usize); - - for ty in tps { - start_or_continue(f, "<", ", ")?; - write!(f, "{}", ty)?; - } - - for projection in projections { - start_or_continue(f, "<", ", ")?; - ty::tls::with(|tcx| - write!(f, "{}={}", - tcx.associated_item(projection.projection_ty.item_def_id).name, - projection.ty) - )?; - } - - start_or_continue(f, "", ">")?; - - // For values, also print their name and type parameters. - if is_value_path { - empty.set(true); - - if has_self { - write!(f, ">")?; + ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { + impl Print for $target { + fn print(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result { + if $cx.is_debug $dbg + else $disp + } } - - if let Some(item_name) = item_name { - write!(f, "::{}", item_name)?; - } - - print_regions(f, "::<", num_regions, usize::MAX)?; - - // FIXME: consider being smart with defaults here too - for ty in substs.types().skip(num_types) { - start_or_continue(f, "::<", ", ")?; - write!(f, "{}", ty)?; - } - - start_or_continue(f, "", ">")?; + }; + ( $generic:tt $target:ty, + $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => { + gen_print_impl! { $generic $target, $vars $disp $dbg } + gen_display_debug! { $generic $target, display $gendisp } + gen_display_debug! { $generic $target, debug $gendbg } } - - Ok(()) } +macro_rules! define_print { + ( $generic:tt $target:ty, + $vars:tt { display $disp:block debug $dbg:block } ) => { + gen_print_impl! { $generic $target, $vars yes $disp yes $dbg } + }; + ( $generic:tt $target:ty, + $vars:tt { debug $dbg:block display $disp:block } ) => { + gen_print_impl! { $generic $target, $vars yes $disp yes $dbg } + }; + ( $generic:tt $target:ty, + $vars:tt { debug $dbg:block } ) => { + gen_print_impl! { $generic $target, $vars no { + bug!(concat!("display not implemented for ", stringify!($target))); + } yes $dbg } + }; + ( $generic:tt $target:ty, + ($self:ident, $f:ident, $cx:ident) { display $disp:block } ) => { + gen_print_impl! { $generic $target, ($self, $f, $cx) yes $disp no { + write!($f, "{:?}", $self) + } } + }; +} +macro_rules! define_print_multi { + ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => { + $(define_print! { $generic $target, $vars $def })* + }; +} +macro_rules! print_inner { + ( $f:expr, $cx:expr, write ($($data:expr),+) ) => { + write!($f, $($data),+) + }; + ( $f:expr, $cx:expr, $kind:ident ($data:expr) ) => { + $data.$kind($f, $cx) + }; +} +macro_rules! print { + ( $f:expr, $cx:expr $(, $kind:ident $data:tt)+ ) => { + Ok(())$(.and_then(|_| print_inner!($f, $cx, $kind $data)))+ + }; +} + struct LateBoundRegionNameCollector(FxHashSet); - impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { match *r { @@ -274,55 +143,339 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { } } -fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - original: &ty::Binder, - lifted: Option>) -> fmt::Result - where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx> -{ - fn name_by_region_index(index: usize) -> Symbol { - match index { - 0 => Symbol::intern("'r"), - 1 => Symbol::intern("'s"), - i => Symbol::intern(&format!("'t{}", i-2)), - } +#[derive(Debug)] +pub struct PrintContext { + is_debug: bool, + is_verbose: bool, + identify_regions: bool, + used_region_names: Option>, + region_index: usize, + binder_depth: usize, +} +impl PrintContext { + fn new() -> Self { + ty::tls::with_opt(|tcx| { + let (is_verbose, identify_regions) = tcx.map( + |tcx| (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions) + ).unwrap_or((false, false)); + PrintContext { + is_debug: false, + is_verbose: is_verbose, + identify_regions: identify_regions, + used_region_names: None, + region_index: 0, + binder_depth: 0, + } + }) } - - // Replace any anonymous late-bound regions with named - // variants, using gensym'd identifiers, so that we can - // clearly differentiate between named and unnamed regions in - // the output. We'll probably want to tweak this over time to - // decide just how much information to give. - let value = if let Some(v) = lifted { - v - } else { - return write!(f, "{}", original.0); - }; - - let mut empty = true; - let mut start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| { - if empty { - empty = false; - write!(f, "{}", start) - } else { - write!(f, "{}", cont) - } - }; - - // If displaying is just started, collect named late-bound regions. - let display_just_started = tcx.display_used_late_bound_region_names.borrow().is_none(); - if display_just_started { + fn prepare_late_bound_region_info<'tcx, T>(&mut self, value: &ty::Binder) + where T: TypeFoldable<'tcx> + { let mut collector = LateBoundRegionNameCollector(FxHashSet()); value.visit_with(&mut collector); - *tcx.display_used_late_bound_region_names.borrow_mut() = Some(collector.0); + self.used_region_names = Some(collector.0); + self.region_index = 0; + } +} + +pub trait Print { + fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result; + fn print_to_string(&self, cx: &mut PrintContext) -> String { + let mut result = String::new(); + let _ = self.print(&mut result, cx); + result + } + fn print_display(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { + let old_debug = cx.is_debug; + cx.is_debug = false; + let result = self.print(f, cx); + cx.is_debug = old_debug; + result + } + fn print_display_to_string(&self, cx: &mut PrintContext) -> String { + let mut result = String::new(); + let _ = self.print_display(&mut result, cx); + result + } + fn print_debug(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { + let old_debug = cx.is_debug; + cx.is_debug = true; + let result = self.print(f, cx); + cx.is_debug = old_debug; + result + } + fn print_debug_to_string(&self, cx: &mut PrintContext) -> String { + let mut result = String::new(); + let _ = self.print_debug(&mut result, cx); + result + } +} + +impl PrintContext { + fn fn_sig(&mut self, + f: &mut F, + inputs: &[Ty], + variadic: bool, + output: Ty) + -> fmt::Result { + write!(f, "(")?; + let mut inputs = inputs.iter(); + if let Some(&ty) = inputs.next() { + print!(f, self, print_display(ty))?; + for &ty in inputs { + print!(f, self, write(", "), print_display(ty))?; + } + if variadic { + write!(f, ", ...")?; + } + } + write!(f, ")")?; + if !output.is_nil() { + print!(f, self, write(" -> "), print_display(output))?; + } + + Ok(()) } - let old_region_index = tcx.display_late_bound_region_index.get(); - let mut region_index = old_region_index; - let new_value = { - let used_region_names = tcx.display_used_late_bound_region_names.borrow(); - let used_region_names = used_region_names.as_ref().unwrap(); - tcx.replace_late_bound_regions(&value, |br| { + fn parameterized(&mut self, + f: &mut F, + substs: &subst::Substs, + mut did: DefId, + projections: &[ty::ProjectionPredicate]) + -> fmt::Result { + let key = ty::tls::with(|tcx| tcx.def_key(did)); + let mut item_name = if let Some(name) = key.disambiguated_data.data.get_opt_name() { + Some(name) + } else { + did.index = key.parent.unwrap_or_else( + || bug!("finding type for {:?}, encountered def-id {:?} with no parent", + did, did)); + self.parameterized(f, substs, did, projections)?; + return write!(f, "::{}", key.disambiguated_data.data.as_interned_str()); + }; + + let verbose = self.is_verbose; + let mut num_supplied_defaults = 0; + let mut has_self = false; + let mut num_regions = 0; + let mut num_types = 0; + let mut is_value_path = false; + let fn_trait_kind = ty::tls::with(|tcx| { + // Unfortunately, some kinds of items (e.g., closures) don't have + // generics. So walk back up the find the closest parent that DOES + // have them. + let mut item_def_id = did; + loop { + let key = tcx.def_key(item_def_id); + match key.disambiguated_data.data { + DefPathData::TypeNs(_) => { + break; + } + DefPathData::ValueNs(_) | DefPathData::EnumVariant(_) => { + is_value_path = true; + break; + } + _ => { + // if we're making a symbol for something, there ought + // to be a value or type-def or something in there + // *somewhere* + item_def_id.index = key.parent.unwrap_or_else(|| { + bug!("finding type for {:?}, encountered def-id {:?} with no \ + parent", did, item_def_id); + }); + } + } + } + let mut generics = tcx.generics_of(item_def_id); + let mut path_def_id = did; + has_self = generics.has_self; + + let mut child_types = 0; + if let Some(def_id) = generics.parent { + // Methods. + assert!(is_value_path); + child_types = generics.types.len(); + generics = tcx.generics_of(def_id); + num_regions = generics.regions.len(); + num_types = generics.types.len(); + + if has_self { + print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?; + } + + path_def_id = def_id; + } else { + item_name = None; + + if is_value_path { + // Functions. + assert_eq!(has_self, false); + } else { + // Types and traits. + num_regions = generics.regions.len(); + num_types = generics.types.len(); + } + } + + if !verbose { + if generics.types.last().map_or(false, |def| def.has_default) { + if let Some(substs) = tcx.lift(&substs) { + let tps = substs.types().rev().skip(child_types); + for (def, actual) in generics.types.iter().rev().zip(tps) { + if !def.has_default { + break; + } + if tcx.type_of(def.def_id).subst(tcx, substs) != actual { + break; + } + num_supplied_defaults += 1; + } + } + } + } + + print!(f, self, write("{}", tcx.item_path_str(path_def_id)))?; + Ok(tcx.lang_items().fn_trait_kind(path_def_id)) + })?; + + if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { + let projection_ty = projections[0].ty; + if let TyTuple(ref args, _) = substs.type_at(1).sty { + return self.fn_sig(f, args, false, projection_ty); + } + } + + let empty = Cell::new(true); + let start_or_continue = |f: &mut F, start: &str, cont: &str| { + if empty.get() { + empty.set(false); + write!(f, "{}", start) + } else { + write!(f, "{}", cont) + } + }; + + let print_regions = |f: &mut F, start: &str, skip, count| { + // Don't print any regions if they're all erased. + let regions = || substs.regions().skip(skip).take(count); + if regions().all(|r: ty::Region| *r == ty::ReErased) { + return Ok(()); + } + + for region in regions() { + let region: ty::Region = region; + start_or_continue(f, start, ", ")?; + if verbose { + write!(f, "{:?}", region)?; + } else { + let s = region.to_string(); + if s.is_empty() { + // This happens when the value of the region + // parameter is not easily serialized. This may be + // because the user omitted it in the first place, + // or because it refers to some block in the code, + // etc. I'm not sure how best to serialize this. + write!(f, "'_")?; + } else { + write!(f, "{}", s)?; + } + } + } + + Ok(()) + }; + + print_regions(f, "<", 0, num_regions)?; + + let tps = substs.types().take(num_types - num_supplied_defaults) + .skip(has_self as usize); + + for ty in tps { + start_or_continue(f, "<", ", ")?; + ty.print_display(f, self)?; + } + + for projection in projections { + start_or_continue(f, "<", ", ")?; + ty::tls::with(|tcx| + print!(f, self, + write("{}=", + tcx.associated_item(projection.projection_ty.item_def_id).name), + print_display(projection.ty)) + )?; + } + + start_or_continue(f, "", ">")?; + + // For values, also print their name and type parameters. + if is_value_path { + empty.set(true); + + if has_self { + write!(f, ">")?; + } + + if let Some(item_name) = item_name { + write!(f, "::{}", item_name)?; + } + + print_regions(f, "::<", num_regions, usize::MAX)?; + + // FIXME: consider being smart with defaults here too + for ty in substs.types().skip(num_types) { + start_or_continue(f, "::<", ", ")?; + ty.print_display(f, self)?; + } + + start_or_continue(f, "", ">")?; + } + + Ok(()) + } + + fn in_binder<'a, 'gcx, 'tcx, T, U, F>(&mut self, + f: &mut F, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + original: &ty::Binder, + lifted: Option>) -> fmt::Result + where T: Print, U: Print + TypeFoldable<'tcx>, F: fmt::Write + { + fn name_by_region_index(index: usize) -> Symbol { + match index { + 0 => Symbol::intern("'r"), + 1 => Symbol::intern("'s"), + i => Symbol::intern(&format!("'t{}", i-2)), + } + } + + // Replace any anonymous late-bound regions with named + // variants, using gensym'd identifiers, so that we can + // clearly differentiate between named and unnamed regions in + // the output. We'll probably want to tweak this over time to + // decide just how much information to give. + let value = if let Some(v) = lifted { + v + } else { + return original.0.print_display(f, self); + }; + + if self.binder_depth == 0 { + self.prepare_late_bound_region_info(&value); + } + + let mut empty = true; + let mut start_or_continue = |f: &mut F, start: &str, cont: &str| { + if empty { + empty = false; + write!(f, "{}", start) + } else { + write!(f, "{}", cont) + } + }; + + let old_region_index = self.region_index; + let mut region_index = old_region_index; + let new_value = tcx.replace_late_bound_regions(&value, |br| { let _ = start_or_continue(f, "for<", ", "); let br = match br { ty::BrNamed(_, name) => { @@ -335,7 +488,7 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, let name = loop { let name = name_by_region_index(region_index); region_index += 1; - if !used_region_names.contains(&name) { + if !self.is_name_used(&name) { break name; } }; @@ -345,47 +498,78 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, } }; tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br)) - }).0 - }; - start_or_continue(f, "", "> ")?; + }).0; + start_or_continue(f, "", "> ")?; - // Push current state to gcx, and restore after writing new_value. - tcx.display_late_bound_region_index.set(region_index); - write!(f, "{}", new_value)?; - tcx.display_late_bound_region_index.set(old_region_index); - if display_just_started { - *tcx.display_used_late_bound_region_names.borrow_mut() = None; + // Push current state to gcx, and restore after writing new_value. + self.binder_depth += 1; + self.region_index = region_index; + let result = new_value.print_display(f, self); + self.region_index = old_region_index; + self.binder_depth -= 1; + result + } + + fn is_name_used(&self, name: &Symbol) -> bool { + match self.used_region_names { + Some(ref names) => names.contains(name), + None => false, + } } - Ok(()) } -impl<'tcx> fmt::Display for &'tcx ty::Slice> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // Generate the main trait ref, including associated types. - ty::tls::with(|tcx| { - // Use a type that can't appear in defaults of type parameters. - let dummy_self = tcx.mk_infer(ty::FreshTy(0)); +pub fn verbose() -> bool { + ty::tls::with(|tcx| tcx.sess.verbose()) +} - if let Some(p) = self.principal() { - let principal = tcx.lift(&p).expect("could not lift TraitRef for printing") - .with_self_ty(tcx, dummy_self); - let projections = self.projection_bounds().map(|p| { - tcx.lift(&p) - .expect("could not lift projection for printing") - .with_self_ty(tcx, dummy_self) - }).collect::>(); - parameterized(f, principal.substs, principal.def_id, &projections)?; - } +pub fn identify_regions() -> bool { + ty::tls::with(|tcx| tcx.sess.opts.debugging_opts.identify_regions) +} - // Builtin bounds. - for did in self.auto_traits() { - write!(f, " + {}", tcx.item_path_str(did))?; - } +pub fn parameterized(f: &mut F, + substs: &subst::Substs, + did: DefId, + projections: &[ty::ProjectionPredicate]) + -> fmt::Result { + PrintContext::new().parameterized(f, substs, did, projections) +} + + +impl<'a, T: Print> Print for &'a T { + fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { + (*self).print(f, cx) + } +} + +define_print! { + ('tcx) &'tcx ty::Slice>, (self, f, cx) { + display { + // Generate the main trait ref, including associated types. + ty::tls::with(|tcx| { + // Use a type that can't appear in defaults of type parameters. + let dummy_self = tcx.mk_infer(ty::FreshTy(0)); + + if let Some(p) = self.principal() { + let principal = tcx.lift(&p).expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self); + let projections = self.projection_bounds().map(|p| { + tcx.lift(&p) + .expect("could not lift projection for printing") + .with_self_ty(tcx, dummy_self) + }).collect::>(); + cx.parameterized(f, principal.substs, principal.def_id, &projections)?; + } + + // Builtin bounds. + for did in self.auto_traits() { + write!(f, " + {}", tcx.item_path_str(did))?; + } + + Ok(()) + })?; Ok(()) - })?; - - Ok(()) + } } } @@ -407,42 +591,6 @@ impl fmt::Debug for ty::RegionParameterDef { } } -impl<'tcx> fmt::Debug for ty::TyS<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", *self) - } -} - -impl<'tcx> fmt::Display for ty::TypeAndMut<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}{}", - if self.mutbl == hir::MutMutable { "mut " } else { "" }, - self.ty) - } -} - -impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // when printing out the debug representation, we don't need - // to enumerate the `for<...>` etc because the debruijn index - // tells you everything you need to know. - write!(f, "<{:?} as {}>", self.self_ty(), *self) - } -} - -impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| { - let dummy_self = tcx.mk_infer(ty::FreshTy(0)); - - let trait_ref = tcx.lift(&ty::Binder(*self)) - .expect("could not lift TraitRef for printing") - .with_self_ty(tcx, dummy_self).0; - parameterized(f, trait_ref.substs, trait_ref.def_id, &[]) - }) - } -} - impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ty::tls::with(|tcx| { @@ -459,100 +607,6 @@ impl fmt::Debug for ty::AdtDef { } } -impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?} -> {}", self.kind, self.target) - } -} - -impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ty::Predicate::Trait(ref a) => write!(f, "{:?}", a), - ty::Predicate::Equate(ref pair) => write!(f, "{:?}", pair), - ty::Predicate::Subtype(ref pair) => write!(f, "{:?}", pair), - ty::Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair), - ty::Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair), - ty::Predicate::Projection(ref pair) => write!(f, "{:?}", pair), - ty::Predicate::WellFormed(ty) => write!(f, "WF({:?})", ty), - ty::Predicate::ObjectSafe(trait_def_id) => { - write!(f, "ObjectSafe({:?})", trait_def_id) - } - ty::Predicate::ClosureKind(closure_def_id, kind) => { - write!(f, "ClosureKind({:?}, {:?})", closure_def_id, kind) - } - ty::Predicate::ConstEvaluatable(def_id, substs) => { - write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs) - } - } - } -} - -impl fmt::Display for ty::BoundRegion { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if verbose() { - return write!(f, "{:?}", *self); - } - - match *self { - BrNamed(_, name) => write!(f, "{}", name), - BrAnon(_) | BrFresh(_) | BrEnv => Ok(()) - } - } -} - -impl fmt::Debug for ty::BoundRegion { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - BrAnon(n) => write!(f, "BrAnon({:?})", n), - BrFresh(n) => write!(f, "BrFresh({:?})", n), - BrNamed(did, name) => { - write!(f, "BrNamed({:?}:{:?}, {:?})", - did.krate, did.index, name) - } - BrEnv => "BrEnv".fmt(f), - } - } -} - -impl fmt::Debug for ty::RegionKind { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ty::ReEarlyBound(ref data) => { - write!(f, "ReEarlyBound({}, {})", - data.index, - data.name) - } - - ty::ReLateBound(binder_id, ref bound_region) => { - write!(f, "ReLateBound({:?}, {:?})", - binder_id, - bound_region) - } - - ty::ReFree(ref fr) => write!(f, "{:?}", fr), - - ty::ReScope(id) => { - write!(f, "ReScope({:?})", id) - } - - ty::ReStatic => write!(f, "ReStatic"), - - ty::ReVar(ref vid) => { - write!(f, "{:?}", vid) - } - - ty::ReSkolemized(id, ref bound_region) => { - write!(f, "ReSkolemized({}, {:?})", id.index, bound_region) - } - - ty::ReEmpty => write!(f, "ReEmpty"), - - ty::ReErased => write!(f, "ReErased") - } - } -} - impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ClosureUpvar({:?},{:?})", @@ -561,94 +615,218 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { } } -impl fmt::Display for ty::RegionKind { +impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if verbose() { - return write!(f, "{:?}", *self); - } + write!(f, "UpvarId({:?};`{}`;{:?})", + self.var_id, + ty::tls::with(|tcx| tcx.hir.name(tcx.hir.hir_to_node_id(self.var_id))), + self.closure_expr_id) + } +} - // These printouts are concise. They do not contain all the information - // the user might want to diagnose an error, but there is basically no way - // to fit that into a short string. Hence the recommendation to use - // `explain_region()` or `note_and_explain_region()`. - match *self { - ty::ReEarlyBound(ref data) => { - write!(f, "{}", data.name) +impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UpvarBorrow({:?}, {:?})", + self.kind, self.region) + } +} + +define_print! { + ('tcx) ty::TypeAndMut<'tcx>, (self, f, cx) { + display { + print!(f, cx, + write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), + print(self.ty)) + } + } +} + +define_print! { + ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) { + debug { + ty::tls::with(|tcx| { + let dummy_self = tcx.mk_infer(ty::FreshTy(0)); + + let trait_ref = tcx.lift(&ty::Binder(*self)) + .expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self).0; + cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[]) + }) + } + } +} + +define_print! { + ('tcx) ty::adjustment::Adjustment<'tcx>, (self, f, cx) { + debug { + print!(f, cx, write("{:?} -> ", self.kind), print(self.target)) + } + } +} + +define_print! { + () ty::BoundRegion, (self, f, cx) { + display { + if cx.is_verbose { + return self.print_debug(f, cx); } - ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::ReSkolemized(_, br) => { - write!(f, "{}", br) + + match *self { + BrNamed(_, name) => write!(f, "{}", name), + BrAnon(_) | BrFresh(_) | BrEnv => Ok(()) } - ty::ReScope(scope) if identify_regions() => { - match scope.data() { - region::ScopeData::Node(id) => - write!(f, "'{}s", id.as_usize()), - region::ScopeData::CallSite(id) => - write!(f, "'{}cs", id.as_usize()), - region::ScopeData::Arguments(id) => - write!(f, "'{}as", id.as_usize()), - region::ScopeData::Destruction(id) => - write!(f, "'{}ds", id.as_usize()), - region::ScopeData::Remainder(BlockRemainder { block, first_statement_index }) => - write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()), + } + debug { + return match *self { + BrAnon(n) => write!(f, "BrAnon({:?})", n), + BrFresh(n) => write!(f, "BrFresh({:?})", n), + BrNamed(did, name) => { + write!(f, "BrNamed({:?}:{:?}, {:?})", + did.krate, did.index, name) } + BrEnv => write!(f, "BrEnv"), + }; + } + } +} + +define_print! { + () ty::RegionKind, (self, f, cx) { + display { + if cx.is_verbose { + return self.print_debug(f, cx); } - ty::ReVar(region_vid) if identify_regions() => { - write!(f, "'{}rv", region_vid.index) + + // These printouts are concise. They do not contain all the information + // the user might want to diagnose an error, but there is basically no way + // to fit that into a short string. Hence the recommendation to use + // `explain_region()` or `note_and_explain_region()`. + match *self { + ty::ReEarlyBound(ref data) => { + write!(f, "{}", data.name) + } + ty::ReLateBound(_, br) | + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::ReSkolemized(_, br) => { + write!(f, "{}", br) + } + ty::ReScope(scope) if cx.identify_regions => { + match scope.data() { + region::ScopeData::Node(id) => + write!(f, "'{}s", id.as_usize()), + region::ScopeData::CallSite(id) => + write!(f, "'{}cs", id.as_usize()), + region::ScopeData::Arguments(id) => + write!(f, "'{}as", id.as_usize()), + region::ScopeData::Destruction(id) => + write!(f, "'{}ds", id.as_usize()), + region::ScopeData::Remainder(BlockRemainder + { block, first_statement_index }) => + write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()), + } + } + ty::ReVar(region_vid) if cx.identify_regions => { + write!(f, "'{}rv", region_vid.index) + } + ty::ReScope(_) | + ty::ReVar(_) | + ty::ReErased => Ok(()), + ty::ReStatic => write!(f, "'static"), + ty::ReEmpty => write!(f, "'"), + } + } + debug { + match *self { + ty::ReEarlyBound(ref data) => { + write!(f, "ReEarlyBound({}, {})", + data.index, + data.name) + } + + ty::ReLateBound(binder_id, ref bound_region) => { + write!(f, "ReLateBound({:?}, {:?})", + binder_id, + bound_region) + } + + ty::ReFree(ref fr) => write!(f, "{:?}", fr), + + ty::ReScope(id) => { + write!(f, "ReScope({:?})", id) + } + + ty::ReStatic => write!(f, "ReStatic"), + + ty::ReVar(ref vid) => { + write!(f, "{:?}", vid) + } + + ty::ReSkolemized(id, ref bound_region) => { + write!(f, "ReSkolemized({}, {:?})", id.index, bound_region) + } + + ty::ReEmpty => write!(f, "ReEmpty"), + + ty::ReErased => write!(f, "ReErased") } - ty::ReScope(_) | - ty::ReVar(_) | - ty::ReErased => Ok(()), - ty::ReStatic => write!(f, "'static"), - ty::ReEmpty => write!(f, "'"), } } } -impl fmt::Debug for ty::FreeRegion { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "ReFree({:?}, {:?})", - self.scope, self.bound_region) - } -} - -impl fmt::Debug for ty::Variance { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(match *self { - ty::Covariant => "+", - ty::Contravariant => "-", - ty::Invariant => "o", - ty::Bivariant => "*", - }) - } -} - -impl<'tcx> fmt::Debug for ty::GenericPredicates<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "GenericPredicates({:?})", self.predicates) - } -} - -impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "InstantiatedPredicates({:?})", - self.predicates) - } -} - -impl<'tcx> fmt::Display for ty::FnSig<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.unsafety == hir::Unsafety::Unsafe { - write!(f, "unsafe ")?; +define_print! { + () ty::FreeRegion, (self, f, cx) { + debug { + write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region) } + } +} - if self.abi != Abi::Rust { - write!(f, "extern {} ", self.abi)?; +define_print! { + () ty::Variance, (self, f, cx) { + debug { + f.write_str(match *self { + ty::Covariant => "+", + ty::Contravariant => "-", + ty::Invariant => "o", + ty::Bivariant => "*", + }) } + } +} - write!(f, "fn")?; - fn_sig(f, self.inputs(), self.variadic, self.output()) +define_print! { + ('tcx) ty::GenericPredicates<'tcx>, (self, f, cx) { + debug { + write!(f, "GenericPredicates({:?})", self.predicates) + } + } +} + +define_print! { + ('tcx) ty::InstantiatedPredicates<'tcx>, (self, f, cx) { + debug { + write!(f, "InstantiatedPredicates({:?})", self.predicates) + } + } +} + +define_print! { + ('tcx) ty::FnSig<'tcx>, (self, f, cx) { + display { + if self.unsafety == hir::Unsafety::Unsafe { + write!(f, "unsafe ")?; + } + + if self.abi != Abi::Rust { + write!(f, "extern {} ", self.abi)?; + } + + write!(f, "fn")?; + cx.fn_sig(f, self.inputs(), self.variadic, self.output()) + } + debug { + write!(f, "({:?}; variadic: {})->{:?}", self.inputs(), self.variadic, self.output()) + } } } @@ -676,21 +854,27 @@ impl fmt::Debug for ty::RegionVid { } } -impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({:?}; variadic: {})->{:?}", self.inputs(), self.variadic, self.output()) - } -} - -impl fmt::Debug for ty::InferTy { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ty::TyVar(ref v) => v.fmt(f), - ty::IntVar(ref v) => v.fmt(f), - ty::FloatVar(ref v) => v.fmt(f), - ty::FreshTy(v) => write!(f, "FreshTy({:?})", v), - ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), - ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v) +define_print! { + () ty::InferTy, (self, f, cx) { + display { + match *self { + ty::TyVar(_) => write!(f, "_"), + ty::IntVar(_) => write!(f, "{}", "{integer}"), + ty::FloatVar(_) => write!(f, "{}", "{float}"), + ty::FreshTy(v) => write!(f, "FreshTy({})", v), + ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v), + ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v) + } + } + debug { + match *self { + ty::TyVar(ref v) => write!(f, "{:?}", v), + ty::IntVar(ref v) => write!(f, "{:?}", v), + ty::FloatVar(ref v) => write!(f, "{:?}", v), + ty::FreshTy(v) => write!(f, "FreshTy({:?})", v), + ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), + ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v) + } } } } @@ -715,406 +899,393 @@ impl fmt::Debug for ty::IntVarValue { } }*/ -impl<'tcx> fmt::Display for ty::Binder<&'tcx ty::Slice>> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) +define_print_multi! { + [ + ('tcx) ty::Binder<&'tcx ty::Slice>>, + ('tcx) ty::Binder>, + ('tcx) ty::Binder>, + ('tcx) ty::Binder>, + ('tcx) ty::Binder>, + ('tcx) ty::Binder>, + ('tcx) ty::Binder>, + ('tcx) ty::Binder, ty::Region<'tcx>>>, + ('tcx) ty::Binder, ty::Region<'tcx>>> + ] + (self, f, cx) { + display { + ty::tls::with(|tcx| cx.in_binder(f, tcx, self, tcx.lift(self))) + } } } -impl<'tcx> fmt::Display for ty::Binder> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) +define_print! { + ('tcx) ty::TraitRef<'tcx>, (self, f, cx) { + display { + cx.parameterized(f, self.substs, self.def_id, &[]) + } + debug { + // when printing out the debug representation, we don't need + // to enumerate the `for<...>` etc because the debruijn index + // tells you everything you need to know. + print!(f, cx, + write("<"), + print(self.self_ty()), + write(" as "))?; + cx.parameterized(f, self.substs, self.def_id, &[])?; + write!(f, ">") + } } } -impl<'tcx> fmt::Display for ty::Binder> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) +define_print! { + ('tcx) ty::GeneratorInterior<'tcx>, (self, f, cx) { + display { + self.witness.print(f, cx) + } } } -impl<'tcx> fmt::Display for ty::Binder> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) - } -} - -impl<'tcx> fmt::Display for ty::Binder> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) - } -} - -impl<'tcx> fmt::Display for ty::Binder> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) - } -} - -impl<'tcx> fmt::Display for ty::Binder> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) - } -} - -impl<'tcx> fmt::Display for ty::Binder, ty::Region<'tcx>>> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) - } -} - -impl<'tcx> fmt::Display for ty::Binder, - ty::Region<'tcx>>> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) - } -} - -impl<'tcx> fmt::Display for ty::TraitRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - parameterized(f, self.substs, self.def_id, &[]) - } -} - -impl<'tcx> fmt::Display for ty::GeneratorInterior<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.witness.fmt(f) - } -} - -impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - TyBool => write!(f, "bool"), - TyChar => write!(f, "char"), - TyInt(t) => write!(f, "{}", t.ty_to_string()), - TyUint(t) => write!(f, "{}", t.ty_to_string()), - TyFloat(t) => write!(f, "{}", t.ty_to_string()), - TyRawPtr(ref tm) => { - write!(f, "*{} {}", match tm.mutbl { - hir::MutMutable => "mut", - hir::MutImmutable => "const", - }, tm.ty) - } - TyRef(r, ref tm) => { - write!(f, "&")?; - let s = r.to_string(); - write!(f, "{}", s)?; - if !s.is_empty() { - write!(f, " ")?; +define_print! { + ('tcx) ty::TypeVariants<'tcx>, (self, f, cx) { + display { + match *self { + TyBool => write!(f, "bool"), + TyChar => write!(f, "char"), + TyInt(t) => write!(f, "{}", t.ty_to_string()), + TyUint(t) => write!(f, "{}", t.ty_to_string()), + TyFloat(t) => write!(f, "{}", t.ty_to_string()), + TyRawPtr(ref tm) => { + write!(f, "*{} ", match tm.mutbl { + hir::MutMutable => "mut", + hir::MutImmutable => "const", + })?; + tm.ty.print(f, cx) } - write!(f, "{}", tm) - } - TyNever => write!(f, "!"), - TyTuple(ref tys, _) => { - write!(f, "(")?; - let mut tys = tys.iter(); - if let Some(&ty) = tys.next() { - write!(f, "{},", ty)?; + TyRef(r, ref tm) => { + write!(f, "&")?; + let s = r.print_to_string(cx); + write!(f, "{}", s)?; + if !s.is_empty() { + write!(f, " ")?; + } + tm.print(f, cx) + } + TyNever => write!(f, "!"), + TyTuple(ref tys, _) => { + write!(f, "(")?; + let mut tys = tys.iter(); if let Some(&ty) = tys.next() { - write!(f, " {}", ty)?; - for &ty in tys { - write!(f, ", {}", ty)?; - } - } - } - write!(f, ")") - } - TyFnDef(def_id, substs) => { - ty::tls::with(|tcx| { - let mut sig = tcx.fn_sig(def_id); - if let Some(substs) = tcx.lift(&substs) { - sig = sig.subst(tcx, substs); - } - write!(f, "{} {{", sig.0) - })?; - parameterized(f, substs, def_id, &[])?; - write!(f, "}}") - } - TyFnPtr(ref bare_fn) => { - write!(f, "{}", bare_fn) - } - TyInfer(infer_ty) => write!(f, "{}", infer_ty), - TyError => write!(f, "[type error]"), - TyParam(ref param_ty) => write!(f, "{}", param_ty), - TyAdt(def, substs) => parameterized(f, substs, def.did, &[]), - TyDynamic(data, r) => { - write!(f, "{}", data)?; - let r = r.to_string(); - if !r.is_empty() { - write!(f, " + {}", r) - } else { - Ok(()) - } - } - TyProjection(ref data) => write!(f, "{}", data), - TyAnon(def_id, substs) => { - ty::tls::with(|tcx| { - // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let predicates_of = tcx.predicates_of(def_id); - let substs = tcx.lift(&substs).unwrap_or_else(|| { - tcx.intern_substs(&[]) - }); - let bounds = predicates_of.instantiate(tcx, substs); - - let mut first = true; - let mut is_sized = false; - write!(f, "impl")?; - for predicate in bounds.predicates { - if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { - // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() { - is_sized = true; - continue; + print!(f, cx, print(ty), write(","))?; + if let Some(&ty) = tys.next() { + print!(f, cx, write(" "), print(ty))?; + for &ty in tys { + print!(f, cx, write(", "), print(ty))?; } - - write!(f, "{}{}", if first { " " } else { "+" }, trait_ref)?; - first = false; } } - if !is_sized { - write!(f, "{}?Sized", if first { " " } else { "+" })?; - } - Ok(()) - }) - } - TyStr => write!(f, "str"), - TyGenerator(did, substs, interior) => ty::tls::with(|tcx| { - let upvar_tys = substs.upvar_tys(did, tcx); - write!(f, "[generator")?; - - if let Some(node_id) = tcx.hir.as_local_node_id(did) { - write!(f, "@{:?}", tcx.hir.span(node_id))?; - let mut sep = " "; - tcx.with_freevars(node_id, |freevars| { - for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - write!(f, - "{}{}:{}", - sep, - tcx.hir.name(freevar.var_id()), - upvar_ty)?; - sep = ", "; - } - Ok(()) - })? - } else { - // cross-crate closure types should only be - // visible in trans bug reports, I imagine. - write!(f, "@{:?}", did)?; - let mut sep = " "; - for (index, upvar_ty) in upvar_tys.enumerate() { - write!(f, "{}{}:{}", sep, index, upvar_ty)?; - sep = ", "; - } + write!(f, ")") } - - write!(f, " {}", interior)?; - - write!(f, "]") - }), - TyClosure(did, substs) => ty::tls::with(|tcx| { - let upvar_tys = substs.upvar_tys(did, tcx); - write!(f, "[closure")?; - - if let Some(node_id) = tcx.hir.as_local_node_id(did) { - if tcx.sess.opts.debugging_opts.span_free_formats { - write!(f, "@{:?}", node_id)?; + TyFnDef(def_id, substs) => { + ty::tls::with(|tcx| { + let mut sig = tcx.fn_sig(def_id); + if let Some(substs) = tcx.lift(&substs) { + sig = sig.subst(tcx, substs); + } + print!(f, cx, print(sig), write(" {{")) + })?; + cx.parameterized(f, substs, def_id, &[])?; + write!(f, "}}") + } + TyFnPtr(ref bare_fn) => { + bare_fn.print(f, cx) + } + TyInfer(infer_ty) => write!(f, "{}", infer_ty), + TyError => write!(f, "[type error]"), + TyParam(ref param_ty) => write!(f, "{}", param_ty), + TyAdt(def, substs) => cx.parameterized(f, substs, def.did, &[]), + TyDynamic(data, r) => { + data.print(f, cx)?; + let r = r.print_to_string(cx); + if !r.is_empty() { + write!(f, " + {}", r) } else { - write!(f, "@{:?}", tcx.hir.span(node_id))?; + Ok(()) } - let mut sep = " "; - tcx.with_freevars(node_id, |freevars| { - for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - write!(f, - "{}{}:{}", - sep, - tcx.hir.name(freevar.var_id()), - upvar_ty)?; - sep = ", "; + } + TyProjection(ref data) => data.print(f, cx), + TyAnon(def_id, substs) => { + ty::tls::with(|tcx| { + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let predicates_of = tcx.predicates_of(def_id); + let substs = tcx.lift(&substs).unwrap_or_else(|| { + tcx.intern_substs(&[]) + }); + let bounds = predicates_of.instantiate(tcx, substs); + + let mut first = true; + let mut is_sized = false; + write!(f, "impl")?; + for predicate in bounds.predicates { + if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { + // Don't print +Sized, but rather +?Sized if absent. + if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() { + is_sized = true; + continue; + } + + print!(f, cx, + write("{}", if first { " " } else { "+" }), + print(trait_ref))?; + first = false; + } + } + if !is_sized { + write!(f, "{}?Sized", if first { " " } else { "+" })?; } Ok(()) - })? - } else { - // cross-crate closure types should only be - // visible in trans bug reports, I imagine. - write!(f, "@{:?}", did)?; - let mut sep = " "; - for (index, upvar_ty) in upvar_tys.enumerate() { - write!(f, "{}{}:{}", sep, index, upvar_ty)?; - sep = ", "; - } + }) } + TyStr => write!(f, "str"), + TyGenerator(did, substs, interior) => ty::tls::with(|tcx| { + let upvar_tys = substs.upvar_tys(did, tcx); + write!(f, "[generator")?; - write!(f, "]") - }), - TyArray(ty, sz) => { - write!(f, "[{}; ", ty)?; - match sz.val { - ConstVal::Integral(ConstInt::Usize(sz)) => { - write!(f, "{}", sz)?; + if let Some(node_id) = tcx.hir.as_local_node_id(did) { + write!(f, "@{:?}", tcx.hir.span(node_id))?; + let mut sep = " "; + tcx.with_freevars(node_id, |freevars| { + for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { + print!(f, cx, + write("{}{}:", + sep, + tcx.hir.name(freevar.var_id())), + print(upvar_ty))?; + sep = ", "; + } + Ok(()) + })? + } else { + // cross-crate closure types should only be + // visible in trans bug reports, I imagine. + write!(f, "@{:?}", did)?; + let mut sep = " "; + for (index, upvar_ty) in upvar_tys.enumerate() { + print!(f, cx, + write("{}{}:", sep, index), + print(upvar_ty))?; + sep = ", "; + } } - ConstVal::Unevaluated(_def_id, substs) => { - write!(f, "", &substs[..])?; + + print!(f, cx, write(" "), print(interior), write("]")) + }), + TyClosure(did, substs) => ty::tls::with(|tcx| { + let upvar_tys = substs.upvar_tys(did, tcx); + write!(f, "[closure")?; + + if let Some(node_id) = tcx.hir.as_local_node_id(did) { + if tcx.sess.opts.debugging_opts.span_free_formats { + write!(f, "@{:?}", node_id)?; + } else { + write!(f, "@{:?}", tcx.hir.span(node_id))?; + } + let mut sep = " "; + tcx.with_freevars(node_id, |freevars| { + for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { + print!(f, cx, + write("{}{}:", + sep, + tcx.hir.name(freevar.var_id())), + print(upvar_ty))?; + sep = ", "; + } + Ok(()) + })? + } else { + // cross-crate closure types should only be + // visible in trans bug reports, I imagine. + write!(f, "@{:?}", did)?; + let mut sep = " "; + for (index, upvar_ty) in upvar_tys.enumerate() { + print!(f, cx, + write("{}{}:", sep, index), + print(upvar_ty))?; + sep = ", "; + } } - _ => { - write!(f, "{:?}", sz)?; + + write!(f, "]") + }), + TyArray(ty, sz) => { + print!(f, cx, write("["), print(ty), write("; "))?; + match sz.val { + ConstVal::Integral(ConstInt::Usize(sz)) => { + write!(f, "{}", sz)?; + } + ConstVal::Unevaluated(_def_id, substs) => { + write!(f, "", &substs[..])?; + } + _ => { + write!(f, "{:?}", sz)?; + } } + write!(f, "]") + } + TySlice(ty) => { + print!(f, cx, write("["), print(ty), write("]")) + } + } + } + } +} + +define_print! { + ('tcx) ty::TyS<'tcx>, (self, f, cx) { + display { + self.sty.print(f, cx) + } + debug { + self.sty.print_display(f, cx) + } + } +} + +define_print! { + () ty::ParamTy, (self, f, cx) { + display { + write!(f, "{}", self.name) + } + debug { + write!(f, "{}/#{}", self.name, self.idx) + } + } +} + +define_print! { + ('tcx, T: Print + fmt::Debug, U: Print + fmt::Debug) ty::OutlivesPredicate, + (self, f, cx) { + display { + print!(f, cx, print(self.0), write(" : "), print(self.1)) + } + } +} + +define_print! { + ('tcx) ty::EquatePredicate<'tcx>, (self, f, cx) { + display { + print!(f, cx, print(self.0), write(" == "), print(self.1)) + } + } +} + +define_print! { + ('tcx) ty::SubtypePredicate<'tcx>, (self, f, cx) { + display { + print!(f, cx, print(self.a), write(" <: "), print(self.b)) + } + } +} + +define_print! { + ('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) { + debug { + write!(f, "TraitPredicate({:?})", + self.trait_ref) + } + display { + print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + } + } +} + +define_print! { + ('tcx) ty::ProjectionPredicate<'tcx>, (self, f, cx) { + debug { + print!(f, cx, + write("ProjectionPredicate("), + print(self.projection_ty), + write(", "), + print(self.ty), + write(")")) + } + display { + print!(f, cx, print(self.projection_ty), write(" == "), print(self.ty)) + } + } +} + +define_print! { + ('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) { + display { + // FIXME(tschottdorf): use something like + // parameterized(f, self.substs, self.item_def_id, &[]) + // (which currently ICEs). + let (trait_ref, item_name) = ty::tls::with(|tcx| + (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).name) + ); + print!(f, cx, print_debug(trait_ref), write("::{}", item_name)) + } + } +} + +define_print! { + () ty::ClosureKind, (self, f, cx) { + display { + match *self { + ty::ClosureKind::Fn => write!(f, "Fn"), + ty::ClosureKind::FnMut => write!(f, "FnMut"), + ty::ClosureKind::FnOnce => write!(f, "FnOnce"), + } + } + } +} + +define_print! { + ('tcx) ty::Predicate<'tcx>, (self, f, cx) { + display { + match *self { + ty::Predicate::Trait(ref data) => data.print(f, cx), + ty::Predicate::Equate(ref predicate) => predicate.print(f, cx), + ty::Predicate::Subtype(ref predicate) => predicate.print(f, cx), + ty::Predicate::RegionOutlives(ref predicate) => predicate.print(f, cx), + ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx), + ty::Predicate::Projection(ref predicate) => predicate.print(f, cx), + ty::Predicate::WellFormed(ty) => print!(f, cx, print(ty), write(" well-formed")), + ty::Predicate::ObjectSafe(trait_def_id) => + ty::tls::with(|tcx| { + write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id)) + }), + ty::Predicate::ClosureKind(closure_def_id, kind) => + ty::tls::with(|tcx| { + write!(f, "the closure `{}` implements the trait `{}`", + tcx.item_path_str(closure_def_id), kind) + }), + ty::Predicate::ConstEvaluatable(def_id, substs) => { + write!(f, "the constant `")?; + cx.parameterized(f, substs, def_id, &[])?; + write!(f, "` can be evaluated") + } + } + } + debug { + match *self { + ty::Predicate::Trait(ref a) => a.print(f, cx), + ty::Predicate::Equate(ref pair) => pair.print(f, cx), + ty::Predicate::Subtype(ref pair) => pair.print(f, cx), + ty::Predicate::RegionOutlives(ref pair) => pair.print(f, cx), + ty::Predicate::TypeOutlives(ref pair) => pair.print(f, cx), + ty::Predicate::Projection(ref pair) => pair.print(f, cx), + ty::Predicate::WellFormed(ty) => ty.print(f, cx), + ty::Predicate::ObjectSafe(trait_def_id) => { + write!(f, "ObjectSafe({:?})", trait_def_id) + } + ty::Predicate::ClosureKind(closure_def_id, kind) => { + write!(f, "ClosureKind({:?}, {:?})", closure_def_id, kind) + } + ty::Predicate::ConstEvaluatable(def_id, substs) => { + write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs) } - write!(f, "]") - } - TySlice(ty) => write!(f, "[{}]", ty) - } - } -} - -impl<'tcx> fmt::Display for ty::TyS<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.sty) - } -} - -impl fmt::Debug for ty::UpvarId { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UpvarId({:?};`{}`;{:?})", - self.var_id, - ty::tls::with(|tcx| tcx.hir.name(tcx.hir.hir_to_node_id(self.var_id))), - self.closure_expr_id) - } -} - -impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UpvarBorrow({:?}, {:?})", - self.kind, self.region) - } -} - -impl fmt::Display for ty::InferTy { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let print_var_ids = verbose(); - match *self { - ty::TyVar(ref vid) if print_var_ids => write!(f, "{:?}", vid), - ty::IntVar(ref vid) if print_var_ids => write!(f, "{:?}", vid), - ty::FloatVar(ref vid) if print_var_ids => write!(f, "{:?}", vid), - ty::TyVar(_) => write!(f, "_"), - ty::IntVar(_) => write!(f, "{}", "{integer}"), - ty::FloatVar(_) => write!(f, "{}", "{float}"), - ty::FreshTy(v) => write!(f, "FreshTy({})", v), - ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v), - ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v) - } - } -} - -impl fmt::Display for ty::ParamTy { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.name) - } -} - -impl fmt::Debug for ty::ParamTy { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}/#{}", self, self.idx) - } -} - -impl<'tcx, T, U> fmt::Display for ty::OutlivesPredicate - where T: fmt::Display, U: fmt::Display -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} : {}", self.0, self.1) - } -} - -impl<'tcx> fmt::Display for ty::EquatePredicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} == {}", self.0, self.1) - } -} - -impl<'tcx> fmt::Display for ty::SubtypePredicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} <: {}", self.a, self.b) - } -} - -impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TraitPredicate({:?})", - self.trait_ref) - } -} - -impl<'tcx> fmt::Display for ty::TraitPredicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}: {}", self.trait_ref.self_ty(), self.trait_ref) - } -} - -impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "ProjectionPredicate({:?}, {:?})", - self.projection_ty, - self.ty) - } -} - -impl<'tcx> fmt::Display for ty::ProjectionPredicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} == {}", - self.projection_ty, - self.ty) - } -} - -impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // FIXME(tschottdorf): use something like - // parameterized(f, self.substs, self.item_def_id, &[]) - // (which currently ICEs). - let (trait_ref, item_name) = ty::tls::with(|tcx| - (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).name) - ); - write!(f, "{:?}::{}", - trait_ref, - item_name) - } -} - -impl fmt::Display for ty::ClosureKind { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ty::ClosureKind::Fn => write!(f, "Fn"), - ty::ClosureKind::FnMut => write!(f, "FnMut"), - ty::ClosureKind::FnOnce => write!(f, "FnOnce"), - } - } -} - -impl<'tcx> fmt::Display for ty::Predicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ty::Predicate::Trait(ref data) => write!(f, "{}", data), - ty::Predicate::Equate(ref predicate) => write!(f, "{}", predicate), - ty::Predicate::Subtype(ref predicate) => write!(f, "{}", predicate), - ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate), - ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate), - ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate), - ty::Predicate::WellFormed(ty) => write!(f, "{} well-formed", ty), - ty::Predicate::ObjectSafe(trait_def_id) => - ty::tls::with(|tcx| { - write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id)) - }), - ty::Predicate::ClosureKind(closure_def_id, kind) => - ty::tls::with(|tcx| { - write!(f, "the closure `{}` implements the trait `{}`", - tcx.item_path_str(closure_def_id), kind) - }), - ty::Predicate::ConstEvaluatable(def_id, substs) => { - write!(f, "the constant `")?; - parameterized(f, substs, def_id, &[])?; - write!(f, "` can be evaluated") } } } From b5b7666120658e332c1ea26e8bb3944aefde31ca Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sun, 1 Oct 2017 14:55:58 -0400 Subject: [PATCH 097/365] Don't encourage people to ignore threading errors in the docs --- src/libstd/thread/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 30887b16c60..07bbddc62b9 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -485,15 +485,17 @@ impl Builder { /// let (tx, rx) = channel(); /// /// let sender = thread::spawn(move || { -/// let _ = tx.send("Hello, thread".to_owned()); +/// tx.send("Hello, thread".to_owned()) +/// .expect("Unable to send on channel"); /// }); /// /// let receiver = thread::spawn(move || { -/// println!("{}", rx.recv().unwrap()); +/// let value = rx.recv().expect("Unable to receive from channel"); +/// println!("{}", value); /// }); /// -/// let _ = sender.join(); -/// let _ = receiver.join(); +/// sender.join().expect("The sender thread has panicked"); +/// receiver.join().expect("The receiver thread has panicked"); /// ``` /// /// A thread can also return a value through its [`JoinHandle`], you can use @@ -1192,7 +1194,7 @@ impl JoinInner { /// }); /// }); /// -/// let _ = original_thread.join(); +/// original_thread.join().expect("The thread being joined has panicked"); /// println!("Original thread is joined."); /// /// // We make sure that the new thread has time to run, before the main From 84cb90f8ee080ed04512620357c1f734146df8c3 Mon Sep 17 00:00:00 2001 From: Wonwoo Choi Date: Tue, 3 Oct 2017 02:04:02 +0900 Subject: [PATCH 098/365] Fix tests --- src/test/compile-fail/hygiene/impl_items.rs | 2 +- src/test/compile-fail/issue-12997-2.rs | 2 +- .../compile-fail/private-inferred-type-3.rs | 2 +- .../compile-fail/private-inferred-type.rs | 2 +- .../regions-fn-subtyping-return-static.rs | 4 +- src/test/mir-opt/validate_1.rs | 2 +- src/test/mir-opt/validate_4.rs | 8 +-- src/test/mir-opt/validate_5.rs | 2 +- src/test/pretty/issue-4264.pp | 50 +++++++++---------- .../regions-fn-subtyping-return-static.stderr | 2 +- 10 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/test/compile-fail/hygiene/impl_items.rs b/src/test/compile-fail/hygiene/impl_items.rs index 445aa62f236..cdba559445d 100644 --- a/src/test/compile-fail/hygiene/impl_items.rs +++ b/src/test/compile-fail/hygiene/impl_items.rs @@ -19,7 +19,7 @@ mod foo { } pub macro m() { - let _: () = S.f(); //~ ERROR type `fn(&foo::S) {foo::S::f}` is private + let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private } } diff --git a/src/test/compile-fail/issue-12997-2.rs b/src/test/compile-fail/issue-12997-2.rs index 276d7f7c9ed..85d91bb2db2 100644 --- a/src/test/compile-fail/issue-12997-2.rs +++ b/src/test/compile-fail/issue-12997-2.rs @@ -15,6 +15,6 @@ #[bench] fn bar(x: isize) { } //~^ ERROR mismatched types -//~| expected type `fn(&mut __test::test::Bencher)` +//~| expected type `for<'r> fn(&'r mut __test::test::Bencher)` //~| found type `fn(isize) {bar}` //~| expected mutable reference, found isize diff --git a/src/test/compile-fail/private-inferred-type-3.rs b/src/test/compile-fail/private-inferred-type-3.rs index fdd9166ef29..c0ba38b2402 100644 --- a/src/test/compile-fail/private-inferred-type-3.rs +++ b/src/test/compile-fail/private-inferred-type-3.rs @@ -15,7 +15,7 @@ // error-pattern:type `fn() {::method}` is private // error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is pr // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv -// error-pattern:type `fn(&ext::Pub) {>::priv_method}` is private +// error-pattern:type `for<'r> fn(&'r ext::Pub) {>::priv_method}` is private #![feature(decl_macro)] diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs index 973d467b112..95e3732d613 100644 --- a/src/test/compile-fail/private-inferred-type.rs +++ b/src/test/compile-fail/private-inferred-type.rs @@ -56,7 +56,7 @@ mod m { PubTupleStruct; //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is privat Pub(0u8).priv_method(); - //~^ ERROR type `fn(&m::Pub) {>::priv_method}` is private + //~^ ERROR type `for<'r> fn(&'r m::Pub) {>::priv_method}` is private } trait Trait {} diff --git a/src/test/compile-fail/regions-fn-subtyping-return-static.rs b/src/test/compile-fail/regions-fn-subtyping-return-static.rs index ac7dd022c7c..6be65a5e359 100644 --- a/src/test/compile-fail/regions-fn-subtyping-return-static.rs +++ b/src/test/compile-fail/regions-fn-subtyping-return-static.rs @@ -58,8 +58,8 @@ fn supply_G() { want_G(bar); want_G(baz); //~^ ERROR mismatched types - //~| expected type `fn(&'cx S) -> &'static S` - //~| found type `fn(&S) -> &S {baz}` + //~| expected type `for<'cx> fn(&'cx S) -> &'static S` + //~| found type `for<'r> fn(&'r S) -> &'r S {baz}` //~| expected concrete lifetime, found bound lifetime parameter 'cx } diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index d2ca65775a4..39f43e4e990 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -57,7 +57,7 @@ fn main() { // START rustc.node50.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _3 = _2; // StorageLive(_4); diff --git a/src/test/mir-opt/validate_4.rs b/src/test/mir-opt/validate_4.rs index d240b51e222..b670d8094dd 100644 --- a/src/test/mir-opt/validate_4.rs +++ b/src/test/mir-opt/validate_4.rs @@ -48,8 +48,8 @@ fn main() { // START rustc.node22.EraseRegions.after.mir // fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]); // StorageLive(_3); // _3 = _2; // (*_3) = const 23i32; @@ -74,8 +74,8 @@ fn main() { // START rustc.node60.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _0 = const write_42(_4) -> bb1; // } diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index e1eeb2102d1..059d3adb407 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -45,7 +45,7 @@ fn main() { // START rustc.node46.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool { // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _3 = _2; // StorageLive(_4); diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 14a499644df..02b8425d88b 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -40,31 +40,31 @@ pub fn bar() ({ ((::fmt::format as - fn(std::fmt::Arguments<'_>) -> std::string::String {std::fmt::format})(((<::std::fmt::Arguments>::new_v1 - as - fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})((&([("test" - as - &'static str)] - as - [&str; 1]) - as - &[&str; 1]), - (&(match (() - as - ()) - { - () - => - ([] - as - [std::fmt::ArgumentV1<'_>; 0]), - } - as - [std::fmt::ArgumentV1<'_>; 0]) - as - &[std::fmt::ArgumentV1<'_>; 0])) - as - std::fmt::Arguments<'_>)) + for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<::std::fmt::Arguments>::new_v1 + as + fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})((&([("test" + as + &'static str)] + as + [&str; 1]) + as + &[&str; 1]), + (&(match (() + as + ()) + { + () + => + ([] + as + [std::fmt::ArgumentV1<'_>; 0]), + } + as + [std::fmt::ArgumentV1<'_>; 0]) + as + &[std::fmt::ArgumentV1<'_>; 0])) + as + std::fmt::Arguments<'_>)) as std::string::String); } as ()) pub type Foo = [i32; (3 as usize)]; diff --git a/src/test/ui/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions-fn-subtyping-return-static.stderr index 0c88c63edeb..4a97537223c 100644 --- a/src/test/ui/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static.stderr @@ -5,7 +5,7 @@ error[E0308]: mismatched types | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx | = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` - found type `fn(&'a S) -> &S {bar::<'_>}` + found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` error: aborting due to previous error From e6728ecdbb52fbf5337a8d962fefcf83a6c65a3f Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 8 Oct 2017 10:40:52 -0500 Subject: [PATCH 099/365] fix documentation typo --- src/librustc/hir/itemlikevisit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs index ce1a34faf5e..2221ecf07b4 100644 --- a/src/librustc/hir/itemlikevisit.rs +++ b/src/librustc/hir/itemlikevisit.rs @@ -41,7 +41,7 @@ use super::intravisit::Visitor; /// - Example: Lifetime resolution, which wants to bring lifetimes declared on the /// impl into scope while visiting the impl-items, and then back out again. /// - How: Implement `intravisit::Visitor` and override the -/// `visit_nested_map()` methods to return +/// `nested_visit_map()` methods to return /// `NestedVisitorMap::All`. Walk your crate with /// `intravisit::walk_crate()` invoked on `tcx.hir.krate()`. /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. From 31f4b570025f46d0b29c79f2b493d2db65438b30 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 28 Sep 2017 23:13:43 -0400 Subject: [PATCH 100/365] Turn `trans_fulfill_obligation` into a query Part of #44891 --- src/librustc/dep_graph/dep_node.rs | 3 +- src/librustc/ich/impls_ty.rs | 126 ++++++++++++++++++++++++++ src/librustc/traits/mod.rs | 2 + src/librustc/traits/trans/mod.rs | 138 +++++++++++++---------------- src/librustc/ty/instance.rs | 3 +- src/librustc/ty/maps/config.rs | 6 ++ src/librustc/ty/maps/keys.rs | 9 ++ src/librustc/ty/maps/mod.rs | 11 +++ src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_trans/monomorphize.rs | 9 +- 10 files changed, 226 insertions(+), 82 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 36236ff25b0..98e2e72f225 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -65,7 +65,7 @@ use hir::map::DefPathHash; use hir::{HirId, ItemLocalId}; use ich::Fingerprint; -use ty::{TyCtxt, Instance, InstanceDef, ParamEnvAnd, Ty}; +use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty}; use ty::subst::Substs; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use ich::StableHashingContext; @@ -486,6 +486,7 @@ define_dep_nodes!( <'tcx> [] InstanceSymbolName { instance: Instance<'tcx> }, [] SpecializationGraph(DefId), [] ObjectSafety(DefId), + [] FulfillObligation { param_env: ParamEnv<'tcx>, trait_ref: PolyTraitRef<'tcx> }, [] IsCopy { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> }, [] IsSized { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> }, diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index fe060aaf426..6e55365980c 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -841,3 +841,129 @@ impl_stable_hash_for!(struct ::util::common::ErrorReported {}); impl_stable_hash_for!(tuple_struct ::middle::reachable::ReachableSet { reachable_set }); + +impl<'gcx, N> HashStable> +for traits::Vtable<'gcx, N> where N: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + use traits::Vtable::*; + + mem::discriminant(self).hash_stable(hcx, hasher); + + match self { + &VtableImpl(ref table_impl) => table_impl.hash_stable(hcx, hasher), + &VtableDefaultImpl(ref table_def_impl) => table_def_impl.hash_stable(hcx, hasher), + &VtableParam(ref table_param) => table_param.hash_stable(hcx, hasher), + &VtableObject(ref table_obj) => table_obj.hash_stable(hcx, hasher), + &VtableBuiltin(ref table_builtin) => table_builtin.hash_stable(hcx, hasher), + &VtableClosure(ref table_closure) => table_closure.hash_stable(hcx, hasher), + &VtableFnPointer(ref table_fn_pointer) => table_fn_pointer.hash_stable(hcx, hasher), + &VtableGenerator(ref table_generator) => table_generator.hash_stable(hcx, hasher), + } + } +} + +impl<'gcx, N> HashStable> +for traits::VtableImplData<'gcx, N> where N: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + let traits::VtableImplData { + impl_def_id, + substs, + ref nested, + } = *self; + impl_def_id.hash_stable(hcx, hasher); + substs.hash_stable(hcx, hasher); + nested.hash_stable(hcx, hasher); + } +} + +impl<'gcx, N> HashStable> +for traits::VtableDefaultImplData where N: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + let traits::VtableDefaultImplData { + trait_def_id, + ref nested, + } = *self; + trait_def_id.hash_stable(hcx, hasher); + nested.hash_stable(hcx, hasher); + } +} + +impl<'gcx, N> HashStable> +for traits::VtableObjectData<'gcx, N> where N: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + let traits::VtableObjectData { + upcast_trait_ref, + vtable_base, + ref nested, + } = *self; + upcast_trait_ref.hash_stable(hcx, hasher); + vtable_base.hash_stable(hcx, hasher); + nested.hash_stable(hcx, hasher); + } +} + +impl<'gcx, N> HashStable> +for traits::VtableBuiltinData where N: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + let traits::VtableBuiltinData { + ref nested, + } = *self; + nested.hash_stable(hcx, hasher); + } +} + +impl<'gcx, N> HashStable> +for traits::VtableClosureData<'gcx, N> where N: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + let traits::VtableClosureData { + closure_def_id, + substs, + ref nested, + } = *self; + closure_def_id.hash_stable(hcx, hasher); + substs.hash_stable(hcx, hasher); + nested.hash_stable(hcx, hasher); + } +} + +impl<'gcx, N> HashStable> +for traits::VtableFnPointerData<'gcx, N> where N: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + let traits::VtableFnPointerData { + fn_ty, + ref nested, + } = *self; + fn_ty.hash_stable(hcx, hasher); + nested.hash_stable(hcx, hasher); + } +} + +impl<'gcx, N> HashStable> +for traits::VtableGeneratorData<'gcx, N> where N: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + let traits::VtableGeneratorData { + closure_def_id, + substs, + ref nested, + } = *self; + closure_def_id.hash_stable(hcx, hasher); + substs.hash_stable(hcx, hasher); + nested.hash_stable(hcx, hasher); + } +} diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a1817f18106..bdfbefd1364 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -835,6 +835,7 @@ pub fn provide(providers: &mut ty::maps::Providers) { is_object_safe: object_safety::is_object_safe_provider, specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, + trans_fulfill_obligation: trans::trans_fulfill_obligation, ..*providers }; } @@ -844,6 +845,7 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) { is_object_safe: object_safety::is_object_safe_provider, specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, + trans_fulfill_obligation: trans::trans_fulfill_obligation, ..*providers }; } diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index 947e7117c4e..aa3179dd01f 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -17,85 +17,77 @@ use dep_graph::{DepGraph, DepKind, DepTrackingMap, DepTrackingMapConfig}; use infer::TransNormalize; use std::cell::RefCell; use std::marker::PhantomData; -use syntax::ast; -use syntax_pos::Span; +use syntax_pos::DUMMY_SP; use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable}; use ty::{self, Ty, TyCtxt}; use ty::subst::{Subst, Substs}; use ty::fold::{TypeFoldable, TypeFolder}; use util::common::MemoizationMap; +/// Attempts to resolve an obligation to a vtable.. The result is +/// a shallow vtable resolution -- meaning that we do not +/// (necessarily) resolve all nested obligations on the impl. Note +/// that type check should guarantee to us that all nested +/// obligations *could be* resolved if we wanted to. +/// Assumes that this is run after the entire crate has been successfully type-checked. +pub fn trans_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>, + (param_env, trait_ref): + (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) + -> Vtable<'tcx, ()> +{ + // Remove any references to regions; this helps improve caching. + let trait_ref = ty.erase_regions(&trait_ref); + + debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})", + (param_env, trait_ref), trait_ref.def_id()); + + // Do the initial selection for the obligation. This yields the + // shallow result we are looking for -- that is, what specific impl. + ty.infer_ctxt().enter(|infcx| { + let mut selcx = SelectionContext::new(&infcx); + + let obligation_cause = ObligationCause::dummy(); + let obligation = Obligation::new(obligation_cause, + param_env, + trait_ref.to_poly_trait_predicate()); + + let selection = match selcx.select(&obligation) { + Ok(Some(selection)) => selection, + Ok(None) => { + // Ambiguity can happen when monomorphizing during trans + // expands to some humongo type that never occurred + // statically -- this humongo type can then overflow, + // leading to an ambiguous result. So report this as an + // overflow bug, since I believe this is the only case + // where ambiguity can result. + bug!("Encountered ambiguity selecting `{:?}` during trans, \ + presuming due to overflow", + trait_ref) + } + Err(e) => { + bug!("Encountered error `{:?}` selecting `{:?}` during trans", + e, trait_ref) + } + }; + + debug!("fulfill_obligation: selection={:?}", selection); + + // Currently, we use a fulfillment context to completely resolve + // all nested obligations. This is because they can inform the + // inference of the impl's type parameters. + let mut fulfill_cx = FulfillmentContext::new(); + let vtable = selection.map(|predicate| { + debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate); + fulfill_cx.register_predicate_obligation(&infcx, predicate); + }); + let vtable = infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &vtable); + + info!("Cache miss: {:?} => {:?}", trait_ref, vtable); + vtable + }) +} + impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { - /// Attempts to resolve an obligation to a vtable.. The result is - /// a shallow vtable resolution -- meaning that we do not - /// (necessarily) resolve all nested obligations on the impl. Note - /// that type check should guarantee to us that all nested - /// obligations *could be* resolved if we wanted to. - /// Assumes that this is run after the entire crate has been successfully type-checked. - pub fn trans_fulfill_obligation(self, - span: Span, - param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>) - -> Vtable<'tcx, ()> - { - // Remove any references to regions; this helps improve caching. - let trait_ref = self.erase_regions(&trait_ref); - - self.trans_trait_caches.trait_cache.memoize((param_env, trait_ref), || { - debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})", - (param_env, trait_ref), trait_ref.def_id()); - - // Do the initial selection for the obligation. This yields the - // shallow result we are looking for -- that is, what specific impl. - self.infer_ctxt().enter(|infcx| { - let mut selcx = SelectionContext::new(&infcx); - - let obligation_cause = ObligationCause::misc(span, - ast::DUMMY_NODE_ID); - let obligation = Obligation::new(obligation_cause, - param_env, - trait_ref.to_poly_trait_predicate()); - - let selection = match selcx.select(&obligation) { - Ok(Some(selection)) => selection, - Ok(None) => { - // Ambiguity can happen when monomorphizing during trans - // expands to some humongo type that never occurred - // statically -- this humongo type can then overflow, - // leading to an ambiguous result. So report this as an - // overflow bug, since I believe this is the only case - // where ambiguity can result. - debug!("Encountered ambiguity selecting `{:?}` during trans, \ - presuming due to overflow", - trait_ref); - self.sess.span_fatal(span, - "reached the recursion limit during monomorphization \ - (selection ambiguity)"); - } - Err(e) => { - span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans", - e, trait_ref) - } - }; - - debug!("fulfill_obligation: selection={:?}", selection); - - // Currently, we use a fulfillment context to completely resolve - // all nested obligations. This is because they can inform the - // inference of the impl's type parameters. - let mut fulfill_cx = FulfillmentContext::new(); - let vtable = selection.map(|predicate| { - debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate); - fulfill_cx.register_predicate_obligation(&infcx, predicate); - }); - let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable); - - info!("Cache miss: {:?} => {:?}", trait_ref, vtable); - vtable - }) - }) - } - /// Monomorphizes a type from the AST by first applying the in-scope /// substitutions and then normalizing any associated types. pub fn trans_apply_param_substs(self, @@ -149,14 +141,12 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> { /// Specializes caches used in trans -- in particular, they assume all /// types are fully monomorphized and that free regions can be erased. pub struct TransTraitCaches<'tcx> { - trait_cache: RefCell>>, project_cache: RefCell>>, } impl<'tcx> TransTraitCaches<'tcx> { pub fn new(graph: DepGraph) -> Self { TransTraitCaches { - trait_cache: RefCell::new(DepTrackingMap::new(graph.clone())), project_cache: RefCell::new(DepTrackingMap::new(graph)), } } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 35ab1cec4cf..600b2572f92 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -13,7 +13,6 @@ use ty::{self, Ty, TypeFoldable, Substs, TyCtxt}; use ty::subst::{Kind, Subst}; use traits; use syntax::abi::Abi; -use syntax::codemap::DUMMY_SP; use util::ppaux; use std::fmt; @@ -212,7 +211,7 @@ fn resolve_associated_item<'a, 'tcx>( def_id, trait_id, rcvr_substs); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, param_env, ty::Binder(trait_ref)); + let vtbl = tcx.trans_fulfill_obligation((param_env, ty::Binder(trait_ref))); // Now that we know which impl is being used, we can dispatch to // the actual function: diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index c8520c5be2d..dee1516e0f8 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -221,6 +221,12 @@ impl<'tcx> QueryDescription for queries::is_mir_available<'tcx> { } } +impl<'tcx> QueryDescription for queries::trans_fulfill_obligation<'tcx> { + fn describe(tcx: TyCtxt, key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String { + format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id())) + } +} + impl<'tcx> QueryDescription for queries::trait_impls_of<'tcx> { fn describe(tcx: TyCtxt, def_id: DefId) -> String { format!("trait impls of `{}`", tcx.item_path_str(def_id)) diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs index e37cf669797..1bd4f3e657e 100644 --- a/src/librustc/ty/maps/keys.rs +++ b/src/librustc/ty/maps/keys.rs @@ -134,6 +134,15 @@ impl Key for (MirSuite, MirPassIndex, DefId) { } } +impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { + fn map_crate(&self) -> CrateNum { + self.1.def_id().krate + } + fn default_span(&self, tcx: TyCtxt) -> Span { + tcx.def_span(self.1.def_id()) + } +} + impl<'tcx> Key for Ty<'tcx> { fn map_crate(&self) -> CrateNum { LOCAL_CRATE diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 3dcbeda94bc..2001de88803 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -30,6 +30,7 @@ use middle::trans::{CodegenUnit, Stats}; use mir; use session::CompileResult; use session::config::OutputFilenames; +use traits::Vtable; use traits::specialization_graph; use ty::{self, CrateInherentImpls, Ty, TyCtxt}; use ty::layout::{Layout, LayoutError}; @@ -228,6 +229,8 @@ define_maps! { <'tcx> [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, [] fn is_mir_available: IsMirAvailable(DefId) -> bool, + [] fn trans_fulfill_obligation: fulfill_obligation_dep_node( + (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Vtable<'tcx, ()>, [] fn trait_impls_of: TraitImpls(DefId) -> Rc, [] fn specialization_graph_of: SpecializationGraph(DefId) -> Rc, [] fn is_object_safe: ObjectSafety(DefId) -> bool, @@ -347,6 +350,14 @@ fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstr } } +fn fulfill_obligation_dep_node<'tcx>((param_env, trait_ref): + (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> DepConstructor<'tcx> { + DepConstructor::FulfillObligation { + param_env, + trait_ref + } +} + fn coherent_trait_dep_node<'tcx>((_, def_id): (CrateNum, DefId)) -> DepConstructor<'tcx> { DepConstructor::CoherenceCheckTrait(def_id) } diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 88b619558d9..88e49369ce6 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -705,6 +705,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::TypeParamPredicates | DepKind::CodegenUnit | DepKind::CompileCodegenUnit | + DepKind::FulfillObligation | // These are just odd DepKind::Null | diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index cd2a881451c..471be439a8f 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -15,8 +15,6 @@ use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt}; -use syntax::codemap::DUMMY_SP; - pub use rustc::ty::Instance; fn fn_once_adapter_instance<'a, 'tcx>( @@ -110,13 +108,14 @@ pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> CustomCoerceUnsized { + let def_id = tcx.lang_items().coerce_unsized_trait().unwrap(); + let trait_ref = ty::Binder(ty::TraitRef { - def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), + def_id: def_id, substs: tcx.mk_substs_trait(source_ty, &[target_ty]) }); - match tcx.trans_fulfill_obligation( - DUMMY_SP, ty::ParamEnv::empty(traits::Reveal::All), trait_ref) { + match tcx.trans_fulfill_obligation( (ty::ParamEnv::empty(traits::Reveal::All), trait_ref)) { traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => { tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap() } From 19029d5627218aa01f52c68b27dec71d39974cd7 Mon Sep 17 00:00:00 2001 From: Pirh Date: Sun, 8 Oct 2017 17:12:14 +0100 Subject: [PATCH 101/365] Add links and examples for std::process::Stdio As per #29370 --- src/libstd/process.rs | 109 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index dbb58991215..2b3f49ee3f7 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -742,21 +742,128 @@ impl fmt::Debug for Output { } } -/// Describes what to do with a standard I/O stream for a child process. +/// Describes what to do with a standard I/O stream for a child process when +/// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`]. +/// +/// [`stdin`]: ./struct.Command.html#method.stdin +/// [`stdout`]: ./struct.Command.html#method.stdout +/// [`stderr`]: ./struct.Command.html#method.stderr +/// [`Command`]: ./struct.Command.html #[stable(feature = "process", since = "1.0.0")] pub struct Stdio(imp::Stdio); impl Stdio { /// A new pipe should be arranged to connect the parent and child processes. + /// + /// # Examples + /// + /// With stdout: + /// + /// ```no_run + /// use std::process::{Command, Stdio}; + /// + /// let output = Command::new("echo") + /// .arg("Hello, world!") + /// .stdout(Stdio::piped()) + /// .output() + /// .expect("Failed to execute command"); + /// + /// assert_eq!(String::from_utf8_lossy(&output.stdout), "Hello, world!\n"); + /// // Nothing echoed to console + /// ``` + /// + /// With stdin: + /// + /// ```no_run + /// use std::io::Write; + /// use std::process::{Command, Stdio}; + /// + /// let mut child = Command::new("rev") + /// .stdin(Stdio::piped()) + /// .stdout(Stdio::piped()) + /// .spawn() + /// .expect("Failed to spawn child process"); + /// + /// { + /// let mut stdin = child.stdin.as_mut().expect("Failed to open stdin"); + /// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin"); + /// } + /// + /// let output = child.wait_with_output().expect("Failed to read stdout"); + /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH\n"); + /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) } /// The child inherits from the corresponding parent descriptor. + /// + /// # Examples + /// + /// With stdout: + /// + /// ```no_run + /// use std::process::{Command, Stdio}; + /// + /// let output = Command::new("echo") + /// .arg("Hello, world!") + /// .stdout(Stdio::inherit()) + /// .output() + /// .expect("Failed to execute command"); + /// + /// assert_eq!(String::from_utf8_lossy(&output.stdout), ""); + /// // "Hello, world!" echoed to console + /// ``` + /// + /// With stdin: + /// + /// ```no_run + /// use std::process::{Command, Stdio}; + /// + /// let output = Command::new("rev") + /// .stdin(Stdio::inherit()) + /// .stdout(Stdio::piped()) + /// .output() + /// .expect("Failed to execute command"); + /// + /// println!("You piped in the reverse of: {}", String::from_utf8_lossy(&output.stdout)); + /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) } /// This stream will be ignored. This is the equivalent of attaching the /// stream to `/dev/null` + /// + /// # Examples + /// + /// With stdout: + /// + /// ```no_run + /// use std::process::{Command, Stdio}; + /// + /// let output = Command::new("echo") + /// .arg("Hello, world!") + /// .stdout(Stdio::null()) + /// .output() + /// .expect("Failed to execute command"); + /// + /// assert_eq!(String::from_utf8_lossy(&output.stdout), ""); + /// // Nothing echoed to console + /// ``` + /// + /// With stdin: + /// + /// ```no_run + /// use std::process::{Command, Stdio}; + /// + /// let output = Command::new("rev") + /// .stdin(Stdio::null()) + /// .stdout(Stdio::piped()) + /// .output() + /// .expect("Failed to execute command"); + /// + /// assert_eq!(String::from_utf8_lossy(&output.stdout), ""); + /// // Ignores any piped-in input + /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn null() -> Stdio { Stdio(imp::Stdio::Null) } } From e8ba32e7a07dbcba124cceeee8c75535309084aa Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Sun, 8 Oct 2017 18:19:51 +0200 Subject: [PATCH 102/365] Fix data-layout field The value was generated according to [this comment by @japaric](https://github.com/rust-lang/rust/issues/31367#issuecomment-213595571). --- src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json b/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json index c1dd0cf4063..3ae01d72fcc 100644 --- a/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json +++ b/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json @@ -1,6 +1,6 @@ { "pre-link-args": ["-m64"], - "data-layout": "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128", + "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", "linker-flavor": "gcc", "llvm-target": "x86_64-unknown-linux-gnu", "target-endian": "little", From 977200310abe3ca6c71d467e585654537b5309c2 Mon Sep 17 00:00:00 2001 From: Pirh Date: Sun, 8 Oct 2017 19:09:16 +0100 Subject: [PATCH 103/365] Remove ./ prefix from relative URLs Also remove trailing whitespace to pass tidy checks. --- src/libstd/process.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 2b3f49ee3f7..af64e681820 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -745,10 +745,10 @@ impl fmt::Debug for Output { /// Describes what to do with a standard I/O stream for a child process when /// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`]. /// -/// [`stdin`]: ./struct.Command.html#method.stdin -/// [`stdout`]: ./struct.Command.html#method.stdout -/// [`stderr`]: ./struct.Command.html#method.stderr -/// [`Command`]: ./struct.Command.html +/// [`stdin`]: struct.Command.html#method.stdin +/// [`stdout`]: struct.Command.html#method.stdout +/// [`stderr`]: struct.Command.html#method.stderr +/// [`Command`]: struct.Command.html #[stable(feature = "process", since = "1.0.0")] pub struct Stdio(imp::Stdio); @@ -783,12 +783,12 @@ impl Stdio { /// .stdout(Stdio::piped()) /// .spawn() /// .expect("Failed to spawn child process"); - /// + /// /// { /// let mut stdin = child.stdin.as_mut().expect("Failed to open stdin"); /// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin"); /// } - /// + /// /// let output = child.wait_with_output().expect("Failed to read stdout"); /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH\n"); /// ``` @@ -818,13 +818,13 @@ impl Stdio { /// /// ```no_run /// use std::process::{Command, Stdio}; - /// + /// /// let output = Command::new("rev") /// .stdin(Stdio::inherit()) /// .stdout(Stdio::piped()) /// .output() /// .expect("Failed to execute command"); - /// + /// /// println!("You piped in the reverse of: {}", String::from_utf8_lossy(&output.stdout)); /// ``` #[stable(feature = "process", since = "1.0.0")] @@ -854,13 +854,13 @@ impl Stdio { /// /// ```no_run /// use std::process::{Command, Stdio}; - /// + /// /// let output = Command::new("rev") /// .stdin(Stdio::null()) /// .stdout(Stdio::piped()) /// .output() /// .expect("Failed to execute command"); - /// + /// /// assert_eq!(String::from_utf8_lossy(&output.stdout), ""); /// // Ignores any piped-in input /// ``` From 35545b36cf1f4fbc20f0a38c367d5f94a6f9a1cf Mon Sep 17 00:00:00 2001 From: Paul Faria Date: Sun, 8 Oct 2017 15:20:12 -0400 Subject: [PATCH 104/365] Improve newtype_index macro to handle description and constants consistently --- src/librustc/mir/mod.rs | 21 +++-- src/librustc_data_structures/indexed_vec.rs | 87 ++++++++++++++++----- 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b909269e153..a68a6acab3f 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -402,9 +402,11 @@ pub enum BorrowKind { /////////////////////////////////////////////////////////////////////////// // Variables and temps -newtype_index!(Local, "_"); - -pub const RETURN_POINTER: Local = Local(0); +newtype_index!(Local, + const { + DESCRIPTION = "_", + RETURN_POINTER = 0, + }); /// Classifies locals into categories. See `Mir::local_kind`. #[derive(PartialEq, Eq, Debug)] @@ -538,7 +540,7 @@ pub struct UpvarDecl { /////////////////////////////////////////////////////////////////////////// // BasicBlock -newtype_index!(BasicBlock, "bb"); +newtype_index!(BasicBlock, const { DESCRIPTION = "bb" }); /////////////////////////////////////////////////////////////////////////// // BasicBlockData and Terminator @@ -1118,7 +1120,7 @@ pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Local, Ty<'tcx> /// and the index is a local. pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>; -newtype_index!(Field, "field"); +newtype_index!(Field, const { DESCRIPTION = "field" }); impl<'tcx> Lvalue<'tcx> { pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> { @@ -1183,8 +1185,11 @@ impl<'tcx> Debug for Lvalue<'tcx> { /////////////////////////////////////////////////////////////////////////// // Scopes -newtype_index!(VisibilityScope, "scope"); -pub const ARGUMENT_VISIBILITY_SCOPE : VisibilityScope = VisibilityScope(0); +newtype_index!(VisibilityScope, + const { + DESCRIPTION = "scope", + ARGUMENT_VISIBILITY_SCOPE = 0, + }); #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct VisibilityScopeData { @@ -1509,7 +1514,7 @@ pub struct Constant<'tcx> { pub literal: Literal<'tcx>, } -newtype_index!(Promoted, "promoted"); +newtype_index!(Promoted, const { DESCRIPTION = "promoted" }); #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum Literal<'tcx> { diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 4b7f55eba06..0973bfd2429 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -40,39 +40,86 @@ impl Idx for u32 { #[macro_export] macro_rules! newtype_index { - ($name:ident) => ( - newtype_index!($name, unsafe { ::std::intrinsics::type_name::<$name>() }); - ); + // ---- private rules ---- - ($name:ident, $debug_name:expr) => ( + // Base case, user-defined constants (if any) have already been defined + (@type[$type:ident] @max[$max:expr] @descr[$descr:expr]) => ( #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, - RustcEncodable, RustcDecodable)] - pub struct $name(u32); + RustcEncodable, RustcDecodable)] + pub struct $type(u32); - impl $name { - // HACK use for constants - #[allow(unused)] - const fn const_new(x: u32) -> Self { - $name(x) - } - } - - impl Idx for $name { + impl Idx for $type { fn new(value: usize) -> Self { - assert!(value < (::std::u32::MAX) as usize); - $name(value as u32) + assert!(value < ($max) as usize); + $type(value as u32) } fn index(self) -> usize { self.0 as usize } } - impl ::std::fmt::Debug for $name { + impl ::std::fmt::Debug for $type { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(fmt, "{}{}", $debug_name, self.0) + write!(fmt, "{}{}", $descr, self.0) } } - ) + ); + + // Replace existing default for max (as final param) + (@type[$type:ident] @max[$_max:expr] @descr[$descr:expr] MAX = $max:expr) => ( + newtype_index!(@type[$type] @max[$max] @descr[$descr]); + ); + + // Replace existing default for max + (@type[$type:ident] @max[$_max:expr] @descr[$descr:expr] MAX = $max:expr, $($idents:ident = $constants:expr),*) => ( + newtype_index!(@type[$type] @max[$max] @descr[$descr]); + ); + + // Replace existing default for description (as final param) + (@type[$type:ident] @max[$max:expr] @descr[$_descr:expr] DESCRIPTION = $descr:expr) => ( + newtype_index!(@type[$type] @max[$max] @descr[$descr]); + ); + + // Replace existing default for description + (@type[$type:ident] @max[$max:expr] @descr[$_descr:expr] DESCRIPTION = $descr:expr, $($idents:ident = $constants:expr),*) => ( + newtype_index!(@type[$type] @max[$max] @descr[$descr] $($idents = $constants),*); + ); + + // Assign a user-defined constant (as final param) + (@type[$type:ident] @max[$max:expr] @descr[$descr:expr] $name:ident = $constant:expr) => ( + pub const $name: $type = $type($constant); + newtype_index!(@type[$type] @max[$max] @descr[$descr]); + ); + + // Assign a user-defined constant + (@type[$type:ident] @max[$max:expr] @descr[$descr:expr] $name:ident = $constant:expr, $($idents:ident = $constants:expr),*) => ( + pub const $name: $type = $type($constant); + newtype_index!(@type[$type] @max[$max] @descr[$descr] $($idents = $constants),*); + ); + + // ---- public rules ---- + + // Use default constants + ($name:ident) => ( + newtype_index!( + @type[$name] + @max[::std::u32::MAX] + @descr[unsafe {::std::intrinsics::type_name::<$name>() }]); + ); + + // Define any constants + ($name:ident, const { $($idents:ident = $constants:expr,)+ }) => ( + newtype_index!( + @type[$name] + @max[::std::u32::MAX] + @descr[unsafe {::std::intrinsics::type_name::<$name>() }] + $($idents = $constants),+); + ); + + // Rewrite missing trailing comma in const to version with trailing comma + ($name:ident, const { $($idents:ident = $constants:expr),+ }) => ( + newtype_index!($name, const { $($idents = $constants,)+ }); + ); } #[derive(Clone, PartialEq, Eq)] From 911d95bfe3076f2ed61798a1cf7373db9852c64f Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Sun, 8 Oct 2017 21:57:03 +0100 Subject: [PATCH 105/365] Don't panic in the coordinator thread, bubble up the failure Fixes #43402 (take 2) --- src/librustc_trans/back/write.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 1988b9f76e4..de07ee8b36f 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1192,7 +1192,7 @@ fn start_executing_work(tcx: TyCtxt, modules_config: Arc, metadata_config: Arc, allocator_config: Arc) - -> thread::JoinHandle { + -> thread::JoinHandle> { let coordinator_send = tcx.tx_to_llvm_workers.clone(); let mut exported_symbols = FxHashMap(); exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE)); @@ -1638,7 +1638,7 @@ fn start_executing_work(tcx: TyCtxt, Message::Done { result: Err(()), worker_id: _ } => { shared_emitter.fatal("aborting due to worker thread failure"); // Exit the coordinator thread - panic!("aborting due to worker thread failure") + return Err(()) } Message::TranslateItem => { bug!("the coordinator should not receive translation requests") @@ -1664,11 +1664,11 @@ fn start_executing_work(tcx: TyCtxt, let compiled_metadata_module = compiled_metadata_module .expect("Metadata module not compiled?"); - CompiledModules { + Ok(CompiledModules { modules: compiled_modules, metadata_module: compiled_metadata_module, allocator_module: compiled_allocator_module, - } + }) }); // A heuristic that determines if we have enough LLVM WorkItems in the @@ -1960,7 +1960,7 @@ pub struct OngoingCrateTranslation { coordinator_send: Sender>, trans_worker_receive: Receiver, shared_emitter_main: SharedEmitterMain, - future: thread::JoinHandle, + future: thread::JoinHandle>, output_filenames: Arc, } @@ -1968,7 +1968,11 @@ impl OngoingCrateTranslation { pub fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation { self.shared_emitter_main.check(sess, true); let compiled_modules = match self.future.join() { - Ok(compiled_modules) => compiled_modules, + Ok(Ok(compiled_modules)) => compiled_modules, + Ok(Err(())) => { + sess.abort_if_errors(); + panic!("expected abort due to worker thread errors") + }, Err(_) => { sess.fatal("Error during translation/LLVM phase."); } From 32c4b714715338e82711e3611681aada3f28cf39 Mon Sep 17 00:00:00 2001 From: Pirh Date: Sun, 8 Oct 2017 22:11:20 +0100 Subject: [PATCH 106/365] Link std::process::Output to Command and Child --- src/libstd/process.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index dbb58991215..847dbd14dd6 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -701,7 +701,14 @@ impl AsInnerMut for Command { fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner } } -/// The output of a finished process. +/// The output of a finished process. This is returned in a Result by +/// either the [`output`] method of a [`Command`], or the +/// [`wait_with_output`] method of a [`Child`] process. +/// +/// [`Command`]: struct.Command.html +/// [`Child`]: struct.Child.html +/// [`output`]: struct.Command.html#method.output +/// [`wait_with_output`]: struct.Child.html#method.wait_with_output #[derive(PartialEq, Eq, Clone)] #[stable(feature = "process", since = "1.0.0")] pub struct Output { From 41320fa52e1e4dd85a200a34195ae32d7efd13e0 Mon Sep 17 00:00:00 2001 From: JLockerman Date: Sun, 8 Oct 2017 18:40:45 -0400 Subject: [PATCH 107/365] cfg out Queue::new for emscripten Queue::new is only used is tests atm, which causes warnings on emscripten which does not run queue tests. --- src/libstd/sync/mpsc/spsc_queue.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index 3ce59270335..45a00978b35 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -76,7 +76,7 @@ impl Node { } impl Queue { - #[cfg(test)] + #[cfg(all(test, not(target_os = "emscripten")))] /// Creates a new queue. /// /// This is unsafe as the type system doesn't enforce a single From 1c4add9c7cebc1220cb3c05da88b11830bb16ecd Mon Sep 17 00:00:00 2001 From: johnthagen Date: Sun, 8 Oct 2017 19:11:34 -0400 Subject: [PATCH 108/365] Fix typo in comment --- src/bootstrap/configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 67337bf4421..29eee0442e2 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -346,7 +346,7 @@ for target in configured_targets: targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", target) # Here we walk through the constructed configuration we have from the parsed -# command line arguemnts. We then apply each piece of configuration by +# command line arguments. We then apply each piece of configuration by # basically just doing a `sed` to change the various configuration line to what # we've got configure. def to_toml(value): From 9e569d7671339ceaecfde6e0c86f9494cf1f3d04 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Sun, 8 Oct 2017 19:15:17 -0400 Subject: [PATCH 109/365] Fix typo in README --- 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 e543b8c070b..ebacc62b0fd 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -39,7 +39,7 @@ The script accepts commands, flags, and arguments to determine what to do: ``` If files are dirty that would normally be rebuilt from stage 0, that can be - overidden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps + overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps that belong to stage n or earlier: ``` From dee517a286de6387ad75291f3f8068ada99f2a92 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Sun, 8 Oct 2017 19:28:21 -0400 Subject: [PATCH 110/365] Fix trying to raise a bare str as an exception. This has been deprecated since Python 2.5 --- src/bootstrap/configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 67337bf4421..176e9435528 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -360,7 +360,7 @@ def to_toml(value): elif isinstance(value, str): return "'" + value + "'" else: - raise 'no toml' + raise RuntimeError('no toml') def configure_section(lines, config): for key in config: From 430e875b262b5e14870057004ea9abb4c3a9762d Mon Sep 17 00:00:00 2001 From: johnthagen Date: Sun, 8 Oct 2017 19:36:37 -0400 Subject: [PATCH 111/365] Fix variable name reference --- src/bootstrap/configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 67337bf4421..0a8e57e6225 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -378,7 +378,7 @@ def configure_section(lines, config): for section_key in config: section_config = config[section_key] if not section_key in sections: - raise RuntimeError("config key {} not in sections".format(key)) + raise RuntimeError("config key {} not in sections".format(section_key)) if section_key == 'target': for target in section_config: From d9e67038346d0b3f6509c7d881f1dc63b04cd160 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Sun, 8 Oct 2017 19:46:58 -0400 Subject: [PATCH 112/365] Use identity operator `is` when comparing to None --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4a8c3dcebcb..25768867439 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -498,7 +498,7 @@ class RustBuild(object): If the key does not exists, the result is None: - >>> rb.get_toml("key3") == None + >>> rb.get_toml("key3") is None True """ for line in self.config_toml.splitlines(): From a263a78b28dd1cef60025b0681689d7b6188d693 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Sun, 8 Oct 2017 20:08:11 -0400 Subject: [PATCH 113/365] Fix PEP8 style issues in bootstrap code --- src/bootstrap/bootstrap.py | 1 + src/bootstrap/configure.py | 48 ++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4a8c3dcebcb..918314804cc 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -302,6 +302,7 @@ def default_build_triple(): return "{}-{}".format(cputype, ostype) + class RustBuild(object): """Provide all the methods required to build Rust""" def __init__(self): diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 67337bf4421..6b9356dec56 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -19,6 +19,7 @@ rust_dir = os.path.dirname(rust_dir) sys.path.append(os.path.join(rust_dir, "src", "bootstrap")) import bootstrap + class Option: def __init__(self, name, rustbuild, desc, value): self.name = name @@ -26,14 +27,18 @@ class Option: self.desc = desc self.value = value + options = [] + def o(*args): options.append(Option(*args, value=False)) + def v(*args): options.append(Option(*args, value=True)) + o("debug", "rust.debug", "debug mode; disables optimization unless `--enable-optimize` given") o("docs", "build.docs", "build standard library documentation") o("compiler-docs", "build.compiler-docs", "build compiler documentation") @@ -136,13 +141,16 @@ v("target", None, "GNUs ./configure syntax LLVM target triples") v("set", None, "set arbitrary key/value pairs in TOML configuration") + def p(msg): print("configure: " + msg) + def err(msg): print("configure: error: " + msg) sys.exit(1) + if '--help' in sys.argv or '-h' in sys.argv: print('Usage: ./configure [options]') print('') @@ -208,7 +216,7 @@ while i < len(sys.argv): continue found = True - if not option.name in known_args: + if option.name not in known_args: known_args[option.name] = [] known_args[option.name].append((option, value)) break @@ -227,27 +235,30 @@ if 'option-checking' not in known_args or known_args['option-checking'][1]: # TOML we're going to write out config = {} + def build(): if 'build' in known_args: return known_args['build'][0][1] return bootstrap.default_build_triple() -def set(key, value): - s = "{:20} := {}".format(key, value) - if len(s) < 70: - p(s) - else: - p(s[:70] + " ...") - arr = config - parts = key.split('.') - for i, part in enumerate(parts): - if i == len(parts) - 1: - arr[part] = value - else: - if not part in arr: - arr[part] = {} - arr = arr[part] +def set(key, value): + s = "{:20} := {}".format(key, value) + if len(s) < 70: + p(s) + else: + p(s[:70] + " ...") + + arr = config + parts = key.split('.') + for i, part in enumerate(parts): + if i == len(parts) - 1: + arr[part] = value + else: + if part not in arr: + arr[part] = {} + arr = arr[part] + for key in known_args: # The `set` option is special and can be passed a bunch of times @@ -345,6 +356,7 @@ for target in configured_targets: targets[target] = sections['target'][:] targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", target) + # Here we walk through the constructed configuration we have from the parsed # command line arguemnts. We then apply each piece of configuration by # basically just doing a `sed` to change the various configuration line to what @@ -362,6 +374,7 @@ def to_toml(value): else: raise 'no toml' + def configure_section(lines, config): for key in config: value = config[key] @@ -375,9 +388,10 @@ def configure_section(lines, config): if not found: raise RuntimeError("failed to find config line for {}".format(key)) + for section_key in config: section_config = config[section_key] - if not section_key in sections: + if section_key not in sections: raise RuntimeError("config key {} not in sections".format(key)) if section_key == 'target': From bb7945e2fe662c86cb8e9e3a93730f20b7480dca Mon Sep 17 00:00:00 2001 From: Joshua Lockerman Date: Fri, 29 Sep 2017 15:58:11 -0400 Subject: [PATCH 114/365] Remove Queue::new. --- src/libstd/sync/mpsc/spsc_queue.rs | 34 +++++------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index 45a00978b35..cc4be92276a 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -75,30 +75,6 @@ impl Node { } } -impl Queue { - #[cfg(all(test, not(target_os = "emscripten")))] - /// Creates a new queue. - /// - /// This is unsafe as the type system doesn't enforce a single - /// consumer-producer relationship. It also allows the consumer to `pop` - /// items while there is a `peek` active due to all methods having a - /// non-mutable receiver. - /// - /// # Arguments - /// - /// * `bound` - This queue implementation is implemented with a linked - /// list, and this means that a push is always a malloc. In - /// order to amortize this cost, an internal cache of nodes is - /// maintained to prevent a malloc from always being - /// necessary. This bound is the limit on the size of the - /// cache (if desired). If the value is 0, then the cache has - /// no bound. Otherwise, the cache will never grow larger than - /// `bound` (although the queue itself could be much larger. - pub unsafe fn new(bound: usize) -> Queue { - Self::with_additions(bound, (), ()) - } -} - impl Queue { /// Creates a new queue. With given additional elements in the producer and @@ -275,7 +251,7 @@ mod tests { #[test] fn smoke() { unsafe { - let queue = Queue::new(0); + let queue = Queue::with_additions(0, (), ()); queue.push(1); queue.push(2); assert_eq!(queue.pop(), Some(1)); @@ -292,7 +268,7 @@ mod tests { #[test] fn peek() { unsafe { - let queue = Queue::new(0); + let queue = Queue::with_additions(0, (), ()); queue.push(vec![1]); // Ensure the borrowchecker works @@ -315,7 +291,7 @@ mod tests { #[test] fn drop_full() { unsafe { - let q: Queue> = Queue::new(0); + let q: Queue> = Queue::with_additions(0, (), ()); q.push(box 1); q.push(box 2); } @@ -324,7 +300,7 @@ mod tests { #[test] fn smoke_bound() { unsafe { - let q = Queue::new(0); + let q = Queue::with_additions(0, (), ()); q.push(1); q.push(2); assert_eq!(q.pop(), Some(1)); @@ -346,7 +322,7 @@ mod tests { } unsafe fn stress_bound(bound: usize) { - let q = Arc::new(Queue::new(bound)); + let q = Arc::new(Queue::with_additions(bound, (), ())); let (tx, rx) = channel(); let q2 = q.clone(); From 8240b872e42f066dc57ac7c59e2970f7a5456c32 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Sun, 8 Oct 2017 18:46:42 -0700 Subject: [PATCH 115/365] Update grammar to parse current rust syntax --- src/grammar/lexer.l | 73 +++++--- src/grammar/parser-lalr.y | 366 ++++++++++++++++++++++---------------- src/grammar/tokens.h | 18 ++ 3 files changed, 271 insertions(+), 186 deletions(-) diff --git a/src/grammar/lexer.l b/src/grammar/lexer.l index 91652bfdf24..2f282c8281d 100644 --- a/src/grammar/lexer.l +++ b/src/grammar/lexer.l @@ -85,16 +85,23 @@ ident [a-zA-Z\x80-\xff_][a-zA-Z0-9\x80-\xff_]* (.|\n) { } _ { return UNDERSCORE; } +abstract { return ABSTRACT; } +alignof { return ALIGNOF; } as { return AS; } +become { return BECOME; } box { return BOX; } break { return BREAK; } +catch { return CATCH; } const { return CONST; } continue { return CONTINUE; } crate { return CRATE; } +default { return DEFAULT; } +do { return DO; } else { return ELSE; } enum { return ENUM; } extern { return EXTERN; } false { return FALSE; } +final { return FINAL; } fn { return FN; } for { return FOR; } if { return IF; } @@ -102,26 +109,36 @@ impl { return IMPL; } in { return IN; } let { return LET; } loop { return LOOP; } +macro { return MACRO; } match { return MATCH; } mod { return MOD; } move { return MOVE; } mut { return MUT; } +offsetof { return OFFSETOF; } +override { return OVERRIDE; } priv { return PRIV; } proc { return PROC; } +pure { return PURE; } pub { return PUB; } ref { return REF; } return { return RETURN; } self { return SELF; } +sizeof { return SIZEOF; } static { return STATIC; } struct { return STRUCT; } +super { return SUPER; } trait { return TRAIT; } true { return TRUE; } type { return TYPE; } typeof { return TYPEOF; } +union { return UNION; } unsafe { return UNSAFE; } +unsized { return UNSIZED; } use { return USE; } +virtual { return VIRTUAL; } where { return WHERE; } while { return WHILE; } +yield { return YIELD; } {ident} { return IDENT; } @@ -189,25 +206,25 @@ while { return WHILE; } \>\>= { return SHREQ; } \> { return '>'; } -\x27 { BEGIN(ltorchar); yymore(); } -static { BEGIN(INITIAL); return STATIC_LIFETIME; } -{ident} { BEGIN(INITIAL); return LIFETIME; } -\\[nrt\\\x27\x220]\x27 { BEGIN(suffix); return LIT_CHAR; } -\\x[0-9a-fA-F]{2}\x27 { BEGIN(suffix); return LIT_CHAR; } -\\u\{[0-9a-fA-F]?{6}\}\x27 { BEGIN(suffix); return LIT_CHAR; } -.\x27 { BEGIN(suffix); return LIT_CHAR; } -[\x80-\xff]{2,4}\x27 { BEGIN(suffix); return LIT_CHAR; } -<> { BEGIN(INITIAL); return -1; } +\x27 { BEGIN(ltorchar); yymore(); } +static { BEGIN(INITIAL); return STATIC_LIFETIME; } +{ident} { BEGIN(INITIAL); return LIFETIME; } +\\[nrt\\\x27\x220]\x27 { BEGIN(suffix); return LIT_CHAR; } +\\x[0-9a-fA-F]{2}\x27 { BEGIN(suffix); return LIT_CHAR; } +\\u\{([0-9a-fA-F]_*){1,6}\}\x27 { BEGIN(suffix); return LIT_CHAR; } +.\x27 { BEGIN(suffix); return LIT_CHAR; } +[\x80-\xff]{2,4}\x27 { BEGIN(suffix); return LIT_CHAR; } +<> { BEGIN(INITIAL); return -1; } b\x22 { BEGIN(bytestr); yymore(); } \x22 { BEGIN(suffix); return LIT_BYTE_STR; } -<> { return -1; } -\\[n\nrt\\\x27\x220] { yymore(); } -\\x[0-9a-fA-F]{2} { yymore(); } -\\u\{[0-9a-fA-F]?{6}\} { yymore(); } -\\[^n\nrt\\\x27\x220] { return -1; } -(.|\n) { yymore(); } +<> { return -1; } +\\[n\nrt\\\x27\x220] { yymore(); } +\\x[0-9a-fA-F]{2} { yymore(); } +\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } +\\[^n\nrt\\\x27\x220] { return -1; } +(.|\n) { yymore(); } br\x22 { BEGIN(rawbytestr_nohash); yymore(); } \x22 { BEGIN(suffix); return LIT_BYTE_STR_RAW; } @@ -252,13 +269,13 @@ br/# { } <> { return -1; } -b\x27 { BEGIN(byte); yymore(); } -\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\x[0-9a-fA-F]{2}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\u[0-9a-fA-F]{4}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -\\U[0-9a-fA-F]{8}\x27 { BEGIN(INITIAL); return LIT_BYTE; } -.\x27 { BEGIN(INITIAL); return LIT_BYTE; } -<> { BEGIN(INITIAL); return -1; } +b\x27 { BEGIN(byte); yymore(); } +\\[nrt\\\x27\x220]\x27 { BEGIN(INITIAL); return LIT_BYTE; } +\\x[0-9a-fA-F]{2}\x27 { BEGIN(INITIAL); return LIT_BYTE; } +\\u([0-9a-fA-F]_*){4}\x27 { BEGIN(INITIAL); return LIT_BYTE; } +\\U([0-9a-fA-F]_*){8}\x27 { BEGIN(INITIAL); return LIT_BYTE; } +.\x27 { BEGIN(INITIAL); return LIT_BYTE; } +<> { BEGIN(INITIAL); return -1; } r\x22 { BEGIN(rawstr); yymore(); } \x22 { BEGIN(suffix); return LIT_STR_RAW; } @@ -310,12 +327,12 @@ r/# { \x22 { BEGIN(str); yymore(); } \x22 { BEGIN(suffix); return LIT_STR; } -<> { return -1; } -\\[n\nr\rt\\\x27\x220] { yymore(); } -\\x[0-9a-fA-F]{2} { yymore(); } -\\u\{[0-9a-fA-F]?{6}\} { yymore(); } -\\[^n\nrt\\\x27\x220] { return -1; } -(.|\n) { yymore(); } +<> { return -1; } +\\[n\nr\rt\\\x27\x220] { yymore(); } +\\x[0-9a-fA-F]{2} { yymore(); } +\\u\{([0-9a-fA-F]_*){1,6}\} { yymore(); } +\\[^n\nrt\\\x27\x220] { return -1; } +(.|\n) { yymore(); } \<- { return LARROW; } -\> { return RARROW; } diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y index c9fcdf7647b..de1f96aac50 100644 --- a/src/grammar/parser-lalr.y +++ b/src/grammar/parser-lalr.y @@ -62,13 +62,19 @@ extern char *yytext; // keywords %token SELF %token STATIC +%token ABSTRACT +%token ALIGNOF %token AS +%token BECOME %token BREAK +%token CATCH %token CRATE +%token DO %token ELSE %token ENUM %token EXTERN %token FALSE +%token FINAL %token FN %token FOR %token IF @@ -76,19 +82,29 @@ extern char *yytext; %token IN %token LET %token LOOP +%token MACRO %token MATCH %token MOD %token MOVE %token MUT +%token OFFSETOF +%token OVERRIDE %token PRIV %token PUB +%token PURE %token REF %token RETURN +%token SIZEOF %token STRUCT +%token SUPER +%token UNION +%token UNSIZED %token TRUE %token TRAIT %token TYPE %token UNSAFE +%token VIRTUAL +%token YIELD %token DEFAULT %token USE %token WHILE @@ -141,6 +157,10 @@ extern char *yytext; // 'foo:bar . <' is shifted (in a trait reference occurring in a // bounds list), parsing as foo:(bar) rather than (foo:bar). %precedence IDENT + // Put the weak keywords that can be used as idents here as well +%precedence CATCH +%precedence DEFAULT +%precedence UNION // A couple fake-precedence symbols to use in rules associated with + // and < in trailing type contexts. These come up when you have a type @@ -161,13 +181,13 @@ extern char *yytext; %precedence FOR // Binops & unops, and their precedences +%precedence '?' %precedence BOX -%precedence BOXPLACE %nonassoc DOTDOT // RETURN needs to be lower-precedence than tokens that start // prefix_exprs -%precedence RETURN +%precedence RETURN YIELD %right '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ %right LARROW @@ -321,6 +341,8 @@ view_path | path_no_types_allowed MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 2, $1, $4); } | MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $3); } | path_no_types_allowed MOD_SEP '*' { $$ = mk_node("ViewPathGlob", 1, $1); } +| MOD_SEP '*' { $$ = mk_atom("ViewPathGlob"); } +| '*' { $$ = mk_atom("ViewPathGlob"); } | '{' '}' { $$ = mk_atom("ViewPathListEmpty"); } | '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 1, $2); } | '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $2); } @@ -334,6 +356,7 @@ block_item | item_foreign_mod { $$ = mk_node("ItemForeignMod", 1, $1); } | item_struct | item_enum +| item_union | item_trait | item_impl ; @@ -387,6 +410,7 @@ struct_decl_field struct_tuple_fields : struct_tuple_field { $$ = mk_node("StructFields", 1, $1); } | struct_tuple_fields ',' struct_tuple_field { $$ = ext_node($1, 1, $3); } +| %empty { $$ = mk_none(); } ; struct_tuple_field @@ -417,6 +441,11 @@ enum_args | %empty { $$ = mk_none(); } ; +// unions +item_union +: UNION ident generic_params maybe_where_clause '{' struct_decl_fields '}' { $$ = mk_node("ItemUnion", 0); } +| UNION ident generic_params maybe_where_clause '{' struct_decl_fields ',' '}' { $$ = mk_node("ItemUnion", 0); } + item_mod : MOD ident ';' { $$ = mk_node("ItemMod", 1, $2); } | MOD ident '{' maybe_mod_items '}' { $$ = mk_node("ItemMod", 2, $2, $4); } @@ -475,7 +504,7 @@ visibility idents_or_self : ident_or_self { $$ = mk_node("IdentsOrSelf", 1, $1); } -| ident_or_self AS ident { $$ = mk_node("IdentsOrSelf", 2, $1, $3); } +| idents_or_self AS ident { $$ = mk_node("IdentsOrSelf", 2, $1, $3); } | idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); } ; @@ -515,6 +544,7 @@ trait_item : trait_const | trait_type | trait_method +| maybe_outer_attrs item_macro { $$ = mk_node("TraitMacroItem", 2, $1, $2); } ; trait_const @@ -547,36 +577,48 @@ trait_method ; type_method -: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' +: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' { $$ = mk_node("TypeMethod", 6, $1, $2, $4, $5, $6, $7); } -| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' +| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' +{ + $$ = mk_node("TypeMethod", 6, $1, $3, $5, $6, $7, $8); +} +| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';' { $$ = mk_node("TypeMethod", 7, $1, $2, $4, $6, $7, $8, $9); } ; method -: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block +: maybe_outer_attrs maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block { $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8); } -| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block +| maybe_outer_attrs CONST maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("Method", 7, $1, $3, $5, $6, $7, $8, $9); +} +| maybe_outer_attrs maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block { $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10); } ; impl_method -: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block +: attrs_and_vis maybe_default maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block { - $$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8); + $$ = mk_node("Method", 8, $1, $2, $3, $5, $6, $7, $8, $9); } -| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block +| attrs_and_vis maybe_default CONST maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block { $$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10); } +| attrs_and_vis maybe_default maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("Method", 9, $1, $2, $3, $5, $7, $8, $9, $10, $11); +} ; // There are two forms of impl: @@ -638,12 +680,17 @@ impl_item | impl_type ; +maybe_default +: DEFAULT { $$ = mk_atom("Default"); } +| %empty { $$ = mk_none(); } +; + impl_const -: attrs_and_vis item_const { $$ = mk_node("ImplConst", 1, $1, $2); } +: attrs_and_vis maybe_default item_const { $$ = mk_node("ImplConst", 3, $1, $2, $3); } ; impl_type -: attrs_and_vis TYPE ident generic_params '=' ty_sum ';' { $$ = mk_node("ImplType", 4, $1, $3, $4, $6); } +: attrs_and_vis maybe_default TYPE ident generic_params '=' ty_sum ';' { $$ = mk_node("ImplType", 5, $1, $2, $4, $5, $7); } ; item_fn @@ -651,6 +698,10 @@ item_fn { $$ = mk_node("ItemFn", 5, $2, $3, $4, $5, $6); } +| CONST FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("ItemFn", 5, $3, $4, $5, $6, $7); +} ; item_unsafe_fn @@ -658,6 +709,10 @@ item_unsafe_fn { $$ = mk_node("ItemUnsafeFn", 5, $3, $4, $5, $6, $7); } +| CONST UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block +{ + $$ = mk_node("ItemUnsafeFn", 5, $4, $5, $6, $7, $8); +} | UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block { $$ = mk_node("ItemUnsafeFn", 6, $3, $5, $6, $7, $8, $9); @@ -723,12 +778,6 @@ inferrable_param : pat maybe_ty_ascription { $$ = mk_node("InferrableParam", 2, $1, $2); } ; -maybe_unboxed_closure_kind -: %empty -| ':' -| '&' maybe_mut ':' -; - maybe_comma_params : ',' { $$ = mk_none(); } | ',' params { $$ = $2; } @@ -784,7 +833,8 @@ ret_ty ; generic_params -: '<' lifetimes '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } +: '<' '>' { $$ = mk_node("Generics", 2, mk_none(), mk_none()); } +| '<' lifetimes '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } | '<' lifetimes ',' '>' { $$ = mk_node("Generics", 2, $2, mk_none()); } | '<' lifetimes SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); } | '<' lifetimes ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); } @@ -837,6 +887,8 @@ path_no_types_allowed | MOD_SEP ident { $$ = mk_node("ViewPath", 1, $2); } | SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); } | MOD_SEP SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); } +| SUPER { $$ = mk_node("ViewPath", 1, mk_atom("Super")); } +| MOD_SEP SUPER { $$ = mk_node("ViewPath", 1, mk_atom("Super")); } | path_no_types_allowed MOD_SEP ident { $$ = ext_node($1, 1, $3); } ; @@ -882,7 +934,7 @@ generic_args ; generic_values -: maybe_lifetimes maybe_ty_sums_and_or_bindings { $$ = mk_node("GenericValues", 2, $1, $2); } +: maybe_ty_sums_and_or_bindings { $$ = mk_node("GenericValues", 1, $1); } ; maybe_ty_sums_and_or_bindings @@ -910,12 +962,11 @@ pat | ANDAND pat { $$ = mk_node("PatRegion", 1, mk_node("PatRegion", 1, $2)); } | '(' ')' { $$ = mk_atom("PatUnit"); } | '(' pat_tup ')' { $$ = mk_node("PatTup", 1, $2); } -| '(' pat_tup ',' ')' { $$ = mk_node("PatTup", 1, $2); } | '[' pat_vec ']' { $$ = mk_node("PatVec", 1, $2); } | lit_or_path | lit_or_path DOTDOTDOT lit_or_path { $$ = mk_node("PatRange", 2, $1, $3); } | path_expr '{' pat_struct '}' { $$ = mk_node("PatStruct", 2, $1, $3); } -| path_expr '(' DOTDOT ')' { $$ = mk_node("PatEnum", 1, $1); } +| path_expr '(' ')' { $$ = mk_node("PatEnum", 2, $1, mk_none()); } | path_expr '(' pat_tup ')' { $$ = mk_node("PatEnum", 2, $1, $3); } | path_expr '!' maybe_ident delimited_token_trees { $$ = mk_node("PatMac", 3, $1, $3, $4); } | binding_mode ident { $$ = mk_node("PatIdent", 2, $1, $2); } @@ -953,6 +1004,7 @@ pat_field | BOX binding_mode ident { $$ = mk_node("PatField", 3, mk_atom("box"), $2, $3); } | ident ':' pat { $$ = mk_node("PatField", 2, $1, $3); } | binding_mode ident ':' pat { $$ = mk_node("PatField", 3, $1, $2, $4); } +| LIT_INTEGER ':' pat { $$ = mk_node("PatField", 2, mk_atom(yytext), $3); } ; pat_fields @@ -965,11 +1017,26 @@ pat_struct | pat_fields ',' { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); } | pat_fields ',' DOTDOT { $$ = mk_node("PatStruct", 2, $1, mk_atom("true")); } | DOTDOT { $$ = mk_node("PatStruct", 1, mk_atom("true")); } +| %empty { $$ = mk_node("PatStruct", 1, mk_none()); } ; pat_tup -: pat { $$ = mk_node("pat_tup", 1, $1); } -| pat_tup ',' pat { $$ = ext_node($1, 1, $3); } +: pat_tup_elts { $$ = mk_node("PatTup", 2, $1, mk_none()); } +| pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, mk_none()); } +| pat_tup_elts DOTDOT { $$ = mk_node("PatTup", 2, $1, mk_none()); } +| pat_tup_elts ',' DOTDOT { $$ = mk_node("PatTup", 2, $1, mk_none()); } +| pat_tup_elts DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, $1, $4); } +| pat_tup_elts DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, $4); } +| pat_tup_elts ',' DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, $1, $5); } +| pat_tup_elts ',' DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, $1, $5); } +| DOTDOT ',' pat_tup_elts { $$ = mk_node("PatTup", 2, mk_none(), $3); } +| DOTDOT ',' pat_tup_elts ',' { $$ = mk_node("PatTup", 2, mk_none(), $3); } +| DOTDOT { $$ = mk_node("PatTup", 2, mk_none(), mk_none()); } +; + +pat_tup_elts +: pat { $$ = mk_node("PatTupElts", 1, $1); } +| pat_tup_elts ',' pat { $$ = ext_node($1, 1, $3); } ; pat_vec @@ -1007,24 +1074,25 @@ ty ; ty_prim -: %prec IDENT path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), $1); } -| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), $2); } -| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), $3); } -| BOX ty { $$ = mk_node("TyBox", 1, $2); } -| '*' maybe_mut_or_const ty { $$ = mk_node("TyPtr", 2, $2, $3); } -| '&' ty { $$ = mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2); } -| '&' MUT ty { $$ = mk_node("TyRptr", 2, mk_atom("MutMutable"), $3); } -| ANDAND ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2)); } -| ANDAND MUT ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), $3)); } -| '&' lifetime maybe_mut ty { $$ = mk_node("TyRptr", 3, $2, $3, $4); } -| ANDAND lifetime maybe_mut ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 3, $2, $3, $4)); } -| '[' ty ']' { $$ = mk_node("TyVec", 1, $2); } -| '[' ty ',' DOTDOT expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $5); } -| '[' ty ';' expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $4); } -| TYPEOF '(' expr ')' { $$ = mk_node("TyTypeof", 1, $3); } -| UNDERSCORE { $$ = mk_atom("TyInfer"); } +: %prec IDENT path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), $1); } +| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), $2); } +| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), $3); } +| %prec IDENT path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node("TyMacro", 3, $1, $3, $4); } +| %prec IDENT MOD_SEP path_generic_args_without_colons '!' maybe_ident delimited_token_trees { $$ = mk_node("TyMacro", 3, $2, $4, $5); } +| BOX ty { $$ = mk_node("TyBox", 1, $2); } +| '*' maybe_mut_or_const ty { $$ = mk_node("TyPtr", 2, $2, $3); } +| '&' ty { $$ = mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2); } +| '&' MUT ty { $$ = mk_node("TyRptr", 2, mk_atom("MutMutable"), $3); } +| ANDAND ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2)); } +| ANDAND MUT ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), $3)); } +| '&' lifetime maybe_mut ty { $$ = mk_node("TyRptr", 3, $2, $3, $4); } +| ANDAND lifetime maybe_mut ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 3, $2, $3, $4)); } +| '[' ty ']' { $$ = mk_node("TyVec", 1, $2); } +| '[' ty ',' DOTDOT expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $5); } +| '[' ty ';' expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $4); } +| TYPEOF '(' expr ')' { $$ = mk_node("TyTypeof", 1, $3); } +| UNDERSCORE { $$ = mk_atom("TyInfer"); } | ty_bare_fn -| ty_proc | for_in_type ; @@ -1046,17 +1114,12 @@ ty_closure | OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $2, $3); } ; -ty_proc -: PROC generic_params fn_params maybe_bounds ret_ty { $$ = mk_node("TyProc", 4, $2, $3, $4, $5); } -; - for_in_type : FOR '<' maybe_lifetimes '>' for_in_type_suffix { $$ = mk_node("ForInType", 2, $3, $5); } ; for_in_type_suffix -: ty_proc -| ty_bare_fn +: ty_bare_fn | trait_ref | ty_closure ; @@ -1100,13 +1163,23 @@ ty_sums ; ty_sum -: ty { $$ = mk_node("TySum", 1, $1); } -| ty '+' ty_param_bounds { $$ = mk_node("TySum", 2, $1, $3); } +: ty_sum_elt { $$ = mk_node("TySum", 1, $1); } +| ty_sum '+' ty_sum_elt { $$ = ext_node($1, 1, $3); } +; + +ty_sum_elt +: ty +| lifetime ; ty_prim_sum -: ty_prim { $$ = mk_node("TySum", 1, $1); } -| ty_prim '+' ty_param_bounds { $$ = mk_node("TySum", 2, $1, $3); } +: ty_prim_sum_elt { $$ = mk_node("TySum", 1, $1); } +| ty_prim_sum '+' ty_prim_sum_elt { $$ = ext_node($1, 1, $3); } +; + +ty_prim_sum_elt +: ty_prim +| lifetime ; maybe_ty_param_bounds @@ -1127,6 +1200,7 @@ boundseq polybound : FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $3, $5); } | bound +| '?' FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $4, $6); } | '?' bound { $$ = $2; } ; @@ -1244,11 +1318,6 @@ maybe_stmts // block, nonblock-prefix, and nonblock-nonprefix. // // In non-stmts contexts, expr can relax this trichotomy. -// -// There is also one other expr subtype: nonparen_expr disallows exprs -// surrounded by parens (including tuple expressions), this is -// necessary for BOX (place) expressions, so a parens expr following -// the BOX is always parsed as the place. stmts : stmt { $$ = mk_node("stmts", 1, $1); } @@ -1256,14 +1325,15 @@ stmts ; stmt -: let +: maybe_outer_attrs let { $$ = $2; } | stmt_item | PUB stmt_item { $$ = $2; } | outer_attrs stmt_item { $$ = $2; } | outer_attrs PUB stmt_item { $$ = $3; } | full_block_expr -| block -| nonblock_expr ';' +| maybe_outer_attrs block { $$ = $2; } +| nonblock_expr ';' +| outer_attrs nonblock_expr ';' { $$ = $2; } | ';' { $$ = mk_none(); } ; @@ -1296,7 +1366,9 @@ path_expr // expressions. path_generic_args_with_colons : ident { $$ = mk_node("components", 1, $1); } +| SUPER { $$ = mk_atom("Super"); } | path_generic_args_with_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); } +| path_generic_args_with_colons MOD_SEP SUPER { $$ = ext_node($1, 1, mk_atom("Super")); } | path_generic_args_with_colons MOD_SEP generic_args { $$ = ext_node($1, 1, $3); } ; @@ -1313,6 +1385,7 @@ nonblock_expr | SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } | macro_expr { $$ = mk_node("ExprMac", 1, $1); } | path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } +| nonblock_expr '?' { $$ = mk_node("ExprTry", 1, $1); } | nonblock_expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } | nonblock_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } | nonblock_expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } @@ -1325,6 +1398,8 @@ nonblock_expr | RETURN expr { $$ = mk_node("ExprRet", 1, $2); } | BREAK { $$ = mk_node("ExprBreak", 0); } | BREAK lifetime { $$ = mk_node("ExprBreak", 1, $2); } +| YIELD { $$ = mk_node("ExprYield", 0); } +| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } | nonblock_expr LARROW expr { $$ = mk_node("ExprInPlace", 2, $1, $3); } | nonblock_expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } | nonblock_expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } @@ -1360,8 +1435,8 @@ nonblock_expr | DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } | DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } | nonblock_expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); } -| %prec BOXPLACE BOX '(' maybe_expr ')' nonblock_expr { $$ = mk_node("ExprBox", 2, $3, $5); } +| nonblock_expr ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } +| BOX expr { $$ = mk_node("ExprBox", 1, $2); } | expr_qualified_path | nonblock_prefix_expr ; @@ -1373,6 +1448,7 @@ expr | SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } | macro_expr { $$ = mk_node("ExprMac", 1, $1); } | path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } +| expr '?' { $$ = mk_node("ExprTry", 1, $1); } | expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } | expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } | expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } @@ -1385,6 +1461,8 @@ expr | RETURN expr { $$ = mk_node("ExprRet", 1, $2); } | BREAK { $$ = mk_node("ExprBreak", 0); } | BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } +| YIELD { $$ = mk_node("ExprYield", 0); } +| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } | expr LARROW expr { $$ = mk_node("ExprInPlace", 2, $1, $3); } | expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); } | expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } @@ -1420,69 +1498,8 @@ expr | DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } | DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } | expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); } -| %prec BOXPLACE BOX '(' maybe_expr ')' expr { $$ = mk_node("ExprBox", 2, $3, $5); } -| expr_qualified_path -| block_expr -| block -| nonblock_prefix_expr -; - -nonparen_expr -: lit { $$ = mk_node("ExprLit", 1, $1); } -| %prec IDENT - path_expr { $$ = mk_node("ExprPath", 1, $1); } -| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } -| macro_expr { $$ = mk_node("ExprMac", 1, $1); } -| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); } -| nonparen_expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } -| nonparen_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } -| nonparen_expr '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } -| nonparen_expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); } -| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); } -| CONTINUE { $$ = mk_node("ExprAgain", 0); } -| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); } -| RETURN { $$ = mk_node("ExprRet", 0); } -| RETURN expr { $$ = mk_node("ExprRet", 1, $2); } -| BREAK { $$ = mk_node("ExprBreak", 0); } -| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } -| nonparen_expr LARROW nonparen_expr { $$ = mk_node("ExprInPlace", 2, $1, $3); } -| nonparen_expr '=' nonparen_expr { $$ = mk_node("ExprAssign", 2, $1, $3); } -| nonparen_expr SHLEQ nonparen_expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); } -| nonparen_expr SHREQ nonparen_expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); } -| nonparen_expr MINUSEQ nonparen_expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); } -| nonparen_expr ANDEQ nonparen_expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); } -| nonparen_expr OREQ nonparen_expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); } -| nonparen_expr PLUSEQ nonparen_expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); } -| nonparen_expr STAREQ nonparen_expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); } -| nonparen_expr SLASHEQ nonparen_expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); } -| nonparen_expr CARETEQ nonparen_expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); } -| nonparen_expr PERCENTEQ nonparen_expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); } -| nonparen_expr OROR nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); } -| nonparen_expr ANDAND nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); } -| nonparen_expr EQEQ nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); } -| nonparen_expr NE nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); } -| nonparen_expr '<' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); } -| nonparen_expr '>' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); } -| nonparen_expr LE nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); } -| nonparen_expr GE nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); } -| nonparen_expr '|' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); } -| nonparen_expr '^' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); } -| nonparen_expr '&' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); } -| nonparen_expr SHL nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); } -| nonparen_expr SHR nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); } -| nonparen_expr '+' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); } -| nonparen_expr '-' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); } -| nonparen_expr '*' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); } -| nonparen_expr '/' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); } -| nonparen_expr '%' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); } -| nonparen_expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); } -| nonparen_expr DOTDOT nonparen_expr { $$ = mk_node("ExprRange", 2, $1, $3); } -| DOTDOT nonparen_expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); } -| DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } -| nonparen_expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); } -| %prec BOXPLACE BOX '(' maybe_expr ')' expr { $$ = mk_node("ExprBox", 1, $3, $5); } +| expr ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } +| BOX expr { $$ = mk_node("ExprBox", 1, $2); } | expr_qualified_path | block_expr | block @@ -1495,6 +1512,7 @@ expr_nostruct path_expr { $$ = mk_node("ExprPath", 1, $1); } | SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); } | macro_expr { $$ = mk_node("ExprMac", 1, $1); } +| expr_nostruct '?' { $$ = mk_node("ExprTry", 1, $1); } | expr_nostruct '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); } | expr_nostruct '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } | expr_nostruct '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); } @@ -1507,6 +1525,8 @@ expr_nostruct | RETURN expr { $$ = mk_node("ExprRet", 1, $2); } | BREAK { $$ = mk_node("ExprBreak", 0); } | BREAK ident { $$ = mk_node("ExprBreak", 1, $2); } +| YIELD { $$ = mk_node("ExprYield", 0); } +| YIELD expr { $$ = mk_node("ExprYield", 1, $2); } | expr_nostruct LARROW expr_nostruct { $$ = mk_node("ExprInPlace", 2, $1, $3); } | expr_nostruct '=' expr_nostruct { $$ = mk_node("ExprAssign", 2, $1, $3); } | expr_nostruct SHLEQ expr_nostruct { $$ = mk_node("ExprAssignShl", 2, $1, $3); } @@ -1542,8 +1562,8 @@ expr_nostruct | DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, mk_none(), $2); } | DOTDOT { $$ = mk_node("ExprRange", 2, mk_none(), mk_none()); } | expr_nostruct AS ty { $$ = mk_node("ExprCast", 2, $1, $3); } -| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); } -| %prec BOXPLACE BOX '(' maybe_expr ')' expr_nostruct { $$ = mk_node("ExprBox", 1, $3, $5); } +| expr_nostruct ':' ty { $$ = mk_node("ExprTypeAscr", 2, $1, $3); } +| BOX expr { $$ = mk_node("ExprBox", 1, $2); } | expr_qualified_path | block_expr | block @@ -1558,7 +1578,6 @@ nonblock_prefix_expr_nostruct | ANDAND maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); } | lambda_expr_nostruct | MOVE lambda_expr_nostruct { $$ = $2; } -| proc_expr_nostruct ; nonblock_prefix_expr @@ -1569,7 +1588,6 @@ nonblock_prefix_expr | ANDAND maybe_mut expr { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); } | lambda_expr | MOVE lambda_expr { $$ = $2; } -| proc_expr ; expr_qualified_path @@ -1606,43 +1624,42 @@ maybe_as_trait_ref lambda_expr : %prec LAMBDA - OROR ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } + OROR ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } | %prec LAMBDA - '|' maybe_unboxed_closure_kind '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $4, $5); } + '|' '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $3, $4); } | %prec LAMBDA - '|' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $2, $4, $5); } + '|' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $2, $4, $5); } | %prec LAMBDA - '|' '&' maybe_mut ':' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $5, $7, $8); } + '|' inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $2, mk_none(), $4); } +; + +lambda_expr_no_first_bar +: %prec LAMBDA + '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } | %prec LAMBDA - '|' ':' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $3, $5, $6); } + inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $1, $3, $4); } +| %prec LAMBDA + inferrable_params OROR lambda_expr_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $1, mk_none(), $3); } ; lambda_expr_nostruct : %prec LAMBDA - OROR expr_nostruct { $$ = mk_node("ExprFnBlock", 2, mk_none(), $2); } + OROR expr_nostruct { $$ = mk_node("ExprFnBlock", 2, mk_none(), $2); } | %prec LAMBDA - '|' maybe_unboxed_closure_kind '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, mk_none(), $4); } + '|' '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, mk_none(), $3, $4); } | %prec LAMBDA - '|' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $2, $4); } + '|' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $2, $4); } | %prec LAMBDA - '|' '&' maybe_mut ':' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $5, $7); } -| %prec LAMBDA - '|' ':' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $3, $5); } - + '|' inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $2, mk_none(), $4); } ; -proc_expr +lambda_expr_nostruct_no_first_bar : %prec LAMBDA - PROC '(' ')' expr { $$ = mk_node("ExprProc", 2, mk_none(), $4); } + '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); } | %prec LAMBDA - PROC '(' inferrable_params ')' expr { $$ = mk_node("ExprProc", 2, $3, $5); } -; - -proc_expr_nostruct -: %prec LAMBDA - PROC '(' ')' expr_nostruct { $$ = mk_node("ExprProc", 2, mk_none(), $4); } + inferrable_params '|' ret_ty expr_nostruct { $$ = mk_node("ExprFnBlock", 3, $1, $3, $4); } | %prec LAMBDA - PROC '(' inferrable_params ')' expr_nostruct { $$ = mk_node("ExprProc", 2, $3, $5); } + inferrable_params OROR lambda_expr_nostruct_no_first_bar { $$ = mk_node("ExprFnBlock", 3, $1, mk_none(), $3); } ; vec_expr @@ -1654,6 +1671,7 @@ struct_expr_fields : field_inits | field_inits ',' | maybe_field_inits default_field_init { $$ = ext_node($1, 1, $2); } +| %empty { $$ = mk_none(); } ; maybe_field_inits @@ -1668,7 +1686,9 @@ field_inits ; field_init -: ident ':' expr { $$ = mk_node("FieldInit", 2, $1, $3); } +: ident { $$ = mk_node("FieldInit", 1, $1); } +| ident ':' expr { $$ = mk_node("FieldInit", 2, $1, $3); } +| LIT_INTEGER ':' expr { $$ = mk_node("FieldInit", 2, mk_atom(yytext), $3); } ; default_field_init @@ -1689,10 +1709,18 @@ block_expr full_block_expr : block_expr -| full_block_expr '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } -| full_block_expr '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } -| full_block_expr '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } -| full_block_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } +| block_expr_dot +; + +block_expr_dot +: block_expr '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } +| block_expr_dot '.' path_generic_args_with_colons %prec IDENT { $$ = mk_node("ExprField", 2, $1, $3); } +| block_expr '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } +| block_expr_dot '.' path_generic_args_with_colons '[' maybe_expr ']' { $$ = mk_node("ExprIndex", 3, $1, $3, $5); } +| block_expr '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } +| block_expr_dot '.' path_generic_args_with_colons '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 3, $1, $3, $5); } +| block_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } +| block_expr_dot '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); } ; expr_match @@ -1714,12 +1742,13 @@ match_clause ; nonblock_match_clause -: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr { $$ = mk_node("Arm", 4, $1, $2, $3, $5); } -| maybe_outer_attrs pats_or maybe_guard FAT_ARROW full_block_expr { $$ = mk_node("Arm", 4, $1, $2, $3, $5); } +: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr { $$ = mk_node("ArmNonblock", 4, $1, $2, $3, $5); } +| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr_dot { $$ = mk_node("ArmNonblock", 4, $1, $2, $3, $5); } ; block_match_clause -: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node("Arm", 4, $1, $2, $3, $5); } +: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node("ArmBlock", 4, $1, $2, $3, $5); } +| maybe_outer_attrs pats_or maybe_guard FAT_ARROW block_expr { $$ = mk_node("ArmBlock", 4, $1, $2, $3, $5); } ; maybe_guard @@ -1796,6 +1825,10 @@ maybe_ident ident : IDENT { $$ = mk_node("ident", 1, mk_atom(yytext)); } +// Weak keywords that can be used as identifiers +| CATCH { $$ = mk_node("ident", 1, mk_atom(yytext)); } +| DEFAULT { $$ = mk_node("ident", 1, mk_atom(yytext)); } +| UNION { $$ = mk_node("ident", 1, mk_atom(yytext)); } ; unpaired_token @@ -1836,13 +1869,20 @@ unpaired_token | LIFETIME { $$ = mk_atom(yytext); } | SELF { $$ = mk_atom(yytext); } | STATIC { $$ = mk_atom(yytext); } +| ABSTRACT { $$ = mk_atom(yytext); } +| ALIGNOF { $$ = mk_atom(yytext); } | AS { $$ = mk_atom(yytext); } +| BECOME { $$ = mk_atom(yytext); } | BREAK { $$ = mk_atom(yytext); } +| CATCH { $$ = mk_atom(yytext); } | CRATE { $$ = mk_atom(yytext); } +| DEFAULT { $$ = mk_atom(yytext); } +| DO { $$ = mk_atom(yytext); } | ELSE { $$ = mk_atom(yytext); } | ENUM { $$ = mk_atom(yytext); } | EXTERN { $$ = mk_atom(yytext); } | FALSE { $$ = mk_atom(yytext); } +| FINAL { $$ = mk_atom(yytext); } | FN { $$ = mk_atom(yytext); } | FOR { $$ = mk_atom(yytext); } | IF { $$ = mk_atom(yytext); } @@ -1850,21 +1890,31 @@ unpaired_token | IN { $$ = mk_atom(yytext); } | LET { $$ = mk_atom(yytext); } | LOOP { $$ = mk_atom(yytext); } +| MACRO { $$ = mk_atom(yytext); } | MATCH { $$ = mk_atom(yytext); } | MOD { $$ = mk_atom(yytext); } | MOVE { $$ = mk_atom(yytext); } | MUT { $$ = mk_atom(yytext); } +| OFFSETOF { $$ = mk_atom(yytext); } +| OVERRIDE { $$ = mk_atom(yytext); } | PRIV { $$ = mk_atom(yytext); } | PUB { $$ = mk_atom(yytext); } +| PURE { $$ = mk_atom(yytext); } | REF { $$ = mk_atom(yytext); } | RETURN { $$ = mk_atom(yytext); } | STRUCT { $$ = mk_atom(yytext); } +| SIZEOF { $$ = mk_atom(yytext); } +| SUPER { $$ = mk_atom(yytext); } | TRUE { $$ = mk_atom(yytext); } | TRAIT { $$ = mk_atom(yytext); } | TYPE { $$ = mk_atom(yytext); } +| UNION { $$ = mk_atom(yytext); } | UNSAFE { $$ = mk_atom(yytext); } +| UNSIZED { $$ = mk_atom(yytext); } | USE { $$ = mk_atom(yytext); } +| VIRTUAL { $$ = mk_atom(yytext); } | WHILE { $$ = mk_atom(yytext); } +| YIELD { $$ = mk_atom(yytext); } | CONTINUE { $$ = mk_atom(yytext); } | PROC { $$ = mk_atom(yytext); } | BOX { $$ = mk_atom(yytext); } @@ -1942,4 +1992,4 @@ brackets_delimited_token_trees $2, mk_node("TTTok", 1, mk_atom("]"))); } -; \ No newline at end of file +; diff --git a/src/grammar/tokens.h b/src/grammar/tokens.h index 081bd050259..15ea738ed00 100644 --- a/src/grammar/tokens.h +++ b/src/grammar/tokens.h @@ -30,6 +30,7 @@ enum Token { DOTDOT, DOTDOTDOT, MOD_SEP, + LARROW, RARROW, FAT_ARROW, LIT_BYTE, @@ -47,13 +48,20 @@ enum Token { // keywords SELF, STATIC, + ABSTRACT, + ALIGNOF, AS, + BECOME, BREAK, + CATCH, CRATE, + DEFAULT, + DO, ELSE, ENUM, EXTERN, FALSE, + FINAL, FN, FOR, IF, @@ -61,21 +69,31 @@ enum Token { IN, LET, LOOP, + MACRO, MATCH, MOD, MOVE, MUT, + OFFSETOF, + OVERRIDE, PRIV, PUB, + PURE, REF, RETURN, + SIZEOF, STRUCT, + SUPER, + UNION, TRUE, TRAIT, TYPE, UNSAFE, + UNSIZED, USE, + VIRTUAL, WHILE, + YIELD, CONTINUE, PROC, BOX, From 53a648522b0263aa13752b78c9e27464d6caf579 Mon Sep 17 00:00:00 2001 From: k0pernicus Date: Thu, 5 Oct 2017 22:34:49 +0200 Subject: [PATCH 116/365] New rebase for the issue #45022 Add pretty printer files into test execution time-stamping Move find_rust_src_path() as a method for Config Move find_rust_src_path() as a method for Config Call find_rust_src_path() from Config Move find_rust_src_path() from common.rs to header.rs Add pretty printer files as relevant files to get up_to_date information Remove dead code Add two pretty printer files to keep a close watch on Move find_rust_src_path() as a method for Config Move find_rust_src_path() as a method for Config Call find_rust_src_path() from Config Move find_rust_src_path() from common.rs to header.rs Remove dead code Add two pretty printer files to keep a close watch on --- src/tools/compiletest/src/header.rs | 13 ++++++++++ src/tools/compiletest/src/main.rs | 27 +++++++++++++++------ src/tools/compiletest/src/runtest.rs | 36 +++++++++++----------------- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index bb9bf57d55e..19195838791 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -567,6 +567,19 @@ impl Config { None } } + + pub fn find_rust_src_root(&self) -> Option { + let mut path = self.src_base.clone(); + let path_postfix = Path::new("src/etc/lldb_batchmode.py"); + + while path.pop() { + if path.join(&path_postfix).is_file() { + return Some(path); + } + } + + None + } } pub fn lldb_version_to_int(version_string: &str) -> isize { diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 26c447d01d3..306497da9e3 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -489,15 +489,28 @@ fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf { } fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> bool { + let rust_src_dir = config.find_rust_src_root().expect( + "Could not find Rust source root", + ); let stamp = mtime(&stamp(config, testpaths)); - let mut inputs = vec![ - mtime(&testpaths.file), - mtime(&config.rustc_path), - ]; + let mut inputs = vec![mtime(&testpaths.file), mtime(&config.rustc_path)]; for aux in props.aux.iter() { - inputs.push(mtime(&testpaths.file.parent().unwrap() - .join("auxiliary") - .join(aux))); + inputs.push(mtime( + &testpaths.file.parent().unwrap().join("auxiliary").join( + aux, + ), + )); + } + // Relevant pretty printer files + let pretty_printer_files = [ + "src/etc/debugger_pretty_printers_common.py", + "src/etc/gdb_load_rust_pretty_printers.py", + "src/etc/gdb_rust_pretty_printing.py", + "src/etc/lldb_batchmode.py", + "src/etc/lldb_rust_formatters.py", + ]; + for pretty_printer_file in &pretty_printer_files { + inputs.push(mtime(&rust_src_dir.join(pretty_printer_file))); } for lib in config.run_lib_path.read_dir().unwrap() { let lib = lib.unwrap(); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 10ef326d9db..870e08cc6e5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -571,9 +571,10 @@ actual:\n\ } } - _=> { - let rust_src_root = self.find_rust_src_root() - .expect("Could not find Rust source root"); + _ => { + let rust_src_root = self.config.find_rust_src_root().expect( + "Could not find Rust source root", + ); let rust_pp_module_rel_path = Path::new("./src/etc"); let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path) .to_str() @@ -664,19 +665,6 @@ actual:\n\ self.check_debugger_output(&debugger_run_result, &check_lines); } - fn find_rust_src_root(&self) -> Option { - let mut path = self.config.src_base.clone(); - let path_postfix = Path::new("src/etc/lldb_batchmode.py"); - - while path.pop() { - if path.join(&path_postfix).is_file() { - return Some(path); - } - } - - None - } - fn run_debuginfo_lldb_test(&self) { assert!(self.revision.is_none(), "revisions not relevant here"); @@ -735,7 +723,9 @@ actual:\n\ script_str.push_str("version\n"); // Switch LLDB into "Rust mode" - let rust_src_root = self.find_rust_src_root().expect("Could not find Rust source root"); + let rust_src_root = self.config.find_rust_src_root().expect( + "Could not find Rust source root", + ); let rust_pp_module_rel_path = Path::new("./src/etc/lldb_rust_formatters.py"); let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path) .to_str() @@ -1717,11 +1707,13 @@ actual:\n\ if self.props.check_test_line_numbers_match { self.check_rustdoc_test_option(proc_res); } else { - let root = self.find_rust_src_root().unwrap(); - let res = self.cmd2procres(Command::new(&self.config.docck_python) - .arg(root.join("src/etc/htmldocck.py")) - .arg(out_dir) - .arg(&self.testpaths.file)); + let root = self.config.find_rust_src_root().unwrap(); + let res = self.cmd2procres( + Command::new(&self.config.docck_python) + .arg(root.join("src/etc/htmldocck.py")) + .arg(out_dir) + .arg(&self.testpaths.file), + ); if !res.status.success() { self.fatal_proc_rec("htmldocck failed!", &res); } From a28b2465d366c0169aedf76ed932dc695d0ff049 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 9 Oct 2017 14:45:41 +0200 Subject: [PATCH 117/365] usize index message for vec --- src/liballoc/lib.rs | 1 + src/liballoc/vec.rs | 25 ++++++++++++++++++++++++- src/test/compile-fail/index-help.rs | 15 +++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/index-help.rs diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d51aaa23c6a..0cbfc9e9dac 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -121,6 +121,7 @@ #![feature(unique)] #![feature(unsize)] #![feature(allocator_internals)] +#![feature(on_unimplemented)] #![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))] #![cfg_attr(test, feature(test, box_heap))] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 861291194f3..cf34e195dea 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1543,6 +1543,7 @@ impl Hash for Vec { } #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl Index for Vec { type Output = T; @@ -1554,6 +1555,7 @@ impl Index for Vec { } #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl IndexMut for Vec { #[inline] fn index_mut(&mut self, index: usize) -> &mut T { @@ -1562,8 +1564,8 @@ impl IndexMut for Vec { } } - #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::Index> for Vec { type Output = [T]; @@ -1572,7 +1574,9 @@ impl ops::Index> for Vec { Index::index(&**self, index) } } + #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::Index> for Vec { type Output = [T]; @@ -1581,7 +1585,9 @@ impl ops::Index> for Vec { Index::index(&**self, index) } } + #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::Index> for Vec { type Output = [T]; @@ -1590,7 +1596,9 @@ impl ops::Index> for Vec { Index::index(&**self, index) } } + #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::Index for Vec { type Output = [T]; @@ -1599,7 +1607,9 @@ impl ops::Index for Vec { self } } + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::Index> for Vec { type Output = [T]; @@ -1608,7 +1618,9 @@ impl ops::Index> for Vec { Index::index(&**self, index) } } + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::Index> for Vec { type Output = [T]; @@ -1619,41 +1631,52 @@ impl ops::Index> for Vec { } #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::IndexMut> for Vec { #[inline] fn index_mut(&mut self, index: ops::Range) -> &mut [T] { IndexMut::index_mut(&mut **self, index) } } + #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::IndexMut> for Vec { #[inline] fn index_mut(&mut self, index: ops::RangeTo) -> &mut [T] { IndexMut::index_mut(&mut **self, index) } } + #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::IndexMut> for Vec { #[inline] fn index_mut(&mut self, index: ops::RangeFrom) -> &mut [T] { IndexMut::index_mut(&mut **self, index) } } + #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::IndexMut for Vec { #[inline] fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [T] { self } } + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::IndexMut> for Vec { #[inline] fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut [T] { IndexMut::index_mut(&mut **self, index) } } + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"] impl ops::IndexMut> for Vec { #[inline] fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut [T] { diff --git a/src/test/compile-fail/index-help.rs b/src/test/compile-fail/index-help.rs new file mode 100644 index 00000000000..2d37fc79250 --- /dev/null +++ b/src/test/compile-fail/index-help.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +fn main() { + let x = vec![1]; + x[0i32]; //~ ERROR E0277 + //~| NOTE vector indices are of type `usize` or ranges of `usize` +} From 4a9df0ec6256d0318b9679c8da62cff3f84d1fe4 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 9 Oct 2017 15:38:51 +0200 Subject: [PATCH 118/365] incr.comp.: Move macro-export test case to src/test/incremental. --- .../macro_export.rs} | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename src/test/{compile-fail/incr_comp_with_macro_export.rs => incremental/macro_export.rs} (90%) diff --git a/src/test/compile-fail/incr_comp_with_macro_export.rs b/src/test/incremental/macro_export.rs similarity index 90% rename from src/test/compile-fail/incr_comp_with_macro_export.rs rename to src/test/incremental/macro_export.rs index eafef172303..914632e96ba 100644 --- a/src/test/compile-fail/incr_comp_with_macro_export.rs +++ b/src/test/incremental/macro_export.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Zincremental=tmp/cfail-tests/incr_comp_with_macro_export +// revisions: cfail1 cfail2 cfail3 // must-compile-successfully - // This test case makes sure that we can compile with incremental compilation // enabled when there are macros exported from this crate. (See #37756) From c3ff62863d9745f690fea65ef12fb205222d01b4 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Mon, 9 Oct 2017 10:02:50 -0400 Subject: [PATCH 119/365] Clarify RAM usage during build --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 95d543b8bb3..779acb9fab4 100644 --- a/README.md +++ b/README.md @@ -193,7 +193,7 @@ Snapshot binaries are currently built and tested on several platforms: You may find that other platforms work, but these are our officially supported build environments that are most likely to work. -Rust currently needs between 600MiB and 1.5GiB to build, depending on platform. +Rust currently needs between 600MiB and 1.5GiB of RAM to build, depending on platform. If it hits swap, it will take a very long time to build. There is more advice about hacking on Rust in [CONTRIBUTING.md]. From fcee9506602829a2ed8505c0ba657d12b972e7ae Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Mon, 2 Oct 2017 18:29:03 -0500 Subject: [PATCH 120/365] let rustdoc print the crate version into docs --- src/librustdoc/clean/mod.rs | 2 ++ src/librustdoc/html/render.rs | 14 ++++++++++++++ src/librustdoc/html/static/rustdoc.css | 9 +++++++++ src/librustdoc/lib.rs | 6 ++++++ src/test/rustdoc/crate-version.rs | 13 +++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 src/test/rustdoc/crate-version.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c9afa3646b2..6cf8ea3c57d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -112,6 +112,7 @@ impl, U> Clean> for P<[T]> { #[derive(Clone, Debug)] pub struct Crate { pub name: String, + pub version: Option, pub src: PathBuf, pub module: Option, pub externs: Vec<(CrateNum, ExternalCrate)>, @@ -183,6 +184,7 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { Crate { name, + version: None, src, module: Some(module), externs, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a3f446885f9..9bc94eff142 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -256,6 +256,9 @@ pub struct Cache { // the access levels from crateanalysis. pub access_levels: Arc>, + /// The version of the crate being documented, if given fron the `--crate-version` flag. + pub crate_version: Option, + // Private fields only used when initially crawling a crate to build a cache stack: Vec, @@ -534,6 +537,7 @@ pub fn run(mut krate: clean::Crate, primitive_locations: FxHashMap(), stripped_mod: false, access_levels: krate.access_levels.clone(), + crate_version: krate.version.take(), orphan_impl_items: Vec::new(), traits: mem::replace(&mut krate.external_traits, FxHashMap()), deref_trait_did, @@ -3422,6 +3426,16 @@ impl<'a> fmt::Display for Sidebar<'a> { write!(fmt, "{}", it.name.as_ref().unwrap())?; write!(fmt, "

")?; + if it.is_crate() { + if let Some(ref version) = cache().crate_version { + write!(fmt, + "
\ +

Version {}

\ +
", + version)?; + } + } + match it.inner { clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?, clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?, diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 27574e67bc8..61a3902098f 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -203,6 +203,15 @@ nav.sub { word-wrap: break-word; } +.sidebar .version { + font-size: 15px; + text-align: center; + border-bottom: #DDDDDD 1px solid; + overflow-wrap: break-word; + word-wrap: break-word; /* deprecated */ + word-break: break-word; /* Chrome, non-standard */ +} + .location:empty { border: none; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 9563ccfcc65..f8bf00ad73f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -243,6 +243,9 @@ pub fn opts() -> Vec { unstable("display-warnings", |o| { o.optflag("", "display-warnings", "to print code warnings when testing doc") }), + unstable("crate-version", |o| { + o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") + }), ] } @@ -460,6 +463,7 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { let triple = matches.opt_str("target"); let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); let crate_name = matches.opt_str("crate-name"); + let crate_version = matches.opt_str("crate-version"); let plugin_path = matches.opt_str("plugin-path"); let cr = PathBuf::from(cratefile); @@ -484,6 +488,8 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { krate.name = name } + krate.version = crate_version; + // Process all of the crate attributes, extracting plugin metadata along // with the passes which we are supposed to run. for attr in krate.module.as_ref().unwrap().attrs.lists("doc") { diff --git a/src/test/rustdoc/crate-version.rs b/src/test/rustdoc/crate-version.rs new file mode 100644 index 00000000000..07ab5ceedfa --- /dev/null +++ b/src/test/rustdoc/crate-version.rs @@ -0,0 +1,13 @@ +// 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. + +// compile-flags: --crate-version=1.3.37 -Z unstable-options + +// @has 'crate_version/index.html' '//div[@class="block version"]/p' 'Version 1.3.37' From 49a73d0901a60b1b77452b92372fd8629f636c2a Mon Sep 17 00:00:00 2001 From: johnthagen Date: Mon, 9 Oct 2017 08:16:18 -0700 Subject: [PATCH 121/365] Add __future__ imports to increase compatibility with Python 3. Derive Option from object to make it a new-style class for Python 3 compatibility. --- src/bootstrap/bootstrap.py | 2 +- src/bootstrap/bootstrap_test.py | 1 + src/bootstrap/configure.py | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4a8c3dcebcb..fecb8e6a05e 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -8,7 +8,7 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. -from __future__ import print_function +from __future__ import absolute_import, division, print_function import argparse import contextlib import datetime diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 32ea4b4abe6..4db7e2ec016 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -10,6 +10,7 @@ """Bootstrap tests""" +from __future__ import absolute_import, division, print_function import os import doctest import unittest diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 67337bf4421..3c161b7bb14 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -11,6 +11,7 @@ # ignore-tidy-linelength +from __future__ import absolute_import, division, print_function import sys import os rust_dir = os.path.dirname(os.path.abspath(__file__)) @@ -19,7 +20,7 @@ rust_dir = os.path.dirname(rust_dir) sys.path.append(os.path.join(rust_dir, "src", "bootstrap")) import bootstrap -class Option: +class Option(object): def __init__(self, name, rustbuild, desc, value): self.name = name self.rustbuild = rustbuild From eb1006f5cfb9429d76423bea5360d59a818fbc43 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 9 Oct 2017 17:29:59 +0200 Subject: [PATCH 122/365] incr.comp.: Add some documentation to force_from_dep_node(). --- src/librustc/ty/maps/plumbing.rs | 51 +++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 88b619558d9..389b0401b86 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -603,6 +603,49 @@ macro_rules! define_provider_struct { }; } + +/// The red/green evaluation system will try to mark a specific DepNode in the +/// dependency graph as green by recursively trying to mark the dependencies of +/// that DepNode as green. While doing so, it will sometimes encounter a DepNode +/// where we don't know if it is red or green and we therefore actually have +/// to recompute its value in order to find out. Since the only piece of +/// information that we have at that point is the DepNode we are trying to +/// re-evaluate, we need some way to re-run a query from just that. This is what +/// `force_from_dep_node()` implements. +/// +/// In the general case, a DepNode consists of a DepKind and an opaque +/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint +/// is usually constructed by computing a stable hash of the query-key that the +/// DepNode corresponds to. Consequently, it is not in general possible to go +/// back from hash to query-key (since hash functions are not reversible). For +/// this reason `force_from_dep_node()` is expected to fail from time to time +/// because we just cannot find out, from the DepNode alone, what the +/// corresponding query-key is and therefore cannot re-run the query. +/// +/// The system deals with this case letting `try_mark_green` fail which forces +/// the root query to be re-evaluated. +/// +/// Now, if force_from_dep_node() would always fail, it would be pretty useless. +/// Fortunately, we can use some contextual information that will allow us to +/// reconstruct query-keys for certain kinds of DepNodes. In particular, we +/// enforce by construction that the GUID/fingerprint of certain DepNodes is a +/// valid DefPathHash. Since we also always build a huge table that maps every +/// DefPathHash in the current codebase to the corresponding DefId, we have +/// everything we need to re-run the query. +/// +/// Take the `mir_validated` query as an example. Like many other queries, it +/// just has a single parameter: the DefId of the item it will compute the +/// validated MIR for. Now, when we call `force_from_dep_node()` on a dep-node +/// with kind `MirValidated`, we know that the GUID/fingerprint of the dep-node +/// is actually a DefPathHash, and can therefore just look up the corresponding +/// DefId in `tcx.def_path_hash_to_def_id`. +/// +/// When you implement a new query, it will likely have a corresponding new +/// DepKind, and you'll have to support it here in `force_from_dep_node()`. As +/// a rule of thumb, if your query takes a DefId or DefIndex as sole parameter, +/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just +/// add it to the "We don't have enough information to reconstruct..." group in +/// the match below. pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, dep_node: &DepNode) -> bool { @@ -687,16 +730,16 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::Hir | // This are anonymous nodes + DepKind::TraitSelect | + + // We don't have enough information to reconstruct the query key of + // these DepKind::IsCopy | DepKind::IsSized | DepKind::IsFreeze | DepKind::NeedsDrop | DepKind::Layout | - DepKind::TraitSelect | DepKind::ConstEval | - - // We don't have enough information to reconstruct the query key of - // these DepKind::InstanceSymbolName | DepKind::MirShim | DepKind::BorrowCheckKrate | From 3e4d9df02bf8a801fb6f4903697ec523590210a9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 9 Oct 2017 20:02:17 +0300 Subject: [PATCH 123/365] Fix a bug in diagnostics for `x as usize < y` Improve diagnostics for `x as usize << y` --- src/libsyntax/parse/parser.rs | 19 ++++++++++++++++--- src/test/ui/issue-22644.rs | 2 ++ src/test/ui/issue-22644.stderr | 15 ++++++++++++--- src/test/ui/issue-44406.rs | 19 +++++++++++++++++++ src/test/ui/issue-44406.stderr | 26 ++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/issue-44406.rs create mode 100644 src/test/ui/issue-44406.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 978e06c75dd..ff020445715 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2890,17 +2890,30 @@ impl<'a> Parser<'a> { match self.parse_path(PathStyle::Expr) { Ok(path) => { + let (op_noun, op_verb) = match self.token { + token::Lt => ("comparison", "comparing"), + token::BinOp(token::Shl) => ("shift", "shifting"), + _ => { + // We can end up here even without `<` being the next token, for + // example because `parse_ty_no_plus` returns `Err` on keywords, + // but `parse_path` returns `Ok` on them due to error recovery. + // Return original error and parser state. + mem::replace(self, parser_snapshot_after_type); + return Err(type_err); + } + }; + // Successfully parsed the type path leaving a `<` yet to parse. type_err.cancel(); // Report non-fatal diagnostics, keep `x as usize` as an expression // in AST and continue parsing. let msg = format!("`<` is interpreted as a start of generic \ - arguments for `{}`, not a comparison", path); + arguments for `{}`, not a {}", path, op_noun); let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg); err.span_label(self.look_ahead_span(1).to(parser_snapshot_after_type.span), "interpreted as generic arguments"); - err.span_label(self.span, "not interpreted as comparison"); + err.span_label(self.span, format!("not interpreted as {}", op_noun)); let expr = mk_expr(self, P(Ty { span: path.span, @@ -2911,7 +2924,7 @@ impl<'a> Parser<'a> { let expr_str = self.sess.codemap().span_to_snippet(expr.span) .unwrap_or(pprust::expr_to_string(&expr)); err.span_suggestion(expr.span, - "try comparing the casted value", + &format!("try {} the casted value", op_verb), format!("({})", expr_str)); err.emit(); diff --git a/src/test/ui/issue-22644.rs b/src/test/ui/issue-22644.rs index b482d0595f7..c8e0cd1763f 100644 --- a/src/test/ui/issue-22644.rs +++ b/src/test/ui/issue-22644.rs @@ -35,5 +35,7 @@ fn main() { < 5); + println!("{}", a as usize << long_name); + println!("{}", a: &mut 4); } diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index 54c325b24a3..f4967c4803b 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -76,9 +76,18 @@ help: try comparing the casted value 33 | ... -error: expected type, found `4` - --> $DIR/issue-22644.rs:38:28 +error: `<` is interpreted as a start of generic arguments for `usize`, not a shift + --> $DIR/issue-22644.rs:38:31 | -38 | println!("{}", a: &mut 4); +38 | println!("{}", a as usize << long_name); + | ---------- ^^ --------- interpreted as generic arguments + | | | + | | not interpreted as shift + | help: try shifting the casted value: `(a as usize)` + +error: expected type, found `4` + --> $DIR/issue-22644.rs:40:28 + | +40 | println!("{}", a: &mut 4); | ^ expecting a type here because of type ascription diff --git a/src/test/ui/issue-44406.rs b/src/test/ui/issue-44406.rs new file mode 100644 index 00000000000..abf572118fc --- /dev/null +++ b/src/test/ui/issue-44406.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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. + +macro_rules! foo { + ($rest: tt) => { + bar(baz: $rest) + } +} + +fn main() { + foo!(true); +} diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr new file mode 100644 index 00000000000..e07face24ba --- /dev/null +++ b/src/test/ui/issue-44406.stderr @@ -0,0 +1,26 @@ +error: expected identifier, found keyword `true` + --> $DIR/issue-44406.rs:18:10 + | +18 | foo!(true); + | ^^^^ + +error: expected type, found keyword `true` + --> $DIR/issue-44406.rs:18:10 + | +13 | bar(baz: $rest) + | - help: did you mean to use `;` here? +... +18 | foo!(true); + | ^^^^ expecting a type here because of type ascription + +error: expected one of `!`, `&&`, `&`, `(`, `*`, `.`, `;`, `<`, `?`, `[`, `_`, `extern`, `fn`, `for`, `impl`, `unsafe`, `}`, an operator, or lifetime, found `true` + --> $DIR/issue-44406.rs:18:10 + | +13 | bar(baz: $rest) + | - expected one of 19 possible tokens here +... +18 | foo!(true); + | ^^^^ unexpected token + +error: aborting due to 3 previous errors + From 29b576e15b371ca7ccf14698399deadae0954688 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Sat, 7 Oct 2017 01:14:44 +0530 Subject: [PATCH 124/365] Update let-expressions.rs --- .../incremental/hashes/let_expressions.rs | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 9e532548e11..d46fbd36760 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -38,6 +38,20 @@ pub fn change_name() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_clean(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn change_name() { let _y = 2u64; } @@ -57,6 +71,20 @@ pub fn add_type() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_clean(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_clean(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn add_type() { let _x: u32 = 2u32; } @@ -76,6 +104,20 @@ pub fn change_type() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn change_type() { let _x: u8 = 2; } @@ -95,6 +137,20 @@ pub fn change_mutability_of_reference_type() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_clean(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; } @@ -114,6 +170,20 @@ pub fn change_mutability_of_slot() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn change_mutability_of_slot() { let _x: u64 = 0; } @@ -133,6 +203,20 @@ pub fn change_simple_binding_to_pattern() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn change_simple_binding_to_pattern() { let (_a, _b) = (0u8, 'x'); } @@ -152,6 +236,20 @@ pub fn change_name_in_pattern() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_clean(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn change_name_in_pattern() { let (_a, _c) = (1u8, 'y'); } @@ -171,6 +269,20 @@ pub fn add_ref_in_pattern() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn add_ref_in_pattern() { let (ref _a, _b) = (1u8, 'y'); } @@ -190,6 +302,12 @@ pub fn add_amp_in_pattern() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] pub fn add_amp_in_pattern() { let (&_a, _b) = (&1u8, 'y'); } @@ -209,6 +327,20 @@ pub fn change_mutability_of_binding_in_pattern() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn change_mutability_of_binding_in_pattern() { let (mut _a, _b) = (99u8, 'q'); } @@ -228,6 +360,20 @@ pub fn add_initializer() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_dirty(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn add_initializer() { let _x: i16 = 3i16; } @@ -247,6 +393,20 @@ pub fn change_initializer() { #[rustc_clean(label="HirBody", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +#[rustc_dirty(label="MirValidated", cfg="cfail2")] +#[rustc_clean(label="MirValidated", cfg="cfail3")] +#[rustc_dirty(label="MirOptimized", cfg="cfail2")] +#[rustc_clean(label="MirOptimized", cfg="cfail3")] +#[rustc_clean(label="TypeckTables", cfg="cfail2")] +#[rustc_clean(label="TypeckTables", cfg="cfail3")] +#[rustc_clean(label="TypeOfItem", cfg="cfail2")] +#[rustc_clean(label="TypeOfItem", cfg="cfail3")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail2")] +#[rustc_clean(label="GenericsOfItem", cfg="cfail3")] +#[rustc_clean(label="FnSignature", cfg="cfail2")] +#[rustc_clean(label="FnSignature", cfg="cfail3")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail2")] +#[rustc_clean(label="PredicatesOfItem", cfg="cfail3")] pub fn change_initializer() { let _x = 5u16; } From 679457ad2a0f33aed6b206107afedcccf5124374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malo=20Jaffr=C3=A9?= Date: Mon, 9 Oct 2017 20:09:08 +0200 Subject: [PATCH 125/365] Refactor to use `debug_struct` in several Debug impls Fixes #44771. --- src/librustc_data_structures/graph/mod.rs | 15 ++------------ src/libstd/sync/mpsc/mod.rs | 24 +++-------------------- src/libstd/sync/mpsc/select.rs | 18 ++--------------- src/libstd/sync/mutex.rs | 13 +++++++++--- src/libstd/sync/rwlock.rs | 13 +++++++++--- src/libstd/sys_common/remutex.rs | 13 +++++++++--- src/libsyntax_pos/lib.rs | 7 +++++-- 7 files changed, 42 insertions(+), 61 deletions(-) diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs index 474622f3669..56d5f5ffa3f 100644 --- a/src/librustc_data_structures/graph/mod.rs +++ b/src/librustc_data_structures/graph/mod.rs @@ -31,7 +31,7 @@ //! be indexed by the direction (see the type `Direction`). use bitvec::BitVector; -use std::fmt::{Formatter, Error, Debug}; +use std::fmt::Debug; use std::usize; use snapshot_vec::{SnapshotVec, SnapshotVecDelegate}; @@ -48,6 +48,7 @@ pub struct Node { pub data: N, } +#[derive(Debug)] pub struct Edge { next_edge: [EdgeIndex; 2], // see module comment source: NodeIndex, @@ -69,18 +70,6 @@ impl SnapshotVecDelegate for Edge { fn reverse(_: &mut Vec>, _: ()) {} } -impl Debug for Edge { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, - "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}", - self.next_edge[0], - self.next_edge[1], - self.source, - self.target, - self.data) - } -} - #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub struct NodeIndex(pub usize); diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index dcd4c8dfdf5..ce1a07b31b2 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -919,7 +919,7 @@ impl Drop for Sender { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for Sender { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Sender {{ .. }}") + f.debug_struct("Sender").finish() } } @@ -1049,7 +1049,7 @@ impl Drop for SyncSender { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for SyncSender { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "SyncSender {{ .. }}") + f.debug_struct("SyncSender").finish() } } @@ -1551,7 +1551,7 @@ impl Drop for Receiver { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl fmt::Debug for Receiver { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Receiver {{ .. }}") + f.debug_struct("Receiver").finish() } } @@ -3009,22 +3009,4 @@ mod sync_tests { repro() } } - - #[test] - fn fmt_debug_sender() { - let (tx, _) = channel::(); - assert_eq!(format!("{:?}", tx), "Sender { .. }"); - } - - #[test] - fn fmt_debug_recv() { - let (_, rx) = channel::(); - assert_eq!(format!("{:?}", rx), "Receiver { .. }"); - } - - #[test] - fn fmt_debug_sync_sender() { - let (tx, _) = sync_channel::(1); - assert_eq!(format!("{:?}", tx), "SyncSender { .. }"); - } } diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index e49f4cff024..a9f3cea243f 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -354,13 +354,13 @@ impl Iterator for Packets { impl fmt::Debug for Select { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Select {{ .. }}") + f.debug_struct("Select").finish() } } impl<'rx, T:Send+'rx> fmt::Debug for Handle<'rx, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Handle {{ .. }}") + f.debug_struct("Handle").finish() } } @@ -774,18 +774,4 @@ mod tests { } } } - - #[test] - fn fmt_debug_select() { - let sel = Select::new(); - assert_eq!(format!("{:?}", sel), "Select { .. }"); - } - - #[test] - fn fmt_debug_handle() { - let (_, rx) = channel::(); - let sel = Select::new(); - let handle = sel.handle(&rx); - assert_eq!(format!("{:?}", handle), "Handle { .. }"); - } } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 62d8de18f4b..a0349fe9d8b 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -384,11 +384,18 @@ impl Default for Mutex { impl fmt::Debug for Mutex { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.try_lock() { - Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard), + Ok(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(), Err(TryLockError::Poisoned(err)) => { - write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref()) + f.debug_struct("Mutex").field("data", &&**err.get_ref()).finish() }, - Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ }}") + Err(TryLockError::WouldBlock) => { + struct LockedPlaceholder; + impl fmt::Debug for LockedPlaceholder { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("") } + } + + f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish() + } } } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 4757faabfb8..5c49d6b5845 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -428,11 +428,18 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock { impl fmt::Debug for RwLock { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.try_read() { - Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", &*guard), + Ok(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(), Err(TryLockError::Poisoned(err)) => { - write!(f, "RwLock {{ data: Poisoned({:?}) }}", &**err.get_ref()) + f.debug_struct("RwLock").field("data", &&**err.get_ref()).finish() }, - Err(TryLockError::WouldBlock) => write!(f, "RwLock {{ }}") + Err(TryLockError::WouldBlock) => { + struct LockedPlaceholder; + impl fmt::Debug for LockedPlaceholder { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("") } + } + + f.debug_struct("RwLock").field("data", &LockedPlaceholder).finish() + } } } } diff --git a/src/libstd/sys_common/remutex.rs b/src/libstd/sys_common/remutex.rs index 4d0407ccf6c..ce43ec6d9ab 100644 --- a/src/libstd/sys_common/remutex.rs +++ b/src/libstd/sys_common/remutex.rs @@ -116,11 +116,18 @@ impl Drop for ReentrantMutex { impl fmt::Debug for ReentrantMutex { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.try_lock() { - Ok(guard) => write!(f, "ReentrantMutex {{ data: {:?} }}", &*guard), + Ok(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(), Err(TryLockError::Poisoned(err)) => { - write!(f, "ReentrantMutex {{ data: Poisoned({:?}) }}", &**err.get_ref()) + f.debug_struct("ReentrantMutex").field("data", &**err.get_ref()).finish() }, - Err(TryLockError::WouldBlock) => write!(f, "ReentrantMutex {{ }}") + Err(TryLockError::WouldBlock) => { + struct LockedPlaceholder; + impl fmt::Debug for LockedPlaceholder { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("") } + } + + f.debug_struct("ReentrantMutex").field("data", &LockedPlaceholder).finish() + } } } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 582f2798181..a06873aac0e 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -338,8 +338,11 @@ impl serialize::UseSpecializedDecodable for Span { } fn default_span_debug(span: Span, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Span {{ lo: {:?}, hi: {:?}, ctxt: {:?} }}", - span.lo(), span.hi(), span.ctxt()) + f.debug_struct("Span") + .field("lo", &span.lo()) + .field("hi", &span.hi()) + .field("ctxt", &span.ctxt()) + .finish() } impl fmt::Debug for Span { From 6f653bb1b15b327c1adb5018e2957631cd708d5d Mon Sep 17 00:00:00 2001 From: Pirh Date: Mon, 9 Oct 2017 19:20:07 +0100 Subject: [PATCH 126/365] Document defaults for stdin, stdout, and stderr methods of Command --- src/libstd/process.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index dbb58991215..1352c640fdd 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -552,6 +552,15 @@ impl Command { /// Configuration for the child process's standard input (stdin) handle. /// + /// Defaults to [`inherit`] when used with `spawn` or `status`, and + /// defaults to [`piped`] when used with `output`. + /// + /// On Windows, if the `#![windows_subsystem = "windows"]` attribute is + /// set, no stdin is connected unless explicitly assigned. + /// + /// [`inherit`]: struct.Stdio.html#method.inherit + /// [`piped`]: struct.Stdio.html#method.piped + /// /// # Examples /// /// Basic usage: @@ -572,6 +581,15 @@ impl Command { /// Configuration for the child process's standard output (stdout) handle. /// + /// Defaults to [`inherit`] when used with `spawn` or `status`, and + /// defaults to [`piped`] when used with `output`. + /// + /// On Windows, if the `#![windows_subsystem = "windows"]` attribute is + /// set, no stdout is connected unless explicitly assigned. + /// + /// [`inherit`]: struct.Stdio.html#method.inherit + /// [`piped`]: struct.Stdio.html#method.piped + /// /// # Examples /// /// Basic usage: @@ -592,6 +610,15 @@ impl Command { /// Configuration for the child process's standard error (stderr) handle. /// + /// Defaults to [`inherit`] when used with `spawn` or `status`, and + /// defaults to [`piped`] when used with `output`. + /// + /// On Windows, if the `#![windows_subsystem = "windows"]` attribute is + /// set, no stderr is connected unless explicitly assigned. + /// + /// [`inherit`]: struct.Stdio.html#method.inherit + /// [`piped`]: struct.Stdio.html#method.piped + /// /// # Examples /// /// Basic usage: From b434c84bab6bcb53f8394eb1bc133061d16f92c7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 8 Oct 2017 11:41:12 +0300 Subject: [PATCH 127/365] cleanup: rustc doesn't use an external archiver --- config.toml.example | 9 ++---- src/bootstrap/compile.rs | 3 -- src/bootstrap/config.rs | 3 -- src/bootstrap/configure.py | 3 +- src/bootstrap/dist.rs | 2 +- src/doc/man/rustc.1 | 3 -- src/librustc/session/config.rs | 3 +- src/librustc_back/build.rs | 1 - .../target/asmjs_unknown_emscripten.rs | 1 - src/librustc_back/target/mod.rs | 5 --- .../target/wasm32_experimental_emscripten.rs | 1 - .../target/wasm32_unknown_emscripten.rs | 1 - src/librustc_back/target/windows_msvc_base.rs | 31 ------------------- .../target/x86_64_rumprun_netbsd.rs | 1 - src/librustc_trans/back/archive.rs | 7 ++--- 15 files changed, 9 insertions(+), 65 deletions(-) diff --git a/config.toml.example b/config.toml.example index a3790c8d202..a2f64e6b705 100644 --- a/config.toml.example +++ b/config.toml.example @@ -250,14 +250,11 @@ # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) #backtrace = true -# The default linker that will be used by the generated compiler. Note that this -# is not the linker used to link said compiler. +# The default linker that will be hard-coded into the generated compiler for +# targets that don't specify linker explicitly in their target specifications. +# Note that this is not the linker used to link said compiler. #default-linker = "cc" -# The default ar utility that will be used by the generated compiler if LLVM -# cannot be used. Note that this is not used to assemble said compiler. -#default-ar = "ar" - # The "channel" for the Rust build to produce. The stable/beta channels only # allow using stable features, whereas the nightly and dev channels allow using # nightly features diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 335e1690a2e..b1c630a8de9 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -560,9 +560,6 @@ pub fn rustc_cargo(build: &Build, if let Some(ref s) = build.config.rustc_default_linker { cargo.env("CFG_DEFAULT_LINKER", s); } - if let Some(ref s) = build.config.rustc_default_ar { - cargo.env("CFG_DEFAULT_AR", s); - } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index c8b2ed042c1..5fb5eb3b7f1 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -88,7 +88,6 @@ pub struct Config { pub rust_debuginfo_only_std: bool, pub rust_rpath: bool, pub rustc_default_linker: Option, - pub rustc_default_ar: Option, pub rust_optimize_tests: bool, pub rust_debuginfo_tests: bool, pub rust_dist_src: bool, @@ -262,7 +261,6 @@ struct Rust { use_jemalloc: Option, backtrace: Option, default_linker: Option, - default_ar: Option, channel: Option, musl_root: Option, rpath: Option, @@ -464,7 +462,6 @@ impl Config { set(&mut config.quiet_tests, rust.quiet_tests); set(&mut config.test_miri, rust.test_miri); config.rustc_default_linker = rust.default_linker.clone(); - config.rustc_default_ar = rust.default_ar.clone(); config.musl_root = rust.musl_root.clone().map(PathBuf::from); match rust.codegen_units { diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 67337bf4421..29ffa2c926d 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -119,9 +119,8 @@ v("experimental-targets", "llvm.experimental-targets", "experimental LLVM targets to build") v("release-channel", "rust.channel", "the name of the release channel to build") -# Used on systems where "cc" and "ar" are unavailable +# Used on systems where "cc" is unavailable v("default-linker", "rust.default-linker", "the default linker") -v("default-ar", "rust.default-ar", "the default ar") # Many of these are saved below during the "writing configuration" step # (others are conditionally saved). diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 3d4aa0413db..b57661715cc 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -176,7 +176,7 @@ fn make_win_dist( } } - let target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"]; + let target_tools = ["gcc.exe", "ld.exe", "dlltool.exe", "libwinpthread-1.dll"]; let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"]; if target_triple.starts_with("i686-") { rustc_dlls.push("libgcc_s_dw2-1.dll"); diff --git a/src/doc/man/rustc.1 b/src/doc/man/rustc.1 index 6c80f11fa72..0bb41cee2c5 100644 --- a/src/doc/man/rustc.1 +++ b/src/doc/man/rustc.1 @@ -152,9 +152,6 @@ never colorize output. .SH CODEGEN OPTIONS -.TP -\fBar\fR=\fI/path/to/ar\fR -Path to the archive utility to use when assembling archives. .TP \fBlinker\fR=\fI/path/to/cc\fR Path to the linker utility to use when linking libraries, executables, and diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index fc1c5e187ec..9ffb3ac332e 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -864,8 +864,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, build_codegen_options, "C", "codegen", CG_OPTIONS, cg_type_desc, cgsetters, ar: Option = (None, parse_opt_string, [UNTRACKED], - "tool to assemble archives with (has no effect currently, \ - rustc doesn't use an external archiver)"), + "this option is deprecated and does nothing"), linker: Option = (None, parse_opt_string, [UNTRACKED], "system linker to link outputs with"), link_arg: Vec = (vec![], parse_string_push, [UNTRACKED], diff --git a/src/librustc_back/build.rs b/src/librustc_back/build.rs index 16f0872b25a..6f6fde1e9e7 100644 --- a/src/librustc_back/build.rs +++ b/src/librustc_back/build.rs @@ -11,5 +11,4 @@ fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-env-changed=CFG_DEFAULT_LINKER"); - println!("cargo:rerun-if-env-changed=CFG_DEFAULT_AR"); } diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs index 033e840f202..a54627279b0 100644 --- a/src/librustc_back/target/asmjs_unknown_emscripten.rs +++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs @@ -20,7 +20,6 @@ pub fn target() -> Result { let opts = TargetOptions { linker: cmd("emcc"), - ar: cmd("emar"), dynamic_linking: false, executables: true, diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 039e0153656..1d0fc3cf6e5 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -268,8 +268,6 @@ pub struct TargetOptions { /// Linker to invoke. Defaults to "cc". pub linker: String, - /// Archive utility to use when managing archives. Defaults to "ar". - pub ar: String, /// Linker arguments that are unconditionally passed *before* any /// user-defined libraries. @@ -439,7 +437,6 @@ impl Default for TargetOptions { TargetOptions { is_builtin: false, linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(), - ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(), pre_link_args: LinkArgs::new(), post_link_args: LinkArgs::new(), asm_args: Vec::new(), @@ -680,7 +677,6 @@ impl Target { key!(is_builtin, bool); key!(linker); - key!(ar); key!(pre_link_args, link_args); key!(pre_link_objects_exe, list); key!(pre_link_objects_dll, list); @@ -872,7 +868,6 @@ impl ToJson for Target { target_option_val!(is_builtin); target_option_val!(linker); - target_option_val!(ar); target_option_val!(link_args - pre_link_args); target_option_val!(pre_link_objects_exe); target_option_val!(pre_link_objects_dll); diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_back/target/wasm32_experimental_emscripten.rs index 71668444d9a..a261c982b3f 100644 --- a/src/librustc_back/target/wasm32_experimental_emscripten.rs +++ b/src/librustc_back/target/wasm32_experimental_emscripten.rs @@ -25,7 +25,6 @@ pub fn target() -> Result { let opts = TargetOptions { linker: cmd("emcc"), - ar: cmd("emar"), dynamic_linking: false, executables: true, diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs index e6584addf4a..197c1f7a4da 100644 --- a/src/librustc_back/target/wasm32_unknown_emscripten.rs +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -22,7 +22,6 @@ pub fn target() -> Result { let opts = TargetOptions { linker: cmd("emcc"), - ar: cmd("emar"), dynamic_linking: false, executables: true, diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index 42a4e6f5f11..64df6624dd1 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -21,37 +21,6 @@ pub fn opts() -> TargetOptions { TargetOptions { function_sections: true, linker: "link.exe".to_string(), - // When taking a look at the value of this `ar` field, one might expect - // `lib.exe` to be the value here! The `lib.exe` program is the default - // tool for managing `.lib` archives on Windows, but unfortunately the - // compiler cannot use it. - // - // To recap, we use `ar` here to manage rlibs (which are just archives). - // LLVM does not expose bindings for modifying archives so we have to - // invoke this utility for write operations (e.g. deleting files, adding - // files, etc). Normally archives only have object files within them, - // but the compiler also uses archives for storing metadata and - // compressed bytecode, so we don't exactly fall within "normal use - // cases". - // - // MSVC's `lib.exe` tool by default will choke when adding a non-object - // file to an archive, which we do on a regular basis, making it - // inoperable for us. Luckily, however, LLVM has already rewritten `ar` - // in the form of `llvm-ar` which is built by default when we build - // LLVM. This tool, unlike `lib.exe`, works just fine with non-object - // files, so we use it instead. - // - // Note that there's a few caveats associated with this: - // - // * This still requires that the *linker* (the consumer of rlibs) will - // ignore non-object files. Thankfully `link.exe` on Windows does - // indeed ignore non-object files in archives. - // * This requires `llvm-ar.exe` to be distributed with the compiler - // itself, but we already make sure of this elsewhere. - // - // Perhaps one day we won't even need this tool at all and we'll just be - // able to make library calls into LLVM! - ar: "llvm-ar.exe".to_string(), dynamic_linking: true, executables: true, dll_prefix: "".to_string(), diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs index ab5a6f71ebc..18f6380b6ee 100644 --- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs +++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs @@ -16,7 +16,6 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.linker = "x86_64-rumprun-netbsd-gcc".to_string(); - base.ar = "x86_64-rumprun-netbsd-ar".to_string(); base.max_atomic_width = Some(64); base.dynamic_linking = false; diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs index 179ef20b19f..775cf3ac4c9 100644 --- a/src/librustc_trans/back/archive.rs +++ b/src/librustc_trans/back/archive.rs @@ -31,8 +31,7 @@ pub struct ArchiveConfig<'a> { pub lib_search_paths: Vec, } -/// Helper for adding many files to an archive with a single invocation of -/// `ar`. +/// Helper for adding many files to an archive. #[must_use = "must call build() to finish building the archive"] pub struct ArchiveBuilder<'a> { config: ArchiveConfig<'a>, @@ -201,8 +200,8 @@ impl<'a> ArchiveBuilder<'a> { }); } - /// Indicate that the next call to `build` should updates all symbols in - /// the archive (run 'ar s' over it). + /// Indicate that the next call to `build` should update all symbols in + /// the archive (equivalent to running 'ar s' over it). pub fn update_symbols(&mut self) { self.should_update_symbols = true; } From 5187763cff184eda0f28fd409a4a8c6dfc57c9f9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Oct 2017 14:38:52 -0700 Subject: [PATCH 128/365] rustc: Allow target-specific default cgus Some targets, like msp430 and nvptx, don't work with multiple codegen units right now for bugs or fundamental reasons. To expose this allow targets to express a default. Closes #45000 --- src/librustc/session/config.rs | 48 ++------------------- src/librustc/session/mod.rs | 37 ++++++++++++++++ src/librustc_back/target/mod.rs | 6 +++ src/librustc_back/target/msp430_none_elf.rs | 5 +++ src/librustc_trans/back/link.rs | 2 +- src/librustc_trans/back/write.rs | 6 +-- src/librustc_trans/base.rs | 2 +- 7 files changed, 56 insertions(+), 50 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index fc1c5e187ec..69ff55ab223 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -352,7 +352,7 @@ top_level_options!( actually_rustdoc: bool [TRACKED], // Number of object files/codegen units to produce on the backend - codegen_units: usize [UNTRACKED], + cli_forced_codegen_units: Option [UNTRACKED], } ); @@ -505,7 +505,7 @@ pub fn basic_options() -> Options { unstable_features: UnstableFeatures::Disallow, debug_assertions: true, actually_rustdoc: false, - codegen_units: 1, + cli_forced_codegen_units: None, } } @@ -1711,48 +1711,6 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) let incremental = debugging_opts.incremental.as_ref().map(|m| PathBuf::from(m)); - let codegen_units = codegen_units.unwrap_or_else(|| { - match opt_level { - // If we're compiling at `-O0` then default to 16 codegen units. - // The number here shouldn't matter too too much as debug mode - // builds don't rely on performance at all, meaning that lost - // opportunities for inlining through multiple codegen units is - // a non-issue. - // - // Note that the high number here doesn't mean that we'll be - // spawning a large number of threads in parallel. The backend - // of rustc contains global rate limiting through the - // `jobserver` crate so we'll never overload the system with too - // much work, but rather we'll only be optimizing when we're - // otherwise cooperating with other instances of rustc. - // - // Rather the high number here means that we should be able to - // keep a lot of idle cpus busy. By ensuring that no codegen - // unit takes *too* long to build we'll be guaranteed that all - // cpus will finish pretty closely to one another and we should - // make relatively optimal use of system resources - // - // Another note worth mentioning here, however, is that this number - // isn't *too* high. When codegen units are increased that means we - // currently have to codegen `#[inline]` functions into each codegen - // unit, which means the more codegen units we're using the more we - // may be generating. In other words, increasing codegen units may - // increase the overall work the compiler does. If we don't have - // enough cores to make up for this loss then increasing the number - // of codegen units could become an overall loss! - // - // As a result we choose a hopefully conservative value 16, which - // should be more than the number of cpus of most hardware compiling - // Rust but also not too much for 2-4 core machines to have too much - // loss of compile time. - OptLevel::No => 16, - - // All other optimization levels default use one codegen unit, - // the historical default in Rust for a Long Time. - _ => 1, - } - }); - (Options { crate_types, optimize: opt_level, @@ -1777,7 +1735,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) unstable_features: UnstableFeatures::from_environment(), debug_assertions, actually_rustdoc: false, - codegen_units, + cli_forced_codegen_units: codegen_units, }, cfg) } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd6e5eb67c8..d8301596a92 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -636,6 +636,43 @@ impl Session { } ret } + + /// Returns the number of codegen units that should be used for this + /// compilation + pub fn codegen_units(&self) -> usize { + if let Some(n) = self.opts.cli_forced_codegen_units { + return n + } + if let Some(n) = self.target.target.options.default_codegen_units { + return n as usize + } + + match self.opts.optimize { + // If we're compiling at `-O0` then default to 16 codegen units. + // The number here shouldn't matter too too much as debug mode + // builds don't rely on performance at all, meaning that lost + // opportunities for inlining through multiple codegen units is + // a non-issue. + // + // Note that the high number here doesn't mean that we'll be + // spawning a large number of threads in parallel. The backend + // of rustc contains global rate limiting through the + // `jobserver` crate so we'll never overload the system with too + // much work, but rather we'll only be optimizing when we're + // otherwise cooperating with other instances of rustc. + // + // Rather the high number here means that we should be able to + // keep a lot of idle cpus busy. By ensuring that no codegen + // unit takes *too* long to build we'll be guaranteed that all + // cpus will finish pretty closely to one another and we should + // make relatively optimal use of system resources + config::OptLevel::No => 16, + + // All other optimization levels default use one codegen unit, + // the historical default in Rust for a Long Time. + _ => 1, + } + } } pub fn build_session(sopts: config::Options, diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 039e0153656..1d6c3871e45 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -430,6 +430,9 @@ pub struct TargetOptions { /// The minimum alignment for global symbols. pub min_global_align: Option, + + /// Default number of codegen units to use in debug mode + pub default_codegen_units: Option, } impl Default for TargetOptions { @@ -492,6 +495,7 @@ impl Default for TargetOptions { crt_static_respected: false, stack_probes: false, min_global_align: None, + default_codegen_units: None, } } } @@ -732,6 +736,7 @@ impl Target { key!(crt_static_respected, bool); key!(stack_probes, bool); key!(min_global_align, Option); + key!(default_codegen_units, Option); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -924,6 +929,7 @@ impl ToJson for Target { target_option_val!(crt_static_respected); target_option_val!(stack_probes); target_option_val!(min_global_align); + target_option_val!(default_codegen_units); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() diff --git a/src/librustc_back/target/msp430_none_elf.rs b/src/librustc_back/target/msp430_none_elf.rs index 9227a96e750..509a7cf5e03 100644 --- a/src/librustc_back/target/msp430_none_elf.rs +++ b/src/librustc_back/target/msp430_none_elf.rs @@ -48,6 +48,11 @@ pub fn target() -> TargetResult { // code because of the extra costs it involves. relocation_model: "static".to_string(), + // Right now we invoke an external assembler and this isn't + // compatible with multiple codegen units, and plus we probably + // don't want to invoke that many gcc instances. + default_codegen_units: Some(1), + .. Default::default( ) } }) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 3f25c182fa2..570a6bbac1e 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -467,7 +467,7 @@ fn link_rlib<'a>(sess: &'a Session, // of when we do and don't keep .#module-name#.bc files around. let user_wants_numbered_bitcode = sess.opts.output_types.contains_key(&OutputType::Bitcode) && - sess.opts.codegen_units > 1; + sess.codegen_units() > 1; if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode { remove(sess, &bc_filename); } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 22b09a0e269..6ebf642ebca 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1037,10 +1037,10 @@ fn produce_final_output_artifacts(sess: &Session, let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe); let keep_numbered_bitcode = needs_crate_bitcode || - (user_wants_bitcode && sess.opts.codegen_units > 1); + (user_wants_bitcode && sess.codegen_units() > 1); let keep_numbered_objects = needs_crate_object || - (user_wants_objects && sess.opts.codegen_units > 1); + (user_wants_objects && sess.codegen_units() > 1); for module in compiled_modules.modules.iter() { let module_name = Some(&module.name[..]); @@ -2052,7 +2052,7 @@ impl OngoingCrateTranslation { // FIXME: time_llvm_passes support - does this use a global context or // something? - if sess.opts.codegen_units == 1 && sess.time_llvm_passes() { + if sess.codegen_units() == 1 && sess.time_llvm_passes() { unsafe { llvm::LLVMRustPrintPassTimings(); } } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 17e00ac1346..6b53b5b6411 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1218,7 +1218,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( let strategy = if tcx.sess.opts.debugging_opts.incremental.is_some() { PartitioningStrategy::PerModule } else { - PartitioningStrategy::FixedUnitCount(tcx.sess.opts.codegen_units) + PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units()) }; let codegen_units = time(time_passes, "codegen unit partitioning", || { From 3a65d12df75751616d28d3d9f6e01c0dd0b898cd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Oct 2017 00:06:07 +0200 Subject: [PATCH 129/365] Add tabs for search for better information access Make tabs work --- src/librustdoc/html/static/main.js | 167 ++++++++++++++++++--- src/librustdoc/html/static/rustdoc.css | 26 ++++ src/librustdoc/html/static/styles/main.css | 4 + 3 files changed, 175 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index da4430d8a15..bccad6c89dc 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -342,6 +342,17 @@ } } + function findArg(obj, val) { + if (obj && obj.type && obj.type.inputs.length > 0) { + for (var i = 0; i < obj.type.inputs.length; i++) { + if (obj.type.inputs[i].name === val) { + return true; + } + } + } + return false; + } + function typePassesFilter(filter, type) { // No filter if (filter < 0) return true; @@ -376,18 +387,28 @@ if (typePassesFilter(typeFilter, searchIndex[i].ty)) { results.push({id: i, index: -1}); } + } else if (findArg(searchIndex[i], val.toLowerCase()) || + (searchIndex[i].type && + searchIndex[i].type.output && + searchIndex[i].type.output.name === val.toLowerCase())) { + if (typePassesFilter(typeFilter, searchIndex[i].ty)) { + results.push({id: i, index: -1, dontValidate: true}); + } } if (results.length === max) { break; } } + query.inputs = [val]; + query.output = val; + query.search = val; // searching by type } else if (val.search("->") > -1) { var trimmer = function (s) { return s.trim(); }; var parts = val.split("->").map(trimmer); var input = parts[0]; // sort inputs so that order does not matter - var inputs = input.split(",").map(trimmer).sort().toString(); + var inputs = input.split(",").map(trimmer).sort(); var output = parts[1]; for (var i = 0; i < nSearchWords; ++i) { @@ -403,12 +424,30 @@ // allow searching for void (no output) functions as well var typeOutput = type.output ? type.output.name : ""; - if ((inputs === "*" || inputs === typeInputs.toString()) && - (output === "*" || output == typeOutput)) { - results.push({id: i, index: -1, dontValidate: true}); + if (output === "*" || output == typeOutput) { + if (input === "*") { + results.push({id: i, index: -1, dontValidate: true}); + } else { + var allFound = true; + for (var it = 0; allFound === true && it < inputs.length; it++) { + var found = false; + for (var y = 0; found === false && y < typeInputs.length; y++) { + found = typeInputs[y] === inputs[it]; + } + allFound = found; + } + if (allFound === true) { + results.push({id: i, index: -1, dontValidate: true}); + } + } } } + query.inputs = inputs; + query.output = output; } else { + query.inputs = [val]; + query.output = val; + query.search = val; // gather matching search results up to a certain maximum val = val.replace(/\_/g, ""); for (var i = 0; i < split.length; ++i) { @@ -437,6 +476,15 @@ lev: lev_distance, }); } + } else if (findArg(searchIndex[j], val)) { + if (typePassesFilter(typeFilter, searchIndex[j].ty)) { + results.push({ + id: j, + index: 0, + // we want lev results to go lower than others + lev: lev_distance, + }); + } } if (results.length === max) { break; @@ -576,8 +624,7 @@ (parent !== undefined && parent.name.toLowerCase().indexOf(keys[i]) > -1) || // lastly check to see if the name was a levenshtein match - levenshtein(name.toLowerCase(), keys[i]) <= - MAX_LEV_DISTANCE)) { + levenshtein(name.toLowerCase(), keys[i]) <= MAX_LEV_DISTANCE)) { return false; } } @@ -692,18 +739,18 @@ return h1.innerHTML; } - function showResults(results) { - var output, shown, query = getQuery(); + function addTab(array, query, display) { + var extraStyle = ''; + if (display === false) { + extraStyle = ' style="display: none;"'; + } - currentResults = query.id; - output = '

Results for ' + escape(query.query) + - (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '

'; - output += ''; + var output = ''; + if (array.length > 0) { + output = `
`; + var shown = []; - if (results.length > 0) { - shown = []; - - results.forEach(function(item) { + array.forEach(function(item) { var name, type, href, displayPath; if (shown.indexOf(item) !== -1) { @@ -752,13 +799,32 @@ '' + escape(item.desc) + ' '; }); + output += '
'; } else { - output += 'No results :( No results :(
` + + 'Try on
Try on DuckDuckGo?'; + '">DuckDuckGo?'; } + return output; + } + + function showResults(results) { + var output, query = getQuery(); + + currentResults = query.id; + output = '

Results for ' + escape(query.query) + + (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '

' + + '
' + + '
Types/modules
' + + '
As parameters
' + + '
As return value
'; + + output += addTab(results['others'], query); + output += addTab(results['in_args'], query, false); + output += addTab(results['returned'], query, false); + output += '
'; - output += "

"; addClass(document.getElementById('main'), 'hidden'); var search = document.getElementById('search'); removeClass(search, 'hidden'); @@ -773,13 +839,17 @@ e.style.width = width + 'px'; }); initSearchNav(); + var elems = document.getElementById('titles').childNodes; + elems[0].onclick = function() { printTab(0); }; + elems[1].onclick = function() { printTab(1); }; + elems[2].onclick = function() { printTab(2); }; } function search(e) { var query, filterdata = [], obj, i, len, - results = [], + results = {"in_args": [], "returned": [], "others": []}, maxResults = 200, resultIndex; var params = getQueryStringParams(); @@ -810,11 +880,43 @@ len = resultIndex.length; for (i = 0; i < len; ++i) { if (resultIndex[i].id > -1) { + var added = false; obj = searchIndex[resultIndex[i].id]; filterdata.push([obj.name, obj.ty, obj.path, obj.desc]); - results.push(obj); + if (obj.type) { + if (results['returned'].length < maxResults && + obj.type.output && + obj.type.output.name.toLowerCase() === query.output) { + results['returned'].push(obj); + added = true; + } + if (results['in_args'].length < maxResults && obj.type.inputs.length > 0) { + var all_founds = true; + for (var it = 0; + all_founds === true && it < query.inputs.length; + it++) { + var found = false; + for (var y = 0; + found === false && y < obj.type.inputs.length; + y++) { + found = query.inputs[it] === obj.type.inputs[y].name; + } + all_founds = found; + } + if (all_founds === true) { + results['in_args'].push(obj); + added = true; + } + } + } + if (results['others'].length < maxResults && + ((query.search && obj.name.indexOf(query.search)) || added === false)) { + results['others'].push(obj); + } } - if (results.length >= maxResults) { + if (results['others'].length >= maxResults && + results['in_args'].length >= maxResults && + results['returned'].length >= maxResults) { break; } } @@ -1290,6 +1392,27 @@ return wrapper; } + // In the search display, allows to switch between tabs. + function printTab(nb) { + var nb_copy = nb; + onEach(document.getElementById('titles').childNodes, function(elem) { + if (nb_copy === 0) { + addClass(elem, 'selected'); + } else { + removeClass(elem, 'selected'); + } + nb_copy -= 1; + }); + onEach(document.getElementById('results').childNodes, function(elem) { + if (nb === 0) { + elem.style.display = ''; + } else { + elem.style.display = 'none'; + } + nb -= 1; + }); + } + onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) { onEach(e.getElementsByClassName('attributes'), function(i_e) { i_e.parentNode.insertBefore(createToggleWrapper(), i_e); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 1b7232bf1bc..67e19925988 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -866,3 +866,29 @@ span.since { pre.rust { position: relative; } + +.search-failed { + text-align: center; + margin-top: 20px; +} + +#titles { + height: 35px; +} + +#titles > div { + float: left; + width: 33.3%; + text-align: center; + border-bottom: 1px solid #ccc; + font-size: 18px; + cursor: pointer; +} + +#titles > div.selected { + border-bottom: 3px solid #0078ee; +} + +#titles > div:hover { + border-bottom: 3px solid #0089ff; +} diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index 42d0ec704f4..4a4ca15170a 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -235,3 +235,7 @@ pre.ignore:hover, .information:hover + pre.ignore { .information > .ignore:hover { color: rgba(255,142,0,1); } + +.search-failed > a { + color: #0089ff; +} From a5e8a0ea7c337225ba96248387b343f044205b7e Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Mon, 9 Oct 2017 21:12:11 -0400 Subject: [PATCH 130/365] Modify MIR testing to require continuous lines Mir testing now requires that lines be continuous. To achive this, instead of collecting the expected mir as a string, it is now wrapped in an `ExpectedLine` enum, that is either `Elision` or `Text(T)` where `T: AsRef`. `Text` lines must be matched in order, unless separated by `Elision` lines. Matches occur greedily, that is, an Elision will skip as few lines as possible. To add a new elision marker. Put a comment containing only "..." and whitespace in any MIR testing block. Like so: ``` // fn write_42(_1: *mut i32) -> bool { // ... // bb0: { // Validate(Acquire, [_1: *mut i32]); // Validate(Release, [_1: *mut i32]); // ... // return; // } // } ``` Right now, all input before the line right after `// START` is elided, and all input after the line right before `// END` is also not tested. Many tests need to be updated. That will follow in the next commit. cc #45153 --- src/tools/compiletest/src/runtest.rs | 130 ++++++++++++++++++++------- 1 file changed, 96 insertions(+), 34 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 10ef326d9db..400599923ff 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -25,6 +25,7 @@ use std::collections::HashSet; use std::env; use std::ffi::OsString; use std::fs::{self, File, create_dir_all}; +use std::fmt; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::{Path, PathBuf}; @@ -2237,7 +2238,7 @@ actual:\n\ let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len()); let tests_text_str = String::from(tests_text); let mut curr_test : Option<&str> = None; - let mut curr_test_contents = Vec::new(); + let mut curr_test_contents = vec![ExpectedLine::Elision]; for l in tests_text_str.lines() { debug!("line: {:?}", l); if l.starts_with("// START ") { @@ -2251,11 +2252,14 @@ actual:\n\ self.compare_mir_test_output(curr_test.unwrap(), &curr_test_contents); curr_test = None; curr_test_contents.clear(); + curr_test_contents.push(ExpectedLine::Elision); } else if l.is_empty() { // ignore + } else if l.starts_with("//") && l.split_at("//".len()).1.trim() == "..." { + curr_test_contents.push(ExpectedLine::Elision) } else if l.starts_with("// ") { let (_, test_content) = l.split_at("// ".len()); - curr_test_contents.push(test_content); + curr_test_contents.push(ExpectedLine::Text(test_content)); } } } @@ -2273,7 +2277,7 @@ actual:\n\ } } - fn compare_mir_test_output(&self, test_name: &str, expected_content: &[&str]) { + fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedLine<&str>]) { let mut output_file = PathBuf::new(); output_file.push(self.get_mir_dump_dir()); output_file.push(test_name); @@ -2285,38 +2289,77 @@ actual:\n\ let mut dumped_string = String::new(); dumped_file.read_to_string(&mut dumped_string).unwrap(); let mut dumped_lines = dumped_string.lines().filter(|l| !l.is_empty()); - let mut expected_lines = expected_content.iter().filter(|l| !l.is_empty()); - - // We expect each non-empty line from expected_content to appear - // in the dump in order, but there may be extra lines interleaved - while let Some(expected_line) = expected_lines.next() { - let e_norm = normalize_mir_line(expected_line); - if e_norm.is_empty() { - continue; - }; - let mut found = false; - while let Some(dumped_line) = dumped_lines.next() { - let d_norm = normalize_mir_line(dumped_line); - debug!("found: {:?}", d_norm); - debug!("expected: {:?}", e_norm); - if e_norm == d_norm { - found = true; - break; - }; + let mut expected_lines = expected_content.iter().filter(|&l| { + if let &ExpectedLine::Text(l) = l { + !l.is_empty() + } else { + true } - if !found { - let normalize_all = dumped_string.lines() - .map(nocomment_mir_line) - .filter(|l| !l.is_empty()) - .collect::>() - .join("\n"); - panic!("ran out of mir dump output to match against.\n\ - Did not find expected line: {:?}\n\ - Expected:\n{}\n\ - Actual:\n{}", - expected_line, - expected_content.join("\n"), - normalize_all); + }).peekable(); + + let compare = |expected_line, dumped_line| { + let e_norm = normalize_mir_line(expected_line); + let d_norm = normalize_mir_line(dumped_line); + debug!("found: {:?}", d_norm); + debug!("expected: {:?}", e_norm); + e_norm == d_norm + }; + + let error = |expected_line, extra_msg| { + let normalize_all = dumped_string.lines() + .map(nocomment_mir_line) + .filter(|l| !l.is_empty()) + .collect::>() + .join("\n"); + let f = |l: &ExpectedLine<_>| match l { + &ExpectedLine::Elision => "... (elided)".into(), + &ExpectedLine::Text(t) => t + }; + let expected_content = expected_content.iter() + .map(|l| f(l)) + .collect::>() + .join("\n"); + panic!("Did not find expected line, error: {}\n\ + Actual Line: {:?}\n\ + Expected:\n{}\n\ + Actual:\n{}", + extra_msg, + expected_line, + expected_content, + normalize_all); + }; + + // We expect each non-empty line to appear consecutively, non-consecutive lines + // must be separated by at least one Elision + while let Some(dumped_line) = dumped_lines.next() { + match expected_lines.next() { + Some(&ExpectedLine::Text(expected_line)) => + if !compare(expected_line, dumped_line) { + error(expected_line, + format!("Mismatch in lines\nExpected Line: {:?}", dumped_line)); + }, + Some(&ExpectedLine::Elision) => { + // skip any number of elisions in a row. + while let Some(&&ExpectedLine::Elision) = expected_lines.peek() { + expected_lines.next(); + } + if let Some(&ExpectedLine::Text(expected_line)) = expected_lines.next() { + let mut found = compare(expected_line, dumped_line); + if found { + continue; + } + while let Some(dumped_line) = dumped_lines.next() { + found = compare(expected_line, dumped_line); + if found { + break; + } + } + if !found { + error(expected_line, "ran out of mir dump to match against".into()); + } + } + }, + None => {}, } } } @@ -2439,6 +2482,25 @@ enum TargetLocation { ThisDirectory(PathBuf), } +#[derive(Clone, PartialEq, Eq)] +enum ExpectedLine> { + Elision, + Text(T) +} + +impl fmt::Debug for ExpectedLine +where + T: AsRef + fmt::Debug +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if let &ExpectedLine::Text(ref t) = self { + write!(formatter, "{:?}", t) + } else { + write!(formatter, "\"...\" (Elision)") + } + } +} + fn normalize_mir_line(line: &str) -> String { nocomment_mir_line(line).replace(char::is_whitespace, "") } From 426183c01bbaf398e8ae68bd554488af23e49dbd Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Mon, 9 Oct 2017 23:14:13 -0400 Subject: [PATCH 131/365] Update README and tests for new infrastructure --- src/test/mir-opt/README.md | 33 ++- src/test/mir-opt/box_expr.rs | 5 +- src/test/mir-opt/copy_propagation.rs | 6 + src/test/mir-opt/deaggregator_test.rs | 6 + src/test/mir-opt/deaggregator_test_enum.rs | 8 + src/test/mir-opt/deaggregator_test_enum_2.rs | 10 +- .../mir-opt/deaggregator_test_multiple.rs | 10 + src/test/mir-opt/end_region_1.rs | 4 +- src/test/mir-opt/end_region_2.rs | 6 + src/test/mir-opt/end_region_3.rs | 6 +- src/test/mir-opt/end_region_4.rs | 5 + src/test/mir-opt/end_region_5.rs | 3 + src/test/mir-opt/end_region_6.rs | 5 +- src/test/mir-opt/end_region_7.rs | 6 +- src/test/mir-opt/end_region_8.rs | 3 + src/test/mir-opt/end_region_9.rs | 7 +- src/test/mir-opt/end_region_cyclic.rs | 1 + src/test/mir-opt/issue-41110.rs | 10 +- .../mir-opt/storage_live_dead_in_statics.rs | 200 +++++++++++++----- src/test/mir-opt/storage_ranges.rs | 1 + src/test/mir-opt/validate_1.rs | 5 + src/test/mir-opt/validate_2.rs | 8 + src/test/mir-opt/validate_3.rs | 15 ++ src/test/mir-opt/validate_4.rs | 9 + src/test/mir-opt/validate_5.rs | 5 + 25 files changed, 304 insertions(+), 73 deletions(-) diff --git a/src/test/mir-opt/README.md b/src/test/mir-opt/README.md index d999ff97551..b00b35aa29f 100644 --- a/src/test/mir-opt/README.md +++ b/src/test/mir-opt/README.md @@ -7,13 +7,13 @@ The test format is: // END RUST SOURCE // START $file_name_of_some_mir_dump_0 // $expected_line_0 -// ... +// (lines or elision) // $expected_line_N // END $file_name_of_some_mir_dump_0 -// ... +// (lines or elision) // START $file_name_of_some_mir_dump_N // $expected_line_0 -// ... +// (lines or elision) // $expected_line_N // END $file_name_of_some_mir_dump_N ``` @@ -22,10 +22,15 @@ All the test information is in comments so the test is runnable. For each $file_name, compiletest expects [$expected_line_0, ..., $expected_line_N] to appear in the dumped MIR in order. Currently it allows -other non-matched lines before, after and in-between. Note that this includes -lines that end basic blocks or begin new ones; it is good practice -in your tests to include the terminator for each of your basic blocks as an -internal sanity check guarding against a test like: +other non-matched lines before and after, but not between $expected_lines, +should you want to skip lines, you must include an elision comment, of the form +(as a regex) `//\s*...\s*`. The lines will be skipped lazily, that is, if there +are two identical lines in the output that match the line after the elision +comment, the first one wil be matched. + +Examples: + +The following blocks will not match the one after it. ``` bb0: { @@ -35,8 +40,6 @@ bb0: { } ``` -that will inadvertantly pattern-matching against: - ``` bb0: { StorageLive(_1); @@ -49,6 +52,18 @@ bb1: { } ``` +But this will match the one above, + +``` +bb0: { + StorageLive(_1); + _1 = const true; + ... + StorageDead(_1); + ... +} +``` + Lines match ignoring whitespace, and the prefix "//" is removed. It also currently strips trailing comments -- partly because the full file path diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs index 4015930ef76..5c3b418e950 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -30,7 +30,10 @@ impl Drop for S { // END RUST SOURCE // START rustc.node4.ElaborateDrops.before.mir // let mut _0: (); -// let _1: std::boxed::Box; +// scope 1 { +// let _1: std::boxed::Box; +// } +// ... // let mut _2: std::boxed::Box; // let mut _3: (); // let mut _4: std::boxed::Box; diff --git a/src/test/mir-opt/copy_propagation.rs b/src/test/mir-opt/copy_propagation.rs index 26b042d0343..0b0d2f45f1c 100644 --- a/src/test/mir-opt/copy_propagation.rs +++ b/src/test/mir-opt/copy_propagation.rs @@ -18,17 +18,23 @@ fn main() { } // END RUST SOURCE // START rustc.node4.CopyPropagation.before.mir // bb0: { +// ... // _2 = _1; +// ... // _4 = _2; // _3 = _4; +// ... // _5 = _3; // _0 = _5; +// ... // return; // } // END rustc.node4.CopyPropagation.before.mir // START rustc.node4.CopyPropagation.after.mir // bb0: { +// ... // _0 = _1; +// ... // return; // } // END rustc.node4.CopyPropagation.after.mir diff --git a/src/test/mir-opt/deaggregator_test.rs b/src/test/mir-opt/deaggregator_test.rs index 81dd1932894..ce2b13ecda7 100644 --- a/src/test/mir-opt/deaggregator_test.rs +++ b/src/test/mir-opt/deaggregator_test.rs @@ -23,19 +23,25 @@ fn main() {} // END RUST SOURCE // START rustc.node13.Deaggregator.before.mir // bb0: { +// ... // _2 = _1; +// ... // _3 = _2; // _0 = Baz { x: _3, y: const 0f32, z: const false }; +// ... // return; // } // END rustc.node13.Deaggregator.before.mir // START rustc.node13.Deaggregator.after.mir // bb0: { +// ... // _2 = _1; +// ... // _3 = _2; // (_0.0: usize) = _3; // (_0.1: f32) = const 0f32; // (_0.2: bool) = const false; +// ... // return; // } // END rustc.node13.Deaggregator.after.mir diff --git a/src/test/mir-opt/deaggregator_test_enum.rs b/src/test/mir-opt/deaggregator_test_enum.rs index 25fa0e90835..d77dcb62781 100644 --- a/src/test/mir-opt/deaggregator_test_enum.rs +++ b/src/test/mir-opt/deaggregator_test_enum.rs @@ -28,18 +28,26 @@ fn main() { // END RUST SOURCE // START rustc.node10.Deaggregator.before.mir // bb0: { +// StorageLive(_2); // _2 = _1; +// StorageLive(_3); // _3 = _2; // _0 = Baz::Foo { x: _3 }; +// StorageDead(_3); +// StorageDead(_2); // return; // } // END rustc.node10.Deaggregator.before.mir // START rustc.node10.Deaggregator.after.mir // bb0: { +// StorageLive(_2); // _2 = _1; +// StorageLive(_3); // _3 = _2; // ((_0 as Foo).0: usize) = _3; // discriminant(_0) = 1; +// StorageDead(_3); +// StorageDead(_2); // return; // } // END rustc.node10.Deaggregator.after.mir diff --git a/src/test/mir-opt/deaggregator_test_enum_2.rs b/src/test/mir-opt/deaggregator_test_enum_2.rs index 02d496b2901..e65830bddc4 100644 --- a/src/test/mir-opt/deaggregator_test_enum_2.rs +++ b/src/test/mir-opt/deaggregator_test_enum_2.rs @@ -28,29 +28,35 @@ fn main() {} // END RUST SOURCE // START rustc.node12.Deaggregator.before.mir // bb1: { +// StorageLive(_6); // _6 = _4; // _0 = Foo::A(_6,); +// StorageDead(_6); // goto -> bb3; // } -// // bb2: { +// StorageLive(_7); // _7 = _4; // _0 = Foo::B(_7,); +// StorageDead(_7); // goto -> bb3; // } // END rustc.node12.Deaggregator.before.mir // START rustc.node12.Deaggregator.after.mir // bb1: { +// StorageLive(_6); // _6 = _4; // ((_0 as A).0: i32) = _6; // discriminant(_0) = 0; +// StorageDead(_6); // goto -> bb3; // } -// // bb2: { +// StorageLive(_7); // _7 = _4; // ((_0 as B).0: i32) = _7; // discriminant(_0) = 1; +// StorageDead(_7); // goto -> bb3; // } // END rustc.node12.Deaggregator.after.mir diff --git a/src/test/mir-opt/deaggregator_test_multiple.rs b/src/test/mir-opt/deaggregator_test_multiple.rs index a180a69be55..ed68d3bf5f7 100644 --- a/src/test/mir-opt/deaggregator_test_multiple.rs +++ b/src/test/mir-opt/deaggregator_test_multiple.rs @@ -24,25 +24,35 @@ fn main() { } // END RUST SOURCE // START rustc.node10.Deaggregator.before.mir // bb0: { +// ... // _2 = _1; +// ... // _4 = _2; // _3 = Foo::A(_4,); +// ... // _6 = _2; // _5 = Foo::A(_6,); +// ... // _0 = [_3, _5]; +// ... // return; // } // END rustc.node10.Deaggregator.before.mir // START rustc.node10.Deaggregator.after.mir // bb0: { +// ... // _2 = _1; +// ... // _4 = _2; // ((_3 as A).0: i32) = _4; // discriminant(_3) = 0; +// ... // _6 = _2; // ((_5 as A).0: i32) = _6; // discriminant(_5) = 0; +// ... // _0 = [_3, _5]; +// ... // return; // } // END rustc.node10.Deaggregator.after.mir diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs index 1941d1bc7be..a0edcc82fe1 100644 --- a/src/test/mir-opt/end_region_1.rs +++ b/src/test/mir-opt/end_region_1.rs @@ -21,9 +21,11 @@ fn main() { // END RUST SOURCE // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); +// ... // let _1: i32; +// ... // let _2: &'10_1rs i32; -// +// ... // bb0: { // StorageLive(_1); // _1 = const 3i32; diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs index d8dd4aeadf4..69042fecc7d 100644 --- a/src/test/mir-opt/end_region_2.rs +++ b/src/test/mir-opt/end_region_2.rs @@ -26,11 +26,16 @@ fn main() { // END RUST SOURCE // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); +// ... // let _2: bool; +// ... // let _3: &'23_1rs bool; +// ... // let _7: &'23_3rs bool; +// ... // let mut _4: (); // let mut _5: bool; +// ... // bb0: { // goto -> bb1; // } @@ -52,6 +57,7 @@ fn main() { // return; // } // bb3: { +// _4 = (); // StorageDead(_5); // StorageLive(_7); // _7 = &'23_3rs _2; diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs index e404af838ce..da423163e84 100644 --- a/src/test/mir-opt/end_region_3.rs +++ b/src/test/mir-opt/end_region_3.rs @@ -27,13 +27,17 @@ fn main() { // END RUST SOURCE // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); +// ... // let mut _1: bool; +// ... // let _3: &'26_1rs bool; +// ... // let _7: &'26_3rs bool; +// ... // let mut _2: (); // let mut _4: (); // let mut _5: bool; -// +// let mut _6: !; // bb0: { // StorageLive(_1); // goto -> bb1; diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs index d51c627d14b..2087485b913 100644 --- a/src/test/mir-opt/end_region_4.rs +++ b/src/test/mir-opt/end_region_4.rs @@ -31,10 +31,15 @@ fn foo(i: i32) { // END RUST SOURCE // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); +// ... // let _1: D; +// ... // let _2: i32; +// ... // let _3: &'26_2rs i32; +// ... // let _6: &'26_4rs i32; +// ... // let mut _4: (); // let mut _5: i32; // bb0: { diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs index 6299ec3815c..4663b71bd7c 100644 --- a/src/test/mir-opt/end_region_5.rs +++ b/src/test/mir-opt/end_region_5.rs @@ -28,8 +28,11 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END RUST SOURCE // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // fn main() -> () { +// ... // let mut _0: (); +// ... // let _1: D; +// ... // let mut _2: (); // let mut _3: [closure@NodeId(18) d:&'14s D]; // let mut _4: &'14s D; diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs index 13ab3e4f2dd..7d2868ee4ba 100644 --- a/src/test/mir-opt/end_region_6.rs +++ b/src/test/mir-opt/end_region_6.rs @@ -29,7 +29,9 @@ fn foo(f: F) where F: FnOnce() -> i32 { // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // fn main() -> () { // let mut _0: (); +// ... // let _1: D; +// ... // let mut _2: (); // let mut _3: [closure@NodeId(22) d:&'19s D]; // let mut _4: &'19s D; @@ -65,9 +67,10 @@ fn foo(f: F) where F: FnOnce() -> i32 { // START rustc.node22.SimplifyCfg-qualify-consts.after.mir // fn main::{{closure}}(_1: [closure@NodeId(22) d:&'19s D]) -> i32 { // let mut _0: i32; +// ... // let _2: &'15_0rs D; +// ... // let mut _3: i32; -// // bb0: { // StorageLive(_2); // _2 = &'15_0rs (*(_1.0: &'19s D)); diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs index 826d3749167..0156c1be7ed 100644 --- a/src/test/mir-opt/end_region_7.rs +++ b/src/test/mir-opt/end_region_7.rs @@ -29,11 +29,12 @@ fn foo(f: F) where F: FnOnce() -> i32 { // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // fn main() -> () { // let mut _0: (); +// ... // let _1: D; +// ... // let mut _2: (); // let mut _3: [closure@NodeId(22) d:D]; // let mut _4: D; -// // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); @@ -74,9 +75,10 @@ fn foo(f: F) where F: FnOnce() -> i32 { // START rustc.node22.SimplifyCfg-qualify-consts.after.mir // fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 { // let mut _0: i32; +// ... // let _2: &'15_0rs D; +// ... // let mut _3: i32; -// // bb0: { // StorageLive(_2); // _2 = &'15_0rs (_1.0: D); diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs index 6438484fcfa..6e8cf4204ee 100644 --- a/src/test/mir-opt/end_region_8.rs +++ b/src/test/mir-opt/end_region_8.rs @@ -30,8 +30,11 @@ fn foo(f: F) where F: FnOnce() -> i32 { // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // fn main() -> () { // let mut _0: (); +// ... // let _1: D; +// ... // let _2: &'21_1rs D; +// ... // let mut _3: (); // let mut _4: [closure@NodeId(22) r:&'21_1rs D]; // let mut _5: &'21_1rs D; diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs index 59d5d934391..fd23d813452 100644 --- a/src/test/mir-opt/end_region_9.rs +++ b/src/test/mir-opt/end_region_9.rs @@ -40,15 +40,18 @@ fn main() { // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // fn main() -> () { // let mut _0: (); +// ... // let mut _1: bool; +// ... // let _2: i32; +// ... // let mut _4: &'33_0rs i32; +// ... // let mut _3: (); // let mut _5: !; // let mut _6: (); // let mut _7: bool; // let mut _8: !; -// // bb0: { // StorageLive(_1); // _1 = const false; @@ -63,7 +66,6 @@ fn main() { // _7 = _1; // switchInt(_7) -> [0u8: bb3, otherwise: bb2]; // } -// // bb2: { // _0 = (); // StorageDead(_7); @@ -73,7 +75,6 @@ fn main() { // StorageDead(_1); // return; // } -// // bb3: { // _4 = &'33_0rs _2; // _6 = (); diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs index 8f9dd79cd75..f70f6519275 100644 --- a/src/test/mir-opt/end_region_cyclic.rs +++ b/src/test/mir-opt/end_region_cyclic.rs @@ -45,6 +45,7 @@ fn query() -> bool { true } // scope 1 { // let _2: S<'35_0rs>; // } +// ... // let mut _1: (); // let mut _3: std::cell::Cell>>; // let mut _4: std::option::Option<&'35_0rs S<'35_0rs>>; diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue-41110.rs index 3a8b5c449c2..384201b7c12 100644 --- a/src/test/mir-opt/issue-41110.rs +++ b/src/test/mir-opt/issue-41110.rs @@ -35,22 +35,26 @@ impl S { // END RUST SOURCE // START rustc.node4.ElaborateDrops.after.mir // let mut _0: (); -// let _1: (); +// scope 1 { +// let _1: (); +// } +// ... // let mut _2: S; // let mut _3: S; // let mut _4: S; // let mut _5: bool; -// // bb0: { // END rustc.node4.ElaborateDrops.after.mir // START rustc.node13.ElaborateDrops.after.mir // let mut _0: (); +// ... // let _1: S; +// ... // let mut _2: S; +// ... // let mut _3: (); // let mut _4: S; // let mut _5: S; // let mut _6: bool; -// // bb0: { // END rustc.node13.ElaborateDrops.after.mir diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs index 9fb725a980e..370ab599eca 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.rs +++ b/src/test/mir-opt/storage_live_dead_in_statics.rs @@ -45,56 +45,156 @@ fn main() { // END RUST SOURCE // START rustc.node4.mir_map.0.mir +// let mut _0: &'static Foo; +// let mut _1: &'static Foo; +// let mut _2: Foo; +// let mut _3: &'static [(u32, u32)]; +// let mut _4: &'static [(u32, u32); 42]; +// let mut _5: &'static [(u32, u32); 42]; +// let mut _6: [(u32, u32); 42]; +// let mut _7: (u32, u32); +// let mut _8: (u32, u32); +// let mut _9: (u32, u32); +// let mut _10: (u32, u32); +// let mut _11: (u32, u32); +// let mut _12: (u32, u32); +// let mut _13: (u32, u32); +// let mut _14: (u32, u32); +// let mut _15: (u32, u32); +// let mut _16: (u32, u32); +// let mut _17: (u32, u32); +// let mut _18: (u32, u32); +// let mut _19: (u32, u32); +// let mut _20: (u32, u32); +// let mut _21: (u32, u32); +// let mut _22: (u32, u32); +// let mut _23: (u32, u32); +// let mut _24: (u32, u32); +// let mut _25: (u32, u32); +// let mut _26: (u32, u32); +// let mut _27: (u32, u32); +// let mut _28: (u32, u32); +// let mut _29: (u32, u32); +// let mut _30: (u32, u32); +// let mut _31: (u32, u32); +// let mut _32: (u32, u32); +// let mut _33: (u32, u32); +// let mut _34: (u32, u32); +// let mut _35: (u32, u32); +// let mut _36: (u32, u32); +// let mut _37: (u32, u32); +// let mut _38: (u32, u32); +// let mut _39: (u32, u32); +// let mut _40: (u32, u32); +// let mut _41: (u32, u32); +// let mut _42: (u32, u32); +// let mut _43: (u32, u32); +// let mut _44: (u32, u32); +// let mut _45: (u32, u32); +// let mut _46: (u32, u32); +// let mut _47: (u32, u32); +// let mut _48: (u32, u32); // bb0: { -// _7 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:9: 29:15 -// _8 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:17: 29:23 -// _9 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:25: 29:31 -// _10 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:9: 30:15 -// _11 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:17: 30:23 -// _12 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:25: 30:31 -// _13 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:9: 31:15 -// _14 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:17: 31:23 -// _15 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:25: 31:31 -// _16 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:9: 32:15 -// _17 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:17: 32:23 -// _18 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:25: 32:31 -// _19 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:9: 33:15 -// _20 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:17: 33:23 -// _21 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:25: 33:31 -// _22 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:9: 34:15 -// _23 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:17: 34:23 -// _24 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:25: 34:31 -// _25 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:9: 35:15 -// _26 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:17: 35:23 -// _27 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:25: 35:31 -// _28 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:9: 36:15 -// _29 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:17: 36:23 -// _30 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:25: 36:31 -// _31 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:9: 37:15 -// _32 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:17: 37:23 -// _33 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:25: 37:31 -// _34 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:9: 38:15 -// _35 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:17: 38:23 -// _36 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:25: 38:31 -// _37 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:9: 39:15 -// _38 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:17: 39:23 -// _39 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:25: 39:31 -// _40 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:9: 40:15 -// _41 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:17: 40:23 -// _42 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:25: 40:31 -// _43 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:9: 41:15 -// _44 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:17: 41:23 -// _45 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:25: 41:31 -// _46 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:9: 42:15 -// _47 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:17: 42:23 -// _48 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:25: 42:31 -// _6 = [_7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48]; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:12: 43:6 -// _5 = &_6; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6 -// _4 = &(*_5); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6 -// _3 = _4 as &'static [(u32, u32)] (Unsize); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6 -// _2 = Foo { tup: const "hi", data: _3 }; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:29: 44:2 -// _1 = &_2; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2 -// _0 = &(*_1); // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2 -// return; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:1: 44:3 +// StorageLive(_1); +// StorageLive(_2); +// StorageLive(_3); +// StorageLive(_4); +// StorageLive(_5); +// StorageLive(_6); +// StorageLive(_7); +// _7 = (const 0u32, const 1u32); +// StorageLive(_8); +// _8 = (const 0u32, const 2u32); +// StorageLive(_9); +// _9 = (const 0u32, const 3u32); +// StorageLive(_10); +// _10 = (const 0u32, const 1u32); +// StorageLive(_11); +// _11 = (const 0u32, const 2u32); +// StorageLive(_12); +// _12 = (const 0u32, const 3u32); +// StorageLive(_13); +// _13 = (const 0u32, const 1u32); +// StorageLive(_14); +// _14 = (const 0u32, const 2u32); +// StorageLive(_15); +// _15 = (const 0u32, const 3u32); +// StorageLive(_16); +// _16 = (const 0u32, const 1u32); +// StorageLive(_17); +// _17 = (const 0u32, const 2u32); +// StorageLive(_18); +// _18 = (const 0u32, const 3u32); +// StorageLive(_19); +// _19 = (const 0u32, const 1u32); +// StorageLive(_20); +// _20 = (const 0u32, const 2u32); +// StorageLive(_21); +// _21 = (const 0u32, const 3u32); +// StorageLive(_22); +// _22 = (const 0u32, const 1u32); +// StorageLive(_23); +// _23 = (const 0u32, const 2u32); +// StorageLive(_24); +// _24 = (const 0u32, const 3u32); +// StorageLive(_25); +// _25 = (const 0u32, const 1u32); +// StorageLive(_26); +// _26 = (const 0u32, const 2u32); +// StorageLive(_27); +// _27 = (const 0u32, const 3u32); +// StorageLive(_28); +// _28 = (const 0u32, const 1u32); +// StorageLive(_29); +// _29 = (const 0u32, const 2u32); +// StorageLive(_30); +// _30 = (const 0u32, const 3u32); +// StorageLive(_31); +// _31 = (const 0u32, const 1u32); +// StorageLive(_32); +// _32 = (const 0u32, const 2u32); +// StorageLive(_33); +// _33 = (const 0u32, const 3u32); +// StorageLive(_34); +// _34 = (const 0u32, const 1u32); +// StorageLive(_35); +// _35 = (const 0u32, const 2u32); +// StorageLive(_36); +// _36 = (const 0u32, const 3u32); +// StorageLive(_37); +// _37 = (const 0u32, const 1u32); +// StorageLive(_38); +// _38 = (const 0u32, const 2u32); +// StorageLive(_39); +// _39 = (const 0u32, const 3u32); +// StorageLive(_40); +// _40 = (const 0u32, const 1u32); +// StorageLive(_41); +// _41 = (const 0u32, const 2u32); +// StorageLive(_42); +// _42 = (const 0u32, const 3u32); +// StorageLive(_43); +// _43 = (const 0u32, const 1u32); +// StorageLive(_44); +// _44 = (const 0u32, const 2u32); +// StorageLive(_45); +// _45 = (const 0u32, const 3u32); +// StorageLive(_46); +// _46 = (const 0u32, const 1u32); +// StorageLive(_47); +// _47 = (const 0u32, const 2u32); +// StorageLive(_48); +// _48 = (const 0u32, const 3u32); +// _6 = [_7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48]; +// _5 = &_6; +// _4 = &(*_5); +// _3 = _4 as &'static [(u32, u32)] (Unsize); +// _2 = Foo { tup: const "hi", data: _3 }; +// _1 = &_2; +// _0 = &(*_1); +// StorageDead(_1); +// StorageDead(_5); +// return; // } +//} // END rustc.node4.mir_map.0.mir diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs index 3fbd1a36f2f..7dbcf82af34 100644 --- a/src/test/mir-opt/storage_ranges.rs +++ b/src/test/mir-opt/storage_ranges.rs @@ -38,5 +38,6 @@ fn main() { // _0 = (); // StorageDead(_6); // StorageDead(_1); +// return; // } // END rustc.node4.TypeckMir.before.mir diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index d2ca65775a4..0c570deae24 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -31,12 +31,15 @@ fn main() { // START rustc.node12.EraseRegions.after.mir // bb0: { // Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[8cd8]::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[8cd8]::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]); +// ... // return; // } // END rustc.node12.EraseRegions.after.mir // START rustc.node23.EraseRegions.after.mir // fn main() -> () { +// ... // bb0: { +// ... // Validate(Suspend(ReScope(Node(ItemLocalId(10)))), [_1: i32]); // _6 = &ReErased mut _1; // Validate(Acquire, [(*_6): i32/ReScope(Node(ItemLocalId(10)))]); @@ -50,12 +53,14 @@ fn main() { // bb1: { // Validate(Acquire, [_2: ()]); // EndRegion(ReScope(Node(ItemLocalId(10)))); +// ... // return; // } // } // END rustc.node23.EraseRegions.after.mir // START rustc.node50.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 { +// ... // bb0: { // Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); diff --git a/src/test/mir-opt/validate_2.rs b/src/test/mir-opt/validate_2.rs index 37ebd720d52..aacf5a5ed0f 100644 --- a/src/test/mir-opt/validate_2.rs +++ b/src/test/mir-opt/validate_2.rs @@ -18,10 +18,18 @@ fn main() { // END RUST SOURCE // START rustc.node4.EraseRegions.after.mir // fn main() -> () { +// ... // bb1: { +// Validate(Acquire, [_2: std::boxed::Box<[i32; 3]>]); // Validate(Release, [_2: std::boxed::Box<[i32; 3]>]); // _1 = _2 as std::boxed::Box<[i32]> (Unsize); // Validate(Acquire, [_1: std::boxed::Box<[i32]>]); +// StorageDead(_2); +// StorageDead(_3); +// _0 = (); +// Validate(Release, [_1: std::boxed::Box<[i32]>]); +// drop(_1) -> bb2; // } +// ... // } // END rustc.node4.EraseRegions.after.mir diff --git a/src/test/mir-opt/validate_3.rs b/src/test/mir-opt/validate_3.rs index 116e35b2d6f..d7d3e023c9e 100644 --- a/src/test/mir-opt/validate_3.rs +++ b/src/test/mir-opt/validate_3.rs @@ -30,8 +30,17 @@ fn main() { // END RUST SOURCE // START rustc.node16.EraseRegions.after.mir // fn main() -> () { +// ... // let mut _5: &ReErased i32; // bb0: { +// StorageLive(_1); +// _1 = Test { x: const 0i32 }; +// StorageLive(_2); +// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 }))), [_1: Test]); +// _2 = &ReErased _1; +// Validate(Acquire, [(*_2): Test/ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })) (imm)]); +// StorageLive(_4); +// StorageLive(_5); // Validate(Suspend(ReScope(Node(ItemLocalId(17)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })) (imm)]); // _5 = &ReErased ((*_2).0: i32); // Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(17))) (imm)]); @@ -42,8 +51,14 @@ fn main() { // _3 = const foo(_4) -> bb1; // } // bb1: { +// Validate(Acquire, [_3: ()]); // EndRegion(ReScope(Node(ItemLocalId(17)))); +// StorageDead(_4); +// StorageDead(_5); +// _0 = (); // EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 }))); +// StorageDead(_2); +// StorageDead(_1); // return; // } // } diff --git a/src/test/mir-opt/validate_4.rs b/src/test/mir-opt/validate_4.rs index d240b51e222..da9a4c7e455 100644 --- a/src/test/mir-opt/validate_4.rs +++ b/src/test/mir-opt/validate_4.rs @@ -38,15 +38,18 @@ fn main() { // END RUST SOURCE // START rustc.node4.EraseRegions.after.mir // fn write_42(_1: *mut i32) -> bool { +// ... // bb0: { // Validate(Acquire, [_1: *mut i32]); // Validate(Release, [_1: *mut i32]); +// ... // return; // } // } // END rustc.node4.EraseRegions.after.mir // START rustc.node22.EraseRegions.after.mir // fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () { +// ... // bb0: { // Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); // Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(22)], _2: *mut i32]); @@ -60,24 +63,30 @@ fn main() { // END rustc.node22.EraseRegions.after.mir // START rustc.node31.EraseRegions.after.mir // fn test(_1: &ReErased mut i32) -> () { +// ... // bb0: { // Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[8cd8]::test[0] }, BrAnon(0)) mut i32]); // Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[8cd8]::test[0] }, BrAnon(0)) mut i32]); +// ... // _3 = const write_42(_4) -> bb1; // } // bb1: { // Validate(Acquire, [_3: bool]); // Validate(Release, [_3: bool]); +// ... // } // } // END rustc.node31.EraseRegions.after.mir // START rustc.node60.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool { +// ... // bb0: { // Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); +// ... // _0 = const write_42(_4) -> bb1; // } +// ... // } // END rustc.node60.EraseRegions.after.mir diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index e1eeb2102d1..0ece83afa13 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -35,15 +35,19 @@ fn main() { // END RUST SOURCE // START rustc.node17.EraseRegions.after.mir // fn test(_1: &ReErased mut i32) -> () { +// ... // bb0: { // Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_5[8cd8]::test[0] }, BrAnon(0)) mut i32]); +// ... // Validate(Release, [_3: bool, _4: *mut i32]); // _3 = const write_42(_4) -> bb1; // } +// ... // } // END rustc.node17.EraseRegions.after.mir // START rustc.node46.EraseRegions.after.mir // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool { +// ... // bb0: { // Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, "BrEnv") [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); @@ -59,5 +63,6 @@ fn main() { // Validate(Release, [_0: bool, _4: *mut i32]); // _0 = const write_42(_4) -> bb1; // } +// ... // } // END rustc.node46.EraseRegions.after.mir From fa14f797f32acbea481989371f6c32739975f160 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 10 Oct 2017 11:03:23 +0900 Subject: [PATCH 132/365] Reword --- src/librustc/traits/error_reporting.rs | 25 ++++++++++--------- .../mismatched_types/closure-arg-count.stderr | 16 ++++++------ 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 5056876f3ad..a192dc6d6ea 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -845,33 +845,34 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let kind = if is_closure { "closure" } else { "function" }; - let args_str = |n| format!( - "{} argument{}", + let args_str = |n, distinct| format!( + "{} {}argument{}", n, - if n == 1 { "" } else { "s" } + if distinct && n >= 2 { "distinct " } else { "" }, + if n == 1 { "" } else { "s" }, ); let mut err = struct_span_err!(self.tcx.sess, span, E0593, - "{} takes {}, but {} {} required", + "{} is expected to take {}, but it takes {}", kind, if expected_tuple.is_some() { - Cow::from("multiple arguments") + Cow::from("a single tuple as argument") } else { - Cow::from(args_str(found)) + Cow::from(args_str(expected, false)) }, if expected_tuple.is_some() { - Cow::from("a tuple argument") + args_str(found, true) } else { - Cow::from(args_str(expected)) + args_str(found, false) }, - if expected == 1 { "is" } else { "are" }); + ); err.span_label( span, format!( "expected {} that takes {}{}", kind, - args_str(expected), + args_str(expected, false), if let Some(n) = expected_tuple { assert!(expected == 1); Cow::from(format!(", a {}-tuple", n)) @@ -884,7 +885,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(span) = found_span { if let (Some(expected_tuple), Some((pats, tys))) = (expected_tuple, closure_args) { if expected_tuple != found || pats.len() != found { - err.span_label(span, format!("takes {}", args_str(found))); + err.span_label(span, format!("takes {}", args_str(found, true))); } else { let sugg = format!( "|({}){}|", @@ -908,7 +909,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.span_suggestion(span, "consider changing to", sugg); } } else { - err.span_label(span, format!("takes {}", args_str(found))); + err.span_label(span, format!("takes {}", args_str(found, false))); } } diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 24860faf2d5..8f508ade68c 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -1,4 +1,4 @@ -error[E0593]: closure takes 0 arguments, but 2 arguments are required +error[E0593]: closure is expected to take 2 arguments, but it takes 0 arguments --> $DIR/closure-arg-count.rs:15:15 | 15 | [1, 2, 3].sort_by(|| panic!()); @@ -6,7 +6,7 @@ error[E0593]: closure takes 0 arguments, but 2 arguments are required | | | expected closure that takes 2 arguments -error[E0593]: closure takes 1 argument, but 2 arguments are required +error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument --> $DIR/closure-arg-count.rs:16:15 | 16 | [1, 2, 3].sort_by(|tuple| panic!()); @@ -23,7 +23,7 @@ error[E0308]: mismatched types = note: expected type `&{integer}` found type `(_, _)` -error[E0593]: closure takes 1 argument, but 2 arguments are required +error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument --> $DIR/closure-arg-count.rs:17:15 | 17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); @@ -31,7 +31,7 @@ error[E0593]: closure takes 1 argument, but 2 arguments are required | | | expected closure that takes 2 arguments -error[E0593]: closure takes 0 arguments, but 1 argument is required +error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:18:5 | 18 | f(|| panic!()); @@ -41,7 +41,7 @@ error[E0593]: closure takes 0 arguments, but 1 argument is required | = note: required by `f` -error[E0593]: closure takes multiple arguments, but a tuple argument is required +error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments --> $DIR/closure-arg-count.rs:20:53 | 20 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); @@ -49,7 +49,7 @@ error[E0593]: closure takes multiple arguments, but a tuple argument is required | | | expected closure that takes 1 argument, a 2-tuple -error[E0593]: closure takes multiple arguments, but a tuple argument is required +error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments --> $DIR/closure-arg-count.rs:21:53 | 21 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i); @@ -57,11 +57,11 @@ error[E0593]: closure takes multiple arguments, but a tuple argument is required | | | expected closure that takes 1 argument, a 2-tuple -error[E0593]: closure takes multiple arguments, but a tuple argument is required +error[E0593]: closure is expected to take a single tuple as argument, but it takes 3 distinct arguments --> $DIR/closure-arg-count.rs:22:53 | 22 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); - | ^^^ --------- takes 3 arguments + | ^^^ --------- takes 3 distinct arguments | | | expected closure that takes 1 argument, a 2-tuple From 06b9168d3362dc60a2e87d475319686332634319 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 10 Oct 2017 10:05:29 +0200 Subject: [PATCH 133/365] Rename test Linux target to avoid conflict with built-in target It seems like the file wasn't actually used, since there is a built-in target with the same name. See https://github.com/rust-lang/rust/pull/45108#issuecomment-335173165 for more details. --- src/test/run-make/target-specs/Makefile | 2 +- ...linux-gnu.json => my-x86_64-unknown-linux-gnu-platform.json} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/test/run-make/target-specs/{x86_64-unknown-linux-gnu.json => my-x86_64-unknown-linux-gnu-platform.json} (100%) diff --git a/src/test/run-make/target-specs/Makefile b/src/test/run-make/target-specs/Makefile index 6b58ad7b6df..5ea96daa3ef 100644 --- a/src/test/run-make/target-specs/Makefile +++ b/src/test/run-make/target-specs/Makefile @@ -5,5 +5,5 @@ all: $(RUSTC) foo.rs --target=my-invalid-platform.json 2>&1 | grep -q "Error loading target specification" $(RUSTC) foo.rs --target=my-incomplete-platform.json 2>&1 | grep 'Field llvm-target' RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm - RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=x86_64-unknown-linux-gnu --crate-type=lib --emit=asm + RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-x86_64-unknown-linux-gnu-platform --crate-type=lib --emit=asm $(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json - diff --git a/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json b/src/test/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json similarity index 100% rename from src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json rename to src/test/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json From 7735f59e8084a69361224da2b1bc7337214c2c85 Mon Sep 17 00:00:00 2001 From: tinaun Date: Tue, 10 Oct 2017 04:20:49 -0400 Subject: [PATCH 134/365] unstable book: OIBIT --- .../language-features/optin-builtin-traits.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/optin-builtin-traits.md diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md new file mode 100644 index 00000000000..9baa7eb3532 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md @@ -0,0 +1,49 @@ +# `optin_builtin_traits` + +The tracking issue for this feature is [#13231] + +[#13231]: https://github.com/rust-lang/rust/issues/13231 + +---- + +The `optin_builtin_traits` feature gate allows you to define _auto traits_. + +Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits +that are automatically implemented for every type, unless the type, or a type it contains, +has explictly opted out via a _negative impl_. + +[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html +[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html + +```rust +impl !Type for Trait +``` + +Example: + +```rust + #![feature(optin_builtin_traits)] + + trait Valid {} + + impl Valid for .. {} + + struct True; + struct False; + + impl !Valid for False {} + + struct MaybeValid(T); + + fn must_be_valid(_t: T) { + + } + + fn main() { + //works + must_be_valid( MaybeValid(True) ); + + // compiler error - trait bound not satisfied + // must_be_valid( MaybeValid(False) ); + } +``` From 364148dbf9d7a3e4a8e0c766ae3395f63fcb5a01 Mon Sep 17 00:00:00 2001 From: tinaun Date: Tue, 10 Oct 2017 04:42:59 -0400 Subject: [PATCH 135/365] unstable book: unboxed_closures --- .../src/language-features/unboxed-closures.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/unboxed-closures.md diff --git a/src/doc/unstable-book/src/language-features/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md new file mode 100644 index 00000000000..5146fcd8739 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/unboxed-closures.md @@ -0,0 +1,25 @@ +# `unboxed_closures` + +The tracking issue for this feature is [#29625] + +See Also: [`fn_traits`](library-features/fn-traits.md) + +[#29625]: https://github.com/rust-lang/rust/issues/29625 + +---- + +The `unboxed_closures` feature allows you to write functions using the `"rust-call"` ABI, +required for implmenting the [`Fn*`] family of traits. `"rust-call"` functions must have +exactly one (non self) argument, a tuple representing the argument list. + +[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html + +```rust +#![feature(unboxed_closures)] + +extern "rust-call" fn add_args(args: (u32, u32)) { + args.0 + args.1 +} + +fn main() {} +``` From d07825258e2d5860442616ede39eb11ca3f8c9b6 Mon Sep 17 00:00:00 2001 From: tinaun Date: Tue, 10 Oct 2017 04:51:39 -0400 Subject: [PATCH 136/365] unstable book: fn_traits --- .../language-features/optin-builtin-traits.md | 2 +- .../src/library-features/fn-traits.md | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/doc/unstable-book/src/library-features/fn-traits.md diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md index 9baa7eb3532..4ff46dedba1 100644 --- a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md +++ b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md @@ -15,7 +15,7 @@ has explictly opted out via a _negative impl_. [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html -```rust +```rust, ignore impl !Type for Trait ``` diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md new file mode 100644 index 00000000000..d0f1fe8dc7c --- /dev/null +++ b/src/doc/unstable-book/src/library-features/fn-traits.md @@ -0,0 +1,35 @@ +# `fn_traits` + +The tracking issue for this feature is [#29625] + +See Also: [`unboxed_closures`](language-features/unboxed_closures.md) + +[#29625]: https://github.com/rust-lang/rust/issues/29625 + +---- + +The `fn_traits` feature allows for implementation of the [`Fn*`] traits +for creating custom closure-like types. + +[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html + +```rust +#![feature(unboxed_closures)] +#![feature(fn_traits)] + +struct Adder { + a: u32 +} + +impl FnOnce<(u32, )> for Adder { + type Output = u32; + extern "rust-call" fn call_once(self, b: (u32, )) -> Self::Output { + self.a + b.0 + } +} + +fn main() { + let adder = Adder { a: 3 }; + assert_eq!(adder(2), 5); +} +``` From 52cb6fc9367f3aed373d8edda7c7fa52ed9f4c25 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 9 Oct 2017 15:50:56 +0200 Subject: [PATCH 137/365] Moved remaining AST-borrowck diagnostic definitions to `rustc_mir` crate. --- src/librustc_borrowck/diagnostics.rs | 469 --------------------------- src/librustc_borrowck/lib.rs | 7 - src/librustc_mir/diagnostics.rs | 461 ++++++++++++++++++++++++++ 3 files changed, 461 insertions(+), 476 deletions(-) diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 031dbcb1ebb..3fea01443be 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -9,472 +9,3 @@ // except according to those terms. #![allow(non_snake_case)] - -register_long_diagnostics! { - -E0373: r##" -This error occurs when an attempt is made to use data captured by a closure, -when that data may no longer exist. It's most commonly seen when attempting to -return a closure: - -```compile_fail,E0373 -fn foo() -> Box u32> { - let x = 0u32; - Box::new(|y| x + y) -} -``` - -Notice that `x` is stack-allocated by `foo()`. By default, Rust captures -closed-over data by reference. This means that once `foo()` returns, `x` no -longer exists. An attempt to access `x` within the closure would thus be -unsafe. - -Another situation where this might be encountered is when spawning threads: - -```compile_fail,E0373 -fn foo() { - let x = 0u32; - let y = 1u32; - - let thr = std::thread::spawn(|| { - x + y - }); -} -``` - -Since our new thread runs in parallel, the stack frame containing `x` and `y` -may well have disappeared by the time we try to use them. Even if we call -`thr.join()` within foo (which blocks until `thr` has completed, ensuring the -stack frame won't disappear), we will not succeed: the compiler cannot prove -that this behaviour is safe, and so won't let us do it. - -The solution to this problem is usually to switch to using a `move` closure. -This approach moves (or copies, where possible) data into the closure, rather -than taking references to it. For example: - -``` -fn foo() -> Box u32> { - let x = 0u32; - Box::new(move |y| x + y) -} -``` - -Now that the closure has its own copy of the data, there's no need to worry -about safety. -"##, - -E0382: r##" -This error occurs when an attempt is made to use a variable after its contents -have been moved elsewhere. For example: - -```compile_fail,E0382 -struct MyStruct { s: u32 } - -fn main() { - let mut x = MyStruct{ s: 5u32 }; - let y = x; - x.s = 6; - println!("{}", x.s); -} -``` - -Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out -of `x` when we set `y`. This is fundamental to Rust's ownership system: outside -of workarounds like `Rc`, a value cannot be owned by more than one variable. - -If we own the type, the easiest way to address this problem is to implement -`Copy` and `Clone` on it, as shown below. This allows `y` to copy the -information in `x`, while leaving the original version owned by `x`. Subsequent -changes to `x` will not be reflected when accessing `y`. - -``` -#[derive(Copy, Clone)] -struct MyStruct { s: u32 } - -fn main() { - let mut x = MyStruct{ s: 5u32 }; - let y = x; - x.s = 6; - println!("{}", x.s); -} -``` - -Alternatively, if we don't control the struct's definition, or mutable shared -ownership is truly required, we can use `Rc` and `RefCell`: - -``` -use std::cell::RefCell; -use std::rc::Rc; - -struct MyStruct { s: u32 } - -fn main() { - let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 })); - let y = x.clone(); - x.borrow_mut().s = 6; - println!("{}", x.borrow().s); -} -``` - -With this approach, x and y share ownership of the data via the `Rc` (reference -count type). `RefCell` essentially performs runtime borrow checking: ensuring -that at most one writer or multiple readers can access the data at any one time. - -If you wish to learn more about ownership in Rust, start with the chapter in the -Book: - -https://doc.rust-lang.org/book/first-edition/ownership.html -"##, - -E0383: r##" -This error occurs when an attempt is made to partially reinitialize a -structure that is currently uninitialized. - -For example, this can happen when a drop has taken place: - -```compile_fail,E0383 -struct Foo { - a: u32, -} -impl Drop for Foo { - fn drop(&mut self) { /* ... */ } -} - -let mut x = Foo { a: 1 }; -drop(x); // `x` is now uninitialized -x.a = 2; // error, partial reinitialization of uninitialized structure `t` -``` - -This error can be fixed by fully reinitializing the structure in question: - -``` -struct Foo { - a: u32, -} -impl Drop for Foo { - fn drop(&mut self) { /* ... */ } -} - -let mut x = Foo { a: 1 }; -drop(x); -x = Foo { a: 2 }; -``` -"##, - -/*E0386: r##" -This error occurs when an attempt is made to mutate the target of a mutable -reference stored inside an immutable container. - -For example, this can happen when storing a `&mut` inside an immutable `Box`: - -```compile_fail,E0386 -let mut x: i64 = 1; -let y: Box<_> = Box::new(&mut x); -**y = 2; // error, cannot assign to data in an immutable container -``` - -This error can be fixed by making the container mutable: - -``` -let mut x: i64 = 1; -let mut y: Box<_> = Box::new(&mut x); -**y = 2; -``` - -It can also be fixed by using a type with interior mutability, such as `Cell` -or `RefCell`: - -``` -use std::cell::Cell; - -let x: i64 = 1; -let y: Box> = Box::new(Cell::new(x)); -y.set(2); -``` -"##,*/ - -E0387: r##" -This error occurs when an attempt is made to mutate or mutably reference data -that a closure has captured immutably. Examples of this error are shown below: - -```compile_fail,E0387 -// Accepts a function or a closure that captures its environment immutably. -// Closures passed to foo will not be able to mutate their closed-over state. -fn foo(f: F) { } - -// Attempts to mutate closed-over data. Error message reads: -// `cannot assign to data in a captured outer variable...` -fn mutable() { - let mut x = 0u32; - foo(|| x = 2); -} - -// Attempts to take a mutable reference to closed-over data. Error message -// reads: `cannot borrow data mutably in a captured outer variable...` -fn mut_addr() { - let mut x = 0u32; - foo(|| { let y = &mut x; }); -} -``` - -The problem here is that foo is defined as accepting a parameter of type `Fn`. -Closures passed into foo will thus be inferred to be of type `Fn`, meaning that -they capture their context immutably. - -If the definition of `foo` is under your control, the simplest solution is to -capture the data mutably. This can be done by defining `foo` to take FnMut -rather than Fn: - -``` -fn foo(f: F) { } -``` - -Alternatively, we can consider using the `Cell` and `RefCell` types to achieve -interior mutability through a shared reference. Our example's `mutable` -function could be redefined as below: - -``` -use std::cell::Cell; - -fn foo(f: F) { } - -fn mutable() { - let x = Cell::new(0u32); - foo(|| x.set(2)); -} -``` - -You can read more about cell types in the API documentation: - -https://doc.rust-lang.org/std/cell/ -"##, - -E0388: r##" -E0388 was removed and is no longer issued. -"##, - -E0389: r##" -An attempt was made to mutate data using a non-mutable reference. This -commonly occurs when attempting to assign to a non-mutable reference of a -mutable reference (`&(&mut T)`). - -Example of erroneous code: - -```compile_fail,E0389 -struct FancyNum { - num: u8, -} - -fn main() { - let mut fancy = FancyNum{ num: 5 }; - let fancy_ref = &(&mut fancy); - fancy_ref.num = 6; // error: cannot assign to data in a `&` reference - println!("{}", fancy_ref.num); -} -``` - -Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an -immutable reference to a value borrows it immutably. There can be multiple -references of type `&(&mut T)` that point to the same value, so they must be -immutable to prevent multiple mutable references to the same value. - -To fix this, either remove the outer reference: - -``` -struct FancyNum { - num: u8, -} - -fn main() { - let mut fancy = FancyNum{ num: 5 }; - - let fancy_ref = &mut fancy; - // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum) - - fancy_ref.num = 6; // No error! - - println!("{}", fancy_ref.num); -} -``` - -Or make the outer reference mutable: - -``` -struct FancyNum { - num: u8 -} - -fn main() { - let mut fancy = FancyNum{ num: 5 }; - - let fancy_ref = &mut (&mut fancy); - // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum) - - fancy_ref.num = 6; // No error! - - println!("{}", fancy_ref.num); -} -``` -"##, - -E0595: r##" -Closures cannot mutate immutable captured variables. - -Erroneous code example: - -```compile_fail,E0595 -let x = 3; // error: closure cannot assign to immutable local variable `x` -let mut c = || { x += 1 }; -``` - -Make the variable binding mutable: - -``` -let mut x = 3; // ok! -let mut c = || { x += 1 }; -``` -"##, - -E0596: r##" -This error occurs because you tried to mutably borrow a non-mutable variable. - -Example of erroneous code: - -```compile_fail,E0596 -let x = 1; -let y = &mut x; // error: cannot borrow mutably -``` - -In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it -fails. To fix this error, you need to make `x` mutable: - -``` -let mut x = 1; -let y = &mut x; // ok! -``` -"##, - -E0597: r##" -This error occurs because a borrow was made inside a variable which has a -greater lifetime than the borrowed one. - -Example of erroneous code: - -```compile_fail,E0597 -struct Foo<'a> { - x: Option<&'a u32>, -} - -let mut x = Foo { x: None }; -let y = 0; -x.x = Some(&y); // error: `y` does not live long enough -``` - -In here, `x` is created before `y` and therefore has a greater lifetime. Always -keep in mind that values in a scope are dropped in the opposite order they are -created. So to fix the previous example, just make the `y` lifetime greater than -the `x`'s one: - -``` -struct Foo<'a> { - x: Option<&'a u32>, -} - -let y = 0; -let mut x = Foo { x: None }; -x.x = Some(&y); -``` -"##, - -E0626: r##" -This error occurs because a borrow in a generator persists across a -yield point. - -```compile_fail,E0626 -# #![feature(generators, generator_trait)] -# use std::ops::Generator; -let mut b = || { - let a = &String::new(); // <-- This borrow... - yield (); // ...is still in scope here, when the yield occurs. - println!("{}", a); -}; -b.resume(); -``` - -At present, it is not permitted to have a yield that occurs while a -borrow is still in scope. To resolve this error, the borrow must -either be "contained" to a smaller scope that does not overlap the -yield or else eliminated in another way. So, for example, we might -resolve the previous example by removing the borrow and just storing -the integer by value: - -``` -# #![feature(generators, generator_trait)] -# use std::ops::Generator; -let mut b = || { - let a = 3; - yield (); - println!("{}", a); -}; -b.resume(); -``` - -This is a very simple case, of course. In more complex cases, we may -wish to have more than one reference to the value that was borrowed -- -in those cases, something like the `Rc` or `Arc` types may be useful. - -This error also frequently arises with iteration: - -```compile_fail,E0626 -# #![feature(generators, generator_trait)] -# use std::ops::Generator; -let mut b = || { - let v = vec![1,2,3]; - for &x in &v { // <-- borrow of `v` is still in scope... - yield x; // ...when this yield occurs. - } -}; -b.resume(); -``` - -Such cases can sometimes be resolved by iterating "by value" (or using -`into_iter()`) to avoid borrowing: - -``` -# #![feature(generators, generator_trait)] -# use std::ops::Generator; -let mut b = || { - let v = vec![1,2,3]; - for x in v { // <-- Take ownership of the values instead! - yield x; // <-- Now yield is OK. - } -}; -b.resume(); -``` - -If taking ownership is not an option, using indices can work too: - -``` -# #![feature(generators, generator_trait)] -# use std::ops::Generator; -let mut b = || { - let v = vec![1,2,3]; - let len = v.len(); // (*) - for i in 0..len { - let x = v[i]; // (*) - yield x; // <-- Now yield is OK. - } -}; -b.resume(); - -// (*) -- Unfortunately, these temporaries are currently required. -// See . -``` -"##, - -} - -register_diagnostics! { -// E0385, // {} in an aliasable location - E0598, // lifetime of {} is too short to guarantee its contents can be... -} diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 9bedbfed5db..94548f57249 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -16,7 +16,6 @@ #![allow(non_camel_case_types)] #![feature(quote)] -#![feature(rustc_diagnostic_macros)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -33,14 +32,8 @@ extern crate rustc_mir; pub use borrowck::check_crate; pub use borrowck::build_borrowck_dataflow_data_for_fn; -// NB: This module needs to be declared first so diagnostics are -// registered before they are used. -mod diagnostics; - mod borrowck; pub mod graphviz; pub use borrowck::provide; - -__build_diagnostic_array! { librustc_borrowck, DIAGNOSTICS } diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 645af0bff64..98c5345c69d 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -229,6 +229,57 @@ fn main() { See also https://doc.rust-lang.org/book/first-edition/unsafe.html "##, +E0373: r##" +This error occurs when an attempt is made to use data captured by a closure, +when that data may no longer exist. It's most commonly seen when attempting to +return a closure: + +```compile_fail,E0373 +fn foo() -> Box u32> { + let x = 0u32; + Box::new(|y| x + y) +} +``` + +Notice that `x` is stack-allocated by `foo()`. By default, Rust captures +closed-over data by reference. This means that once `foo()` returns, `x` no +longer exists. An attempt to access `x` within the closure would thus be +unsafe. + +Another situation where this might be encountered is when spawning threads: + +```compile_fail,E0373 +fn foo() { + let x = 0u32; + let y = 1u32; + + let thr = std::thread::spawn(|| { + x + y + }); +} +``` + +Since our new thread runs in parallel, the stack frame containing `x` and `y` +may well have disappeared by the time we try to use them. Even if we call +`thr.join()` within foo (which blocks until `thr` has completed, ensuring the +stack frame won't disappear), we will not succeed: the compiler cannot prove +that this behaviour is safe, and so won't let us do it. + +The solution to this problem is usually to switch to using a `move` closure. +This approach moves (or copies, where possible) data into the closure, rather +than taking references to it. For example: + +``` +fn foo() -> Box u32> { + let x = 0u32; + Box::new(move |y| x + y) +} +``` + +Now that the closure has its own copy of the data, there's no need to worry +about safety. +"##, + E0381: r##" It is not allowed to use or capture an uninitialized variable. For example: @@ -250,6 +301,104 @@ fn main() { ``` "##, +E0382: r##" +This error occurs when an attempt is made to use a variable after its contents +have been moved elsewhere. For example: + +```compile_fail,E0382 +struct MyStruct { s: u32 } + +fn main() { + let mut x = MyStruct{ s: 5u32 }; + let y = x; + x.s = 6; + println!("{}", x.s); +} +``` + +Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out +of `x` when we set `y`. This is fundamental to Rust's ownership system: outside +of workarounds like `Rc`, a value cannot be owned by more than one variable. + +If we own the type, the easiest way to address this problem is to implement +`Copy` and `Clone` on it, as shown below. This allows `y` to copy the +information in `x`, while leaving the original version owned by `x`. Subsequent +changes to `x` will not be reflected when accessing `y`. + +``` +#[derive(Copy, Clone)] +struct MyStruct { s: u32 } + +fn main() { + let mut x = MyStruct{ s: 5u32 }; + let y = x; + x.s = 6; + println!("{}", x.s); +} +``` + +Alternatively, if we don't control the struct's definition, or mutable shared +ownership is truly required, we can use `Rc` and `RefCell`: + +``` +use std::cell::RefCell; +use std::rc::Rc; + +struct MyStruct { s: u32 } + +fn main() { + let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 })); + let y = x.clone(); + x.borrow_mut().s = 6; + println!("{}", x.borrow().s); +} +``` + +With this approach, x and y share ownership of the data via the `Rc` (reference +count type). `RefCell` essentially performs runtime borrow checking: ensuring +that at most one writer or multiple readers can access the data at any one time. + +If you wish to learn more about ownership in Rust, start with the chapter in the +Book: + +https://doc.rust-lang.org/book/first-edition/ownership.html +"##, + +E0383: r##" +This error occurs when an attempt is made to partially reinitialize a +structure that is currently uninitialized. + +For example, this can happen when a drop has taken place: + +```compile_fail,E0383 +struct Foo { + a: u32, +} +impl Drop for Foo { + fn drop(&mut self) { /* ... */ } +} + +let mut x = Foo { a: 1 }; +drop(x); // `x` is now uninitialized +x.a = 2; // error, partial reinitialization of uninitialized structure `t` +``` + +This error can be fixed by fully reinitializing the structure in question: + +``` +struct Foo { + a: u32, +} +impl Drop for Foo { + fn drop(&mut self) { /* ... */ } +} + +let mut x = Foo { a: 1 }; +drop(x); +x = Foo { a: 2 }; +``` +"##, + E0384: r##" This error occurs when an attempt is made to reassign an immutable variable. For example: @@ -272,6 +421,161 @@ fn main() { ``` "##, +/*E0386: r##" +This error occurs when an attempt is made to mutate the target of a mutable +reference stored inside an immutable container. + +For example, this can happen when storing a `&mut` inside an immutable `Box`: + +```compile_fail,E0386 +let mut x: i64 = 1; +let y: Box<_> = Box::new(&mut x); +**y = 2; // error, cannot assign to data in an immutable container +``` + +This error can be fixed by making the container mutable: + +``` +let mut x: i64 = 1; +let mut y: Box<_> = Box::new(&mut x); +**y = 2; +``` + +It can also be fixed by using a type with interior mutability, such as `Cell` +or `RefCell`: + +``` +use std::cell::Cell; + +let x: i64 = 1; +let y: Box> = Box::new(Cell::new(x)); +y.set(2); +``` +"##,*/ + +E0387: r##" +This error occurs when an attempt is made to mutate or mutably reference data +that a closure has captured immutably. Examples of this error are shown below: + +```compile_fail,E0387 +// Accepts a function or a closure that captures its environment immutably. +// Closures passed to foo will not be able to mutate their closed-over state. +fn foo(f: F) { } + +// Attempts to mutate closed-over data. Error message reads: +// `cannot assign to data in a captured outer variable...` +fn mutable() { + let mut x = 0u32; + foo(|| x = 2); +} + +// Attempts to take a mutable reference to closed-over data. Error message +// reads: `cannot borrow data mutably in a captured outer variable...` +fn mut_addr() { + let mut x = 0u32; + foo(|| { let y = &mut x; }); +} +``` + +The problem here is that foo is defined as accepting a parameter of type `Fn`. +Closures passed into foo will thus be inferred to be of type `Fn`, meaning that +they capture their context immutably. + +If the definition of `foo` is under your control, the simplest solution is to +capture the data mutably. This can be done by defining `foo` to take FnMut +rather than Fn: + +``` +fn foo(f: F) { } +``` + +Alternatively, we can consider using the `Cell` and `RefCell` types to achieve +interior mutability through a shared reference. Our example's `mutable` +function could be redefined as below: + +``` +use std::cell::Cell; + +fn foo(f: F) { } + +fn mutable() { + let x = Cell::new(0u32); + foo(|| x.set(2)); +} +``` + +You can read more about cell types in the API documentation: + +https://doc.rust-lang.org/std/cell/ +"##, + +E0388: r##" +E0388 was removed and is no longer issued. +"##, + +E0389: r##" +An attempt was made to mutate data using a non-mutable reference. This +commonly occurs when attempting to assign to a non-mutable reference of a +mutable reference (`&(&mut T)`). + +Example of erroneous code: + +```compile_fail,E0389 +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + let fancy_ref = &(&mut fancy); + fancy_ref.num = 6; // error: cannot assign to data in a `&` reference + println!("{}", fancy_ref.num); +} +``` + +Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an +immutable reference to a value borrows it immutably. There can be multiple +references of type `&(&mut T)` that point to the same value, so they must be +immutable to prevent multiple mutable references to the same value. + +To fix this, either remove the outer reference: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + + let fancy_ref = &mut fancy; + // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum) + + fancy_ref.num = 6; // No error! + + println!("{}", fancy_ref.num); +} +``` + +Or make the outer reference mutable: + +``` +struct FancyNum { + num: u8 +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + + let fancy_ref = &mut (&mut fancy); + // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum) + + fancy_ref.num = 6; // No error! + + println!("{}", fancy_ref.num); +} +``` +"##, E0394: r##" A static was referred to by value by another static. @@ -1265,12 +1569,169 @@ fn main() { ``` "##, +E0595: r##" +Closures cannot mutate immutable captured variables. + +Erroneous code example: + +```compile_fail,E0595 +let x = 3; // error: closure cannot assign to immutable local variable `x` +let mut c = || { x += 1 }; +``` + +Make the variable binding mutable: + +``` +let mut x = 3; // ok! +let mut c = || { x += 1 }; +``` +"##, + +E0596: r##" +This error occurs because you tried to mutably borrow a non-mutable variable. + +Example of erroneous code: + +```compile_fail,E0596 +let x = 1; +let y = &mut x; // error: cannot borrow mutably +``` + +In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it +fails. To fix this error, you need to make `x` mutable: + +``` +let mut x = 1; +let y = &mut x; // ok! +``` +"##, + +E0597: r##" +This error occurs because a borrow was made inside a variable which has a +greater lifetime than the borrowed one. + +Example of erroneous code: + +```compile_fail,E0597 +struct Foo<'a> { + x: Option<&'a u32>, +} + +let mut x = Foo { x: None }; +let y = 0; +x.x = Some(&y); // error: `y` does not live long enough +``` + +In here, `x` is created before `y` and therefore has a greater lifetime. Always +keep in mind that values in a scope are dropped in the opposite order they are +created. So to fix the previous example, just make the `y` lifetime greater than +the `x`'s one: + +``` +struct Foo<'a> { + x: Option<&'a u32>, +} + +let y = 0; +let mut x = Foo { x: None }; +x.x = Some(&y); +``` +"##, + +E0626: r##" +This error occurs because a borrow in a generator persists across a +yield point. + +```compile_fail,E0626 +# #![feature(generators, generator_trait)] +# use std::ops::Generator; +let mut b = || { + let a = &String::new(); // <-- This borrow... + yield (); // ...is still in scope here, when the yield occurs. + println!("{}", a); +}; +b.resume(); +``` + +At present, it is not permitted to have a yield that occurs while a +borrow is still in scope. To resolve this error, the borrow must +either be "contained" to a smaller scope that does not overlap the +yield or else eliminated in another way. So, for example, we might +resolve the previous example by removing the borrow and just storing +the integer by value: + +``` +# #![feature(generators, generator_trait)] +# use std::ops::Generator; +let mut b = || { + let a = 3; + yield (); + println!("{}", a); +}; +b.resume(); +``` + +This is a very simple case, of course. In more complex cases, we may +wish to have more than one reference to the value that was borrowed -- +in those cases, something like the `Rc` or `Arc` types may be useful. + +This error also frequently arises with iteration: + +```compile_fail,E0626 +# #![feature(generators, generator_trait)] +# use std::ops::Generator; +let mut b = || { + let v = vec![1,2,3]; + for &x in &v { // <-- borrow of `v` is still in scope... + yield x; // ...when this yield occurs. + } +}; +b.resume(); +``` + +Such cases can sometimes be resolved by iterating "by value" (or using +`into_iter()`) to avoid borrowing: + +``` +# #![feature(generators, generator_trait)] +# use std::ops::Generator; +let mut b = || { + let v = vec![1,2,3]; + for x in v { // <-- Take ownership of the values instead! + yield x; // <-- Now yield is OK. + } +}; +b.resume(); +``` + +If taking ownership is not an option, using indices can work too: + +``` +# #![feature(generators, generator_trait)] +# use std::ops::Generator; +let mut b = || { + let v = vec![1,2,3]; + let len = v.len(); // (*) + for i in 0..len { + let x = v[i]; // (*) + yield x; // <-- Now yield is OK. + } +}; +b.resume(); + +// (*) -- Unfortunately, these temporaries are currently required. +// See . +``` +"##, + } register_diagnostics! { +// E0385, // {} in an aliasable location E0493, // destructors cannot be evaluated at compile-time E0524, // two closures require unique access to `..` at the same time E0526, // shuffle indices are not constant E0594, // cannot assign to {} + E0598, // lifetime of {} is too short to guarantee its contents can be... E0625, // thread-local statics cannot be accessed at compile-time } From cf11ef436bb8883dce57213c27a73bc39870aa9b Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 9 Oct 2017 17:44:56 +0200 Subject: [PATCH 138/365] Fixed client code for diagnostics migration, adding new methods to `trait BorrowckErrors` as necessary. --- src/librustc_borrowck/borrowck/mod.rs | 71 ++++---------- src/librustc_borrowck/lib.rs | 2 +- src/librustc_driver/lib.rs | 1 - src/librustc_mir/util/borrowck_errors.rs | 118 +++++++++++++++++++++++ 4 files changed, 138 insertions(+), 54 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index a3f1340d429..5b5d9f5a7cf 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -614,11 +614,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let partial = moved_lp.depth() > lp.depth(); let msg = if !has_fork && partial { "partially " } else if has_fork && !has_common { "collaterally "} - else { "" }; - let mut err = struct_span_err!( - self.tcx.sess, use_span, E0382, - "{} of {}moved value: `{}`", - verb, msg, nl); + else { "" }; + let mut err = self.cannot_act_on_moved_value(use_span, + verb, + msg, + &format!("{}", nl)); let need_note = match lp.ty.sty { ty::TypeVariants::TyClosure(id, _) => { let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); @@ -698,10 +698,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { &self, span: Span, lp: &LoanPath<'tcx>) { - span_err!( - self.tcx.sess, span, E0383, - "partial reinitialization of uninitialized structure `{}`", - self.loan_path_to_string(lp)); + self.cannot_partially_reinit_an_uninit_struct(span, &self.loan_path_to_string(lp)) + .emit(); } pub fn report_reassigned_immutable_variable(&self, @@ -762,8 +760,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.cannot_assign(error_span, &descr, Origin::Ast) } BorrowViolation(euv::ClosureCapture(_)) => { - struct_span_err!(self.tcx.sess, error_span, E0595, - "closure cannot assign to {}", descr) + self.closure_cannot_assign_to_borrowed(error_span, &descr) } BorrowViolation(euv::OverloadedOperator) | BorrowViolation(euv::AddrOf) | @@ -772,8 +769,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { BorrowViolation(euv::AutoUnsafe) | BorrowViolation(euv::ForLoop) | BorrowViolation(euv::MatchDiscriminant) => { - struct_span_err!(self.tcx.sess, error_span, E0596, - "cannot borrow {} as mutable", descr) + self.cannot_borrow_path_as_mutable(error_span, &descr) } BorrowViolation(euv::ClosureInvocation) => { span_bug!(err.span, @@ -855,21 +851,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let Some((yield_span, _)) = maybe_borrow_across_yield { debug!("err_out_of_scope: opt_yield_span = {:?}", yield_span); - struct_span_err!(self.tcx.sess, - error_span, - E0626, - "borrow may still be in use when generator yields") - .span_label(yield_span, "possible yield occurs here") + self.cannot_borrow_across_generator_yield(error_span, yield_span) .emit(); return; } - let mut db = struct_span_err!(self.tcx.sess, - error_span, - E0597, - "{} does not live long enough", - msg); - + let mut db = self.path_does_not_live_long_enough(error_span, &msg); let (value_kind, value_msg) = match err.cmt.cat { mc::Categorization::Rvalue(..) => ("temporary value", "temporary value created here"), @@ -978,11 +965,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } err_borrowed_pointer_too_short(loan_scope, ptr_scope) => { let descr = self.cmt_to_path_or_string(&err.cmt); - let mut db = struct_span_err!(self.tcx.sess, error_span, E0598, - "lifetime of {} is too short to guarantee \ - its contents can be safely reborrowed", - descr); - + let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr); let descr = match opt_loan_path(&err.cmt) { Some(lp) => { format!("`{}`", self.loan_path_to_string(&lp)) @@ -1054,12 +1037,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let blame = cmt.immutability_blame(); let mut err = match blame { Some(ImmutabilityBlame::ClosureEnv(id)) => { - let mut err = struct_span_err!( - self.tcx.sess, span, E0387, - "{} in a captured outer variable in an `Fn` closure", prefix); - // FIXME: the distinction between these 2 messages looks wrong. - let help = if let BorrowViolation(euv::ClosureCapture(_)) = kind { + let help_msg = if let BorrowViolation(euv::ClosureCapture(_)) = kind { // The aliasability violation with closure captures can // happen for nested closures, so we know the enclosing // closure incorrectly accepts an `Fn` while it needs to @@ -1070,15 +1049,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { "consider changing this closure to take self by mutable reference" }; let node_id = self.tcx.hir.def_index_to_node_id(id); - err.span_help(self.tcx.hir.span(node_id), help); - err + let help_span = self.tcx.hir.span(node_id); + self.cannot_act_on_capture_in_sharable_fn(span, prefix, (help_span, help_msg)) } _ => { - let mut err = struct_span_err!( - self.tcx.sess, span, E0389, - "{} in a `&` reference", prefix); - err.span_label(span, "assignment into an immutable reference"); - err + self.cannot_assign_into_immutable_reference(span, prefix) } }; self.note_immutability_blame(&mut err, blame); @@ -1230,17 +1205,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { Err(_) => format!("move || ") }; - struct_span_err!(self.tcx.sess, err.span, E0373, - "closure may outlive the current function, \ - but it borrows {}, \ - which is owned by the current function", - cmt_path_or_string) - .span_label(capture_span, - format!("{} is borrowed here", - cmt_path_or_string)) - .span_label(err.span, - format!("may outlive borrowed value {}", - cmt_path_or_string)) + self.cannot_capture_in_long_lived_closure(err.span, + &cmt_path_or_string, + capture_span) .span_suggestion(err.span, &format!("to force the closure to take ownership of {} \ (and any other referenced variables), \ diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 94548f57249..11120d2e46f 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -18,7 +18,7 @@ #![feature(quote)] #[macro_use] extern crate log; -#[macro_use] extern crate syntax; +extern crate syntax; extern crate syntax_pos; extern crate rustc_errors as errors; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index cd21060aff6..3514302c6c8 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1259,7 +1259,6 @@ pub fn diagnostics_registry() -> errors::registry::Registry { let mut all_errors = Vec::new(); all_errors.extend_from_slice(&rustc::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_typeck::DIAGNOSTICS); - all_errors.extend_from_slice(&rustc_borrowck::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS); #[cfg(feature="llvm")] diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 37d53ca829e..3c002b586fa 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -294,6 +294,124 @@ pub trait BorrowckErrors { err.span_label(move_from_span, "cannot move out of here"); err } + + fn cannot_act_on_moved_value(&self, + use_span: Span, + verb: &str, + optional_adverb_for_moved: &str, + moved_path: &str) + -> DiagnosticBuilder + { + let err = struct_span_err!(self, use_span, E0382, + "{} of {}moved value: `{}`", + verb, optional_adverb_for_moved, moved_path); + err + } + + fn cannot_partially_reinit_an_uninit_struct(&self, + span: Span, + uninit_path: &str) + -> DiagnosticBuilder + { + let err = struct_span_err!(self, + span, + E0383, + "partial reinitialization of uninitialized structure `{}`", + uninit_path); + err + } + + fn closure_cannot_assign_to_borrowed(&self, + span: Span, + descr: &str) + -> DiagnosticBuilder + { + let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}", descr); + err + } + + fn cannot_borrow_path_as_mutable(&self, + span: Span, + path: &str) + -> DiagnosticBuilder + { + let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable", path); + err + } + + fn cannot_borrow_across_generator_yield(&self, + span: Span, + yield_span: Span) + -> DiagnosticBuilder + { + let mut err = struct_span_err!(self, + span, + E0626, + "borrow may still be in use when generator yields"); + err.span_label(yield_span, "possible yield occurs here"); + err + } + + fn path_does_not_live_long_enough(&self, + span: Span, + path: &str) + -> DiagnosticBuilder + { + let err = struct_span_err!(self, span, E0597, "{} does not live long enough", path); + err + } + + fn lifetime_too_short_for_reborrow(&self, + span: Span, + path: &str) + -> DiagnosticBuilder + { + let err = struct_span_err!(self, span, E0598, + "lifetime of {} is too short to guarantee \ + its contents can be safely reborrowed", + path); + err + } + + fn cannot_act_on_capture_in_sharable_fn(&self, + span: Span, + bad_thing: &str, + help: (Span, &str)) + -> DiagnosticBuilder + { + let (help_span, help_msg) = help; + let mut err = struct_span_err!(self, span, E0387, + "{} in a captured outer variable in an `Fn` closure", + bad_thing); + err.span_help(help_span, help_msg); + err + } + + fn cannot_assign_into_immutable_reference(&self, + span: Span, + bad_thing: &str) + -> DiagnosticBuilder + { + let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference", bad_thing); + err.span_label(span, "assignment into an immutable reference"); + err + } + + fn cannot_capture_in_long_lived_closure(&self, + closure_span: Span, + borrowed_path: &str, + capture_span: Span) + -> DiagnosticBuilder + { + let mut err = struct_span_err!(self, closure_span, E0373, + "closure may outlive the current function, \ + but it borrows {}, \ + which is owned by the current function", + borrowed_path); + err.span_label(capture_span, format!("{} is borrowed here", borrowed_path)) + .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path)); + err + } } impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> { From 5b68e1f8da35ed361633d1838988e9ce15f51620 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 10 Oct 2017 12:39:48 +0200 Subject: [PATCH 139/365] Add `Origin::Ast` arguments to all of the migrated AST-borrowck diagnostics. --- src/librustc_borrowck/borrowck/mod.rs | 28 ++++++---- src/librustc_mir/util/borrowck_errors.rs | 65 +++++++++++++++--------- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 5b5d9f5a7cf..9fe272463dd 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -618,7 +618,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let mut err = self.cannot_act_on_moved_value(use_span, verb, msg, - &format!("{}", nl)); + &format!("{}", nl), + Origin::Ast); let need_note = match lp.ty.sty { ty::TypeVariants::TyClosure(id, _) => { let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); @@ -698,7 +699,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { &self, span: Span, lp: &LoanPath<'tcx>) { - self.cannot_partially_reinit_an_uninit_struct(span, &self.loan_path_to_string(lp)) + self.cannot_partially_reinit_an_uninit_struct(span, + &self.loan_path_to_string(lp), + Origin::Ast) .emit(); } @@ -760,7 +763,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.cannot_assign(error_span, &descr, Origin::Ast) } BorrowViolation(euv::ClosureCapture(_)) => { - self.closure_cannot_assign_to_borrowed(error_span, &descr) + self.closure_cannot_assign_to_borrowed(error_span, &descr, Origin::Ast) } BorrowViolation(euv::OverloadedOperator) | BorrowViolation(euv::AddrOf) | @@ -769,7 +772,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { BorrowViolation(euv::AutoUnsafe) | BorrowViolation(euv::ForLoop) | BorrowViolation(euv::MatchDiscriminant) => { - self.cannot_borrow_path_as_mutable(error_span, &descr) + self.cannot_borrow_path_as_mutable(error_span, &descr, Origin::Ast) } BorrowViolation(euv::ClosureInvocation) => { span_bug!(err.span, @@ -851,12 +854,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let Some((yield_span, _)) = maybe_borrow_across_yield { debug!("err_out_of_scope: opt_yield_span = {:?}", yield_span); - self.cannot_borrow_across_generator_yield(error_span, yield_span) + self.cannot_borrow_across_generator_yield(error_span, yield_span, Origin::Ast) .emit(); return; } - let mut db = self.path_does_not_live_long_enough(error_span, &msg); + let mut db = self.path_does_not_live_long_enough(error_span, &msg, Origin::Ast); let (value_kind, value_msg) = match err.cmt.cat { mc::Categorization::Rvalue(..) => ("temporary value", "temporary value created here"), @@ -965,7 +968,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } err_borrowed_pointer_too_short(loan_scope, ptr_scope) => { let descr = self.cmt_to_path_or_string(&err.cmt); - let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr); + let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr, Origin::Ast); let descr = match opt_loan_path(&err.cmt) { Some(lp) => { format!("`{}`", self.loan_path_to_string(&lp)) @@ -1050,10 +1053,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { }; let node_id = self.tcx.hir.def_index_to_node_id(id); let help_span = self.tcx.hir.span(node_id); - self.cannot_act_on_capture_in_sharable_fn(span, prefix, (help_span, help_msg)) + self.cannot_act_on_capture_in_sharable_fn(span, + prefix, + (help_span, help_msg), + Origin::Ast) } _ => { - self.cannot_assign_into_immutable_reference(span, prefix) + self.cannot_assign_into_immutable_reference(span, prefix, + Origin::Ast) } }; self.note_immutability_blame(&mut err, blame); @@ -1207,7 +1214,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.cannot_capture_in_long_lived_closure(err.span, &cmt_path_or_string, - capture_span) + capture_span, + Origin::Ast) .span_suggestion(err.span, &format!("to force the closure to take ownership of {} \ (and any other referenced variables), \ diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 3c002b586fa..216f6e44570 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -299,100 +299,114 @@ pub trait BorrowckErrors { use_span: Span, verb: &str, optional_adverb_for_moved: &str, - moved_path: &str) + moved_path: &str, + o: Origin) -> DiagnosticBuilder { let err = struct_span_err!(self, use_span, E0382, - "{} of {}moved value: `{}`", - verb, optional_adverb_for_moved, moved_path); + "{} of {}moved value: `{}`{OGN}", + verb, optional_adverb_for_moved, moved_path, OGN=o); err } fn cannot_partially_reinit_an_uninit_struct(&self, span: Span, - uninit_path: &str) + uninit_path: &str, + o: Origin) -> DiagnosticBuilder { let err = struct_span_err!(self, span, E0383, - "partial reinitialization of uninitialized structure `{}`", - uninit_path); + "partial reinitialization of uninitialized structure `{}`{OGN}", + uninit_path, OGN=o); err } fn closure_cannot_assign_to_borrowed(&self, span: Span, - descr: &str) + descr: &str, + o: Origin) -> DiagnosticBuilder { - let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}", descr); + let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}", + descr, OGN=o); err } fn cannot_borrow_path_as_mutable(&self, span: Span, - path: &str) + path: &str, + o: Origin) -> DiagnosticBuilder { - let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable", path); + let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}", + path, OGN=o); err } fn cannot_borrow_across_generator_yield(&self, span: Span, - yield_span: Span) + yield_span: Span, + o: Origin) -> DiagnosticBuilder { let mut err = struct_span_err!(self, span, E0626, - "borrow may still be in use when generator yields"); + "borrow may still be in use when generator yields{OGN}", + OGN=o); err.span_label(yield_span, "possible yield occurs here"); err } fn path_does_not_live_long_enough(&self, span: Span, - path: &str) + path: &str, + o: Origin) -> DiagnosticBuilder { - let err = struct_span_err!(self, span, E0597, "{} does not live long enough", path); + let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}", + path, OGN=o); err } fn lifetime_too_short_for_reborrow(&self, span: Span, - path: &str) + path: &str, + o: Origin) -> DiagnosticBuilder { let err = struct_span_err!(self, span, E0598, "lifetime of {} is too short to guarantee \ - its contents can be safely reborrowed", - path); + its contents can be safely reborrowed{OGN}", + path, OGN=o); err } fn cannot_act_on_capture_in_sharable_fn(&self, span: Span, bad_thing: &str, - help: (Span, &str)) + help: (Span, &str), + o: Origin) -> DiagnosticBuilder { let (help_span, help_msg) = help; let mut err = struct_span_err!(self, span, E0387, - "{} in a captured outer variable in an `Fn` closure", - bad_thing); + "{} in a captured outer variable in an `Fn` closure{OGN}", + bad_thing, OGN=o); err.span_help(help_span, help_msg); err } fn cannot_assign_into_immutable_reference(&self, span: Span, - bad_thing: &str) + bad_thing: &str, + o: Origin) -> DiagnosticBuilder { - let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference", bad_thing); + let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}", + bad_thing, OGN=o); err.span_label(span, "assignment into an immutable reference"); err } @@ -400,14 +414,15 @@ pub trait BorrowckErrors { fn cannot_capture_in_long_lived_closure(&self, closure_span: Span, borrowed_path: &str, - capture_span: Span) + capture_span: Span, + o: Origin) -> DiagnosticBuilder { let mut err = struct_span_err!(self, closure_span, E0373, "closure may outlive the current function, \ but it borrows {}, \ - which is owned by the current function", - borrowed_path); + which is owned by the current function{OGN}", + borrowed_path, OGN=o); err.span_label(capture_span, format!("{} is borrowed here", borrowed_path)) .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path)); err From 8628d51c3b4c9a45e9066019f0e0853da7643794 Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Tue, 10 Oct 2017 13:11:28 +0100 Subject: [PATCH 140/365] Band-aid fix to stop race conditions in llvm errors This is a big hammer, but should be effective at completely removing a few issues, including inconsistent error messages and segfaults when LLVM workers race to report results LLVM_THREAD_LOCAL has been present in LLVM since 8 months before 3.7 (the earliest supported LLVM version that Rust can use) Maybe fixes #43402 (third time lucky?) --- src/rustllvm/RustWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index bc616f64881..20ea8d70302 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -57,7 +57,7 @@ static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) { llvm_unreachable("Invalid LLVMAtomicOrdering value!"); } -static char *LastError; +static LLVM_THREAD_LOCAL char *LastError; extern "C" LLVMMemoryBufferRef LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { From 1138f853e194a79f7465233adefe550e7b8c6b5a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 10 Oct 2017 15:45:04 +0300 Subject: [PATCH 141/365] Fix a mistake in release notes for 1.21.0 Also reorder changes to put the important one first. --- RELEASES.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index e65934a89e6..194745d9caa 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -3,12 +3,6 @@ Version 1.21.0 (2017-10-12) Language -------- -- [Relaxed path syntax. You can now add type parameters to values][43540] - Example: - ```rust - my_macro!(Vec::new); // Always worked - my_macro!(Vec::::new); // Now works - ``` - [You can now use static references for literals.][43838] Example: ```rust @@ -16,6 +10,12 @@ Language let x: &'static u32 = &0; } ``` +- [Relaxed path syntax. Optional `::` before `<` is now allowed in all contexts.][43540] + Example: + ```rust + my_macro!(Vec::new); // Always worked + my_macro!(Vec::::new); // Now works + ``` Compiler -------- From 1cb9f70b22dcae385365d7e87ddbf8c0a28b2843 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 10 Oct 2017 16:12:11 +0200 Subject: [PATCH 142/365] Upgrade some comments to doc comments --- src/librustc/session/mod.rs | 54 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd6e5eb67c8..89dca3e020d 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -54,24 +54,24 @@ pub mod config; pub mod filesearch; pub mod search_paths; -// Represents the data associated with a compilation -// session for a single crate. +/// Represents the data associated with a compilation +/// session for a single crate. pub struct Session { pub target: config::Config, pub host: Target, pub opts: config::Options, pub parse_sess: ParseSess, - // For a library crate, this is always none + /// For a library crate, this is always none pub entry_fn: RefCell>, pub entry_type: Cell>, pub plugin_registrar_fn: Cell>, pub derive_registrar_fn: Cell>, pub default_sysroot: Option, - // The name of the root source file of the crate, in the local file system. - // `None` means that there is no source file. + /// The name of the root source file of the crate, in the local file system. + /// `None` means that there is no source file. pub local_crate_source_file: Option, - // The directory the compiler has been executed in plus a flag indicating - // if the value stored here has been affected by path remapping. + /// The directory the compiler has been executed in plus a flag indicating + /// if the value stored here has been affected by path remapping. pub working_dir: (String, bool), pub lint_store: RefCell, pub buffered_lints: RefCell>, @@ -83,11 +83,11 @@ pub struct Session { pub plugin_attributes: RefCell>, pub crate_types: RefCell>, pub dependency_formats: RefCell, - // The crate_disambiguator is constructed out of all the `-C metadata` - // arguments passed to the compiler. Its value together with the crate-name - // forms a unique global identifier for the crate. It is used to allow - // multiple crates with the same name to coexist. See the - // trans::back::symbol_names module for more information. + /// The crate_disambiguator is constructed out of all the `-C metadata` + /// arguments passed to the compiler. Its value together with the crate-name + /// forms a unique global identifier for the crate. It is used to allow + /// multiple crates with the same name to coexist. See the + /// trans::back::symbol_names module for more information. pub crate_disambiguator: RefCell>, pub features: RefCell, @@ -143,17 +143,17 @@ pub struct Session { } pub struct PerfStats { - // The accumulated time needed for computing the SVH of the crate + /// The accumulated time needed for computing the SVH of the crate pub svh_time: Cell, - // The accumulated time spent on computing incr. comp. hashes + /// The accumulated time spent on computing incr. comp. hashes pub incr_comp_hashes_time: Cell, - // The number of incr. comp. hash computations performed + /// The number of incr. comp. hash computations performed pub incr_comp_hashes_count: Cell, - // The number of bytes hashed when computing ICH values + /// The number of bytes hashed when computing ICH values pub incr_comp_bytes_hashed: Cell, - // The accumulated time spent on computing symbol hashes + /// The accumulated time spent on computing symbol hashes pub symbol_hash_time: Cell, - // The accumulated time spent decoding def path tables from metadata + /// The accumulated time spent decoding def path tables from metadata pub decode_def_path_tables_time: Cell, } @@ -804,24 +804,24 @@ pub fn build_session_(sopts: config::Options, /// Holds data on the current incremental compilation session, if there is one. #[derive(Debug)] pub enum IncrCompSession { - // This is the state the session will be in until the incr. comp. dir is - // needed. + /// This is the state the session will be in until the incr. comp. dir is + /// needed. NotInitialized, - // This is the state during which the session directory is private and can - // be modified. + /// This is the state during which the session directory is private and can + /// be modified. Active { session_directory: PathBuf, lock_file: flock::Lock, load_dep_graph: bool, }, - // This is the state after the session directory has been finalized. In this - // state, the contents of the directory must not be modified any more. + /// This is the state after the session directory has been finalized. In this + /// state, the contents of the directory must not be modified any more. Finalized { session_directory: PathBuf, }, - // This is an error state that is reached when some compilation error has - // occurred. It indicates that the contents of the session directory must - // not be used, since they might be invalid. + /// This is an error state that is reached when some compilation error has + /// occurred. It indicates that the contents of the session directory must + /// not be used, since they might be invalid. InvalidBecauseOfErrors { session_directory: PathBuf, } From 7a016c1ca6a6f27876fd07b1aa67e55ca6cba231 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 10 Oct 2017 17:08:29 +0200 Subject: [PATCH 143/365] incr.comp.: Add missing match branch in HashStable impl for ty::RegionKind. --- src/librustc/ich/impls_ty.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index fe060aaf426..582c4e13a82 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -61,6 +61,9 @@ for ty::RegionKind { def_id.hash_stable(hcx, hasher); name.hash_stable(hcx, hasher); } + ty::ReLateBound(db, ty::BrEnv) => { + db.depth.hash_stable(hcx, hasher); + } ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => { def_id.hash_stable(hcx, hasher); index.hash_stable(hcx, hasher); From 1235836f678eeae33c841ae5b8975b3967be886f Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 10 Oct 2017 17:11:08 +0200 Subject: [PATCH 144/365] incr.comp.: Fix instability in CodegenUnitExt::items_in_deterministic_order(). --- src/librustc_trans/partitioning.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 0d46ea64f9f..386806e4c9c 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -163,10 +163,27 @@ pub trait CodegenUnitExt<'tcx> { fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: TransItem<'tcx>) -> ItemSortKey { ItemSortKey(match item { - TransItem::Fn(instance) => { - tcx.hir.as_local_node_id(instance.def_id()) + TransItem::Fn(ref instance) => { + match instance.def { + // We only want to take NodeIds of user-defined + // instances into account. The others don't matter for + // the codegen tests and can even make item order + // unstable. + InstanceDef::Item(def_id) => { + tcx.hir.as_local_node_id(def_id) + } + InstanceDef::Intrinsic(..) | + InstanceDef::FnPtrShim(..) | + InstanceDef::Virtual(..) | + InstanceDef::ClosureOnceShim { .. } | + InstanceDef::DropGlue(..) | + InstanceDef::CloneShim(..) => { + None + } + } } - TransItem::Static(node_id) | TransItem::GlobalAsm(node_id) => { + TransItem::Static(node_id) | + TransItem::GlobalAsm(node_id) => { Some(node_id) } }, item.symbol_name(tcx)) From 8e900aaa2b92fdd5adce736b512efc5517c58592 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 10 Oct 2017 17:18:44 +0200 Subject: [PATCH 145/365] Enable building clippy in CI --- src/bootstrap/check.rs | 9 +++++++-- src/bootstrap/tool.rs | 4 ++-- src/tools/clippy | 2 +- src/tools/toolstate.toml | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 6e276f44668..daf965493d4 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -358,6 +358,7 @@ impl Step for Miri { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Clippy { + stage: u32, host: Interned, } @@ -372,6 +373,7 @@ impl Step for Clippy { fn make_run(run: RunConfig) { run.builder.ensure(Clippy { + stage: run.builder.top_stage, host: run.target, }); } @@ -379,10 +381,11 @@ impl Step for Clippy { /// Runs `cargo test` for clippy. fn run(self, builder: &Builder) { let build = builder.build; + let stage = self.stage; let host = self.host; - let compiler = builder.compiler(1, host); + let compiler = builder.compiler(stage, host); - let _clippy = builder.ensure(tool::Clippy { compiler, target: self.host }); + let clippy = builder.ensure(tool::Clippy { compiler, target: self.host }); let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml")); @@ -390,6 +393,8 @@ impl Step for Clippy { cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); // clippy tests need to know about the stage sysroot cargo.env("SYSROOT", builder.sysroot(compiler)); + // clippy tests need to find the driver + cargo.env("CLIPPY_DRIVER_PATH", clippy); builder.add_rustc_lib_path(compiler, &mut cargo); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index a05e58e6a22..e95a5e07436 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -387,7 +387,7 @@ pub struct Clippy { impl Step for Clippy { type Output = PathBuf; - const DEFAULT: bool = false; + const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun) -> ShouldRun { @@ -411,7 +411,7 @@ impl Step for Clippy { builder.ensure(ToolBuild { compiler: self.compiler, target: self.target, - tool: "clippy", + tool: "clippy-driver", mode: Mode::Librustc, path: "src/tools/clippy", expectation: builder.build.config.toolstate.clippy.passes(ToolState::Compiling), diff --git a/src/tools/clippy b/src/tools/clippy index 25444585592..b62b1b68edc 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 25444585592f5da648edd5317fcdd21f2db8bb64 +Subproject commit b62b1b68edcdf23a70cb12f31403c80e97f13634 diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml index 1700daa0aff..f5e96e3f56b 100644 --- a/src/tools/toolstate.toml +++ b/src/tools/toolstate.toml @@ -26,7 +26,7 @@ miri = "Broken" # ping @Manishearth @llogiq @mcarton @oli-obk -clippy = "Broken" +clippy = "Building" # ping @nrc rls = "Testing" From 843dc604447139463b76014d51e6976dc07ec0db Mon Sep 17 00:00:00 2001 From: Thomas Jespersen Date: Tue, 10 Oct 2017 00:21:09 +0200 Subject: [PATCH 146/365] Add suggestions for misspelled labels Another part of #30197 --- src/librustc_resolve/lib.rs | 36 +++++++++++++------ src/test/ui/suggestions/suggest-labels.rs | 26 ++++++++++++++ src/test/ui/suggestions/suggest-labels.stderr | 20 +++++++++++ 3 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-labels.rs create mode 100644 src/test/ui/suggestions/suggest-labels.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 36cd69f91b9..4aab43cbec7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -137,7 +137,7 @@ enum ResolutionError<'a> { /// error E0416: identifier is bound more than once in the same pattern IdentifierBoundMoreThanOnceInSamePattern(&'a str), /// error E0426: use of undeclared label - UndeclaredLabel(&'a str), + UndeclaredLabel(&'a str, Option), /// error E0429: `self` imports are only allowed within a { } list SelfImportsOnlyAllowedWithin, /// error E0430: `self` import can only appear once in the list @@ -263,13 +263,17 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, err.span_label(span, "used in a pattern more than once"); err } - ResolutionError::UndeclaredLabel(name) => { + ResolutionError::UndeclaredLabel(name, lev_candidate) => { let mut err = struct_span_err!(resolver.session, span, E0426, "use of undeclared label `{}`", name); - err.span_label(span, format!("undeclared label `{}`", name)); + if let Some(lev_candidate) = lev_candidate { + err.span_label(span, format!("did you mean `{}`?", lev_candidate)); + } else { + err.span_label(span, format!("undeclared label `{}`", name)); + } err } ResolutionError::SelfImportsOnlyAllowedWithin => { @@ -1790,9 +1794,13 @@ impl<'a> Resolver<'a> { } } - /// Searches the current set of local scopes for labels. + /// Searches the current set of local scopes for labels. Returns the first non-None label that + /// is returned by the given predicate function + /// /// Stops after meeting a closure. - fn search_label(&self, mut ident: Ident) -> Option { + fn search_label(&self, mut ident: Ident, pred: P) -> Option + where P: Fn(&Rib, Ident) -> Option + { for rib in self.label_ribs.iter().rev() { match rib.kind { NormalRibKind => {} @@ -1808,9 +1816,9 @@ impl<'a> Resolver<'a> { return None; } } - let result = rib.bindings.get(&ident).cloned(); - if result.is_some() { - return result; + let r = pred(rib, ident); + if r.is_some() { + return r; } } None @@ -3202,12 +3210,20 @@ impl<'a> Resolver<'a> { } ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { - match self.search_label(label.node) { + match self.search_label(label.node, |rib, id| rib.bindings.get(&id).cloned()) { None => { + // Search again for close matches... + // Picks the first label that is "close enough", which is not necessarily + // the closest match + let close_match = self.search_label(label.node, |rib, ident| { + let names = rib.bindings.iter().map(|(id, _)| &id.name); + find_best_match_for_name(names, &*ident.name.as_str(), None) + }); self.record_def(expr.id, err_path_resolution()); resolve_error(self, label.span, - ResolutionError::UndeclaredLabel(&label.node.name.as_str())); + ResolutionError::UndeclaredLabel(&label.node.name.as_str(), + close_match)); } Some(def @ Def::Label(_)) => { // Since this def is a label, it is never read. diff --git a/src/test/ui/suggestions/suggest-labels.rs b/src/test/ui/suggestions/suggest-labels.rs new file mode 100644 index 00000000000..5bebce79ecc --- /dev/null +++ b/src/test/ui/suggestions/suggest-labels.rs @@ -0,0 +1,26 @@ +// Copyright 2017 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. + +#[allow(unreachable_code)] +fn main() { + 'foo: loop { + break 'fo; + } + + 'bar: loop { + continue 'bor; + } + + 'longlabel: loop { + 'longlabel1: loop { + break 'longlable; + } + } +} diff --git a/src/test/ui/suggestions/suggest-labels.stderr b/src/test/ui/suggestions/suggest-labels.stderr new file mode 100644 index 00000000000..23aa18a3655 --- /dev/null +++ b/src/test/ui/suggestions/suggest-labels.stderr @@ -0,0 +1,20 @@ +error[E0426]: use of undeclared label `'fo` + --> $DIR/suggest-labels.rs:14:15 + | +14 | break 'fo; + | ^^^ did you mean `'foo`? + +error[E0426]: use of undeclared label `'bor` + --> $DIR/suggest-labels.rs:18:18 + | +18 | continue 'bor; + | ^^^^ did you mean `'bar`? + +error[E0426]: use of undeclared label `'longlable` + --> $DIR/suggest-labels.rs:23:19 + | +23 | break 'longlable; + | ^^^^^^^^^^ did you mean `'longlabel1`? + +error: aborting due to 3 previous errors + From c6c47fa6c0ee0569ba1ab725904c814aa33051ca Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 10 Oct 2017 18:16:18 +0200 Subject: [PATCH 147/365] Update toolstate.toml --- src/tools/toolstate.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml index f5e96e3f56b..b03e4f05641 100644 --- a/src/tools/toolstate.toml +++ b/src/tools/toolstate.toml @@ -3,7 +3,7 @@ # # There are three states a tool can be in: # 1. Broken: The tool doesn't build -# 2. Building: The tool builds but its tests are failing +# 2. Compiling: The tool builds but its tests are failing # 3. Testing: The tool builds and its tests are passing # # In the future there will be further states like "Distributing", which @@ -26,7 +26,7 @@ miri = "Broken" # ping @Manishearth @llogiq @mcarton @oli-obk -clippy = "Building" +clippy = "Compiling" # ping @nrc rls = "Testing" From 210c91100fe76926647eb5d71a77dc3b527ef038 Mon Sep 17 00:00:00 2001 From: Pirh Date: Tue, 10 Oct 2017 17:58:13 +0100 Subject: [PATCH 148/365] Remove misleading line on Windows Subsystem stdio --- src/libstd/process.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 1352c640fdd..d110fcfee6b 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -555,9 +555,6 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// On Windows, if the `#![windows_subsystem = "windows"]` attribute is - /// set, no stdin is connected unless explicitly assigned. - /// /// [`inherit`]: struct.Stdio.html#method.inherit /// [`piped`]: struct.Stdio.html#method.piped /// @@ -584,9 +581,6 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// On Windows, if the `#![windows_subsystem = "windows"]` attribute is - /// set, no stdout is connected unless explicitly assigned. - /// /// [`inherit`]: struct.Stdio.html#method.inherit /// [`piped`]: struct.Stdio.html#method.piped /// @@ -613,9 +607,6 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// On Windows, if the `#![windows_subsystem = "windows"]` attribute is - /// set, no stderr is connected unless explicitly assigned. - /// /// [`inherit`]: struct.Stdio.html#method.inherit /// [`piped`]: struct.Stdio.html#method.piped /// From 9e8b33e811bca10e23bb9e80445122a8ab31225c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Oct 2017 10:18:34 -0700 Subject: [PATCH 149/365] core: derive Clone for result::IntoIter It appears to be a simple oversight that `result::IntoIter` doesn't implement `Clone` (where `T: Clone`). We do already have `Clone` for `result::Iter`, as well as the similar `option::IntoIter` and `Iter`. --- src/libcore/result.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index ea064ca5c39..db5bffced10 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1060,7 +1060,7 @@ unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} /// [`Result`]: enum.Result.html /// [`into_iter`]: ../iter/trait.IntoIterator.html#tymethod.into_iter /// [`IntoIterator`]: ../iter/trait.IntoIterator.html -#[derive(Debug)] +#[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { inner: Option } From a84c62a7f13cd26faaf79a3a77d30706b73afaf8 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Tue, 10 Oct 2017 16:36:53 +0600 Subject: [PATCH 150/365] Fix path to x.py in configure.py script We may see a help message in the end of the output of the ./configure script: $ ./configure configure: processing command line configure: configure: build.configure-args := [] configure: configure: writing `config.toml` in current directory configure: configure: run `python ./src/bootstrap/x.py --help` configure: but the x.py script is actually in the rust root directory and executing of such help string will give us error: $ python ./src/bootstrap/x.py --help python: can't open file './src/bootstrap/x.py': [Errno 2] No such file or directory This patch fixes path to the x.py script in the output of the ./configure --- src/bootstrap/configure.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 67337bf4421..81a5dcfcd76 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -407,11 +407,6 @@ with open('Makefile', 'w') as f: contents = contents.replace("$(CFG_PYTHON)", sys.executable) f.write(contents) -# Finally, clean up with a bit of a help message -relpath = os.path.dirname(__file__) -if relpath == '': - relpath = '.' - p("") -p("run `python {}/x.py --help`".format(relpath)) +p("run `python {}/x.py --help`".format(rust_dir)) p("") From ca61ea2c44b22d082235c77223c3813df4c1174f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 11 Oct 2017 02:36:40 +0300 Subject: [PATCH 151/365] Shorten some test names Paths to object files generated from them were too long and caused errors --- ...zation-allowed-cross-crate.rs => allowed-cross-crate.rs} | 0 .../{specialization-assoc-fns.rs => assoc-fns.rs} | 0 .../{specialization_cross_crate.rs => cross_crate.rs} | 0 ...tion_cross_crate_defaults.rs => cross_crate_defaults.rs} | 0 .../{specialization-basics-unsafe.rs => basics-unsafe.rs} | 0 .../defaultimpl/{specialization-basics.rs => basics.rs} | 0 ...tion-cross-crate-defaults.rs => cross-crate-defaults.rs} | 6 +++--- ...zation-cross-crate-no-gate.rs => cross-crate-no-gate.rs} | 6 +++--- .../{specialization-cross-crate.rs => cross-crate.rs} | 6 +++--- ...specialization-default-methods.rs => default-methods.rs} | 0 .../{specialization-out-of-order.rs => out-of-order.rs} | 0 ...lization-overlap-projection.rs => overlap-projection.rs} | 0 ...ecialization-projection-alias.rs => projection-alias.rs} | 0 .../{specialization-projection.rs => projection.rs} | 0 14 files changed, 9 insertions(+), 9 deletions(-) rename src/test/run-pass/specialization/defaultimpl/{specialization-allowed-cross-crate.rs => allowed-cross-crate.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/{specialization-assoc-fns.rs => assoc-fns.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/auxiliary/{specialization_cross_crate.rs => cross_crate.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/auxiliary/{specialization_cross_crate_defaults.rs => cross_crate_defaults.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/{specialization-basics-unsafe.rs => basics-unsafe.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/{specialization-basics.rs => basics.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/{specialization-cross-crate-defaults.rs => cross-crate-defaults.rs} (87%) rename src/test/run-pass/specialization/defaultimpl/{specialization-cross-crate-no-gate.rs => cross-crate-no-gate.rs} (89%) rename src/test/run-pass/specialization/defaultimpl/{specialization-cross-crate.rs => cross-crate.rs} (93%) rename src/test/run-pass/specialization/defaultimpl/{specialization-default-methods.rs => default-methods.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/{specialization-out-of-order.rs => out-of-order.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/{specialization-overlap-projection.rs => overlap-projection.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/{specialization-projection-alias.rs => projection-alias.rs} (100%) rename src/test/run-pass/specialization/defaultimpl/{specialization-projection.rs => projection.rs} (100%) diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-allowed-cross-crate.rs b/src/test/run-pass/specialization/defaultimpl/allowed-cross-crate.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-allowed-cross-crate.rs rename to src/test/run-pass/specialization/defaultimpl/allowed-cross-crate.rs diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-assoc-fns.rs b/src/test/run-pass/specialization/defaultimpl/assoc-fns.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-assoc-fns.rs rename to src/test/run-pass/specialization/defaultimpl/assoc-fns.rs diff --git a/src/test/run-pass/specialization/defaultimpl/auxiliary/specialization_cross_crate.rs b/src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/auxiliary/specialization_cross_crate.rs rename to src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate.rs diff --git a/src/test/run-pass/specialization/defaultimpl/auxiliary/specialization_cross_crate_defaults.rs b/src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate_defaults.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/auxiliary/specialization_cross_crate_defaults.rs rename to src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate_defaults.rs diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs b/src/test/run-pass/specialization/defaultimpl/basics-unsafe.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs rename to src/test/run-pass/specialization/defaultimpl/basics-unsafe.rs diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-basics.rs b/src/test/run-pass/specialization/defaultimpl/basics.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-basics.rs rename to src/test/run-pass/specialization/defaultimpl/basics.rs diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-cross-crate-defaults.rs b/src/test/run-pass/specialization/defaultimpl/cross-crate-defaults.rs similarity index 87% rename from src/test/run-pass/specialization/defaultimpl/specialization-cross-crate-defaults.rs rename to src/test/run-pass/specialization/defaultimpl/cross-crate-defaults.rs index 62c7e3e2e44..19e1af15bdd 100644 --- a/src/test/run-pass/specialization/defaultimpl/specialization-cross-crate-defaults.rs +++ b/src/test/run-pass/specialization/defaultimpl/cross-crate-defaults.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:specialization_cross_crate_defaults.rs +// aux-build:cross_crate_defaults.rs #![feature(specialization)] -extern crate specialization_cross_crate_defaults; +extern crate cross_crate_defaults; -use specialization_cross_crate_defaults::*; +use cross_crate_defaults::*; struct LocalDefault; struct LocalOverride; diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-cross-crate-no-gate.rs b/src/test/run-pass/specialization/defaultimpl/cross-crate-no-gate.rs similarity index 89% rename from src/test/run-pass/specialization/defaultimpl/specialization-cross-crate-no-gate.rs rename to src/test/run-pass/specialization/defaultimpl/cross-crate-no-gate.rs index b9548539e16..67cc694ae12 100644 --- a/src/test/run-pass/specialization/defaultimpl/specialization-cross-crate-no-gate.rs +++ b/src/test/run-pass/specialization/defaultimpl/cross-crate-no-gate.rs @@ -10,11 +10,11 @@ // Test that specialization works even if only the upstream crate enables it -// aux-build:specialization_cross_crate.rs +// aux-build:cross_crate.rs -extern crate specialization_cross_crate; +extern crate cross_crate; -use specialization_cross_crate::*; +use cross_crate::*; fn main() { assert!(0u8.foo() == "generic Clone"); diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-cross-crate.rs b/src/test/run-pass/specialization/defaultimpl/cross-crate.rs similarity index 93% rename from src/test/run-pass/specialization/defaultimpl/specialization-cross-crate.rs rename to src/test/run-pass/specialization/defaultimpl/cross-crate.rs index 7517824b62b..f1ad105db8f 100644 --- a/src/test/run-pass/specialization/defaultimpl/specialization-cross-crate.rs +++ b/src/test/run-pass/specialization/defaultimpl/cross-crate.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:specialization_cross_crate.rs +// aux-build:cross_crate.rs #![feature(specialization)] -extern crate specialization_cross_crate; +extern crate cross_crate; -use specialization_cross_crate::*; +use cross_crate::*; struct NotClone; diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-default-methods.rs b/src/test/run-pass/specialization/defaultimpl/default-methods.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-default-methods.rs rename to src/test/run-pass/specialization/defaultimpl/default-methods.rs diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-out-of-order.rs b/src/test/run-pass/specialization/defaultimpl/out-of-order.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-out-of-order.rs rename to src/test/run-pass/specialization/defaultimpl/out-of-order.rs diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-overlap-projection.rs b/src/test/run-pass/specialization/defaultimpl/overlap-projection.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-overlap-projection.rs rename to src/test/run-pass/specialization/defaultimpl/overlap-projection.rs diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-projection-alias.rs b/src/test/run-pass/specialization/defaultimpl/projection-alias.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-projection-alias.rs rename to src/test/run-pass/specialization/defaultimpl/projection-alias.rs diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-projection.rs b/src/test/run-pass/specialization/defaultimpl/projection.rs similarity index 100% rename from src/test/run-pass/specialization/defaultimpl/specialization-projection.rs rename to src/test/run-pass/specialization/defaultimpl/projection.rs From 72cfd209410da7f9dd09357a3361bb5b561dee33 Mon Sep 17 00:00:00 2001 From: Badel2 <2badel2@gmail.com> Date: Tue, 10 Oct 2017 04:11:22 +0200 Subject: [PATCH 152/365] Add error for comma after base struct field `let x = { ..default(), } // This comma is an error` --- src/libsyntax/parse/parser.rs | 11 +++++++++ src/test/ui/struct-field-init-syntax.rs | 27 +++++++++++++++++++++ src/test/ui/struct-field-init-syntax.stderr | 18 ++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/test/ui/struct-field-init-syntax.rs create mode 100644 src/test/ui/struct-field-init-syntax.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 978e06c75dd..c1f9b4a7a22 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2314,6 +2314,7 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Brace) { if self.eat(&token::DotDot) { + let exp_span = self.prev_span; match self.parse_expr() { Ok(e) => { base = Some(e); @@ -2323,6 +2324,16 @@ impl<'a> Parser<'a> { self.recover_stmt(); } } + if self.token == token::Comma { + let mut err = self.sess.span_diagnostic.mut_span_err( + exp_span.to(self.prev_span), + "cannot use a comma after the base struct", + ); + err.span_suggestion_short(self.span, "remove this comma", "".to_owned()); + err.note("the base struct must always be the last field"); + err.emit(); + self.recover_stmt(); + } break; } diff --git a/src/test/ui/struct-field-init-syntax.rs b/src/test/ui/struct-field-init-syntax.rs new file mode 100644 index 00000000000..8ea62fef9fa --- /dev/null +++ b/src/test/ui/struct-field-init-syntax.rs @@ -0,0 +1,27 @@ +// Copyright 2017 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. + +// compile-flags: -Z parse-only + +// issue #41834 + +fn main() { + let foo = Foo { + one: 111, + ..Foo::default(), + //~^ ERROR cannot use a comma after struct expansion + }; + + let foo = Foo { + ..Foo::default(), + //~^ ERROR cannot use a comma after struct expansion + one: 111, + }; +} diff --git a/src/test/ui/struct-field-init-syntax.stderr b/src/test/ui/struct-field-init-syntax.stderr new file mode 100644 index 00000000000..0bca3f83eb1 --- /dev/null +++ b/src/test/ui/struct-field-init-syntax.stderr @@ -0,0 +1,18 @@ +error: cannot use a comma after the base struct + --> $DIR/struct-field-init-syntax.rs:18:9 + | +18 | ..Foo::default(), + | ^^^^^^^^^^^^^^^^- help: remove this comma + | + = note: the base struct must always be the last field + +error: cannot use a comma after the base struct + --> $DIR/struct-field-init-syntax.rs:23:9 + | +23 | ..Foo::default(), + | ^^^^^^^^^^^^^^^^- help: remove this comma + | + = note: the base struct must always be the last field + +error: aborting due to 2 previous errors + From 7ea286e854d88529af76ca486ed676c9fb06e8ee Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Mon, 9 Oct 2017 15:21:11 -0500 Subject: [PATCH 153/365] render the rust version into std/compiler/test docs --- src/bootstrap/bin/rustdoc.rs | 8 ++++++++ src/bootstrap/builder.rs | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index d7d72d5dd56..d18512b257d 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -48,6 +48,14 @@ fn main() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } + // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick + // it up so we can make rustdoc print this into the docs + if let Some(version) = env::var_os("RUSTDOC_CRATE_VERSION") { + // This "unstable-options" can be removed when `--crate-version` is stabilized + cmd.arg("-Z").arg("unstable-options") + .arg("--crate-version").arg(version); + } + std::process::exit(match cmd.status() { Ok(s) => s.code().unwrap_or(1), Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e), diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e7a5196178c..1d63e112ca6 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -418,7 +418,8 @@ impl<'a> Builder<'a> { .env("RUSTC_SYSROOT", self.sysroot(compiler)) .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build)) .env("CFG_RELEASE_CHANNEL", &self.build.config.channel) - .env("RUSTDOC_REAL", self.rustdoc(host)); + .env("RUSTDOC_REAL", self.rustdoc(host)) + .env("RUSTDOC_CRATE_VERSION", self.build.rust_version()); cmd } @@ -574,6 +575,9 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); } + // For `cargo doc` invocations, make rustdoc print the Rust version into the docs + cargo.env("RUSTDOC_CRATE_VERSION", self.build.rust_version()); + // Environment variables *required* throughout the build // // FIXME: should update code to not require this env var From d5d449421398fe4005f3b3ded551a6274e3d856e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Oct 2017 18:59:40 -0700 Subject: [PATCH 154/365] ci: Fix installing the Android SDK Apparently the https urls are broken due to some certificate validation whatnots, and so far the least intrusive solution I've found is to just disable that. --- src/ci/docker/scripts/android-sdk.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/android-sdk.sh b/src/ci/docker/scripts/android-sdk.sh index d343aae9dfb..3aa2b9d58d5 100644 --- a/src/ci/docker/scripts/android-sdk.sh +++ b/src/ci/docker/scripts/android-sdk.sh @@ -31,7 +31,7 @@ download_sysimage() { # Keep printing yes to accept the licenses while true; do echo yes; sleep 10; done | \ /android/sdk/tools/android update sdk -a --no-ui \ - --filter "$filter" + --filter "$filter" --no-https } create_avd() { From db91b00065181137fa4a298aeee796ff10755d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Louren=C3=A7o?= Date: Sun, 8 Oct 2017 15:01:44 -0300 Subject: [PATCH 155/365] output compiler message updated output message is shown in another 'help:' block line with +100 columns formatted test adjusted --- src/libsyntax/parse/parser.rs | 1 + src/test/parse-fail/require-parens-for-chained-comparison.rs | 3 ++- src/test/ui/did_you_mean/issue-40396.stderr | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 65dabe98a06..0e691624231 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2947,6 +2947,7 @@ impl<'a> Parser<'a> { { // Foo>> err.help( "use `::<...>` instead of `<...>` if you meant to specify type arguments"); + err.help("or use `(...)` if you meant to specify fn arguments"); } err.emit(); } diff --git a/src/test/parse-fail/require-parens-for-chained-comparison.rs b/src/test/parse-fail/require-parens-for-chained-comparison.rs index 7e76dbd31f0..1ee6996ce9c 100644 --- a/src/test/parse-fail/require-parens-for-chained-comparison.rs +++ b/src/test/parse-fail/require-parens-for-chained-comparison.rs @@ -21,5 +21,6 @@ fn main() { f(); //~^ ERROR: chained comparison operators require parentheses - //~^^ HELP: use `::<...>` instead of `<...>` + //~| HELP: use `::<...>` instead of `<...>` + //~| HELP: or use `(...)` } diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 1a0c74dc01a..11279f5c612 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -5,6 +5,7 @@ error: chained comparison operators require parentheses | ^^^^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:16:25 @@ -13,6 +14,7 @@ error: chained comparison operators require parentheses | ^^^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:20:37 @@ -21,6 +23,7 @@ error: chained comparison operators require parentheses | ^^^^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:20:41 @@ -29,6 +32,7 @@ error: chained comparison operators require parentheses | ^^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments + = help: or use `(...)` if you meant to specify fn arguments error: aborting due to 4 previous errors From d5ef9f9036743c77cbc30286a3b3b8e8185330d1 Mon Sep 17 00:00:00 2001 From: tinaun Date: Tue, 10 Oct 2017 05:03:47 -0400 Subject: [PATCH 156/365] formatting fixes --- .../language-features/optin-builtin-traits.md | 36 +++++++++---------- .../src/language-features/unboxed-closures.md | 4 +-- .../src/library-features/fn-traits.md | 2 +- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md index 4ff46dedba1..ee24dd87d90 100644 --- a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md +++ b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md @@ -6,44 +6,42 @@ The tracking issue for this feature is [#13231] ---- -The `optin_builtin_traits` feature gate allows you to define _auto traits_. +The `optin_builtin_traits` feature gate allows you to define auto traits. Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits that are automatically implemented for every type, unless the type, or a type it contains, -has explictly opted out via a _negative impl_. +has explictly opted out via a negative impl. [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html -```rust, ignore +```rust,ignore impl !Type for Trait ``` Example: ```rust - #![feature(optin_builtin_traits)] +#![feature(optin_builtin_traits)] - trait Valid {} +trait Valid {} - impl Valid for .. {} +impl Valid for .. {} - struct True; - struct False; +struct True; +struct False; - impl !Valid for False {} +impl !Valid for False {} - struct MaybeValid(T); +struct MaybeValid(T); - fn must_be_valid(_t: T) { +fn must_be_valid(_t: T) { } - } - - fn main() { - //works - must_be_valid( MaybeValid(True) ); +fn main() { + // works + must_be_valid( MaybeValid(True) ); - // compiler error - trait bound not satisfied - // must_be_valid( MaybeValid(False) ); - } + // compiler error - trait bound not satisfied + // must_be_valid( MaybeValid(False) ); +} ``` diff --git a/src/doc/unstable-book/src/language-features/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md index 5146fcd8739..0eaed7a1989 100644 --- a/src/doc/unstable-book/src/language-features/unboxed-closures.md +++ b/src/doc/unstable-book/src/language-features/unboxed-closures.md @@ -2,7 +2,7 @@ The tracking issue for this feature is [#29625] -See Also: [`fn_traits`](library-features/fn-traits.md) +See Also: [`fn_traits`](library-features/fn-traits.html) [#29625]: https://github.com/rust-lang/rust/issues/29625 @@ -17,7 +17,7 @@ exactly one (non self) argument, a tuple representing the argument list. ```rust #![feature(unboxed_closures)] -extern "rust-call" fn add_args(args: (u32, u32)) { +extern "rust-call" fn add_args(args: (u32, u32)) -> u32 { args.0 + args.1 } diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md index d0f1fe8dc7c..72a3f36c10b 100644 --- a/src/doc/unstable-book/src/library-features/fn-traits.md +++ b/src/doc/unstable-book/src/library-features/fn-traits.md @@ -2,7 +2,7 @@ The tracking issue for this feature is [#29625] -See Also: [`unboxed_closures`](language-features/unboxed_closures.md) +See Also: [`unboxed_closures`](language-features/unboxed-closures.html) [#29625]: https://github.com/rust-lang/rust/issues/29625 From 3cb52949666fee2005402e71b879742f5baecf25 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Wed, 11 Oct 2017 07:36:43 -0400 Subject: [PATCH 157/365] Fix typo during merge from master --- src/bootstrap/configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index a296fa9459d..725dd6dca72 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -394,7 +394,7 @@ for section_key in config: if section_key not in sections: raise RuntimeError("config key {} not in sections".format(section_key)) - if __key == 'target': + if section_key == 'target': for target in section_config: configure_section(targets[target], section_config[target]) else: From 057bc7d6506bb0208b5da782602c5cf7692d10c8 Mon Sep 17 00:00:00 2001 From: clippered Date: Sat, 7 Oct 2017 18:50:50 +1100 Subject: [PATCH 158/365] Fix #44968 Windows path in UI tests --- src/test/ui/lint/unused_parens_json_suggestion.rs | 2 -- src/test/ui/lint/unused_parens_json_suggestion.stderr | 2 +- src/tools/compiletest/src/runtest.rs | 9 ++++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs index d7cbd11472a..9decb0cff36 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.rs +++ b/src/test/ui/lint/unused_parens_json_suggestion.rs @@ -10,8 +10,6 @@ // compile-flags: --error-format json -// ignore-windows (see Issue #44968) - // The output for humans should just highlight the whole span without showing // the suggested replacement, but we also want to test that suggested // replacement only removes one set of parentheses, rather than naïvely diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr index 140224e0814..4b4dd92855d 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr @@ -1 +1 @@ -{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1014,"byte_end":1027,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"#[warn(unused_parens)] on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1014,"byte_end":1027,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":" let _a = 1 / (2 + 3);"}],"rendered":null} +{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":976,"byte_end":989,"line_start":22,"line_end":22,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"#[warn(unused_parens)] on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":976,"byte_end":989,"line_start":22,"line_end":22,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":" let _a = 1 / (2 + 3);"}],"rendered":null} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 870e08cc6e5..0ffc8b563bb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2325,8 +2325,15 @@ actual:\n\ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { let parent_dir = self.testpaths.file.parent().unwrap(); - let parent_dir_str = parent_dir.display().to_string(); + let cflags = self.props.compile_flags.join(" "); + let parent_dir_str = if cflags.contains("--error-format json") { + parent_dir.display().to_string().replace("\\", "\\\\") + } else { + parent_dir.display().to_string() + }; + let mut normalized = output.replace(&parent_dir_str, "$DIR") + .replace("\\\\", "\\") // denormalize for paths on windows .replace("\\", "/") // normalize for paths on windows .replace("\r\n", "\n") // normalize for linebreaks on windows .replace("\t", "\\t"); // makes tabs visible From 8a28c676c89173a88c2568deb8964e0960f2afb6 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 11 Oct 2017 17:39:45 +0300 Subject: [PATCH 159/365] MIR-borrowck: add false edges to match arms --- src/librustc_mir/build/matches/mod.rs | 29 +++++++++++++++---- .../borrowck-match-already-borrowed.rs | 25 ++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index f04dede6e40..56c926eaa61 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -21,7 +21,7 @@ use rustc::mir::*; use rustc::hir; use hair::*; use syntax::ast::{Name, NodeId}; -use syntax_pos::Span; +use syntax_pos::{DUMMY_SP, Span}; // helper functions, broken out by category: mod simplify; @@ -398,10 +398,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { candidates.iter().take_while(|c| c.match_pairs.is_empty()).count(); debug!("match_candidates: {:?} candidates fully matched", fully_matched); let mut unmatched_candidates = candidates.split_off(fully_matched); - for candidate in candidates { + for (index, candidate) in candidates.into_iter().enumerate() { // If so, apply any bindings, test the guard (if any), and // branch to the arm. - if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, candidate) { + let is_last = index == fully_matched - 1; + if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, + candidate, is_last) { block = b; } else { // if None is returned, then any remaining candidates @@ -664,7 +666,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn bind_and_guard_matched_candidate<'pat>(&mut self, mut block: BasicBlock, arm_blocks: &mut ArmBlocks, - candidate: Candidate<'pat, 'tcx>) + candidate: Candidate<'pat, 'tcx>, + is_last_arm: bool) -> Option { debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})", block, candidate); @@ -685,10 +688,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.cfg.terminate(block, source_info, TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise)); Some(otherwise) + } else if !is_last_arm { + // Add always true guard in case of more than one arm + // it creates false edges and allow MIR borrowck detects errors + // FIXME(#45184) -- permit "false edges" + let source_info = self.source_info(candidate.span); + let true_expr = Expr { + temp_lifetime: None, + ty: self.hir.tcx().types.bool, + span: DUMMY_SP, + kind: ExprKind::Literal{literal: self.hir.true_literal()}, + }; + let cond = unpack!(block = self.as_local_operand(block, true_expr)); + let otherwise = self.cfg.start_new_block(); + self.cfg.terminate(block, source_info, + TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise)); + Some(otherwise) } else { let source_info = self.source_info(candidate.span); self.cfg.terminate(block, source_info, - TerminatorKind::Goto { target: arm_block }); + TerminatorKind::Goto { target: arm_block }); None } } diff --git a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs new file mode 100644 index 00000000000..1d21f40fcca --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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. + +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + +fn main() { + let mut x = 1; + let _x = &mut x; + let _ = match x { + x => x + 1, //[ast]~ ERROR E0503 + //[mir]~^ ERROR (Mir) [E0503] + //[mir]~| ERROR (Ast) [E0503] + y => y + 2, //[ast]~ ERROR [E0503] + //[mir]~^ ERROR (Mir) [E0503] + //[mir]~| ERROR (Ast) [E0503] + }; +} From 24cc38e3b00ff399acc99a57f92bfdef4ab8c949 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 4 Oct 2017 14:54:28 -0700 Subject: [PATCH 160/365] rustc: Add LLVM `nounwind` with `-C panic=abort` This informs LLVM that functions can't unwind, which while it should typically have already been inferred when necessary or otherwise not impact codegen is apparently needed on targets like ARM to avoid references to unnecessary symbols. Closes #44992 --- src/librustc_trans/callee.rs | 7 +++++-- src/librustc_trans/declare.rs | 5 +++++ src/test/codegen/auxiliary/nounwind.rs | 13 +++++++++++++ src/test/codegen/nounwind.rs | 26 +++++++++++++++++++++++++ src/test/codegen/panic-abort-windows.rs | 2 +- 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/test/codegen/auxiliary/nounwind.rs create mode 100644 src/test/codegen/nounwind.rs diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 18b91b18d8e..b515c9420bf 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -24,6 +24,7 @@ use rustc::hir::def_id::DefId; use rustc::ty::{self, TypeFoldable}; use rustc::traits; use rustc::ty::subst::Substs; +use rustc_back::PanicStrategy; use type_of; /// Translates a reference to a fn/method item, monomorphizing and @@ -105,8 +106,10 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // *in Rust code* may unwind. Foreign items like `extern "C" { // fn foo(); }` are assumed not to unwind **unless** they have // a `#[unwind]` attribute. - if !tcx.is_foreign_item(instance_def_id) { - attributes::unwind(llfn, true); + if tcx.sess.panic_strategy() == PanicStrategy::Unwind { + if !tcx.is_foreign_item(instance_def_id) { + attributes::unwind(llfn, true); + } } // Apply an appropriate linkage/visibility value to our item that we diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index 3c8ff454997..f894bdf16e4 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -24,6 +24,7 @@ use llvm::{self, ValueRef}; use llvm::AttributePlace::Function; use rustc::ty::Ty; use rustc::session::config::Sanitizer; +use rustc_back::PanicStrategy; use abi::{Abi, FnType}; use attributes; use context::CrateContext; @@ -98,6 +99,10 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: _ => {}, } + if ccx.tcx().sess.panic_strategy() != PanicStrategy::Unwind { + attributes::unwind(llfn, false); + } + llfn } diff --git a/src/test/codegen/auxiliary/nounwind.rs b/src/test/codegen/auxiliary/nounwind.rs new file mode 100644 index 00000000000..5e40e8ede15 --- /dev/null +++ b/src/test/codegen/auxiliary/nounwind.rs @@ -0,0 +1,13 @@ +// Copyright 2017 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. + +#[no_mangle] +pub fn bar() { +} diff --git a/src/test/codegen/nounwind.rs b/src/test/codegen/nounwind.rs new file mode 100644 index 00000000000..9fea907d3c8 --- /dev/null +++ b/src/test/codegen/nounwind.rs @@ -0,0 +1,26 @@ +// Copyright 2017 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. + +// aux-build:nounwind.rs +// compile-flags: -C no-prepopulate-passes -C panic=abort -C metadata=a +// ignore-windows + +#![crate_type = "lib"] + +extern crate nounwind; + +#[no_mangle] +pub fn foo() { + nounwind::bar(); +// CHECK: @foo() unnamed_addr #0 +// CHECK: @bar() unnamed_addr #0 +// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } +} + diff --git a/src/test/codegen/panic-abort-windows.rs b/src/test/codegen/panic-abort-windows.rs index 2ab15277084..15688bdc2a1 100644 --- a/src/test/codegen/panic-abort-windows.rs +++ b/src/test/codegen/panic-abort-windows.rs @@ -28,7 +28,7 @@ #![crate_type = "lib"] -// CHECK: Function Attrs: uwtable +// CHECK: Function Attrs: nounwind uwtable // CHECK-NEXT: define void @normal_uwtable() #[no_mangle] pub fn normal_uwtable() { From a2aba791f1c348fe93b2a9bcec95605dfe66df29 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 11 Oct 2017 08:33:46 -0700 Subject: [PATCH 161/365] rustc: Update LLVM with a ThinLTO fix This commit updates LLVM with a patch that's landed upstream to fix an assertion that was tripping when ThinLTO was activated. Unfortunately I wasn't able to get a reduced test case, but I've tested manually on the affected crates and the assertion is indeed fixed. Closes #45131 --- src/llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm b/src/llvm index c7a16bd57c2..83b72cedfd7 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit c7a16bd57c2a9c643a52f0cebecdaf0b6a996da1 +Subproject commit 83b72cedfd7800ffc983d2855a85c5d06a545aa7 From 90d58a362aaa27dab9a820f60c636811deb26de5 Mon Sep 17 00:00:00 2001 From: kennytm Date: Thu, 12 Oct 2017 01:20:55 +0800 Subject: [PATCH 162/365] rustbuild: Make openssl download more reliable. 1. Add -f flag to curl, so when the server returns 403 or 500 it will fail immediately. 2. Moved the checksum part into the retry loop, assuming checksum failure is due to broken download that can be fixed by downloading again. --- src/bootstrap/native.rs | 57 ++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index c4e80630315..2c8e5004041 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -352,34 +352,51 @@ impl Step for Openssl { // originally from https://www.openssl.org/source/... let url = format!("https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/{}", name); - let mut ok = false; + let mut last_error = None; for _ in 0..3 { let status = Command::new("curl") .arg("-o").arg(&tmp) + .arg("-f") // make curl fail if the URL does not return HTTP 200 .arg(&url) .status() .expect("failed to spawn curl"); - if status.success() { - ok = true; - break + + // Retry if download failed. + if !status.success() { + last_error = Some(status.to_string()); + continue; } + + // Ensure the hash is correct. + let mut shasum = if target.contains("apple") || build.build.contains("netbsd") { + let mut cmd = Command::new("shasum"); + cmd.arg("-a").arg("256"); + cmd + } else { + Command::new("sha256sum") + }; + let output = output(&mut shasum.arg(&tmp)); + let found = output.split_whitespace().next().unwrap(); + + // If the hash is wrong, probably the download is incomplete or S3 served an error + // page. In any case, retry. + if found != OPENSSL_SHA256 { + last_error = Some(format!( + "downloaded openssl sha256 different\n\ + expected: {}\n\ + found: {}\n", + OPENSSL_SHA256, + found + )); + continue; + } + + // Everything is fine, so exit the retry loop. + last_error = None; + break; } - if !ok { - panic!("failed to download openssl source") - } - let mut shasum = if target.contains("apple") || build.build.contains("netbsd") { - let mut cmd = Command::new("shasum"); - cmd.arg("-a").arg("256"); - cmd - } else { - Command::new("sha256sum") - }; - let output = output(&mut shasum.arg(&tmp)); - let found = output.split_whitespace().next().unwrap(); - if found != OPENSSL_SHA256 { - panic!("downloaded openssl sha256 different\n\ - expected: {}\n\ - found: {}\n", OPENSSL_SHA256, found); + if let Some(error) = last_error { + panic!("failed to download openssl source: {}", error); } t!(fs::rename(&tmp, &tarball)); } From a6cfdd2b98c166b21a041ebdd43d7428c32a239e Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Wed, 11 Oct 2017 16:15:42 -0300 Subject: [PATCH 163/365] Add x86_64-unknown-linux-gnux32 target --- src/librustc_back/target/mod.rs | 1 + .../target/x86_64_unknown_linux_gnux32.rs | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/librustc_back/target/x86_64_unknown_linux_gnux32.rs diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 039e0153656..ee7a77ea6d8 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -135,6 +135,7 @@ macro_rules! supported_targets { supported_targets! { ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu), + ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32), ("i686-unknown-linux-gnu", i686_unknown_linux_gnu), ("i586-unknown-linux-gnu", i586_unknown_linux_gnu), ("mips-unknown-linux-gnu", mips_unknown_linux_gnu), diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnux32.rs b/src/librustc_back/target/x86_64_unknown_linux_gnux32.rs new file mode 100644 index 00000000000..70382032836 --- /dev/null +++ b/src/librustc_back/target/x86_64_unknown_linux_gnux32.rs @@ -0,0 +1,35 @@ +// Copyright 2017 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. + +use LinkerFlavor; +use target::{Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_base::opts(); + base.cpu = "x86-64".to_string(); + base.max_atomic_width = Some(64); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string()); + base.stack_probes = true; + base.has_elf_tls = false; + + Ok(Target { + llvm_target: "x86_64-unknown-linux-gnux32".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "linux".to_string(), + target_env: "gnu".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} From dcada26f5b1d83c4e51d9bdf0c7304ed497a63c6 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 4 Oct 2017 17:46:46 +0200 Subject: [PATCH 164/365] MIR-borrowck: Big fix to `fn check_if_path_is_moved`. Fix #44833 (a very specific instance of a very broad bug). In `check_if_path_is_moved(L)`, check nearest prefix of L with MovePath, and suffixes of L with MovePaths. Over the course of review, ariel pointed out a number of issues that led to this version of the commit: 1. Looking solely at supporting prefixes does not suffice: it overlooks checking if the path was ever actually initialized in the first place. So you need to be willing to consider non-supporting prefixes. Once you are looking at all prefixes, you *could* just look at the local that forms the base of the projection, but to handle partial initialization (which still needs to be formally specified), this code instead looks at the nearest prefix of L that has an associated MovePath (which, in the limit, will end up being a local). 2. You also need to consider the suffixes of the given Lvalue, due to how dataflow is representing partial moves of individual fields out of struct values. 3. (There was originally a third search, but ariel pointed out that the first and third could be folded into one.) Also includes some drive-by refactorings to simplify some method signatures and prefer `for _ in _` over `loop { }` (at least when it comes semi-naturally). --- src/librustc_mir/borrow_check.rs | 151 ++++++++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index db6a0ee4ba5..7e18de27489 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -586,7 +586,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> context: Context, (lvalue, span): (&Lvalue<'gcx>, Span), flow_state: &InProgress<'b, 'gcx>) { - let move_data = flow_state.inits.base_results.operator().move_data(); + let move_data = self.move_data; // determine if this path has a non-mut owner (and thus needs checking). let mut l = lvalue; @@ -611,7 +611,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> } } - if let Some(mpi) = self.move_path_for_lvalue(context, move_data, lvalue) { + if let Some(mpi) = self.move_path_for_lvalue(lvalue) { if flow_state.inits.curr_state.contains(&mpi) { // may already be assigned before reaching this statement; // report error. @@ -642,21 +642,107 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> let lvalue = self.base_path(lvalue_span.0); let maybe_uninits = &flow_state.uninits; - let move_data = maybe_uninits.base_results.operator().move_data(); - if let Some(mpi) = self.move_path_for_lvalue(context, move_data, lvalue) { - if maybe_uninits.curr_state.contains(&mpi) { - // find and report move(s) that could cause this to be uninitialized + + // Bad scenarios: + // + // 1. Move of `a.b.c`, use of `a.b.c` + // 2. Move of `a.b.c`, use of `a.b.c.d` (without first reinitializing `a.b.c.d`) + // 3. Move of `a.b.c`, use of `a` or `a.b` + // 4. Uninitialized `(a.b.c: &_)`, use of `*a.b.c`; note that with + // partial initialization support, one might have `a.x` + // initialized but not `a.b`. + // + // OK scenarios: + // + // 5. Move of `a.b.c`, use of `a.b.d` + // 6. Uninitialized `a.x`, initialized `a.b`, use of `a.b` + // 7. Copied `(a.b: &_)`, use of `*(a.b).c`; note that `a.b` + // must have been initialized for the use to be sound. + // 8. Move of `a.b.c` then reinit of `a.b.c.d`, use of `a.b.c.d` + + // The dataflow tracks shallow prefixes distinctly (that is, + // field-accesses on P distinctly from P itself), in order to + // track substructure initialization separately from the whole + // structure. + // + // E.g., when looking at (*a.b.c).d, if the closest prefix for + // which we have a MovePath is `a.b`, then that means that the + // initialization state of `a.b` is all we need to inspect to + // know if `a.b.c` is valid (and from that we infer that the + // dereference and `.d` access is also valid, since we assume + // `a.b.c` is assigned a reference to a initialized and + // well-formed record structure.) + + // Therefore, if we seek out the *closest* prefix for which we + // have a MovePath, that should capture the initialization + // state for the lvalue scenario. + // + // This code covers scenarios 1, 2, and 4. + + debug!("check_if_path_is_moved part1 lvalue: {:?}", lvalue); + match self.move_path_closest_to(lvalue) { + Ok(mpi) => { + if maybe_uninits.curr_state.contains(&mpi) { + self.report_use_of_moved(context, desired_action, lvalue_span); + return; // don't bother finding other problems. + } + } + Err(NoMovePathFound::ReachedStatic) => { + // Okay: we do not build MoveData for static variables + } + + // Only query longest prefix with a MovePath, not further + // ancestors; dataflow recurs on children when parents + // move (to support partial (re)inits). + // + // (I.e. querying parents breaks scenario 8; but may want + // to do such a query based on partial-init feature-gate.) + } + + // A move of any shallow suffix of `lvalue` also interferes + // with an attempt to use `lvalue`. This is scenario 3 above. + // + // (Distinct from handling of scenarios 1+2+4 above because + // `lvalue` does not interfere with suffixes of its prefixes, + // e.g. `a.b.c` does not interfere with `a.b.d`) + + debug!("check_if_path_is_moved part2 lvalue: {:?}", lvalue); + if let Some(mpi) = self.move_path_for_lvalue(lvalue) { + if let Some(_) = maybe_uninits.has_any_child_of(mpi) { self.report_use_of_moved(context, desired_action, lvalue_span); - } else { - // sanity check: initialized on *some* path, right? - assert!(flow_state.inits.curr_state.contains(&mpi)); + return; // don't bother finding other problems. } } } + /// Currently MoveData does not store entries for all lvalues in + /// the input MIR. For example it will currently filter out + /// lvalues that are Copy; thus we do not track lvalues of shared + /// reference type. This routine will walk up an lvalue along its + /// prefixes, searching for a foundational lvalue that *is* + /// tracked in the MoveData. + /// + /// An Err result includes a tag indicated why the search failed. + /// Currenly this can only occur if the lvalue is built off of a + /// static variable, as we do not track those in the MoveData. + fn move_path_closest_to(&mut self, lvalue: &Lvalue<'gcx>) + -> Result + { + let mut last_prefix = lvalue; + for prefix in self.prefixes(lvalue, PrefixSet::All) { + if let Some(mpi) = self.move_path_for_lvalue(prefix) { + return Ok(mpi); + } + last_prefix = prefix; + } + match *last_prefix { + Lvalue::Local(_) => panic!("should have move path for every Local"), + Lvalue::Projection(_) => panic!("PrefixSet::All meant dont stop for Projection"), + Lvalue::Static(_) => return Err(NoMovePathFound::ReachedStatic), + } + } + fn move_path_for_lvalue(&mut self, - _context: Context, - move_data: &MoveData<'gcx>, lvalue: &Lvalue<'gcx>) -> Option { @@ -664,7 +750,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> // to a direct owner of `lvalue` (which means there is nothing // that borrowck tracks for its analysis). - match move_data.rev_lookup.find(lvalue) { + match self.move_data.rev_lookup.find(lvalue) { LookupResult::Parent(_) => None, LookupResult::Exact(mpi) => Some(mpi), } @@ -733,6 +819,11 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> } } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum NoMovePathFound { + ReachedStatic, +} + impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { fn each_borrow_involving_path(&mut self, _context: Context, @@ -846,12 +937,19 @@ mod prefixes { #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub(super) enum PrefixSet { + /// Doesn't stop until it returns the base case (a Local or + /// Static prefix). All, + /// Stops at any dereference. Shallow, + /// Stops at the deref of a shared reference. Supporting, } impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + /// Returns an iterator over the prefixes of `lvalue` + /// (inclusive) from longest to smallest, potentially + /// terminating the iteration early based on `kind`. pub(super) fn prefixes<'d>(&self, lvalue: &'d Lvalue<'gcx>, kind: PrefixSet) @@ -1266,6 +1364,35 @@ impl<'b, 'tcx: 'b> InProgress<'b, 'tcx> { } } +impl<'b, 'tcx> FlowInProgress> { + fn has_any_child_of(&self, mpi: MovePathIndex) -> Option { + let move_data = self.base_results.operator().move_data(); + + let mut todo = vec![mpi]; + let mut push_siblings = false; // don't look at siblings of original `mpi`. + while let Some(mpi) = todo.pop() { + if self.curr_state.contains(&mpi) { + return Some(mpi); + } + let move_path = &move_data.move_paths[mpi]; + if let Some(child) = move_path.first_child { + todo.push(child); + } + if push_siblings { + if let Some(sibling) = move_path.next_sibling { + todo.push(sibling); + } + } else { + // after we've processed the original `mpi`, we should + // always traverse the siblings of any of its + // children. + push_siblings = true; + } + } + return None; + } +} + impl FlowInProgress where BD: BitDenotation { fn each_state_bit(&self, f: F) where F: FnMut(BD::Idx) { self.curr_state.each_bit(self.base_results.operator().bits_per_block(), f) From ae5fc76dceea5b03e400110315728a0baaa1a1f9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 4 Oct 2017 17:47:19 +0200 Subject: [PATCH 165/365] Test against accesses to uninitialized fields. --- .../borrowck/borrowck-uninit-field-access.rs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs diff --git a/src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs b/src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs new file mode 100644 index 00000000000..957086f6af1 --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs @@ -0,0 +1,49 @@ +// Copyright 2017 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. + +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + +// Check that do not allow access to fields of uninitialized or moved +// structs. + +#[derive(Default)] +struct Point { + x: isize, + y: isize, +} + +#[derive(Default)] +struct Line { + origin: Point, + middle: Point, + target: Point, +} + +impl Line { fn consume(self) { } } + +fn main() { + let mut a: Point; + let _ = a.x + 1; //[ast]~ ERROR use of possibly uninitialized variable: `a.x` + //[mir]~^ ERROR [E0381] + //[mir]~| ERROR (Mir) [E0381] + + let mut line1 = Line::default(); + let _moved = line1.origin; + let _ = line1.origin.x + 1; //[ast]~ ERROR use of collaterally moved value: `line1.origin.x` + //[mir]~^ [E0382] + //[mir]~| (Mir) [E0381] + + let mut line2 = Line::default(); + let _moved = (line2.origin, line2.middle); + line2.consume(); //[ast]~ ERROR use of partially moved value: `line2` [E0382] + //[mir]~^ [E0382] + //[mir]~| (Mir) [E0381] +} From b62b67a7323a5f58b0d8e001fc4be9cbdde1760a Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 5 Oct 2017 14:32:05 +0200 Subject: [PATCH 166/365] Test case illustrating some variants of the issue pointed out by ariel. Expanded to cover partial-initialization ideas. --- .../borrowck/borrowck-uninit-ref-chain.rs | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/test/compile-fail/borrowck/borrowck-uninit-ref-chain.rs diff --git a/src/test/compile-fail/borrowck/borrowck-uninit-ref-chain.rs b/src/test/compile-fail/borrowck/borrowck-uninit-ref-chain.rs new file mode 100644 index 00000000000..71f8693b210 --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-uninit-ref-chain.rs @@ -0,0 +1,60 @@ +// Copyright 2017 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. + +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + +struct S { + x: X, + y: Y, +} + +fn main() { + let x: &&Box; + let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] + //[mir]~^ (Ast) [E0381] + //[mir]~| (Mir) [E0381] + + let x: &&S; + let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] + //[mir]~^ (Ast) [E0381] + //[mir]~| (Mir) [E0381] + + let x: &&i32; + let _y = &**x; //[ast]~ ERROR use of possibly uninitialized variable: `**x` [E0381] + //[mir]~^ (Ast) [E0381] + //[mir]~| (Mir) [E0381] + + + let mut a: S; + a.x = 0; + let _b = &a.x; //[ast]~ ERROR use of possibly uninitialized variable: `a.x` [E0381] + //[mir]~^ ERROR (Ast) [E0381] + // (deliberately *not* an error under MIR-borrowck) + + let mut a: S<&&i32, &&i32>; + a.x = &&0; + let _b = &**a.x; //[ast]~ ERROR use of possibly uninitialized variable: `**a.x` [E0381] + //[mir]~^ ERROR (Ast) [E0381] + // (deliberately *not* an error under MIR-borrowck) + + + let mut a: S; + a.x = 0; + let _b = &a.y; //[ast]~ ERROR use of possibly uninitialized variable: `a.y` [E0381] + //[mir]~^ ERROR (Ast) [E0381] + //[mir]~| ERROR (Mir) [E0381] + + let mut a: S<&&i32, &&i32>; + a.x = &&0; + let _b = &**a.y; //[ast]~ ERROR use of possibly uninitialized variable: `**a.y` [E0381] + //[mir]~^ ERROR (Ast) [E0381] + //[mir]~| ERROR (Mir) [E0381] +} From d6caf737b30f94f4e734f59cde88e7d5295dc4a1 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 11 Oct 2017 12:46:47 +0200 Subject: [PATCH 167/365] Added `revisions: ast mir` template to tests that this PR sync'ed ast+mir borrowcks. (There are other tests that this PR also improves, but were not completely synchronized. I chose to wait until later to pull those into the `revisions: ast mir` testing pattern; later being either when they *are* synchronized, or in some PR where we migrate all borrowck tests, regardless of whether MIR-borrowck is "finished" for them or not.) --- .../compile-fail/borrowck/borrowck-init-in-fru.rs | 8 +++++++- .../borrowck/borrowck-use-in-index-lvalue.rs | 11 +++++++++-- .../borrowck-use-uninitialized-in-cast-trait.rs | 7 ++++++- .../borrowck/borrowck-use-uninitialized-in-cast.rs | 7 ++++++- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/test/compile-fail/borrowck/borrowck-init-in-fru.rs b/src/test/compile-fail/borrowck/borrowck-init-in-fru.rs index 569ddb80c2f..017318b6b21 100644 --- a/src/test/compile-fail/borrowck/borrowck-init-in-fru.rs +++ b/src/test/compile-fail/borrowck/borrowck-init-in-fru.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + #[derive(Clone)] struct point { x: isize, @@ -16,6 +19,9 @@ struct point { fn main() { let mut origin: point; - origin = point {x: 10,.. origin}; //~ ERROR use of possibly uninitialized variable: `origin.y` + origin = point {x: 10,.. origin}; + //[ast]~^ ERROR use of possibly uninitialized variable: `origin.y` [E0381] + //[mir]~^^ ERROR (Ast) [E0381] + //[mir]~| ERROR (Mir) [E0381] origin.clone(); } diff --git a/src/test/compile-fail/borrowck/borrowck-use-in-index-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-use-in-index-lvalue.rs index 7291bcd2ce1..2b567ebd2db 100644 --- a/src/test/compile-fail/borrowck/borrowck-use-in-index-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-use-in-index-lvalue.rs @@ -8,12 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + fn test() { let w: &mut [isize]; - w[5] = 0; //~ ERROR use of possibly uninitialized variable: `*w` + w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381] + //[mir]~^ ERROR (Ast) [E0381] + //[mir]~| ERROR (Mir) [E0381] let mut w: &mut [isize]; - w[5] = 0; //~ ERROR use of possibly uninitialized variable: `*w` + w[5] = 0; //[ast]~ ERROR use of possibly uninitialized variable: `*w` [E0381] + //[mir]~^ ERROR (Ast) [E0381] + //[mir]~| ERROR (Mir) [E0381] } fn main() { test(); } diff --git a/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast-trait.rs b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast-trait.rs index 796b455f5c7..a48d09b195a 100644 --- a/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast-trait.rs +++ b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast-trait.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + // Variation on `borrowck-use-uninitialized-in-cast` in which we do a // trait cast from an uninitialized source. Issue #20791. @@ -16,5 +19,7 @@ impl Foo for i32 { } fn main() { let x: &i32; - let y = x as *const Foo; //~ ERROR use of possibly uninitialized variable: `*x` + let y = x as *const Foo; //[ast]~ ERROR use of possibly uninitialized variable: `*x` + //[mir]~^ ERROR (Ast) [E0381] + //[mir]~| ERROR (Mir) [E0381] } diff --git a/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs index 3f429bbd4b6..bdd90a3ce1e 100644 --- a/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs +++ b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs @@ -8,11 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir + // Check that we detect unused values that are cast to other things. // The problem was specified to casting to `*`, as creating unsafe // pointers was not being fully checked. Issue #20791. fn main() { let x: &i32; - let y = x as *const i32; //~ ERROR use of possibly uninitialized variable: `*x` + let y = x as *const i32; //[ast]~ ERROR use of possibly uninitialized variable: `*x` [E0381] + //[mir]~^ ERROR (Ast) [E0381] + //[mir]~| ERROR (Mir) [E0381] } From d5bdfbced63c3d31b0f55a999cd0beb9de286d01 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 11 Oct 2017 17:51:37 -0500 Subject: [PATCH 168/365] ffi/c_str.rs: Make all descriptions have a single-sentence summary at the beginning Per https://github.com/rust-lang/rust/pull/44855#discussion_r144048837 and subsequent ones. --- src/libstd/ffi/c_str.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 0d0280e2586..6541ad3f872 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -208,11 +208,12 @@ pub struct CStr { inner: [c_char] } -/// An error returned from [`CString::new`] to indicate that a nul byte was found -/// in the vector provided. While Rust strings may contain nul bytes in the middle, -/// C strings can't, as that byte would effectively truncate the string. +/// An error indicating that an interior nul byte was found. /// -/// This `struct` is created by the [`new`][`CString::new`] method on +/// While Rust strings may contain nul bytes in the middle, C strings +/// can't, as that byte would effectively truncate the string. +/// +/// This error is created by the [`new`][`CString::new`] method on /// [`CString`]. See its documentation for more. /// /// [`CString`]: struct.CString.html @@ -229,13 +230,12 @@ pub struct CStr { #[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); -/// An error returned from [`CStr::from_bytes_with_nul`] to indicate -/// that a nul byte was found too early in the slice provided, or one -/// wasn't found at all for the nul terminator. The slice used to -/// create a `CStr` must have one and only one nul byte at the end of -/// the slice. +/// An error indicating that a nul byte was not in the expected position. /// -/// This `struct` is created by the +/// The slice used to create a [`CStr`] must have one and only one nul +/// byte at the end of the slice. +/// +/// This error is created by the /// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on /// [`CStr`]. See its documentation for more. /// @@ -274,16 +274,17 @@ impl FromBytesWithNulError { } } -/// An error returned from [`CString::into_string`] to indicate that a -/// UTF-8 error was encountered during the conversion. `CString` is -/// just a wrapper over a buffer of bytes with a nul terminator; -/// [`into_string`][`CString::into_string`] performs UTF-8 validation -/// and may return this error. +/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`]. +/// +/// `CString` is just a wrapper over a buffer of bytes with a nul +/// terminator; [`into_string`][`CString::into_string`] performs UTF-8 +/// validation on those bytes and may return this error. /// /// This `struct` is created by the /// [`into_string`][`CString::into_string`] method on [`CString`]. See /// its documentation for more. /// +/// [`String`]: ../string/struct.String.html /// [`CString`]: struct.CString.html /// [`CString::into_string`]: struct.CString.html#method.into_string #[derive(Clone, PartialEq, Eq, Debug)] From a9a4ce6dcc694e2ea35344aa790a73a5dea573f0 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 11 Oct 2017 17:52:39 -0500 Subject: [PATCH 169/365] ffi/c_str.rs: Fix method/function confusion Per https://github.com/rust-lang/rust/pull/44855#discussion_r144049179 --- src/libstd/ffi/c_str.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 6541ad3f872..51a5865d29c 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -297,10 +297,10 @@ pub struct IntoStringError { impl CString { /// Creates a new C-compatible string from a container of bytes. /// - /// This method will consume the provided data and use the + /// This function will consume the provided data and use the /// underlying bytes to construct a new string, ensuring that - /// there is a trailing 0 byte. This trailing 0 byte will be - /// appended by this method; the provided data should *not* + /// there is a trailing 0 byte. This trailing 0 byte will be + /// appended by this function; the provided data should *not* /// contain any 0 bytes in it. /// /// # Examples From 026451093dbce9d1d2077d4c2bae3a92d413c203 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 11 Oct 2017 17:53:13 -0500 Subject: [PATCH 170/365] ffi/c_str.rs: Use only one space after a period ending a sentence --- src/libstd/ffi/c_str.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 51a5865d29c..7d3313fb9d5 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -49,7 +49,7 @@ use str::{self, Utf8Error}; /// # Extracting a raw pointer to the whole C string /// /// `CString` implements a [`as_ptr`] method through the [`Deref`] -/// trait. This method will give you a `*const c_char` which you can +/// trait. This method will give you a `*const c_char` which you can /// feed directly to extern functions that expect a nul-terminated /// string, like C's `strdup()`. /// @@ -70,7 +70,7 @@ use str::{self, Utf8Error}; /// Once you have the kind of slice you need (with or without a nul /// terminator), you can call the slice's own /// [`as_ptr`][slice.as_ptr] method to get a raw pointer to pass to -/// extern functions. See the documentation for that function for a +/// extern functions. See the documentation for that function for a /// discussion on ensuring the lifetime of the raw pointer. /// /// [`Into`]: ../convert/trait.Into.html @@ -130,8 +130,8 @@ pub struct CString { /// Representation of a borrowed C string. /// /// This type represents a borrowed reference to a nul-terminated -/// array of bytes. It can be constructed safely from a `&[`[`u8`]`]` -/// slice, or unsafely from a raw `*const c_char`. It can then be +/// array of bytes. It can be constructed safely from a `&[`[`u8`]`]` +/// slice, or unsafely from a raw `*const c_char`. It can then be /// converted to a Rust [`&str`] by performing UTF-8 validation, or /// into an owned [`CString`]. /// @@ -374,7 +374,7 @@ impl CString { /// to undefined behavior or allocator corruption. /// /// > **Note:** If you need to borrow a string that was allocated by - /// > foreign code, use [`CStr`]. If you need to take ownership of + /// > foreign code, use [`CStr`]. If you need to take ownership of /// > a string that was allocated by foreign code, you will need to /// > make your own provisions for freeing it appropriately, likely /// > with the foreign code's API to do that. @@ -521,7 +521,7 @@ impl CString { /// /// The returned slice does **not** contain the trailing nul /// terminator, and it is guaranteed to not have any interior nul - /// bytes. If you need the nul terminator, use + /// bytes. If you need the nul terminator, use /// [`as_bytes_with_nul`] instead. /// /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul @@ -1035,7 +1035,7 @@ impl CStr { /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8. /// /// If the contents of the `CStr` are valid UTF-8 data, this - /// function will return the corresponding [`&str`] slice. Otherwise, + /// function will return the corresponding [`&str`] slice. Otherwise, /// it will return an error with details of where UTF-8 validation failed. /// /// > **Note**: This method is currently implemented to check for validity @@ -1066,7 +1066,7 @@ impl CStr { /// /// If the contents of the `CStr` are valid UTF-8 data, this /// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)` - /// with the the corresponding [`&str`] slice. Otherwise, it will + /// with the the corresponding [`&str`] slice. Otherwise, it will /// replace any invalid UTF-8 sequences with `U+FFFD REPLACEMENT /// CHARACTER` and return a [`Cow`]`::`[`Owned`]`(`[`String`]`)` /// with the result. From c8e232dfe83a95cf866c967752634db3ff7a98bb Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 11 Oct 2017 17:55:01 -0500 Subject: [PATCH 171/365] ffi/mod.rs: Keep the one-sentence summary at the beginning of the module --- src/libstd/ffi/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index f8a4a904fc5..6b751904c9f 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Utilities related to FFI bindings. +//! //! This module provides utilities to handle data across non-Rust //! interfaces, like other programming languages and the underlying //! operating system. It is mainly of use for FFI (Foreign Function From fab6a10c00ffda25ed9ec3195b28a9f6a58150a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 11 Oct 2017 14:38:52 -0700 Subject: [PATCH 172/365] Point at immutable outer variable When attempting to mutate an immutable outer variable from a closure, point at the outer variable and suggest making it mutable. --- src/librustc_borrowck/borrowck/mod.rs | 16 ++++++++++++++- .../closure-immutable-outer-variable.rs | 20 +++++++++++++++++++ .../closure-immutable-outer-variable.stderr | 10 ++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/closure-immutable-outer-variable.rs create mode 100644 src/test/ui/suggestions/closure-immutable-outer-variable.stderr diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index a3f1340d429..d6f7c2aa887 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -759,7 +759,21 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let mut db = match err.cause { MutabilityViolation => { - self.cannot_assign(error_span, &descr, Origin::Ast) + let mut db = self.cannot_assign(error_span, &descr, Origin::Ast); + if let mc::NoteClosureEnv(upvar_id) = err.cmt.note { + let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id); + let sp = self.tcx.hir.span(node_id); + match self.tcx.sess.codemap().span_to_snippet(sp) { + Ok(snippet) => { + let msg = &format!("consider making `{}` mutable", snippet); + db.span_suggestion(sp, msg, format!("mut {}", snippet)); + } + _ => { + db.span_help(sp, "consider making this binding mutable"); + } + } + } + db } BorrowViolation(euv::ClosureCapture(_)) => { struct_span_err!(self.tcx.sess, error_span, E0595, diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.rs b/src/test/ui/suggestions/closure-immutable-outer-variable.rs new file mode 100644 index 00000000000..fe8e2bc6c8e --- /dev/null +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.rs @@ -0,0 +1,20 @@ +// Copyright 2017 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. + +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let y = true; + foo(Box::new(move || y = false) as Box<_>); +} diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr b/src/test/ui/suggestions/closure-immutable-outer-variable.stderr new file mode 100644 index 00000000000..19f1cd07171 --- /dev/null +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.stderr @@ -0,0 +1,10 @@ +error[E0594]: cannot assign to captured outer variable in an `FnMut` closure + --> $DIR/closure-immutable-outer-variable.rs:19:26 + | +18 | let y = true; + | - help: consider making `y` mutable: `mut y` +19 | foo(Box::new(move || y = false) as Box<_>); + | ^^^^^^^^^ + +error: aborting due to previous error + From 5fb8e3d829e77643e9c153172fb3a67f85eebe81 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 11 Oct 2017 17:57:56 -0500 Subject: [PATCH 173/365] ffi/mod.rs: Use only one space after a period ending a sentence --- src/libstd/ffi/mod.rs | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 6b751904c9f..a75596351e4 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -12,24 +12,24 @@ //! //! This module provides utilities to handle data across non-Rust //! interfaces, like other programming languages and the underlying -//! operating system. It is mainly of use for FFI (Foreign Function +//! operating system. It is mainly of use for FFI (Foreign Function //! Interface) bindings and code that needs to exchange C-like strings //! with other languages. //! //! # Overview //! //! Rust represents owned strings with the [`String`] type, and -//! borrowed slices of strings with the [`str`] primitive. Both are +//! borrowed slices of strings with the [`str`] primitive. Both are //! always in UTF-8 encoding, and may contain nul bytes in the middle, //! i.e. if you look at the bytes that make up the string, there may -//! be a `\0` among them. Both `String` and `str` store their length +//! be a `\0` among them. Both `String` and `str` store their length //! explicitly; there are no nul terminators at the end of strings //! like in C. //! //! C strings are different from Rust strings: //! //! * **Encodings** - Rust strings are UTF-8, but C strings may use -//! other encodings. If you are using a string from C, you should +//! other encodings. If you are using a string from C, you should //! check its encoding explicitly, rather than just assuming that it //! is UTF-8 like you can do in Rust. //! @@ -37,22 +37,22 @@ //! characters; please **note** that C's `char` is different from Rust's. //! The C standard leaves the actual sizes of those types open to //! interpretation, but defines different APIs for strings made up of -//! each character type. Rust strings are always UTF-8, so different +//! each character type. Rust strings are always UTF-8, so different //! Unicode characters will be encoded in a variable number of bytes -//! each. The Rust type [`char`] represents a '[Unicode scalar +//! each. The Rust type [`char`] represents a '[Unicode scalar //! value]', which is similar to, but not the same as, a '[Unicode //! code point]'. //! //! * **Nul terminators and implicit string lengths** - Often, C //! strings are nul-terminated, i.e. they have a `\0` character at the -//! end. The length of a string buffer is not stored, but has to be +//! end. The length of a string buffer is not stored, but has to be //! calculated; to compute the length of a string, C code must //! manually call a function like `strlen()` for `char`-based strings, -//! or `wcslen()` for `wchar_t`-based ones. Those functions return +//! or `wcslen()` for `wchar_t`-based ones. Those functions return //! the number of characters in the string excluding the nul //! terminator, so the buffer length is really `len+1` characters. //! Rust strings don't have a nul terminator; their length is always -//! stored and does not need to be calculated. While in Rust +//! stored and does not need to be calculated. While in Rust //! accessing a string's length is a O(1) operation (becasue the //! length is stored); in C it is an O(length) operation because the //! length needs to be computed by scanning the string for the nul @@ -61,7 +61,7 @@ //! * **Internal nul characters** - When C strings have a nul //! terminator character, this usually means that they cannot have nul //! characters in the middle — a nul character would essentially -//! truncate the string. Rust strings *can* have nul characters in +//! truncate the string. Rust strings *can* have nul characters in //! the middle, because nul does not have to mark the end of the //! string in Rust. //! @@ -80,30 +80,30 @@ //! //! * **From C to Rust:** [`CStr`] represents a borrowed C string; it //! is what you would use to wrap a raw `*const u8` that you got from -//! a C function. A `CStr` is guaranteed to be a nul-terminated array -//! of bytes. Once you have a `CStr`, you can convert it to a Rust +//! a C function. A `CStr` is guaranteed to be a nul-terminated array +//! of bytes. Once you have a `CStr`, you can convert it to a Rust //! `&str` if it's valid UTF-8, or lossily convert it by adding //! replacement characters. //! //! [`OsString`] and [`OsStr`] are useful when you need to transfer //! strings to and from the operating system itself, or when capturing -//! the output of external commands. Conversions between `OsString`, +//! the output of external commands. Conversions between `OsString`, //! `OsStr` and Rust strings work similarly to those for [`CString`] //! and [`CStr`]. //! //! * [`OsString`] represents an owned string in whatever -//! representation the operating system prefers. In the Rust standard +//! representation the operating system prefers. In the Rust standard //! library, various APIs that transfer strings to/from the operating -//! system use `OsString` instead of plain strings. For example, +//! system use `OsString` instead of plain strings. For example, //! [`env::var_os()`] is used to query environment variables; it -//! returns an `Option`. If the environment variable exists +//! returns an `Option`. If the environment variable exists //! you will get a `Some(os_string)`, which you can *then* try to -//! convert to a Rust string. This yields a [`Result<>`], so that +//! convert to a Rust string. This yields a [`Result<>`], so that //! your code can detect errors in case the environment variable did //! not in fact contain valid Unicode data. //! //! * [`OsStr`] represents a borrowed reference to a string in a -//! format that can be passed to the operating system. It can be +//! format that can be passed to the operating system. It can be //! converted into an UTF-8 Rust string slice in a similar way to //! `OsString`. //! @@ -125,12 +125,12 @@ //! //! On Windows, [`OsStr`] implements the //! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait, -//! which provides an [`encode_wide`] method. This provides an +//! which provides an [`encode_wide`] method. This provides an //! iterator that can be [`collect`]ed into a vector of [`u16`]. //! //! Additionally, on Windows [`OsString`] implements the //! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt] -//! trait, which provides a [`from_wide`] method. The result of this +//! trait, which provides a [`from_wide`] method. The result of this //! method is an `OsString` which can be round-tripped to a Windows //! string losslessly. //! From 9423bee6d306195f8905cb4d594c047144e6d701 Mon Sep 17 00:00:00 2001 From: Paul Faria Date: Wed, 11 Oct 2017 20:01:55 -0400 Subject: [PATCH 174/365] Move const qualifier from brackets to constant values and remove comma from after identifier --- src/librustc/mir/mod.rs | 22 +++--- src/librustc_data_structures/indexed_vec.rs | 83 +++++++++------------ 2 files changed, 47 insertions(+), 58 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index a68a6acab3f..01e3957a808 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -402,10 +402,10 @@ pub enum BorrowKind { /////////////////////////////////////////////////////////////////////////// // Variables and temps -newtype_index!(Local, - const { - DESCRIPTION = "_", - RETURN_POINTER = 0, +newtype_index!(Local + { + DEBUG_NAME = "_", + const RETURN_POINTER = 0, }); /// Classifies locals into categories. See `Mir::local_kind`. @@ -540,7 +540,7 @@ pub struct UpvarDecl { /////////////////////////////////////////////////////////////////////////// // BasicBlock -newtype_index!(BasicBlock, const { DESCRIPTION = "bb" }); +newtype_index!(BasicBlock { DEBUG_NAME = "bb" }); /////////////////////////////////////////////////////////////////////////// // BasicBlockData and Terminator @@ -1120,7 +1120,7 @@ pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Local, Ty<'tcx> /// and the index is a local. pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>; -newtype_index!(Field, const { DESCRIPTION = "field" }); +newtype_index!(Field { DEBUG_NAME = "field" }); impl<'tcx> Lvalue<'tcx> { pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> { @@ -1185,10 +1185,10 @@ impl<'tcx> Debug for Lvalue<'tcx> { /////////////////////////////////////////////////////////////////////////// // Scopes -newtype_index!(VisibilityScope, - const { - DESCRIPTION = "scope", - ARGUMENT_VISIBILITY_SCOPE = 0, +newtype_index!(VisibilityScope + { + DEBUG_NAME = "scope", + const ARGUMENT_VISIBILITY_SCOPE = 0, }); #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] @@ -1514,7 +1514,7 @@ pub struct Constant<'tcx> { pub literal: Literal<'tcx>, } -newtype_index!(Promoted, const { DESCRIPTION = "promoted" }); +newtype_index!(Promoted { DEBUG_NAME = "promoted" }); #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum Literal<'tcx> { diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 0973bfd2429..c10f7372a8d 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -40,10 +40,29 @@ impl Idx for u32 { #[macro_export] macro_rules! newtype_index { + // ---- public rules ---- + + // Use default constants + ($name:ident) => ( + newtype_index!( + @type[$name] + @max[::std::u32::MAX] + @debug_name[unsafe {::std::intrinsics::type_name::<$name>() }]); + ); + + // Define any constants + ($name:ident { $($tokens:tt)+ }) => ( + newtype_index!( + @type[$name] + @max[::std::u32::MAX] + @debug_name[unsafe {::std::intrinsics::type_name::<$name>() }] + $($tokens)+); + ); + // ---- private rules ---- // Base case, user-defined constants (if any) have already been defined - (@type[$type:ident] @max[$max:expr] @descr[$descr:expr]) => ( + (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]) => ( #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub struct $type(u32); @@ -60,65 +79,35 @@ macro_rules! newtype_index { impl ::std::fmt::Debug for $type { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(fmt, "{}{}", $descr, self.0) + write!(fmt, "{}{}", $debug_name, self.0) } } ); - // Replace existing default for max (as final param) - (@type[$type:ident] @max[$_max:expr] @descr[$descr:expr] MAX = $max:expr) => ( - newtype_index!(@type[$type] @max[$max] @descr[$descr]); + // Rewrite final without comma to one that includes comma + (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr] $name:ident = $constant:expr) => ( + newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $name = $constant,); + ); + + // Rewrite final const without comma to one that includes comma + (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr] const $name:ident = $constant:expr) => ( + newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] const $name = $constant,); ); // Replace existing default for max - (@type[$type:ident] @max[$_max:expr] @descr[$descr:expr] MAX = $max:expr, $($idents:ident = $constants:expr),*) => ( - newtype_index!(@type[$type] @max[$max] @descr[$descr]); + (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr] MAX = $max:expr, $($tokens:tt)*) => ( + newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $(tokens)*); ); - // Replace existing default for description (as final param) - (@type[$type:ident] @max[$max:expr] @descr[$_descr:expr] DESCRIPTION = $descr:expr) => ( - newtype_index!(@type[$type] @max[$max] @descr[$descr]); - ); - - // Replace existing default for description - (@type[$type:ident] @max[$max:expr] @descr[$_descr:expr] DESCRIPTION = $descr:expr, $($idents:ident = $constants:expr),*) => ( - newtype_index!(@type[$type] @max[$max] @descr[$descr] $($idents = $constants),*); + // Replace existing default for debug_name + (@type[$type:ident] @max[$max:expr] @debug_name[$_debug_name:expr] DEBUG_NAME = $debug_name:expr, $($tokens:tt)*) => ( + newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*); ); // Assign a user-defined constant (as final param) - (@type[$type:ident] @max[$max:expr] @descr[$descr:expr] $name:ident = $constant:expr) => ( + (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr] const $name:ident = $constant:expr, $($tokens:tt)*) => ( pub const $name: $type = $type($constant); - newtype_index!(@type[$type] @max[$max] @descr[$descr]); - ); - - // Assign a user-defined constant - (@type[$type:ident] @max[$max:expr] @descr[$descr:expr] $name:ident = $constant:expr, $($idents:ident = $constants:expr),*) => ( - pub const $name: $type = $type($constant); - newtype_index!(@type[$type] @max[$max] @descr[$descr] $($idents = $constants),*); - ); - - // ---- public rules ---- - - // Use default constants - ($name:ident) => ( - newtype_index!( - @type[$name] - @max[::std::u32::MAX] - @descr[unsafe {::std::intrinsics::type_name::<$name>() }]); - ); - - // Define any constants - ($name:ident, const { $($idents:ident = $constants:expr,)+ }) => ( - newtype_index!( - @type[$name] - @max[::std::u32::MAX] - @descr[unsafe {::std::intrinsics::type_name::<$name>() }] - $($idents = $constants),+); - ); - - // Rewrite missing trailing comma in const to version with trailing comma - ($name:ident, const { $($idents:ident = $constants:expr),+ }) => ( - newtype_index!($name, const { $($idents = $constants,)+ }); + newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*); ); } From 97fe353ce65c67401ef3a9ce2b90a216d982daba Mon Sep 17 00:00:00 2001 From: Paul Faria Date: Wed, 11 Oct 2017 20:06:24 -0400 Subject: [PATCH 175/365] Split lines longer than 100 columns --- src/librustc_data_structures/indexed_vec.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index c10f7372a8d..6c5a37aa1e5 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -85,27 +85,32 @@ macro_rules! newtype_index { ); // Rewrite final without comma to one that includes comma - (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr] $name:ident = $constant:expr) => ( + (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr] + $name:ident = $constant:expr) => ( newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $name = $constant,); ); // Rewrite final const without comma to one that includes comma - (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr] const $name:ident = $constant:expr) => ( + (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr] + const $name:ident = $constant:expr) => ( newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] const $name = $constant,); ); // Replace existing default for max - (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr] MAX = $max:expr, $($tokens:tt)*) => ( + (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr] + MAX = $max:expr, $($tokens:tt)*) => ( newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $(tokens)*); ); // Replace existing default for debug_name - (@type[$type:ident] @max[$max:expr] @debug_name[$_debug_name:expr] DEBUG_NAME = $debug_name:expr, $($tokens:tt)*) => ( + (@type[$type:ident] @max[$max:expr] @debug_name[$_debug_name:expr] + DEBUG_NAME = $debug_name:expr, $($tokens:tt)*) => ( newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*); ); // Assign a user-defined constant (as final param) - (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr] const $name:ident = $constant:expr, $($tokens:tt)*) => ( + (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr] + const $name:ident = $constant:expr, $($tokens:tt)*) => ( pub const $name: $type = $type($constant); newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*); ); From 5d415e8d080792615b424f3f0a931058519879b5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 11 Oct 2017 08:47:47 -0700 Subject: [PATCH 176/365] rustc: Handle #[inline(always)] at -O0 This commit updates the handling of `#[inline(always)]` functions at -O0 to ensure that it's always inlined regardless of the number of codegen units used. Closes #45201 --- src/librustc_trans/trans_item.rs | 32 ++++++++++++++----- .../local-inlining-but-not-all.rs | 2 +- .../run-make/inline-always-many-cgu/Makefile | 8 +++++ .../run-make/inline-always-many-cgu/foo.rs | 25 +++++++++++++++ 4 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 src/test/run-make/inline-always-many-cgu/Makefile create mode 100644 src/test/run-make/inline-always-many-cgu/foo.rs diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index e40b1617d0a..060f02ee23e 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -31,7 +31,7 @@ use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use syntax::ast; -use syntax::attr; +use syntax::attr::{self, InlineAttr}; use syntax_pos::Span; use syntax_pos::symbol::Symbol; use type_of; @@ -175,16 +175,32 @@ pub trait TransItemExt<'a, 'tcx>: fmt::Debug { match *self.as_trans_item() { TransItem::Fn(ref instance) => { - if self.explicit_linkage(tcx).is_none() && - common::requests_inline(tcx, instance) + // If this function isn't inlined or otherwise has explicit + // linkage, then we'll be creating a globally shared version. + if self.explicit_linkage(tcx).is_some() || + !common::requests_inline(tcx, instance) { - if inline_in_all_cgus { - InstantiationMode::LocalCopy - } else { + return InstantiationMode::GloballyShared { may_conflict: false } + } + + // At this point we don't have explicit linkage and we're an + // inlined function. If we're inlining into all CGUs then we'll + // be creating a local copy per CGU + if inline_in_all_cgus { + return InstantiationMode::LocalCopy + } + + // Finally, if this is `#[inline(always)]` we're sure to respect + // that with an inline copy per CGU, but otherwise we'll be + // creating one copy of this `#[inline]` function which may + // conflict with upstream crates as it could be an exported + // symbol. + let attrs = instance.def.attrs(tcx); + match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) { + InlineAttr::Always => InstantiationMode::LocalCopy, + _ => { InstantiationMode::GloballyShared { may_conflict: true } } - } else { - InstantiationMode::GloballyShared { may_conflict: false } } } TransItem::Static(..) => { diff --git a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs index ccc8f03a40f..84464a627be 100644 --- a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs +++ b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs @@ -20,7 +20,7 @@ mod inline { //~ TRANS_ITEM fn local_inlining_but_not_all::inline[0]::inlined_function[0] @@ local_inlining_but_not_all-inline[External] - #[inline(always)] + #[inline] pub fn inlined_function() { diff --git a/src/test/run-make/inline-always-many-cgu/Makefile b/src/test/run-make/inline-always-many-cgu/Makefile new file mode 100644 index 00000000000..edf88a6327c --- /dev/null +++ b/src/test/run-make/inline-always-many-cgu/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 + if grep -w call $(TMPDIR)/*.ll; then \ + echo "found call instruction when one wasn't expected"; \ + exit 1; \ + fi diff --git a/src/test/run-make/inline-always-many-cgu/foo.rs b/src/test/run-make/inline-always-many-cgu/foo.rs new file mode 100644 index 00000000000..539dcdfa9b3 --- /dev/null +++ b/src/test/run-make/inline-always-many-cgu/foo.rs @@ -0,0 +1,25 @@ +// Copyright 2017 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. + +#![crate_type = "lib"] + +pub mod a { + #[inline(always)] + pub fn foo() { + } + + pub fn bar() { + } +} + +#[no_mangle] +pub fn bar() { + a::foo(); +} From 03419c846af0dea71e38064223d5e51550350a61 Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Wed, 11 Oct 2017 21:29:46 -0300 Subject: [PATCH 177/365] Bump cc to 1.01 to include x86_64-unknown-linux-gnux32 support --- src/Cargo.lock | 36 ++++++++++----------- src/bootstrap/Cargo.toml | 2 +- src/liballoc_jemalloc/Cargo.toml | 2 +- src/libprofiler_builtins/Cargo.toml | 2 +- src/librustc_llvm/Cargo.toml | 2 +- src/librustc_trans/Cargo.toml | 2 +- src/librustdoc/Cargo.toml | 2 +- src/libstd/Cargo.toml | 2 +- src/rustc/compiler_builtins_shim/Cargo.toml | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 77e33855f23..30fc7ee8d8c 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -42,7 +42,7 @@ dependencies = [ "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.0.0", ] @@ -99,7 +99,7 @@ name = "backtrace-sys" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -136,7 +136,7 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -246,7 +246,7 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -275,7 +275,7 @@ name = "cmake" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -290,7 +290,7 @@ dependencies = [ name = "compiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -407,7 +407,7 @@ name = "curl-sys" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -833,7 +833,7 @@ name = "libgit2-sys" version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -860,7 +860,7 @@ name = "libz-sys" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -880,7 +880,7 @@ name = "lzma-sys" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -968,7 +968,7 @@ name = "miniz-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1104,7 +1104,7 @@ name = "openssl-sys" version = "0.9.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1208,7 +1208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "profiler_builtins" version = "0.0.0" dependencies = [ - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1623,7 +1623,7 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "build_helper 0.1.0", - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", ] @@ -1755,7 +1755,7 @@ name = "rustc_trans" version = "0.0.0" dependencies = [ "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1824,7 +1824,7 @@ name = "rustdoc" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "html-diff 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1994,7 +1994,7 @@ dependencies = [ "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", @@ -2485,7 +2485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" -"checksum cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1" +"checksum cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c674f0870e3dbd4105184ea035acb1c32c8ae69939c9e228d2b11bbfe29efad" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2" "checksum cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "357c07e7a1fc95732793c1edb5901e1a1f305cfcf63a90eb12dbd22bdb6b789d" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 3f1d03b1872..bbbbf0e1915 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -34,7 +34,7 @@ cmake = "0.1.23" filetime = "0.1" num_cpus = "1.0" getopts = "0.2" -cc = "1.0" +cc = "1.0.1" libc = "0.2" serde = "1.0.8" serde_derive = "1.0.8" diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml index 4042c4d2d4e..6d7d83dd993 100644 --- a/src/liballoc_jemalloc/Cargo.toml +++ b/src/liballoc_jemalloc/Cargo.toml @@ -19,7 +19,7 @@ libc = { path = "../rustc/libc_shim" } [build-dependencies] build_helper = { path = "../build_helper" } -cc = "1.0" +cc = "1.0.1" [features] debug = [] diff --git a/src/libprofiler_builtins/Cargo.toml b/src/libprofiler_builtins/Cargo.toml index eb31f5730d1..04f456917b9 100644 --- a/src/libprofiler_builtins/Cargo.toml +++ b/src/libprofiler_builtins/Cargo.toml @@ -15,4 +15,4 @@ doc = false core = { path = "../libcore" } [build-dependencies] -cc = "1.0" +cc = "1.0.1" diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index de5add56b76..a9566c4bcac 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -18,4 +18,4 @@ rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } [build-dependencies] build_helper = { path = "../build_helper" } -cc = "1.0" +cc = "1.0.1" diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 482350d04b5..5b7879ea58e 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -32,4 +32,4 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } [target."cfg(windows)".dependencies] -cc = "1.0" +cc = "1.0.1" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index b295b414a03..e168222058f 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -18,4 +18,4 @@ html-diff = "0.0.4" [build-dependencies] build_helper = { path = "../build_helper" } -cc = "1.0" +cc = "1.0.1" diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index fb276448ffa..c95287390b4 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -36,7 +36,7 @@ rustc_tsan = { path = "../librustc_tsan" } [build-dependencies] build_helper = { path = "../build_helper" } -cc = "1.0" +cc = "1.0.1" [features] backtrace = [] diff --git a/src/rustc/compiler_builtins_shim/Cargo.toml b/src/rustc/compiler_builtins_shim/Cargo.toml index 886e239246d..608e5f5f36d 100644 --- a/src/rustc/compiler_builtins_shim/Cargo.toml +++ b/src/rustc/compiler_builtins_shim/Cargo.toml @@ -30,7 +30,7 @@ doctest = false core = { path = "../../libcore" } [build-dependencies] -cc = "1.0" +cc = "1.0.1" [features] c = [] From 0f427036c737666d16e1188f731199bd96750555 Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Wed, 11 Oct 2017 21:36:37 -0300 Subject: [PATCH 178/365] Add builder for x86_64-unknown-linux-gnux32 in cross2 --- src/ci/docker/cross2/Dockerfile | 1 + src/tools/build-manifest/src/main.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/ci/docker/cross2/Dockerfile b/src/ci/docker/cross2/Dockerfile index f5fc06767ce..76690fd2e15 100644 --- a/src/ci/docker/cross2/Dockerfile +++ b/src/ci/docker/cross2/Dockerfile @@ -47,6 +47,7 @@ ENV TARGETS=x86_64-unknown-fuchsia ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,x86_64-sun-solaris +ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index daeac35a017..8c1b130b116 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -95,6 +95,7 @@ static TARGETS: &'static [&'static str] = &[ "x86_64-unknown-freebsd", "x86_64-unknown-fuchsia", "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", "x86_64-unknown-redox", From 986a7c2df9fd4c94713a43a44e1c59410cac41b9 Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Wed, 11 Oct 2017 21:39:42 -0300 Subject: [PATCH 179/365] Test x86_64-unknown-linux-gnux32 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 139f06ec570..bc88a8b2b9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -116,7 +116,7 @@ matrix: - env: IMAGE=cross DEPLOY=1 if: branch = auto - env: IMAGE=cross2 DEPLOY=1 - if: branch = auto + # if: branch = auto - env: IMAGE=dist-aarch64-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-android DEPLOY=1 From 1a2ce7d51a1dd48a4adcfc698595ea4586399d6d Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Wed, 11 Oct 2017 23:17:50 -0300 Subject: [PATCH 180/365] Add gcc-multilib to cross2 --- src/ci/docker/cross2/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/docker/cross2/Dockerfile b/src/ci/docker/cross2/Dockerfile index 76690fd2e15..58932c51aec 100644 --- a/src/ci/docker/cross2/Dockerfile +++ b/src/ci/docker/cross2/Dockerfile @@ -5,6 +5,7 @@ RUN sh /scripts/cross-apt-packages.sh RUN apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \ build-essential \ + gcc-multilib \ libedit-dev \ libgmp-dev \ libisl-dev \ From 67b3e7cc435931330cae5ae104ec7a7d37df89dd Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Tue, 10 Oct 2017 22:54:06 -0500 Subject: [PATCH 181/365] Implement query ensure `$query::ensure()` guarantees that one of two things is true after it returns: - The query has all green inputs. - The query has been executed. and counts as a read from the source query --- src/librustc/ty/maps/plumbing.rs | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 88b619558d9..28397ac33d9 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -344,6 +344,48 @@ macro_rules! define_maps { } } + /// Ensure that either this query has all green inputs or been executed. + /// Executing query::ensure(D) is considered a read of the dep-node D. + /// + /// This function is particularly useful when executing passes for their + /// side-effects -- e.g., in order to report errors for erroneous programs. + /// + /// Note: The optimization is only available during incr. comp. + pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () { + let dep_node = Self::to_dep_node(tcx, &key); + + // Ensuring an "input" or anonymous query makes no sense + assert!(!dep_node.kind.is_anon()); + assert!(!dep_node.kind.is_input()); + use dep_graph::DepNodeColor; + match tcx.dep_graph.node_color(&dep_node) { + Some(DepNodeColor::Green(dep_node_index)) => { + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + tcx.dep_graph.read_index(dep_node_index); + } + Some(DepNodeColor::Red) => { + let _ = tcx.$name(key); + } + None => { + // Huh + if !tcx.dep_graph.is_fully_enabled() { + let _ = tcx.$name(key); + return; + } + match tcx.dep_graph.try_mark_green(tcx, &dep_node) { + Some(dep_node_index) => { + debug_assert!(tcx.dep_graph.is_green(dep_node_index)); + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + tcx.dep_graph.read_index(dep_node_index); + } + None => { + let _ = tcx.$name(key); + } + } + } + } + } + fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V { let provider = tcx.maps.providers[key.map_crate()].$name; provider(tcx.global_tcx(), key) From bbdc61313df2c54c08cddcfde803cc2b40aa2ba3 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Tue, 10 Oct 2017 22:55:23 -0500 Subject: [PATCH 182/365] Ensure typeck_tables_of from typck_item_bodies This should make TypeckTables lazier. --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9c6a4abfbd7..02a41aefd13 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -728,7 +728,7 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum debug_assert!(crate_num == LOCAL_CRATE); Ok(tcx.sess.track_errors(|| { for body_owner_def_id in tcx.body_owners() { - tcx.typeck_tables_of(body_owner_def_id); + ty::maps::queries::typeck_tables_of::ensure(tcx, body_owner_def_id); } })?) } From 818d2249475910fa1f7844486abb2d7239056d96 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 11 Oct 2017 21:25:13 +0200 Subject: [PATCH 183/365] Fix out of date unstable book entries for `alloc_*` features. --- .../src/library-features/alloc-jemalloc.md | 53 +------------------ .../src/library-features/alloc-system.md | 31 ++++++++--- src/liballoc_system/lib.rs | 2 +- 3 files changed, 26 insertions(+), 60 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/alloc-jemalloc.md b/src/doc/unstable-book/src/library-features/alloc-jemalloc.md index 18ff838dd32..425d4cb79b2 100644 --- a/src/doc/unstable-book/src/library-features/alloc-jemalloc.md +++ b/src/doc/unstable-book/src/library-features/alloc-jemalloc.md @@ -8,55 +8,6 @@ See also [`alloc_system`](library-features/alloc-system.html). ------------------------ -The compiler currently ships two default allocators: `alloc_system` and -`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators -are normal Rust crates and contain an implementation of the routines to -allocate and deallocate memory. The standard library is not compiled assuming -either one, and the compiler will decide which allocator is in use at -compile-time depending on the type of output artifact being produced. - -Binaries generated by the compiler will use `alloc_jemalloc` by default (where -available). In this situation the compiler "controls the world" in the sense of -it has power over the final link. Primarily this means that the allocator -decision can be left up the compiler. - -Dynamic and static libraries, however, will use `alloc_system` by default. Here -Rust is typically a 'guest' in another application or another world where it -cannot authoritatively decide what allocator is in use. As a result it resorts -back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing -memory. - -# Switching Allocators - -Although the compiler's default choices may work most of the time, it's often -necessary to tweak certain aspects. Overriding the compiler's decision about -which allocator is in use is done simply by linking to the desired allocator: - -```rust,no_run -#![feature(alloc_system)] - -extern crate alloc_system; - -fn main() { - let a = Box::new(4); // Allocates from the system allocator. - println!("{}", a); -} -``` - -In this example the binary generated will not link to jemalloc by default but -instead use the system allocator. Conversely to generate a dynamic library which -uses jemalloc by default one would write: - -```rust,ignore -#![feature(alloc_jemalloc)] -#![crate_type = "dylib"] - -extern crate alloc_jemalloc; - -pub fn foo() { - let a = Box::new(4); // Allocates from jemalloc. - println!("{}", a); -} -# fn main() {} -``` +This feature has been replaced by [the `jemallocator` crate on crates.io.][jemallocator]. +[jemallocator]: https://crates.io/crates/jemallocator diff --git a/src/doc/unstable-book/src/library-features/alloc-system.md b/src/doc/unstable-book/src/library-features/alloc-system.md index 1d261db6ba1..9effab202ca 100644 --- a/src/doc/unstable-book/src/library-features/alloc-system.md +++ b/src/doc/unstable-book/src/library-features/alloc-system.md @@ -1,10 +1,10 @@ # `alloc_system` -The tracking issue for this feature is: [#33082] +The tracking issue for this feature is: [#32838] -[#33082]: https://github.com/rust-lang/rust/issues/33082 +[#32838]: https://github.com/rust-lang/rust/issues/32838 -See also [`alloc_jemalloc`](library-features/alloc-jemalloc.html). +See also [`global_allocator`](language-features/global-allocator.html). ------------------------ @@ -30,13 +30,18 @@ memory. Although the compiler's default choices may work most of the time, it's often necessary to tweak certain aspects. Overriding the compiler's decision about -which allocator is in use is done simply by linking to the desired allocator: +which allocator is in use is done through the `#[global_allocator]` attribute: ```rust,no_run -#![feature(alloc_system)] +#![feature(alloc_system, global_allocator, allocator_api)] extern crate alloc_system; +use alloc_system::System; + +#[global_allocator] +static A: System = System; + fn main() { let a = Box::new(4); // Allocates from the system allocator. println!("{}", a); @@ -47,11 +52,22 @@ In this example the binary generated will not link to jemalloc by default but instead use the system allocator. Conversely to generate a dynamic library which uses jemalloc by default one would write: +(The `alloc_jemalloc` crate cannot be used to control the global allocator, +crate.io’s `jemallocator` crate provides equivalent functionality.) + +```toml +# Cargo.toml +[dependencies] +jemallocator = "0.1" +``` ```rust,ignore -#![feature(alloc_jemalloc)] +#![feature(global_allocator)] #![crate_type = "dylib"] -extern crate alloc_jemalloc; +extern crate jemallocator; + +#[global_allocator] +static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; pub fn foo() { let a = Box::new(4); // Allocates from jemalloc. @@ -59,4 +75,3 @@ pub fn foo() { } # fn main() {} ``` - diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 2eb659699eb..7aa5f8a9186 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -14,7 +14,7 @@ #![unstable(feature = "alloc_system", reason = "this library is unlikely to be stabilized in its current \ form or name", - issue = "27783")] + issue = "32838")] #![feature(global_allocator)] #![feature(allocator_api)] #![feature(alloc)] From 7199feea9d480d44e1f5dac9342cc9951f20e6ad Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Thu, 12 Oct 2017 06:59:14 -0300 Subject: [PATCH 184/365] Revert "Test x86_64-unknown-linux-gnux32" --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bc88a8b2b9c..139f06ec570 100644 --- a/.travis.yml +++ b/.travis.yml @@ -116,7 +116,7 @@ matrix: - env: IMAGE=cross DEPLOY=1 if: branch = auto - env: IMAGE=cross2 DEPLOY=1 - # if: branch = auto + if: branch = auto - env: IMAGE=dist-aarch64-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-android DEPLOY=1 From f03af1b8f1be0fdb04cc9d641e2777ff3a6ec817 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Thu, 12 Oct 2017 08:48:49 -0500 Subject: [PATCH 185/365] Remove query profiling from ensure --- src/librustc/ty/maps/plumbing.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 28397ac33d9..57e3e0496e2 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -360,7 +360,6 @@ macro_rules! define_maps { use dep_graph::DepNodeColor; match tcx.dep_graph.node_color(&dep_node) { Some(DepNodeColor::Green(dep_node_index)) => { - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); tcx.dep_graph.read_index(dep_node_index); } Some(DepNodeColor::Red) => { @@ -375,7 +374,6 @@ macro_rules! define_maps { match tcx.dep_graph.try_mark_green(tcx, &dep_node) { Some(dep_node_index) => { debug_assert!(tcx.dep_graph.is_green(dep_node_index)); - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); tcx.dep_graph.read_index(dep_node_index); } None => { From d0cb4d09cd4eb7626130cc9e59ef69dbfec04d0e Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Thu, 12 Oct 2017 08:54:42 -0500 Subject: [PATCH 186/365] Explain why `ensure` of a red node == the query --- src/librustc/ty/maps/plumbing.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 57e3e0496e2..715d5993fc5 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -363,6 +363,12 @@ macro_rules! define_maps { tcx.dep_graph.read_index(dep_node_index); } Some(DepNodeColor::Red) => { + // A DepNodeColor::Red DepNode means that this query was executed + // before. We can not call `dep_graph.read()` here as we don't have + // the DepNodeIndex. Instead, We call the query again to issue the + // appropriate `dep_graph.read()` call. The performance cost this + // introduces should be negligible as we'll immediately hit the + // in-memory cache. let _ = tcx.$name(key); } None => { From e6da40c6697f3e6b8b87d07a1c9517dcc94338f3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 12 Oct 2017 08:02:39 -0700 Subject: [PATCH 187/365] rustbuild: Prevent spurious rebuilds of the RLS The RLS currently is rebuilt every time you test it because the `OPENSSL_DIR` env var is changing, which is in turn caused by an accidental omission of `prepare_tool_cargo` when testing the RLS. --- src/bootstrap/check.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 6e276f44668..06edbd8e9ee 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -246,8 +246,11 @@ impl Step for Rls { let compiler = builder.compiler(stage, host); builder.ensure(tool::Rls { compiler, target: self.host }); - let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); - cargo.arg("--manifest-path").arg(build.src.join("src/tools/rls/Cargo.toml")); + let mut cargo = tool::prepare_tool_cargo(builder, + compiler, + host, + "test", + "src/tools/rls"); // Don't build tests dynamically, just a pain to work with cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); @@ -291,8 +294,11 @@ impl Step for Rustfmt { let compiler = builder.compiler(stage, host); builder.ensure(tool::Rustfmt { compiler, target: self.host }); - let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); - cargo.arg("--manifest-path").arg(build.src.join("src/tools/rustfmt/Cargo.toml")); + let mut cargo = tool::prepare_tool_cargo(builder, + compiler, + host, + "test", + "src/tools/rustfmt"); // Don't build tests dynamically, just a pain to work with cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); From 6cae0805166002c2a70007b11528d3ccec434633 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Oct 2017 15:54:49 -0700 Subject: [PATCH 188/365] rustc: Handle `#[linkage]` anywhere in a crate This commit updates the reachability pass of the compiler to seed the local worklist with `#[linkage]`-like items anywhere in a crate, not just those reachable from public items. Closes #45165 --- src/librustc/middle/reachable.rs | 6 +++ src/test/run-pass/smallest-hello-world.rs | 41 ------------------- .../run-pass/thin-lto-global-allocator.rs | 19 +++++++++ 3 files changed, 25 insertions(+), 41 deletions(-) delete mode 100644 src/test/run-pass/smallest-hello-world.rs create mode 100644 src/test/run-pass/thin-lto-global-allocator.rs diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 55d0c6b4c66..bb6213cb5fa 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -336,6 +336,12 @@ struct CollectPrivateImplItemsVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { + // Anything which has custom linkage gets thrown on the worklist no + // matter where it is in the crate. + if attr::contains_name(&item.attrs, "linkage") { + self.worklist.push(item.id); + } + // We need only trait impls here, not inherent impls, and only non-exported ones if let hir::ItemImpl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node { if !self.access_levels.is_reachable(item.id) { diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs deleted file mode 100644 index bcbd3fd3786..00000000000 --- a/src/test/run-pass/smallest-hello-world.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2013-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. - -// Smallest "hello world" with a libc runtime - -// ignore-windows -// ignore-android - -#![feature(intrinsics, lang_items, start, no_core, alloc_system)] -#![feature(global_allocator, allocator_api)] -#![no_std] - -extern crate alloc_system; - -use alloc_system::System; - -#[global_allocator] -static A: System = System; - -extern { - fn puts(s: *const u8); -} - -#[no_mangle] -#[lang = "eh_personality"] pub extern fn rust_eh_personality() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } - -#[start] -fn main(_: isize, _: *const *const u8) -> isize { - unsafe { - puts("Hello!\0".as_ptr() as *const u8); - } - return 0 -} diff --git a/src/test/run-pass/thin-lto-global-allocator.rs b/src/test/run-pass/thin-lto-global-allocator.rs new file mode 100644 index 00000000000..1c15da5469e --- /dev/null +++ b/src/test/run-pass/thin-lto-global-allocator.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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. + +// compile-flags: -Z thinlto -C codegen-units=2 +// min-llvm-version 4.0 + +#![feature(allocator_api, global_allocator)] + +#[global_allocator] +static A: std::heap::System = std::heap::System; + +fn main() {} From 19901df00282d11e39bdee8d81b773a5826330fb Mon Sep 17 00:00:00 2001 From: kennytm Date: Thu, 12 Oct 2017 14:53:26 +0800 Subject: [PATCH 189/365] Fix typo in libsyntax/parse/lexer/unicode_chars.rs ` (U+0060) should be the "grave" accent, not "Greek" accent. --- src/libsyntax/parse/lexer/unicode_chars.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index 39b5482a066..35afe8dd56d 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -144,7 +144,7 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('‵', "Reversed Prime", '\''), ('՚', "Armenian Apostrophe", '\''), ('׳', "Hebrew Punctuation Geresh", '\''), - ('`', "Greek Accent", '\''), + ('`', "Grave Accent", '\''), ('`', "Greek Varia", '\''), ('`', "Fullwidth Grave Accent", '\''), ('´', "Acute Accent", '\''), From 9da9c3be624e24e4ab989e811d614b7c1ad8b025 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Oct 2017 20:00:34 +0200 Subject: [PATCH 190/365] Small improvement for the sidebar on mobile devices --- src/librustdoc/html/static/rustdoc.css | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 27574e67bc8..813531c0954 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -764,17 +764,19 @@ span.since { } .sidebar { - height: 40px; + height: 45px; min-height: 40px; - width: 100%; - margin: 0px; - padding: 0px; + width: calc(100% + 30px); + margin: 0; + margin-left: -15px; + padding: 0 15px; position: static; } .sidebar .location { float: right; margin: 0px; + margin-top: 2px; padding: 3px 10px 1px 10px; min-height: 39px; background: inherit; @@ -789,7 +791,7 @@ span.since { .sidebar img { width: 35px; margin-top: 5px; - margin-bottom: 0px; + margin-bottom: 5px; float: left; } From 16ec7b949fb62db3956687fbf8660fc8524c9cf4 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 12 Oct 2017 22:57:51 +0200 Subject: [PATCH 191/365] Increase padding between consecutive impls --- src/librustdoc/html/static/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 27574e67bc8..e03a9201b6a 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -385,7 +385,7 @@ h4 > code, h3 > code, .invisible > code { padding: 0; } -.content .item-list li { margin-bottom: 3px; } +.content .item-list li { margin-bottom: 1em; } .content .multi-column { -moz-column-count: 5; From f577847aa22cda4935562fe8e7c9420bcc58f148 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 13 Oct 2017 09:56:50 +0900 Subject: [PATCH 192/365] Reword --- src/librustc/traits/error_reporting.rs | 51 +++++++++++-------- .../mismatched_types/closure-arg-count.stderr | 12 ++--- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index a192dc6d6ea..030b7e4f646 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -852,40 +852,45 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if n == 1 { "" } else { "s" }, ); + let expected_str = if let Some(n) = expected_tuple { + assert!(expected == 1); + if closure_args.as_ref().map(|&(ref pats, _)| pats.len()) == Some(n) { + Cow::from("a single tuple as argument") + } else { + // be verbose when numbers differ + Cow::from(format!("a single {}-tuple as argument", n)) + } + } else { + Cow::from(args_str(expected, false)) + }; + + let found_str = if expected_tuple.is_some() { + args_str(found, true) + } else { + args_str(found, false) + }; + + let mut err = struct_span_err!(self.tcx.sess, span, E0593, "{} is expected to take {}, but it takes {}", kind, - if expected_tuple.is_some() { - Cow::from("a single tuple as argument") - } else { - Cow::from(args_str(expected, false)) - }, - if expected_tuple.is_some() { - args_str(found, true) - } else { - args_str(found, false) - }, + expected_str, + found_str, ); err.span_label( span, format!( - "expected {} that takes {}{}", + "expected {} that takes {}", kind, - args_str(expected, false), - if let Some(n) = expected_tuple { - assert!(expected == 1); - Cow::from(format!(", a {}-tuple", n)) - } else { - Cow::from("") - } + expected_str, ) ); if let Some(span) = found_span { if let (Some(expected_tuple), Some((pats, tys))) = (expected_tuple, closure_args) { if expected_tuple != found || pats.len() != found { - err.span_label(span, format!("takes {}", args_str(found, true))); + err.span_label(span, format!("takes {}", found_str)); } else { let sugg = format!( "|({}){}|", @@ -906,10 +911,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }, ); - err.span_suggestion(span, "consider changing to", sugg); + err.span_suggestion( + span, + "consider changing the closure to accept a tuple", + sugg + ); } } else { - err.span_label(span, format!("takes {}", args_str(found, false))); + err.span_label(span, format!("takes {}", found_str)); } } diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 8f508ade68c..9d4ac630546 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -45,25 +45,25 @@ error[E0593]: closure is expected to take a single tuple as argument, but it tak --> $DIR/closure-arg-count.rs:20:53 | 20 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); - | ^^^ ------ help: consider changing to: `|(i, x)|` + | ^^^ ------ help: consider changing the closure to accept a tuple: `|(i, x)|` | | - | expected closure that takes 1 argument, a 2-tuple + | expected closure that takes a single tuple as argument error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments --> $DIR/closure-arg-count.rs:21:53 | 21 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i); - | ^^^ ------------- help: consider changing to: `|(i, x): (usize, _)|` + | ^^^ ------------- help: consider changing the closure to accept a tuple: `|(i, x): (usize, _)|` | | - | expected closure that takes 1 argument, a 2-tuple + | expected closure that takes a single tuple as argument -error[E0593]: closure is expected to take a single tuple as argument, but it takes 3 distinct arguments +error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments --> $DIR/closure-arg-count.rs:22:53 | 22 | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); | ^^^ --------- takes 3 distinct arguments | | - | expected closure that takes 1 argument, a 2-tuple + | expected closure that takes a single 2-tuple as argument error: aborting due to 8 previous errors From 8d20030a03d0d809819a538da32452d262ee0b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Br=C3=A1ulio=20Bezerra?= Date: Thu, 12 Oct 2017 23:30:46 -0300 Subject: [PATCH 193/365] Moved details of unstable non-ascii identifiers from the Reference to the Unstable book --- .../src/language-features/non-ascii-idents.md | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/non-ascii-idents.md b/src/doc/unstable-book/src/language-features/non-ascii-idents.md index d5600c58fd9..a1bb0ce7869 100644 --- a/src/doc/unstable-book/src/language-features/non-ascii-idents.md +++ b/src/doc/unstable-book/src/language-features/non-ascii-idents.md @@ -15,4 +15,34 @@ The `non_ascii_idents` feature adds support for non-ASCII identifiers. const ε: f64 = 0.00001f64; const Π: f64 = 3.14f64; -``` \ No newline at end of file +``` + +## Changes to the language reference + +> **Lexer:** +> IDENTIFIER : +>       XID_start XID_continue\* +>    | `_` XID_continue+ + +An identifier is any nonempty Unicode string of the following form: + +Either + + * The first character has property [`XID_start`] + * The remaining characters have property [`XID_continue`] + +Or + + * The first character is `_` + * The identifier is more than one character, `_` alone is not an identifier + * The remaining characters have property [`XID_continue`] + +that does _not_ occur in the set of [strict keywords]. + +> **Note**: [`XID_start`] and [`XID_continue`] as character properties cover the +> character ranges used to form the more familiar C and Java language-family +> identifiers. + +[`XID_start`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i= +[`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i= +[strict keywords]: keywords.html#strict-keywords From f7fe970400042ff09d3eead47fb3850d6a5d63df Mon Sep 17 00:00:00 2001 From: Garrett Berg Date: Fri, 6 Oct 2017 16:15:29 -0600 Subject: [PATCH 194/365] incr comp: rustc_clean/dirty auto assert This adds auto-assertion to `rustc_clean/dirty` and also implements more comprehensive testing for - src/test/incremental/hashes/enum_constructors.rs - src/test/incremental/hashes/enum_defs.rs - src/test/incremental/hashes/extern_mods.rs - src/test/incremental/hashes/inherent_impls.rs - src/test/incremental/hashes/statics.rs - src/test/incremental/hashes/struct_constructors.rs - src/test/incremental/hashes/type_defs.rs trait_defs.rs and trait_impl.rs are blocked on a hard to triage compiler ICE (at least hard for a newbie like me) having to do with some DepNodes not getting computed for traits. A FIXME has been added in the source to reflect this continued work. --- src/librustc/dep_graph/mod.rs | 2 +- .../persist/dirty_clean.rs | 422 ++++++++++++++++-- .../incremental/hashes/call_expressions.rs | 50 +-- src/test/incremental/hashes/consts.rs | 45 +- .../incremental/hashes/enum_constructors.rs | 100 ++--- src/test/incremental/hashes/enum_defs.rs | 152 +++---- src/test/incremental/hashes/extern_mods.rs | 56 +-- src/test/incremental/hashes/inherent_impls.rs | 228 +++++----- src/test/incremental/hashes/statics.rs | 60 ++- .../incremental/hashes/struct_constructors.rs | 60 +-- src/test/incremental/hashes/type_defs.rs | 64 +-- 11 files changed, 774 insertions(+), 465 deletions(-) diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 8d2cf676849..690db8a5522 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -19,7 +19,7 @@ mod safe; mod serialized; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; -pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId}; +pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs}; pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor}; pub use self::prev::PreviousDepGraph; pub use self::query::DepGraphQuery; diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 0270e3618e2..5f97eaf21d2 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -13,12 +13,12 @@ //! we will compare the fingerprint from the current and from the previous //! compilation session as appropriate: //! -//! - `#[rustc_dirty(label="TypeckTables", cfg="rev2")]` if we are +//! - `#[rustc_clean(cfg="rev2", except="TypeckTables")]` if we are //! in `#[cfg(rev2)]`, then the fingerprints associated with //! `DepNode::TypeckTables(X)` must be DIFFERENT (`X` is the def-id of the //! current node). -//! - `#[rustc_clean(label="TypeckTables", cfg="rev2")]` same as above, -//! except that the fingerprints must be the SAME. +//! - `#[rustc_clean(cfg="rev2")]` same as above, except that the +//! fingerprints must be the SAME (along with all other fingerprints). //! //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. @@ -39,10 +39,15 @@ //! previous revision to compare things to. //! +#![allow(dead_code)] + use std::collections::HashSet; +use std::iter::FromIterator; use std::vec::Vec; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::{DepNode, label_strs}; use rustc::hir; +use rustc::hir::{Item_ as HirItem, ImplItemKind, TraitItemKind}; +use rustc::hir::map::Node as HirNode; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit; @@ -53,11 +58,182 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use syntax_pos::Span; use rustc::ty::TyCtxt; -const LABEL: &'static str = "label"; -const CFG: &'static str = "cfg"; +const EXCEPT: &str = "except"; +const LABEL: &str = "label"; +const CFG: &str = "cfg"; + +// Base and Extra labels to build up the labels + +/// For typedef, constants, and statics +const BASE_CONST: &[&str] = &[ + label_strs::TypeOfItem, +]; + +/// DepNodes for functions + methods +const BASE_FN: &[&str] = &[ + // Callers will depend on the signature of these items, so we better test + label_strs::FnSignature, + label_strs::GenericsOfItem, + label_strs::PredicatesOfItem, + label_strs::TypeOfItem, + + // And a big part of compilation (that we eventually want to cache) is type inference + // information: + label_strs::TypeckTables, +]; + +/// DepNodes for Hir, which is pretty much everything +const BASE_HIR: &[&str] = &[ + // Hir and HirBody should be computed for all nodes + label_strs::Hir, + label_strs::HirBody, +]; + +/// `impl` implementation of struct/trait +const BASE_IMPL: &[&str] = &[ + label_strs::AssociatedItemDefIds, + label_strs::GenericsOfItem, + label_strs::ImplTraitRef, +]; + +/// DepNodes for MirValidated/Optimized, which is relevant in "executable" +/// code, i.e. functions+methods +const BASE_MIR: &[&str] = &[ + label_strs::MirOptimized, + label_strs::MirValidated, +]; + +/// Struct, Enum and Union DepNodes +/// +/// Note that changing the type of a field does not change the type of the struct or enum, but +/// adding/removing fields or changing a fields name or visibility does. +const BASE_STRUCT: &[&str] = &[ + label_strs::GenericsOfItem, + label_strs::PredicatesOfItem, + label_strs::TypeOfItem, +]; + +/// Trait Definition DepNodes +const BASE_TRAIT_DEF: &[&str] = &[ + label_strs::AssociatedItemDefIds, + label_strs::GenericsOfItem, + label_strs::ObjectSafety, + label_strs::PredicatesOfItem, + label_strs::SpecializationGraph, + label_strs::TraitDefOfItem, + label_strs::TraitImpls, +]; + +/// extra DepNodes for methods (+fn) +const EXTRA_ASSOCIATED: &[&str] = &[ + label_strs::AssociatedItems, +]; + +const EXTRA_TRAIT: &[&str] = &[ + label_strs::TraitOfItem, +]; + +// Fully Built Labels + +const LABELS_CONST: &[&[&str]] = &[ + BASE_HIR, + BASE_CONST, +]; + +/// Constant/Typedef in an impl +const LABELS_CONST_ASSOCIATED: &[&[&str]] = &[ + BASE_HIR, + BASE_CONST, + EXTRA_ASSOCIATED, +]; + +/// Trait-Const/Typedef DepNodes +const LABELS_CONST_TRAIT: &[&[&str]] = &[ + BASE_HIR, + BASE_CONST, + EXTRA_ASSOCIATED, + EXTRA_TRAIT, +]; + +/// Function DepNode +const LABELS_FN: &[&[&str]] = &[ + BASE_HIR, + BASE_MIR, + BASE_FN, +]; + +/// Method DepNodes +const LABELS_FN_ASSOCIATED: &[&[&str]] = &[ + BASE_HIR, + BASE_MIR, + BASE_FN, + EXTRA_ASSOCIATED, +]; + +/// Trait-Method DepNodes +const LABELS_FN_TRAIT: &[&[&str]] = &[ + BASE_HIR, + BASE_MIR, + BASE_FN, + EXTRA_ASSOCIATED, + EXTRA_TRAIT, +]; + +/// For generic cases like inline-assemply/mod/etc +const LABELS_HIR_ONLY: &[&[&str]] = &[ + BASE_HIR, +]; + +/// Impl DepNodes +const LABELS_IMPL: &[&[&str]] = &[ + BASE_HIR, + BASE_IMPL, +]; + +/// Struct DepNodes +const LABELS_STRUCT: &[&[&str]] = &[ + BASE_HIR, + BASE_STRUCT, +]; + +/// Trait Definition DepNodes +const LABELS_TRAIT: &[&[&str]] = &[ + BASE_HIR, + BASE_TRAIT_DEF, +]; + + +// FIXME: Struct/Enum/Unions Fields (there is currently no way to attach these) +// +// Fields are kind of separate from their containers, as they can change independently from +// them. We should at least check +// +// TypeOfItem for these. type Labels = HashSet; +/// Represents the requested configuration by rustc_clean/dirty +struct Assertion { + clean: Labels, + dirty: Labels, +} + +impl Assertion { + fn from_clean_labels(labels: Labels) -> Assertion { + Assertion { + clean: labels, + dirty: Labels::new(), + } + } + + fn from_dirty_labels(labels: Labels) -> Assertion { + Assertion { + clean: Labels::new(), + dirty: labels, + } + } +} + pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // can't add `#[rustc_dirty]` etc without opting in to this feature if !tcx.sess.features.borrow().rustc_attrs { @@ -91,14 +267,189 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> { } impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { - fn labels(&self, attr: &Attribute) -> Labels { + + /// Possibly "deserialize" the attribute into a clean/dirty assertion + fn assertion_maybe(&mut self, item_id: ast::NodeId, attr: &Attribute) + -> Option + { + let is_clean = if attr.check_name(ATTR_DIRTY) { + false + } else if attr.check_name(ATTR_CLEAN) { + true + } else { + // skip: not rustc_clean/dirty + return None + }; + if !check_config(self.tcx, attr) { + // skip: not the correct `cfg=` + return None; + } + let assertion = if let Some(labels) = self.labels(attr) { + if is_clean { + Assertion::from_clean_labels(labels) + } else { + Assertion::from_dirty_labels(labels) + } + } else { + self.assertion_auto(item_id, attr, is_clean) + }; + Some(assertion) + } + + /// Get the "auto" assertion on pre-validated attr, along with the `except` labels + fn assertion_auto(&mut self, item_id: ast::NodeId, attr: &Attribute, is_clean: bool) + -> Assertion + { + let (name, mut auto) = self.auto_labels(item_id, attr); + let except = self.except(attr); + for e in except.iter() { + if !auto.remove(e) { + let msg = format!( + "`except` specified DepNodes that can not be affected for \"{}\": \"{}\"", + name, + e + ); + self.tcx.sess.span_fatal(attr.span, &msg); + } + } + if is_clean { + Assertion { + clean: auto, + dirty: except, + } + } else { + Assertion { + clean: except, + dirty: auto, + } + } + } + + fn labels(&self, attr: &Attribute) -> Option { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(LABEL) { + let value = expect_associated_value(self.tcx, &item); + return Some(self.resolve_labels(&item, value.as_str().as_ref())); + } + } + None + } + + /// `except=` attribute value + fn except(&self, attr: &Attribute) -> Labels { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { + if item.check_name(EXCEPT) { let value = expect_associated_value(self.tcx, &item); return self.resolve_labels(&item, value.as_str().as_ref()); } } - self.tcx.sess.span_fatal(attr.span, "no `label` found"); + // if no `label` or `except` is given, only the node's group are asserted + Labels::new() + } + + /// Return all DepNode labels that should be asserted for this item. + /// index=0 is the "name" used for error messages + fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static str, Labels) { + let node = self.tcx.hir.get(item_id); + let (name, labels) = match node { + HirNode::NodeItem(item) => { + match item.node { + // note: these are in the same order as hir::Item_; + // FIXME(michaelwoerister): do commented out ones + + // // An `extern crate` item, with optional original crate name, + // HirItem::ItemExternCrate(..), // intentionally no assertions + + // // `use foo::bar::*;` or `use foo::bar::baz as quux;` + // HirItem::ItemUse(..), // intentionally no assertions + + // A `static` item + HirItem::ItemStatic(..) => ("ItemStatic", LABELS_CONST), + + // A `const` item + HirItem::ItemConst(..) => ("ItemConst", LABELS_CONST), + + // A function declaration + HirItem::ItemFn(..) => ("ItemFn", LABELS_FN), + + // // A module + HirItem::ItemMod(..) =>("ItemMod", LABELS_HIR_ONLY), + + // // An external module + HirItem::ItemForeignMod(..) => ("ItemForeignMod", LABELS_HIR_ONLY), + + // Module-level inline assembly (from global_asm!) + HirItem::ItemGlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY), + + // A type alias, e.g. `type Foo = Bar` + HirItem::ItemTy(..) => ("ItemTy", LABELS_CONST), + + // An enum definition, e.g. `enum Foo {C, D}` + HirItem::ItemEnum(..) => ("ItemEnum", LABELS_STRUCT), + + // A struct definition, e.g. `struct Foo {x: A}` + HirItem::ItemStruct(..) => ("ItemStruct", LABELS_STRUCT), + + // A union definition, e.g. `union Foo {x: A, y: B}` + HirItem::ItemUnion(..) => ("ItemUnion", LABELS_STRUCT), + + // Represents a Trait Declaration + // FIXME(michaelwoerister): trait declaration is buggy because sometimes some of + // the depnodes don't exist (because they legitametely didn't need to be + // calculated) + // + // michaelwoerister and vitiral came up with a possible solution, + // to just do this before every query + // ``` + // ::rustc::ty::maps::plumbing::force_from_dep_node(tcx, dep_node) + // ``` + // + // However, this did not seem to work effectively and more bugs were hit. + // Nebie @vitiral gave up :) + // + //HirItem::ItemTrait(..) => ("ItemTrait", LABELS_TRAIT), + + // `impl Trait for .. {}` + HirItem::ItemDefaultImpl(..) => ("ItemDefaultImpl", LABELS_IMPL), + + // An implementation, eg `impl Trait for Foo { .. }` + HirItem::ItemImpl(..) => ("ItemImpl", LABELS_IMPL), + + _ => self.tcx.sess.span_fatal( + attr.span, + &format!( + "clean/dirty auto-assertions not yet defined for NodeItem.node={:?}", + item.node + ) + ), + } + }, + HirNode::NodeTraitItem(item) => { + match item.node { + TraitItemKind::Method(..) => ("NodeTraitItem", LABELS_FN_TRAIT), + TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_TRAIT), + TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_TRAIT), + } + }, + HirNode::NodeImplItem(item) => { + match item.node { + ImplItemKind::Method(..) => ("NodeImplItem", LABELS_FN_ASSOCIATED), + ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_ASSOCIATED), + ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_ASSOCIATED), + } + }, + _ => self.tcx.sess.span_fatal( + attr.span, + &format!( + "clean/dirty auto-assertions not yet defined for {:?}", + node + ) + ), + }; + let labels = Labels::from_iter( + labels.iter().flat_map(|s| s.iter().map(|l| l.to_string())) + ); + (name, labels) } fn resolve_labels(&self, item: &NestedMetaItem, value: &str) -> Labels { @@ -174,22 +525,16 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { fn check_item(&mut self, item_id: ast::NodeId, item_span: Span) { let def_id = self.tcx.hir.local_def_id(item_id); for attr in self.tcx.get_attrs(def_id).iter() { - if attr.check_name(ATTR_DIRTY) { - if check_config(self.tcx, attr) { - self.checked_attrs.insert(attr.id); - let labels = self.labels(attr); - for dep_node in self.dep_nodes(&labels, def_id) { - self.assert_dirty(item_span, dep_node); - } - } - } else if attr.check_name(ATTR_CLEAN) { - if check_config(self.tcx, attr) { - self.checked_attrs.insert(attr.id); - let labels = self.labels(attr); - for dep_node in self.dep_nodes(&labels, def_id) { - self.assert_clean(item_span, dep_node); - } - } + let assertion = match self.assertion_maybe(item_id, attr) { + Some(a) => a, + None => continue, + }; + self.checked_attrs.insert(attr.id); + for dep_node in self.dep_nodes(&assertion.clean, def_id) { + self.assert_clean(item_span, dep_node); + } + for dep_node in self.dep_nodes(&assertion.dirty, def_id) { + self.assert_dirty(item_span, dep_node); } } } @@ -363,21 +708,42 @@ impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { /// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan /// for a `cfg="foo"` attribute and check whether we have a cfg /// flag called `foo`. +/// +/// Also make sure that the `label` and `except` fields do not +/// both exist. fn check_config(tcx: TyCtxt, attr: &Attribute) -> bool { debug!("check_config(attr={:?})", attr); let config = &tcx.sess.parse_sess.config; debug!("check_config: config={:?}", config); + let (mut cfg, mut except, mut label) = (None, false, false); for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(CFG) { let value = expect_associated_value(tcx, &item); debug!("check_config: searching for cfg {:?}", value); - return config.contains(&(value, None)); + cfg = Some(config.contains(&(value, None))); + } + if item.check_name(LABEL) { + label = true; + } + if item.check_name(EXCEPT) { + except = true; } } - tcx.sess.span_fatal( - attr.span, - "no cfg attribute"); + if label && except { + tcx.sess.span_fatal( + attr.span, + "must specify only one of: `label`, `except`" + ); + } + + match cfg { + None => tcx.sess.span_fatal( + attr.span, + "no cfg attribute" + ), + Some(c) => c, + } } fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name { diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index 647ff5dedf3..6e1014b573a 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -36,10 +36,8 @@ pub fn change_callee_function() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_callee_function() { @@ -55,10 +53,8 @@ pub fn change_argument_function() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_argument_function() { @@ -100,10 +96,8 @@ pub fn change_callee_method() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_callee_method() { @@ -121,10 +115,8 @@ pub fn change_argument_method() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_argument_method() { @@ -142,10 +134,8 @@ pub fn change_ufcs_callee_method() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_ufcs_callee_method() { @@ -163,10 +153,8 @@ pub fn change_argument_method_ufcs() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_argument_method_ufcs() { @@ -183,11 +171,11 @@ pub fn change_to_ufcs() { s.method1('x', true); } +// FIXME(vitiral): why would this change anything, doesn't the Mir/Hir expand this +// sort of stuff? #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_to_ufcs() { @@ -208,10 +196,8 @@ mod change_ufcs_callee_indirectly { #[cfg(not(cfail1))] use super::Struct2 as Struct; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_ufcs_callee_indirectly() { diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index 28e85c94b66..35641e978b7 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -30,8 +30,8 @@ const CONST_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub const CONST_VISIBILITY: u8 = 0; @@ -42,8 +42,8 @@ pub const CONST_VISIBILITY: u8 = 0; const CONST_CHANGE_TYPE_1: i32 = 0; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_1: u32 = 0; @@ -54,8 +54,8 @@ const CONST_CHANGE_TYPE_1: u32 = 0; const CONST_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_2: Option = None; @@ -66,11 +66,8 @@ const CONST_CHANGE_TYPE_2: Option = None; const CONST_CHANGE_VALUE_1: i16 = 1; #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_1: i16 = 2; @@ -80,10 +77,8 @@ const CONST_CHANGE_VALUE_1: i16 = 2; const CONST_CHANGE_VALUE_2: i16 = 1 + 1; #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_2: i16 = 1 + 2; @@ -93,10 +88,8 @@ const CONST_CHANGE_VALUE_2: i16 = 1 + 2; const CONST_CHANGE_VALUE_3: i16 = 2 + 3; #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_3: i16 = 2 * 3; @@ -106,10 +99,8 @@ const CONST_CHANGE_VALUE_3: i16 = 2 * 3; const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 3; #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 4; @@ -126,14 +117,14 @@ mod const_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_2: Option = None; diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index 7f991b30fc4..ffb62f7f7a0 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -45,10 +45,8 @@ fn change_field_value_struct_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_field_value_struct_like() -> Enum { @@ -72,10 +70,8 @@ fn change_field_order_struct_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_field_order_struct_like() -> Enum { @@ -113,10 +109,8 @@ fn change_constructor_path_struct_like() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_constructor_path_struct_like() { @@ -140,10 +134,8 @@ fn change_constructor_variant_struct_like() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_constructor_variant_struct_like() { @@ -162,10 +154,11 @@ mod change_constructor_path_indirectly_struct_like { #[cfg(not(cfail1))] use super::Enum2 as TheEnum; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,TypeckTables" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn function() -> TheEnum { @@ -186,10 +179,8 @@ mod change_constructor_variant_indirectly_struct_like { #[cfg(not(cfail1))] use super::Enum2::Struct2 as Variant; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn function() -> Enum2 { @@ -209,10 +200,8 @@ fn change_field_value_tuple_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_field_value_tuple_like() -> Enum { @@ -228,10 +217,8 @@ fn change_constructor_path_tuple_like() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_constructor_path_tuple_like() { @@ -247,10 +234,8 @@ fn change_constructor_variant_tuple_like() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_constructor_variant_tuple_like() { @@ -265,10 +250,11 @@ mod change_constructor_path_indirectly_tuple_like { #[cfg(not(cfail1))] use super::Enum2 as TheEnum; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,TypeckTables" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn function() -> TheEnum { @@ -286,10 +272,8 @@ mod change_constructor_variant_indirectly_tuple_like { #[cfg(not(cfail1))] use super::Enum2::Tuple2 as Variant; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn function() -> Enum2 { @@ -317,11 +301,8 @@ fn change_constructor_path_c_like() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] -#[rustc_metadata_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] fn change_constructor_path_c_like() { let _ = Clike2::B; @@ -336,10 +317,8 @@ fn change_constructor_variant_c_like() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_constructor_variant_c_like() { @@ -354,10 +333,11 @@ mod change_constructor_path_indirectly_c_like { #[cfg(not(cfail1))] use super::Clike2 as TheEnum; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,TypeckTables" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn function() -> TheEnum { @@ -375,10 +355,8 @@ mod change_constructor_variant_indirectly_c_like { #[cfg(not(cfail1))] use super::Clike::B as Variant; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn function() -> Clike { diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 8f84266d5a4..3aaa1f307c7 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -37,8 +37,8 @@ enum EnumVisibility { A } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub enum EnumVisibility { @@ -57,8 +57,8 @@ enum EnumChangeNameCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeNameCStyleVariant { @@ -79,8 +79,8 @@ enum EnumChangeNameTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeNameTupleStyleVariant { @@ -98,8 +98,8 @@ enum EnumChangeNameStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeNameStructStyleVariant { @@ -117,10 +117,8 @@ enum EnumChangeValueCStyleVariant0 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant0 { @@ -141,10 +139,8 @@ enum EnumChangeValueCStyleVariant1 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant1 { @@ -161,8 +157,8 @@ enum EnumAddCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumAddCStyleVariant { @@ -180,8 +176,8 @@ enum EnumRemoveCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumRemoveCStyleVariant { @@ -197,8 +193,8 @@ enum EnumAddTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumAddTupleStyleVariant { @@ -216,8 +212,8 @@ enum EnumRemoveTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumRemoveTupleStyleVariant { @@ -233,8 +229,8 @@ enum EnumAddStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumAddStructStyleVariant { @@ -252,8 +248,8 @@ enum EnumRemoveStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumRemoveStructStyleVariant { @@ -269,8 +265,8 @@ enum EnumChangeFieldTypeTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeFieldTypeTupleStyleVariant { @@ -290,8 +286,8 @@ enum EnumChangeFieldTypeStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeFieldTypeStructStyleVariant { @@ -313,8 +309,8 @@ enum EnumChangeFieldNameStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeFieldNameStructStyleVariant { @@ -330,8 +326,8 @@ enum EnumChangeOrderTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeOrderTupleStyleVariant { @@ -353,8 +349,8 @@ enum EnumChangeFieldOrderStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeFieldOrderStructStyleVariant { @@ -370,8 +366,8 @@ enum EnumAddFieldTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumAddFieldTupleStyleVariant { @@ -387,8 +383,8 @@ enum EnumAddFieldStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumAddFieldStructStyleVariant { @@ -405,8 +401,8 @@ enum EnumAddMustUse { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[must_use] @@ -425,8 +421,8 @@ enum EnumAddReprC { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -444,8 +440,8 @@ enum EnumChangeNameOfTypeParameter { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -463,8 +459,8 @@ enum EnumAddTypeParameter { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -482,8 +478,8 @@ enum EnumChangeNameOfLifetimeParameter<'a> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2", except="PredicatesOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -501,8 +497,8 @@ enum EnumAddLifetimeParameter<'a> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2", except="PredicatesOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -521,8 +517,8 @@ enum EnumAddLifetimeParameterBound<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2", except="GenericsOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -539,8 +535,8 @@ enum EnumAddLifetimeBoundToParameter<'a, T> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -558,8 +554,8 @@ enum EnumAddTraitBound { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -577,8 +573,8 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2", except="GenericsOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -597,8 +593,8 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -616,8 +612,8 @@ enum EnumAddTraitBoundWhere { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[repr(C)] @@ -635,8 +631,8 @@ enum EnumSwapUsageTypeParameters { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumSwapUsageTypeParameters { @@ -666,8 +662,8 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { @@ -701,8 +697,8 @@ mod change_field_type_indirectly_tuple_style { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum TupleStyle { @@ -725,8 +721,8 @@ mod change_field_type_indirectly_struct_style { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum StructStyle { @@ -754,8 +750,8 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,PredicatesOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum Enum { @@ -772,8 +768,8 @@ mod change_trait_bound_indirectly_where { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,PredicatesOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum Enum where T: Trait { diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index 1d26e6c07d1..ec5e088088c 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -34,8 +34,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -51,8 +51,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -70,8 +70,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -89,8 +89,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -108,8 +108,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -127,8 +127,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -146,8 +146,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -165,8 +165,8 @@ extern "C" { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern "rust-call" { @@ -184,8 +184,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -203,8 +203,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -222,8 +222,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[link_args = "-foo -bar -baz"] @@ -241,8 +241,8 @@ extern { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[link(name = "bar")] @@ -260,8 +260,8 @@ mod indirectly_change_parameter_type { #[cfg(not(cfail1))] use super::c_i64 as c_int; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(cfg="cfail2")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { @@ -280,8 +280,8 @@ mod indirectly_change_return_type { #[cfg(not(cfail1))] use super::c_i64 as c_int; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(cfg="cfail2")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index daddc0c9f54..0460d046099 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -34,12 +34,12 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,AssociatedItemDefIds")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] pub fn method_name2() { } } @@ -53,15 +53,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn method_body() { @@ -80,15 +78,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[inline] @@ -105,13 +101,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="AssociatedItems,Hir,HirBody")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn method_privacy() { } @@ -124,13 +120,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(cfg="cfail2", except="TypeOfItem,PredicatesOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn method_selfness(&self) { } @@ -143,13 +139,16 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirValidated" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn method_selfmutness(&mut self) { } @@ -164,18 +163,18 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,AssociatedItemDefIds")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_method_to_impl1(&self) { } - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_method_to_impl2(&self) { } } @@ -189,13 +188,16 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirValidated" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_method_parameter(&self, _: i32) { } @@ -210,15 +212,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_method_parameter_name(&self, b: i64) { } @@ -233,13 +233,15 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="Hir,HirBody,FnSignature,MirOptimized,MirValidated,TypeckTables")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_method_return_type(&self) -> u8 { 0 } @@ -254,13 +256,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[inline] @@ -276,15 +278,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_method_parameter_order(&self, b: i64, a: i64) { } @@ -299,13 +299,16 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirValidated" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub unsafe fn make_method_unsafe(&self) { } @@ -320,13 +323,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,FnSignature,TypeckTables")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub extern fn make_method_extern(&self) { } @@ -341,13 +344,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,FnSignature,TypeckTables")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub extern "system" fn change_method_calling_convention(&self) { } @@ -362,13 +365,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } @@ -383,13 +386,16 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,TypeOfItem", + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_type_parameter_to_method(&self) { } @@ -404,13 +410,16 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,TypeOfItem,TypeckTables" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -425,13 +434,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,TypeOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } @@ -446,13 +455,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,PredicatesOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_trait_bound_to_type_param_of_method(&self) { } @@ -467,13 +476,13 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[no_mangle] @@ -491,13 +500,16 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,GenericsOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Bar { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="GenericsOfItem,FnSignature,TypeckTables,TypeOfItem,MirOptimized,MirValidated" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_type_parameter_to_impl(&self) { } @@ -512,13 +524,13 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Bar { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="FnSignature,MirOptimized,MirValidated,TypeckTables")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_impl_self_type(&self) { } @@ -533,13 +545,13 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Bar { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_impl_parameter(&self) { } @@ -554,13 +566,13 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Bar { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_trait_bound_to_impl_parameter(&self) { } diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index 7c6da3ba9fe..4ff80ead89d 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -32,8 +32,8 @@ static STATIC_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub static STATIC_VISIBILITY: u8 = 0; @@ -44,8 +44,8 @@ pub static STATIC_VISIBILITY: u8 = 0; static STATIC_MUTABILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static mut STATIC_MUTABILITY: u8 = 0; @@ -56,8 +56,8 @@ static mut STATIC_MUTABILITY: u8 = 0; static STATIC_LINKAGE: u8 = 0; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[linkage="weak_odr"] @@ -69,8 +69,8 @@ static STATIC_LINKAGE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[no_mangle] @@ -82,8 +82,8 @@ static STATIC_NO_MANGLE: u8 = 0; static STATIC_THREAD_LOCAL: u8 = 0; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] #[thread_local] @@ -95,8 +95,8 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_CHANGE_TYPE_1: i16 = 0; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_1: u64 = 0; @@ -107,8 +107,8 @@ static STATIC_CHANGE_TYPE_1: u64 = 0; static STATIC_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_2: Option = None; @@ -119,10 +119,8 @@ static STATIC_CHANGE_TYPE_2: Option = None; static STATIC_CHANGE_VALUE_1: i16 = 1; #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_1: i16 = 2; @@ -133,10 +131,8 @@ static STATIC_CHANGE_VALUE_1: i16 = 2; static STATIC_CHANGE_VALUE_2: i16 = 1 + 1; #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_2: i16 = 1 + 2; @@ -146,10 +142,8 @@ static STATIC_CHANGE_VALUE_2: i16 = 1 + 2; static STATIC_CHANGE_VALUE_3: i16 = 2 + 3; #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_3: i16 = 2 * 3; @@ -159,10 +153,8 @@ static STATIC_CHANGE_VALUE_3: i16 = 2 * 3; static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 3; #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 4; @@ -179,14 +171,14 @@ mod static_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index 0e23d953baf..231e29b79c4 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -42,10 +42,8 @@ fn change_field_value_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_field_value_regular_struct() -> RegularStruct { @@ -69,10 +67,8 @@ fn change_field_order_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_field_order_regular_struct() -> RegularStruct { @@ -101,10 +97,8 @@ fn add_field_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn add_field_regular_struct() -> RegularStruct { @@ -140,10 +134,8 @@ fn change_field_label_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_field_label_regular_struct() -> RegularStruct { @@ -179,10 +171,8 @@ fn change_constructor_path_regular_struct() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_constructor_path_regular_struct() { @@ -202,10 +192,11 @@ mod change_constructor_path_indirectly_regular_struct { #[cfg(not(cfail1))] use super::RegularStruct2 as Struct; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,TypeckTables" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn function() -> Struct { @@ -228,10 +219,8 @@ fn change_field_value_tuple_struct() -> TupleStruct { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_field_value_tuple_struct() -> TupleStruct { @@ -249,10 +238,8 @@ fn change_constructor_path_tuple_struct() { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn change_constructor_path_tuple_struct() { @@ -268,10 +255,11 @@ mod change_constructor_path_indirectly_tuple_struct { #[cfg(not(cfail1))] use super::TupleStruct2 as Struct; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean( + cfg="cfail2", + except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,TypeckTables" + )] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn function() -> Struct { diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs index 35fb583cd4e..33bef5d05b7 100644 --- a/src/test/incremental/hashes/type_defs.rs +++ b/src/test/incremental/hashes/type_defs.rs @@ -35,8 +35,8 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -47,8 +47,8 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -59,8 +59,8 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -74,8 +74,8 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -86,8 +86,8 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -107,8 +107,8 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -119,8 +119,8 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -131,8 +131,8 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -143,8 +143,8 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -155,8 +155,8 @@ type AddTypeParam = (T1, T2); type AddTypeParamBound = (T1, u32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddTypeParamBound = (T1, u32); @@ -167,8 +167,8 @@ type AddTypeParamBound = (T1, u32); type AddTypeParamBoundWhereClause where T1: Clone = (T1, u32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); @@ -179,8 +179,8 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); @@ -191,8 +191,8 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32); @@ -205,8 +205,8 @@ where 'b: 'a = (&'a u32, &'b u32, &'c u32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddLifetimeParamBoundWhereClause<'a, 'b, 'c> where 'b: 'a, @@ -225,8 +225,8 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly = (T, u32); @@ -241,8 +241,8 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly where T : Trait = (T, u32); From 11775ab80dbbd39024d33cfa025e0bf2110f2ecc Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 13 Oct 2017 02:29:10 -0400 Subject: [PATCH 195/365] Clarify how needs_drop is conservative --- src/libcore/mem.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 680a0f5b2c0..16d5fadc536 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -429,9 +429,11 @@ pub fn align_of_val(val: &T) -> usize { /// Returns whether dropping values of type `T` matters. /// -/// This is purely an optimization hint, and may be implemented conservatively. -/// For instance, always returning `true` would be a valid implementation of -/// this function. +/// This is purely an optimization hint, and may be implemented conservatively: +/// it may return `true` for types that don't actually need to be dropped. +/// As such always returning `true` would be a valid implementation of +/// this function. However if this function actually returns `false`, then you +/// can be certain dropping `T` has no side effect. /// /// Low level implementations of things like collections, which need to manually /// drop their data, should use this function to avoid unnecessarily From 8f4ff6307f0a4c8be9b9c0ec57b57a354cbba005 Mon Sep 17 00:00:00 2001 From: bgermann Date: Fri, 13 Oct 2017 11:36:44 +0200 Subject: [PATCH 196/365] Make Solaris builder compatible with Solaris 10 --- src/ci/docker/cross2/Dockerfile | 12 +++++----- .../docker/cross2/build-solaris-toolchain.sh | 22 +++++++++++-------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/ci/docker/cross2/Dockerfile b/src/ci/docker/cross2/Dockerfile index f5fc06767ce..029d2c18d4a 100644 --- a/src/ci/docker/cross2/Dockerfile +++ b/src/ci/docker/cross2/Dockerfile @@ -36,12 +36,12 @@ ENV \ AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \ CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \ CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ \ - AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-ar \ - CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-gcc \ - CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-g++ \ - AR_x86_64_sun_solaris=x86_64-sun-solaris2.11-ar \ - CC_x86_64_sun_solaris=x86_64-sun-solaris2.11-gcc \ - CXX_x86_64_sun_solaris=x86_64-sun-solaris2.11-g++ + AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-ar \ + CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-gcc \ + CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-g++ \ + AR_x86_64_sun_solaris=x86_64-sun-solaris2.10-ar \ + CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \ + CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++ ENV TARGETS=x86_64-unknown-fuchsia ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia diff --git a/src/ci/docker/cross2/build-solaris-toolchain.sh b/src/ci/docker/cross2/build-solaris-toolchain.sh index ae84cc62b60..935cbe5d61b 100755 --- a/src/ci/docker/cross2/build-solaris-toolchain.sh +++ b/src/ci/docker/cross2/build-solaris-toolchain.sh @@ -25,7 +25,7 @@ cd binutils curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.xz | tar xJf - mkdir binutils-build cd binutils-build -hide_output ../binutils-$BINUTILS/configure --target=$ARCH-sun-solaris2.11 +hide_output ../binutils-$BINUTILS/configure --target=$ARCH-sun-solaris2.10 hide_output make -j10 hide_output make install @@ -58,13 +58,17 @@ for deb in *$APT_ARCH.deb; do dpkg -x $deb . done -mkdir /usr/local/$ARCH-sun-solaris2.11/usr -mv usr/include /usr/local/$ARCH-sun-solaris2.11/usr/include -mv usr/lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.11/lib -mv lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.11/lib +# Strip Solaris 11 functions that are optionally used by libbacktrace. +# This is for Solaris 10 compatibility. +$ARCH-sun-solaris2.10-strip -N dl_iterate_phdr -N strnlen lib/$LIB_ARCH/libc.so -ln -s /usr/local/$ARCH-sun-solaris2.11/usr/include /usr/local/$ARCH-sun-solaris2.11/sys-include -ln -s /usr/local/$ARCH-sun-solaris2.11/usr/include /usr/local/$ARCH-sun-solaris2.11/include +mkdir /usr/local/$ARCH-sun-solaris2.10/usr +mv usr/include /usr/local/$ARCH-sun-solaris2.10/usr/include +mv usr/lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.10/lib +mv lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.10/lib + +ln -s /usr/local/$ARCH-sun-solaris2.10/usr/include /usr/local/$ARCH-sun-solaris2.10/sys-include +ln -s /usr/local/$ARCH-sun-solaris2.10/usr/include /usr/local/$ARCH-sun-solaris2.10/include cd .. rm -rf solaris @@ -80,7 +84,7 @@ mkdir ../gcc-build cd ../gcc-build hide_output ../gcc-$GCC/configure \ --enable-languages=c,c++ \ - --target=$ARCH-sun-solaris2.11 \ + --target=$ARCH-sun-solaris2.10 \ --with-gnu-as \ --with-gnu-ld \ --disable-multilib \ @@ -94,7 +98,7 @@ hide_output ../gcc-$GCC/configure \ --disable-libsanitizer \ --disable-libquadmath-support \ --disable-lto \ - --with-sysroot=/usr/local/$ARCH-sun-solaris2.11 + --with-sysroot=/usr/local/$ARCH-sun-solaris2.10 hide_output make -j10 hide_output make install From 45502d23fb7849bc4afc2dc6a2ebf15b7ef13ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ho=C3=A0ng=20=C4=90=E1=BB=A9c=20Hi=E1=BA=BFu?= Date: Fri, 13 Oct 2017 14:12:49 +0700 Subject: [PATCH 197/365] compiletest/runtest: format ErrorKind with Display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The strings are nouns for the most part, so we give ErrorKind::Help a more sensible string. This reduces quote hiccups in failure output. unexpected "error": '...' ↓ unexpected error: '...' --- src/tools/compiletest/src/errors.rs | 2 +- src/tools/compiletest/src/runtest.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index b7fb3670165..251dd4d5edb 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -45,7 +45,7 @@ impl FromStr for ErrorKind { impl fmt::Display for ErrorKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - ErrorKind::Help => write!(f, "help"), + ErrorKind::Help => write!(f, "help message"), ErrorKind::Error => write!(f, "error"), ErrorKind::Note => write!(f, "note"), ErrorKind::Suggestion => write!(f, "suggestion"), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 870e08cc6e5..8ff571bc8b8 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1040,7 +1040,7 @@ actual:\n\ None => { if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) { self.error( - &format!("{}:{}: unexpected {:?}: '{}'", + &format!("{}:{}: unexpected {}: '{}'", file_name, actual_error.line_num, actual_error.kind.as_ref() From cc2a1c7bd8e3271919dad8719e53c9d3ff007e2a Mon Sep 17 00:00:00 2001 From: Paul Faria Date: Mon, 9 Oct 2017 22:16:57 -0400 Subject: [PATCH 198/365] Initial attempt at implementation of inference layout for nll --- src/librustc_mir/transform/nll/infer.rs | 206 ++++++++++++++++++++++++ src/librustc_mir/transform/nll/mod.rs | 23 ++- 2 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 src/librustc_mir/transform/nll/infer.rs diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs new file mode 100644 index 00000000000..e5d8b2e1379 --- /dev/null +++ b/src/librustc_mir/transform/nll/infer.rs @@ -0,0 +1,206 @@ +use super::{Region, RegionIndex}; +use std::mem; +use rustc::infer::InferCtxt; +use rustc::mir::{Location, Mir}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::fx::FxHashSet; + +pub struct InferenceContext { + definitions: IndexVec, + constraints: IndexVec, + errors: IndexVec, +} + +pub struct InferenceError { + pub constraint_point: Location, + pub name: (), // TODO(nashenas88) RegionName +} + +newtype_index!(InferenceErrorIndex); + +struct VarDefinition { + name: (), // TODO(nashenas88) RegionName + value: Region, + capped: bool, +} + +impl VarDefinition { + pub fn new(value: Region) -> Self { + Self { + name: (), + value, + capped: false, + } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct Constraint { + sub: RegionIndex, + sup: RegionIndex, + point: Location, +} + +newtype_index!(ConstraintIndex); + +impl InferenceContext { + pub fn new(values: IndexVec) -> Self { + Self { + definitions: values.into_iter().map(VarDefinition::new).collect(), + constraints: IndexVec::new(), + errors: IndexVec::new(), + } + } + + pub fn cap_var(&mut self, v: RegionIndex) { + self.definitions[v].capped = true; + } + + pub fn add_live_point(&mut self, v: RegionIndex, point: Location) { + debug!("add_live_point({:?}, {:?})", v, point); + let definition = &mut self.definitions[v]; + if definition.value.add_point(point) { + if definition.capped { + self.errors.push(InferenceError { + constraint_point: point, + name: definition.name, + }); + } + } + } + + pub fn add_outlives(&mut self, sup: RegionIndex, sub: RegionIndex, point: Location) { + debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point); + self.constraints.push(Constraint { sup, sub, point }); + } + + pub fn region(&self, v: RegionIndex) -> &Region { + &self.definitions[v].value + } + + pub fn solve<'a, 'gcx, 'tcx>( + &mut self, + infcx: InferCtxt<'a, 'gcx, 'tcx>, + mir: &'a Mir<'tcx>, + ) -> IndexVec + where + 'gcx: 'tcx + 'a, + 'tcx: 'a, + { + let mut changed = true; + let mut dfs = Dfs::new(infcx, mir); + while changed { + changed = false; + for constraint in &self.constraints { + let sub = &self.definitions[constraint.sub].value.clone(); + let sup_def = &self.definitions[constraint.sup]; + debug!("constraint: {:?}", constraint); + debug!(" sub (before): {:?}", sub); + debug!(" sup (before): {:?}", sup_def.value); + + if dfs.copy(sub, &mut sup_def.value, constraint.point) { + changed = true; + if sup_def.capped { + // This is kind of a hack, but when we add a + // constraint, the "point" is always the point + // AFTER the action that induced the + // constraint. So report the error on the + // action BEFORE that. + assert!(constraint.point.statement_index > 0); + let p = Location { + block: constraint.point.block, + statement_index: constraint.point.statement_index - 1, + }; + + self.errors.push(InferenceError { + constraint_point: p, + name: sup_def.name, + }); + } + } + + debug!(" sup (after) : {:?}", sup_def.value); + debug!(" changed : {:?}", changed); + } + debug!("\n"); + } + + mem::replace(&mut self.errors, IndexVec::new()) + } +} + +struct Dfs<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { + infcx: InferCtxt<'a, 'gcx, 'tcx>, + mir: &'a Mir<'tcx>, +} + +impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> { + fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { + Self { infcx, mir } + } + + fn copy( + &mut self, + from_region: &Region, + to_region: &mut Region, + start_point: Location, + ) -> bool { + let mut changed = false; + + let mut stack = vec![]; + let mut visited = FxHashSet(); + + stack.push(start_point); + while let Some(p) = stack.pop() { + debug!(" dfs: p={:?}", p); + + if !from_region.may_contain(p) { + debug!(" not in from-region"); + continue; + } + + if !visited.insert(p) { + debug!(" already visited"); + continue; + } + + changed |= to_region.add_point(p); + + let block_data = self.mir[p.block]; + let successor_points = if p.statement_index < block_data.statements.len() { + vec![Location { + statement_index: p.statement_index + 1, + ..p + }] + } else { + block_data.terminator() + .successors() + .iter() + .map(|&basic_block| Location { + statement_index: 0, + block: basic_block, + }) + .collect::>() + }; + + if successor_points.is_empty() { + // If we reach the END point in the graph, then copy + // over any skolemized end points in the `from_region` + // and make sure they are included in the `to_region`. + for region_decl in self.infcx.tcx.tables.borrow().free_region_map() { + // TODO(nashenas88) figure out skolemized_end points + let block = self.env.graph.skolemized_end(region_decl.name); + let skolemized_end_point = Location { + block, + statement_index: 0, + }; + changed |= to_region.add_point(skolemized_end_point); + } + } else { + stack.extend(successor_points); + } + } + + changed + } +} diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index 4925b1fcfed..ab3e16e4ebb 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use self::infer::InferenceContext; use rustc::ty::TypeFoldable; use rustc::ty::subst::{Kind, Substs}; use rustc::ty::{Ty, TyCtxt, ClosureSubsts, RegionVid, RegionKind}; use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind}; use rustc::mir::visit::{MutVisitor, Lookup}; use rustc::mir::transform::{MirPass, MirSource}; -use rustc::infer::{self, InferCtxt}; +use rustc::infer::{self as rustc_infer, InferCtxt}; use rustc::util::nodemap::FxHashSet; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use syntax_pos::DUMMY_SP; @@ -24,6 +25,8 @@ use std::fmt; use util as mir_util; use self::mir_util::PassWhere; +mod infer; + #[allow(dead_code)] struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { lookup_map: HashMap, @@ -40,14 +43,14 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> { } } - pub fn into_results(self) -> HashMap { - self.lookup_map + pub fn into_results(self) -> (HashMap, IndexVec) { + (self.lookup_map, self.regions) } fn renumber_regions(&mut self, value: &T) -> T where T: TypeFoldable<'tcx> { self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| { self.regions.push(Region::default()); - self.infcx.next_region_var(infer::MiscVariable(DUMMY_SP)) + self.infcx.next_region_var(rustc_infer::MiscVariable(DUMMY_SP)) }) } @@ -157,7 +160,9 @@ impl MirPass for NLL { } Ok(()) }); - let _results = visitor.into_results(); + let (_lookup_map, regions) = visitor.into_results(); + let inference_context = InferenceContext::new(regions); + inference_context.solve(infcx, &renumbered_mir); }) } } @@ -173,6 +178,14 @@ impl fmt::Debug for Region { } } +impl Region { + pub fn add_point(&mut self, point: Location) -> bool { + self.points.insert(point) + } + pub fn may_contain(&self, point: Location) -> bool { + self.points.contains(&point) + } +} newtype_index!(RegionIndex); From 3372b899d894a4f5c05f6deaa25889b384a4a12f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 10 Oct 2017 14:25:04 -0300 Subject: [PATCH 199/365] Mark free regions handling as TODO --- src/librustc_mir/transform/nll/infer.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs index e5d8b2e1379..3ffe6b9f4fc 100644 --- a/src/librustc_mir/transform/nll/infer.rs +++ b/src/librustc_mir/transform/nll/infer.rs @@ -184,18 +184,19 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> { }; if successor_points.is_empty() { + // TODO handle free regions // If we reach the END point in the graph, then copy // over any skolemized end points in the `from_region` // and make sure they are included in the `to_region`. - for region_decl in self.infcx.tcx.tables.borrow().free_region_map() { - // TODO(nashenas88) figure out skolemized_end points - let block = self.env.graph.skolemized_end(region_decl.name); - let skolemized_end_point = Location { - block, - statement_index: 0, - }; - changed |= to_region.add_point(skolemized_end_point); - } + // for region_decl in self.infcx.tcx.tables.borrow().free_region_map() { + // // TODO(nashenas88) figure out skolemized_end points + // let block = self.env.graph.skolemized_end(region_decl.name); + // let skolemized_end_point = Location { + // block, + // statement_index: 0, + // }; + // changed |= to_region.add_point(skolemized_end_point); + // } } else { stack.extend(successor_points); } From 25aa6eaf300ae7089881fead11e74688872b903a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 10 Oct 2017 14:25:39 -0300 Subject: [PATCH 200/365] Mark Region as public --- src/librustc_mir/transform/nll/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index ab3e16e4ebb..34a7568d210 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -168,7 +168,7 @@ impl MirPass for NLL { } #[derive(Clone, Default, PartialEq, Eq)] -struct Region { +pub struct Region { points: FxHashSet, } From 2720f635a34eea0c614aa16ac67b3af2007f44de Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 10 Oct 2017 19:18:19 -0300 Subject: [PATCH 201/365] inteference_context should be mut --- src/librustc_mir/transform/nll/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index 34a7568d210..986b308f484 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -161,7 +161,7 @@ impl MirPass for NLL { Ok(()) }); let (_lookup_map, regions) = visitor.into_results(); - let inference_context = InferenceContext::new(regions); + let mut inference_context = InferenceContext::new(regions); inference_context.solve(infcx, &renumbered_mir); }) } From c0e6a15130228ffaa4e4a61f848a3e43acfdeba9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 10 Oct 2017 19:23:16 -0300 Subject: [PATCH 202/365] sup_def is a mutable reference --- src/librustc_mir/transform/nll/infer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs index 3ffe6b9f4fc..8e08fc91735 100644 --- a/src/librustc_mir/transform/nll/infer.rs +++ b/src/librustc_mir/transform/nll/infer.rs @@ -93,7 +93,7 @@ impl InferenceContext { changed = false; for constraint in &self.constraints { let sub = &self.definitions[constraint.sub].value.clone(); - let sup_def = &self.definitions[constraint.sup]; + let sup_def = &mut self.definitions[constraint.sup]; debug!("constraint: {:?}", constraint); debug!(" sub (before): {:?}", sub); debug!(" sup (before): {:?}", sup_def.value); From 6c52275c2d191c501b4354fed712e35955ca3c5f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 10 Oct 2017 19:23:30 -0300 Subject: [PATCH 203/365] borrow block_data instead of moving it --- src/librustc_mir/transform/nll/infer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs index 8e08fc91735..92942c38f4a 100644 --- a/src/librustc_mir/transform/nll/infer.rs +++ b/src/librustc_mir/transform/nll/infer.rs @@ -166,7 +166,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> { changed |= to_region.add_point(p); - let block_data = self.mir[p.block]; + let block_data = &self.mir[p.block]; let successor_points = if p.statement_index < block_data.statements.len() { vec![Location { statement_index: p.statement_index + 1, From 50ac63b9b179dca946c5fcbd50541359ccfc68c9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 10 Oct 2017 19:37:34 -0300 Subject: [PATCH 204/365] Do not move infcx, just borrow it --- src/librustc_mir/transform/nll/infer.rs | 6 +++--- src/librustc_mir/transform/nll/mod.rs | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs index 92942c38f4a..61e320d9702 100644 --- a/src/librustc_mir/transform/nll/infer.rs +++ b/src/librustc_mir/transform/nll/infer.rs @@ -80,7 +80,7 @@ impl InferenceContext { pub fn solve<'a, 'gcx, 'tcx>( &mut self, - infcx: InferCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, ) -> IndexVec where @@ -130,12 +130,12 @@ impl InferenceContext { } struct Dfs<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { - infcx: InferCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, } impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> { - fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { + fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { Self { infcx, mir } } diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs index 986b308f484..805e9c976e4 100644 --- a/src/librustc_mir/transform/nll/mod.rs +++ b/src/librustc_mir/transform/nll/mod.rs @@ -31,11 +31,12 @@ mod infer; struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { lookup_map: HashMap, regions: IndexVec, - infcx: InferCtxt<'a, 'gcx, 'tcx>, + #[allow(dead_code)] + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, } impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> { - pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self { + pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { NLLVisitor { infcx, lookup_map: HashMap::new(), @@ -150,7 +151,7 @@ impl MirPass for NLL { tcx.infer_ctxt().enter(|infcx| { // Clone mir so we can mutate it without disturbing the rest of the compiler let mut renumbered_mir = mir.clone(); - let mut visitor = NLLVisitor::new(infcx); + let mut visitor = NLLVisitor::new(&infcx); visitor.visit_mir(&mut renumbered_mir); mir_util::dump_mir(tcx, None, "nll", &0, source, mir, |pass_where, out| { if let PassWhere::BeforeCFG = pass_where { @@ -162,7 +163,7 @@ impl MirPass for NLL { }); let (_lookup_map, regions) = visitor.into_results(); let mut inference_context = InferenceContext::new(regions); - inference_context.solve(infcx, &renumbered_mir); + inference_context.solve(&infcx, &renumbered_mir); }) } } From 88b02ef857317313cebd3833e0b6e847789f67c0 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 10 Oct 2017 19:41:29 -0300 Subject: [PATCH 205/365] Add allow_dead code directive to unused methods --- src/librustc_mir/transform/nll/infer.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs index 61e320d9702..f3f4228b421 100644 --- a/src/librustc_mir/transform/nll/infer.rs +++ b/src/librustc_mir/transform/nll/infer.rs @@ -52,10 +52,12 @@ impl InferenceContext { } } + #[allow(dead_code)] pub fn cap_var(&mut self, v: RegionIndex) { self.definitions[v].capped = true; } + #[allow(dead_code)] pub fn add_live_point(&mut self, v: RegionIndex, point: Location) { debug!("add_live_point({:?}, {:?})", v, point); let definition = &mut self.definitions[v]; @@ -69,11 +71,13 @@ impl InferenceContext { } } + #[allow(dead_code)] pub fn add_outlives(&mut self, sup: RegionIndex, sub: RegionIndex, point: Location) { debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point); self.constraints.push(Constraint { sup, sub, point }); } + #[allow(dead_code)] pub fn region(&self, v: RegionIndex) -> &Region { &self.definitions[v].value } @@ -130,6 +134,7 @@ impl InferenceContext { } struct Dfs<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { + #[allow(dead_code)] infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, } From e99702f5700d5b74b05d8ac4b6441f6bce18ff87 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 11 Oct 2017 18:40:35 -0300 Subject: [PATCH 206/365] TODO -> FIXME --- src/librustc_mir/transform/nll/infer.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs index f3f4228b421..2d613f9b4bd 100644 --- a/src/librustc_mir/transform/nll/infer.rs +++ b/src/librustc_mir/transform/nll/infer.rs @@ -13,13 +13,13 @@ pub struct InferenceContext { pub struct InferenceError { pub constraint_point: Location, - pub name: (), // TODO(nashenas88) RegionName + pub name: (), // FIXME(nashenas88) RegionName } newtype_index!(InferenceErrorIndex); struct VarDefinition { - name: (), // TODO(nashenas88) RegionName + name: (), // FIXME(nashenas88) RegionName value: Region, capped: bool, } @@ -189,12 +189,12 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> { }; if successor_points.is_empty() { - // TODO handle free regions + // FIXME handle free regions // If we reach the END point in the graph, then copy // over any skolemized end points in the `from_region` // and make sure they are included in the `to_region`. // for region_decl in self.infcx.tcx.tables.borrow().free_region_map() { - // // TODO(nashenas88) figure out skolemized_end points + // // FIXME(nashenas88) figure out skolemized_end points // let block = self.env.graph.skolemized_end(region_decl.name); // let skolemized_end_point = Location { // block, From 9603e240d4e90c73507bf09957199de6f25bbc71 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 11 Oct 2017 18:41:20 -0300 Subject: [PATCH 207/365] Add License to infer.rs --- src/librustc_mir/transform/nll/infer.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs index 2d613f9b4bd..e6e00f295ca 100644 --- a/src/librustc_mir/transform/nll/infer.rs +++ b/src/librustc_mir/transform/nll/infer.rs @@ -1,3 +1,13 @@ +// Copyright 2017 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. + use super::{Region, RegionIndex}; use std::mem; use rustc::infer::InferCtxt; From 4e116e14263ac27b4f0e4362638f281c06183813 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Sat, 7 Oct 2017 09:20:13 -0500 Subject: [PATCH 208/365] Convert return type of get_vtable_methods to Vec --- src/librustc/traits/mod.rs | 4 ++-- src/librustc_trans/collector.rs | 2 +- src/librustc_trans/meth.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index bdfbefd1364..b58ffd4c7b8 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -653,7 +653,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn get_vtable_methods<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) - -> impl Iterator)>> + 'a + -> Vec)>> { debug!("get_vtable_methods({:?})", trait_ref); @@ -696,7 +696,7 @@ pub fn get_vtable_methods<'a, 'tcx>( Some((def_id, substs)) }) - }) + }).collect() } impl<'tcx,O> Obligation<'tcx,O> { diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 9d1e36fa581..835283aa09b 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -850,7 +850,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Walk all methods of the trait, including those of its supertraits let methods = traits::get_vtable_methods(tcx, poly_trait_ref); - let methods = methods.filter_map(|method| method) + let methods = methods.into_iter().filter_map(|method| method) .map(|(def_id, substs)| ty::Instance::resolve( tcx, ty::ParamEnv::empty(traits::Reveal::All), diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 88407947f0e..72f580c2d38 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -87,7 +87,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, if let Some(trait_ref) = trait_ref { let trait_ref = trait_ref.with_self_ty(tcx, ty); - let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| { + let methods = traits::get_vtable_methods(tcx, trait_ref).into_iter().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { callee::resolve_and_get_fn(ccx, def_id, substs) }) From b640c2b95a13ead0285490323b55bfbe01da8e60 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Sat, 7 Oct 2017 16:55:09 -0500 Subject: [PATCH 209/365] get_vtable_methods => vtable_methods query --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/traits/mod.rs | 12 +++++++----- src/librustc/ty/maps/config.rs | 6 ++++++ src/librustc/ty/maps/keys.rs | 9 +++++++++ src/librustc/ty/maps/mod.rs | 6 ++++++ src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_trans/collector.rs | 2 +- src/librustc_trans/meth.rs | 3 +-- 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index b4426241634..4600cdbc692 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -506,6 +506,7 @@ define_dep_nodes!( <'tcx> [] SpecializationGraph(DefId), [] ObjectSafety(DefId), [] FulfillObligation { param_env: ParamEnv<'tcx>, trait_ref: PolyTraitRef<'tcx> }, + [] VtableMethods { trait_ref: PolyTraitRef<'tcx> }, [] IsCopy { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> }, [] IsSized { param_env: ParamEnvAnd<'tcx, Ty<'tcx>> }, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b58ffd4c7b8..8da0f8f13ff 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -650,12 +650,12 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// Given a trait `trait_ref`, iterates the vtable entries /// that come from `trait_ref`, including its supertraits. #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. -pub fn get_vtable_methods<'a, 'tcx>( +pub fn vtable_methods<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Vec)>> { - debug!("get_vtable_methods({:?})", trait_ref); + debug!("vtable_methods({:?})", trait_ref); supertraits(tcx, trait_ref).flat_map(move |trait_ref| { let trait_methods = tcx.associated_items(trait_ref.def_id()) @@ -664,12 +664,12 @@ pub fn get_vtable_methods<'a, 'tcx>( // Now list each method's DefId and Substs (for within its trait). // If the method can never be called from this object, produce None. trait_methods.map(move |trait_method| { - debug!("get_vtable_methods: trait_method={:?}", trait_method); + debug!("vtable_methods: trait_method={:?}", trait_method); let def_id = trait_method.def_id; // Some methods cannot be called on an object; skip those. if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { - debug!("get_vtable_methods: not vtable safe"); + debug!("vtable_methods: not vtable safe"); return None; } @@ -690,7 +690,7 @@ pub fn get_vtable_methods<'a, 'tcx>( // do not want to try and trans it, in that case (see #23435). let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); if !normalize_and_test_predicates(tcx, predicates.predicates) { - debug!("get_vtable_methods: predicates do not hold"); + debug!("vtable_methods: predicates do not hold"); return None; } @@ -836,6 +836,7 @@ pub fn provide(providers: &mut ty::maps::Providers) { specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, trans_fulfill_obligation: trans::trans_fulfill_obligation, + vtable_methods, ..*providers }; } @@ -846,6 +847,7 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) { specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, trans_fulfill_obligation: trans::trans_fulfill_obligation, + vtable_methods, ..*providers }; } diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index dee1516e0f8..137039598a5 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -503,6 +503,12 @@ impl<'tcx> QueryDescription for queries::has_clone_closures<'tcx> { } } +impl<'tcx> QueryDescription for queries::vtable_methods<'tcx> { + fn describe(tcx: TyCtxt, key: ty::PolyTraitRef<'tcx> ) -> String { + format!("finding all methods for trait {}", tcx.item_path_str(key.def_id())) + } +} + impl<'tcx> QueryDescription for queries::has_copy_closures<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { format!("seeing if the crate has enabled `Copy` closures") diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs index 1bd4f3e657e..ee4523d6f3e 100644 --- a/src/librustc/ty/maps/keys.rs +++ b/src/librustc/ty/maps/keys.rs @@ -143,6 +143,15 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { } } +impl<'tcx> Key for ty::PolyTraitRef<'tcx>{ + fn map_crate(&self) -> CrateNum { + self.def_id().krate + } + fn default_span(&self, tcx: TyCtxt) -> Span { + tcx.def_span(self.def_id()) + } +} + impl<'tcx> Key for Ty<'tcx> { fn map_crate(&self) -> CrateNum { LOCAL_CRATE diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 2001de88803..872069d381b 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -228,6 +228,8 @@ define_maps! { <'tcx> [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies, [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, [] fn is_mir_available: IsMirAvailable(DefId) -> bool, + [] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>) + -> Vec)>>, [] fn trans_fulfill_obligation: fulfill_obligation_dep_node( (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Vtable<'tcx, ()>, @@ -470,3 +472,7 @@ fn collect_and_partition_translation_items_node<'tcx>(_: CrateNum) -> DepConstru fn output_filenames_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::OutputFilenames } + +fn vtable_methods_node<'tcx>(trait_ref: ty::PolyTraitRef<'tcx>) -> DepConstructor<'tcx> { + DepConstructor::VtableMethods{ trait_ref } +} diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 61355381761..462149c2ed8 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -749,6 +749,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::CodegenUnit | DepKind::CompileCodegenUnit | DepKind::FulfillObligation | + DepKind::VtableMethods | // These are just odd DepKind::Null | diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 835283aa09b..08478700001 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -849,7 +849,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert!(!poly_trait_ref.has_escaping_regions()); // Walk all methods of the trait, including those of its supertraits - let methods = traits::get_vtable_methods(tcx, poly_trait_ref); + let methods = tcx.vtable_methods(poly_trait_ref); let methods = methods.into_iter().filter_map(|method| method) .map(|(def_id, substs)| ty::Instance::resolve( tcx, diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 72f580c2d38..66d633cf9a1 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -9,7 +9,6 @@ // except according to those terms. use llvm::ValueRef; -use rustc::traits; use callee; use common::*; use builder::Builder; @@ -87,7 +86,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, if let Some(trait_ref) = trait_ref { let trait_ref = trait_ref.with_self_ty(tcx, ty); - let methods = traits::get_vtable_methods(tcx, trait_ref).into_iter().map(|opt_mth| { + let methods = tcx.vtable_methods(trait_ref).into_iter().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { callee::resolve_and_get_fn(ccx, def_id, substs) }) From 81f9d4e78f3bc17bc803c793ecac43861ee5eed5 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Mon, 9 Oct 2017 10:39:53 -0500 Subject: [PATCH 210/365] Wrap vtable_methods return type in RC --- src/librustc/traits/mod.rs | 72 +++++++++++++++++---------------- src/librustc/ty/maps/mod.rs | 2 +- src/librustc_trans/collector.rs | 2 +- src/librustc_trans/meth.rs | 3 +- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8da0f8f13ff..53a974a4bbb 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -653,50 +653,52 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn vtable_methods<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) - -> Vec)>> + -> Rc)>>> { debug!("vtable_methods({:?})", trait_ref); - supertraits(tcx, trait_ref).flat_map(move |trait_ref| { - let trait_methods = tcx.associated_items(trait_ref.def_id()) - .filter(|item| item.kind == ty::AssociatedKind::Method); + Rc::new( + supertraits(tcx, trait_ref).flat_map(move |trait_ref| { + let trait_methods = tcx.associated_items(trait_ref.def_id()) + .filter(|item| item.kind == ty::AssociatedKind::Method); - // Now list each method's DefId and Substs (for within its trait). - // If the method can never be called from this object, produce None. - trait_methods.map(move |trait_method| { - debug!("vtable_methods: trait_method={:?}", trait_method); - let def_id = trait_method.def_id; + // Now list each method's DefId and Substs (for within its trait). + // If the method can never be called from this object, produce None. + trait_methods.map(move |trait_method| { + debug!("vtable_methods: trait_method={:?}", trait_method); + let def_id = trait_method.def_id; - // Some methods cannot be called on an object; skip those. - if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { - debug!("vtable_methods: not vtable safe"); - return None; - } + // Some methods cannot be called on an object; skip those. + if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { + debug!("vtable_methods: not vtable safe"); + return None; + } - // the method may have some early-bound lifetimes, add - // regions for those - let substs = Substs::for_item(tcx, def_id, - |_, _| tcx.types.re_erased, - |def, _| trait_ref.substs().type_for_def(def)); + // the method may have some early-bound lifetimes, add + // regions for those + let substs = Substs::for_item(tcx, def_id, + |_, _| tcx.types.re_erased, + |def, _| trait_ref.substs().type_for_def(def)); - // the trait type may have higher-ranked lifetimes in it; - // so erase them if they appear, so that we get the type - // at some particular call site - let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs)); + // the trait type may have higher-ranked lifetimes in it; + // so erase them if they appear, so that we get the type + // at some particular call site + let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs)); - // It's possible that the method relies on where clauses that - // do not hold for this particular set of type parameters. - // Note that this method could then never be called, so we - // do not want to try and trans it, in that case (see #23435). - let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); - if !normalize_and_test_predicates(tcx, predicates.predicates) { - debug!("vtable_methods: predicates do not hold"); - return None; - } + // It's possible that the method relies on where clauses that + // do not hold for this particular set of type parameters. + // Note that this method could then never be called, so we + // do not want to try and trans it, in that case (see #23435). + let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); + if !normalize_and_test_predicates(tcx, predicates.predicates) { + debug!("vtable_methods: predicates do not hold"); + return None; + } - Some((def_id, substs)) - }) - }).collect() + Some((def_id, substs)) + }) + }).collect() + ) } impl<'tcx,O> Obligation<'tcx,O> { diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 872069d381b..4b68f5addd2 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -229,7 +229,7 @@ define_maps! { <'tcx> [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, [] fn is_mir_available: IsMirAvailable(DefId) -> bool, [] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>) - -> Vec)>>, + -> Rc)>>>, [] fn trans_fulfill_obligation: fulfill_obligation_dep_node( (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Vtable<'tcx, ()>, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 08478700001..33a2e96ee66 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -850,7 +850,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Walk all methods of the trait, including those of its supertraits let methods = tcx.vtable_methods(poly_trait_ref); - let methods = methods.into_iter().filter_map(|method| method) + let methods = methods.iter().cloned().filter_map(|method| method) .map(|(def_id, substs)| ty::Instance::resolve( tcx, ty::ParamEnv::empty(traits::Reveal::All), diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 66d633cf9a1..3253a0339a8 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -86,7 +86,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, if let Some(trait_ref) = trait_ref { let trait_ref = trait_ref.with_self_ty(tcx, ty); - let methods = tcx.vtable_methods(trait_ref).into_iter().map(|opt_mth| { + let methods = tcx.vtable_methods(trait_ref); + let methods = methods.iter().cloned().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { callee::resolve_and_get_fn(ccx, def_id, substs) }) From 2160bab0dac479e72f49932c1c71cb3d01f4e9f6 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Mon, 9 Oct 2017 10:41:19 -0500 Subject: [PATCH 211/365] Remove export of vtable_methods --- src/librustc/traits/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 53a974a4bbb..1fddb186417 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -650,7 +650,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// Given a trait `trait_ref`, iterates the vtable entries /// that come from `trait_ref`, including its supertraits. #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. -pub fn vtable_methods<'a, 'tcx>( +fn vtable_methods<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Rc)>>> From fcb8bc9d4e08924d4e4bde1ef4995b329fbc11b5 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Thu, 12 Oct 2017 16:45:07 -0500 Subject: [PATCH 212/365] Remove recursion from `define_{provider|map}_struct` --- src/librustc/ty/maps/plumbing.rs | 103 ++----------------------------- 1 file changed, 4 insertions(+), 99 deletions(-) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 462149c2ed8..3f215303ccb 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -468,8 +468,7 @@ macro_rules! define_maps { define_provider_struct! { tcx: $tcx, - input: ($(([$($modifiers)*] [$name] [$K] [$V]))*), - output: () + input: ($(([$($modifiers)*] [$name] [$K] [$V]))*) } impl<$tcx> Copy for Providers<$tcx> {} @@ -480,78 +479,19 @@ macro_rules! define_maps { } macro_rules! define_map_struct { - // Initial state (tcx: $tcx:tt, - input: $input:tt) => { - define_map_struct! { - tcx: $tcx, - input: $input, - output: () - } - }; - - // Final output - (tcx: $tcx:tt, - input: (), - output: ($($output:tt)*)) => { + input: ($(([$(modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => { pub struct Maps<$tcx> { providers: IndexVec>, query_stack: RefCell)>>, - $($output)* - } - }; - - // Field recognized and ready to shift into the output - (tcx: $tcx:tt, - ready: ([$($pub:tt)*] [$($attr:tt)*] [$name:ident]), - input: $input:tt, - output: ($($output:tt)*)) => { - define_map_struct! { - tcx: $tcx, - input: $input, - output: ($($output)* - $(#[$attr])* $($pub)* $name: RefCell>>,) - } - }; - - // No modifiers left? This is a private item. - (tcx: $tcx:tt, - input: (([] $attrs:tt $name:tt) $($input:tt)*), - output: $output:tt) => { - define_map_struct! { - tcx: $tcx, - ready: ([] $attrs $name), - input: ($($input)*), - output: $output - } - }; - - // Skip other modifiers - (tcx: $tcx:tt, - input: (([$other_modifier:tt $($modifiers:tt)*] $($fields:tt)*) $($input:tt)*), - output: $output:tt) => { - define_map_struct! { - tcx: $tcx, - input: (([$($modifiers)*] $($fields)*) $($input)*), - output: $output + $($(#[$attr])* $name: RefCell>>,)* } }; } macro_rules! define_provider_struct { - // Initial state: - (tcx: $tcx:tt, input: $input:tt) => { - define_provider_struct! { - tcx: $tcx, - input: $input, - output: () - } - }; - - // Final state: (tcx: $tcx:tt, - input: (), - output: ($(([$name:ident] [$K:ty] [$R:ty]))*)) => { + input: ($(([$($modifiers:tt)*] [$name:ident] [$K:ty] [$R:ty]))*)) => { pub struct Providers<$tcx> { $(pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $R,)* } @@ -566,41 +506,6 @@ macro_rules! define_provider_struct { } } }; - - // Something ready to shift: - (tcx: $tcx:tt, - ready: ($name:tt $K:tt $V:tt), - input: $input:tt, - output: ($($output:tt)*)) => { - define_provider_struct! { - tcx: $tcx, - input: $input, - output: ($($output)* ($name $K $V)) - } - }; - - // Regular queries produce a `V` only. - (tcx: $tcx:tt, - input: (([] $name:tt $K:tt $V:tt) $($input:tt)*), - output: $output:tt) => { - define_provider_struct! { - tcx: $tcx, - ready: ($name $K $V), - input: ($($input)*), - output: $output - } - }; - - // Skip modifiers. - (tcx: $tcx:tt, - input: (([$other_modifier:tt $($modifiers:tt)*] $($fields:tt)*) $($input:tt)*), - output: $output:tt) => { - define_provider_struct! { - tcx: $tcx, - input: (([$($modifiers)*] $($fields)*) $($input)*), - output: $output - } - }; } From 80c13ce13403e4aba7a73b765bfd8c40997f196d Mon Sep 17 00:00:00 2001 From: Garrett Berg Date: Fri, 13 Oct 2017 10:04:59 -0600 Subject: [PATCH 213/365] fix review comments --- .../persist/dirty_clean.rs | 35 +++++++++---------- .../incremental/hashes/call_expressions.rs | 4 +-- .../incremental/hashes/enum_constructors.rs | 21 ++++++++--- src/test/incremental/hashes/enum_defs.rs | 18 +++------- src/test/incremental/hashes/inherent_impls.rs | 2 ++ src/test/incremental/hashes/type_defs.rs | 20 +++++------ 6 files changed, 51 insertions(+), 49 deletions(-) diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 5f97eaf21d2..0cb920a111d 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -39,8 +39,6 @@ //! previous revision to compare things to. //! -#![allow(dead_code)] - use std::collections::HashSet; use std::iter::FromIterator; use std::vec::Vec; @@ -141,14 +139,14 @@ const LABELS_CONST: &[&[&str]] = &[ ]; /// Constant/Typedef in an impl -const LABELS_CONST_ASSOCIATED: &[&[&str]] = &[ +const LABELS_CONST_IN_IMPL: &[&[&str]] = &[ BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED, ]; /// Trait-Const/Typedef DepNodes -const LABELS_CONST_TRAIT: &[&[&str]] = &[ +const LABELS_CONST_IN_TRAIT: &[&[&str]] = &[ BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED, @@ -163,7 +161,7 @@ const LABELS_FN: &[&[&str]] = &[ ]; /// Method DepNodes -const LABELS_FN_ASSOCIATED: &[&[&str]] = &[ +const LABELS_FN_IN_IMPL: &[&[&str]] = &[ BASE_HIR, BASE_MIR, BASE_FN, @@ -171,7 +169,7 @@ const LABELS_FN_ASSOCIATED: &[&[&str]] = &[ ]; /// Trait-Method DepNodes -const LABELS_FN_TRAIT: &[&[&str]] = &[ +const LABELS_FN_IN_TRAIT: &[&[&str]] = &[ BASE_HIR, BASE_MIR, BASE_FN, @@ -190,13 +188,14 @@ const LABELS_IMPL: &[&[&str]] = &[ BASE_IMPL, ]; -/// Struct DepNodes -const LABELS_STRUCT: &[&[&str]] = &[ +/// Abstract Data Type (Struct, Enum, Unions) DepNodes +const LABELS_ADT: &[&[&str]] = &[ BASE_HIR, BASE_STRUCT, ]; /// Trait Definition DepNodes +#[allow(dead_code)] const LABELS_TRAIT: &[&[&str]] = &[ BASE_HIR, BASE_TRAIT_DEF, @@ -382,16 +381,16 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { HirItem::ItemGlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY), // A type alias, e.g. `type Foo = Bar` - HirItem::ItemTy(..) => ("ItemTy", LABELS_CONST), + HirItem::ItemTy(..) => ("ItemTy", LABELS_HIR_ONLY), // An enum definition, e.g. `enum Foo {C, D}` - HirItem::ItemEnum(..) => ("ItemEnum", LABELS_STRUCT), + HirItem::ItemEnum(..) => ("ItemEnum", LABELS_ADT), // A struct definition, e.g. `struct Foo {x: A}` - HirItem::ItemStruct(..) => ("ItemStruct", LABELS_STRUCT), + HirItem::ItemStruct(..) => ("ItemStruct", LABELS_ADT), // A union definition, e.g. `union Foo {x: A, y: B}` - HirItem::ItemUnion(..) => ("ItemUnion", LABELS_STRUCT), + HirItem::ItemUnion(..) => ("ItemUnion", LABELS_ADT), // Represents a Trait Declaration // FIXME(michaelwoerister): trait declaration is buggy because sometimes some of @@ -426,16 +425,16 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { }, HirNode::NodeTraitItem(item) => { match item.node { - TraitItemKind::Method(..) => ("NodeTraitItem", LABELS_FN_TRAIT), - TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_TRAIT), - TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_TRAIT), + TraitItemKind::Method(..) => ("NodeTraitItem", LABELS_FN_IN_TRAIT), + TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_IN_TRAIT), + TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT), } }, HirNode::NodeImplItem(item) => { match item.node { - ImplItemKind::Method(..) => ("NodeImplItem", LABELS_FN_ASSOCIATED), - ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_ASSOCIATED), - ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_ASSOCIATED), + ImplItemKind::Method(..) => ("NodeImplItem", LABELS_FN_IN_IMPL), + ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), + ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), } }, _ => self.tcx.sess.span_fatal( diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index 6e1014b573a..0090c2aeef9 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -171,13 +171,13 @@ pub fn change_to_ufcs() { s.method1('x', true); } -// FIXME(vitiral): why would this change anything, doesn't the Mir/Hir expand this -// sort of stuff? #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +// One might think this would be expanded in the HirBody/Mir, but it actually +// results in slightly different Hir/Mir. pub fn change_to_ufcs() { let s = Struct; Struct::method1(&s, 'x', true); diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index ffb62f7f7a0..f826d47c3e5 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -74,6 +74,8 @@ fn change_field_order_struct_like() -> Enum { #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] +// FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it +// would if it were not all constants fn change_field_order_struct_like() -> Enum { Enum::Struct { y: 4, @@ -156,7 +158,8 @@ mod change_constructor_path_indirectly_struct_like { #[rustc_clean( cfg="cfail2", - except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,TypeckTables" + except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,\ + TypeckTables" )] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] @@ -217,7 +220,10 @@ fn change_constructor_path_tuple_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean( + cfg="cfail2", + except="HirBody,MirOptimized,MirValidated,TypeckTables" +)] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -234,7 +240,10 @@ fn change_constructor_variant_tuple_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")] +#[rustc_clean( + cfg="cfail2", + except="HirBody,MirOptimized,MirValidated,TypeckTables" +)] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -252,7 +261,8 @@ mod change_constructor_path_indirectly_tuple_like { #[rustc_clean( cfg="cfail2", - except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,TypeckTables" + except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,\ + TypeckTables" )] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] @@ -335,7 +345,8 @@ mod change_constructor_path_indirectly_c_like { #[rustc_clean( cfg="cfail2", - except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,TypeckTables" + except="FnSignature,Hir,HirBody,MirOptimized,MirValidated,\ + TypeckTables" )] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 3aaa1f307c7..22393fad3d0 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -444,7 +444,6 @@ enum EnumChangeNameOfTypeParameter { #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumChangeNameOfTypeParameter { Variant1(T), } @@ -463,7 +462,6 @@ enum EnumAddTypeParameter { #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumAddTypeParameter { Variant1(S), Variant2(T), @@ -482,7 +480,6 @@ enum EnumChangeNameOfLifetimeParameter<'a> { #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumChangeNameOfLifetimeParameter<'b> { Variant1(&'b u32), } @@ -501,7 +498,6 @@ enum EnumAddLifetimeParameter<'a> { #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumAddLifetimeParameter<'a, 'b> { Variant1(&'a u32), Variant2(&'b u32), @@ -517,11 +513,10 @@ enum EnumAddLifetimeParameterBound<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(cfg="cfail2", except="GenericsOfItem")] +#[rustc_dirty(cfg="cfail2", except="GenericsOfItem,TypeOfItem")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumAddLifetimeParameterBound<'a, 'b: 'a> { Variant1(&'a u32), Variant2(&'b u32), @@ -535,11 +530,10 @@ enum EnumAddLifetimeBoundToParameter<'a, T> { } #[cfg(not(cfail1))] -#[rustc_dirty(cfg="cfail2")] +#[rustc_dirty(cfg="cfail2", except="TypeOfItem")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumAddLifetimeBoundToParameter<'a, T: 'a> { Variant1(T), Variant2(&'a u32), @@ -558,7 +552,6 @@ enum EnumAddTraitBound { #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumAddTraitBound { Variant1(T), } @@ -573,11 +566,10 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(cfg="cfail2", except="GenericsOfItem")] +#[rustc_dirty(cfg="cfail2", except="GenericsOfItem,TypeOfItem")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a { Variant1(&'a u32), Variant2(&'b u32), @@ -593,11 +585,10 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> { } #[cfg(not(cfail1))] -#[rustc_dirty(cfg="cfail2")] +#[rustc_dirty(cfg="cfail2", except="TypeOfItem")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a { Variant1(T), Variant2(&'a u32), @@ -616,7 +607,6 @@ enum EnumAddTraitBoundWhere { #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -#[repr(C)] enum EnumAddTraitBoundWhere where T: Sync { Variant1(T), } diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 0460d046099..5067b571ee6 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -370,6 +370,8 @@ impl Foo { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { + // FIXME(michaelwoerister): This is curious but an unused lifetime parameter doesn't seem to + // show up in any of the derived data structures. #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs index 33bef5d05b7..b0a93eea523 100644 --- a/src/test/incremental/hashes/type_defs.rs +++ b/src/test/incremental/hashes/type_defs.rs @@ -35,7 +35,7 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -47,7 +47,7 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -59,7 +59,7 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -74,7 +74,7 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -86,7 +86,7 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -107,7 +107,7 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -119,7 +119,7 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -131,7 +131,7 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -143,7 +143,7 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -179,7 +179,7 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeOfItem")] +#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); From 8c4a68dca1428fab4bfb9c9f176ad66e2e1d85fc Mon Sep 17 00:00:00 2001 From: Pirh Date: Fri, 13 Oct 2017 18:18:09 +0100 Subject: [PATCH 214/365] Add line break after summary of process::Output --- src/libstd/process.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 847dbd14dd6..8287c43ba96 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -701,9 +701,11 @@ impl AsInnerMut for Command { fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner } } -/// The output of a finished process. This is returned in a Result by -/// either the [`output`] method of a [`Command`], or the -/// [`wait_with_output`] method of a [`Child`] process. +/// The output of a finished process. +/// +/// This is returned in a Result by either the [`output`] method of a +/// [`Command`], or the [`wait_with_output`] method of a [`Child`] +/// process. /// /// [`Command`]: struct.Command.html /// [`Child`]: struct.Child.html From 7439da61fcb3b484eeea9461b10d1ae70c3963ed Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Fri, 13 Oct 2017 23:51:38 +0600 Subject: [PATCH 215/365] fix typo in src/bootstrap/README.md --- 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 ebacc62b0fd..6eb074605fc 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -126,7 +126,7 @@ install a nightly, presumably using `rustup`. You will then want to configure your directory to use this build, like so: ``` -# configure to use local rust instead of downloding a beta. +# configure to use local rust instead of downloading a beta. # `--local-rust-root` is optional here. If elided, we will # use whatever rustc we find on your PATH. > configure --enable-rustbuild --local-rust-root=~/.cargo/ --enable-local-rebuild From 8e6119f353ab424657080776243d6f9af4f7dfe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Br=C3=A1ulio=20Bezerra?= Date: Fri, 13 Oct 2017 17:15:28 -0300 Subject: [PATCH 216/365] Fixed link to keywords page in the reference --- src/doc/unstable-book/src/language-features/non-ascii-idents.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/non-ascii-idents.md b/src/doc/unstable-book/src/language-features/non-ascii-idents.md index a1bb0ce7869..efb5495fe26 100644 --- a/src/doc/unstable-book/src/language-features/non-ascii-idents.md +++ b/src/doc/unstable-book/src/language-features/non-ascii-idents.md @@ -45,4 +45,4 @@ that does _not_ occur in the set of [strict keywords]. [`XID_start`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i= [`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i= -[strict keywords]: keywords.html#strict-keywords +[strict keywords]: ../reference/keywords.html#strict-keywords From 9e1c577b713600e6fcb46584414263993347f67e Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Sat, 23 Sep 2017 14:40:18 -0500 Subject: [PATCH 217/365] rustdoc: don't create directories more than once --- src/librustdoc/html/render.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a3f446885f9..ad671e37e69 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -125,6 +125,21 @@ pub struct SharedContext { /// Warnings for the user if rendering would differ using different markdown /// parsers. pub markdown_warnings: RefCell)>>, + /// The directories that have already been created in this doc run. Used to reduce the number + /// of spurious `create_dir_all` calls. + pub created_dirs: RefCell>, +} + +impl SharedContext { + fn ensure_dir(&self, dst: &Path) -> io::Result<()> { + let mut dirs = self.created_dirs.borrow_mut(); + if !dirs.contains(dst) { + fs::create_dir_all(dst)?; + dirs.insert(dst.to_path_buf()); + } + + Ok(()) + } } /// Indicates where an external crate can be found. @@ -460,6 +475,7 @@ pub fn run(mut krate: clean::Crate, }, css_file_extension: css_file_extension.clone(), markdown_warnings: RefCell::new(vec![]), + created_dirs: RefCell::new(FxHashSet()), }; // If user passed in `--playground-url` arg, we fill in crate name here @@ -790,7 +806,6 @@ fn write_shared(cx: &Context, // Write out the shared files. Note that these are shared among all rustdoc // docs placed in the output directory, so this needs to be a synchronized // operation with respect to all other rustdocs running around. - try_err!(fs::create_dir_all(&cx.dst), &cx.dst); let _lock = flock::Lock::panicking_new(&cx.dst.join(".lock"), true, true, true); // Add all the static files. These may already exist, but we just @@ -1503,8 +1518,8 @@ impl Context { this.render_item(&mut buf, &item, false).unwrap(); // buf will be empty if the module is stripped and there is no redirect for it if !buf.is_empty() { + try_err!(this.shared.ensure_dir(&this.dst), &this.dst); let joint_dst = this.dst.join("index.html"); - try_err!(fs::create_dir_all(&this.dst), &this.dst); let mut dst = try_err!(File::create(&joint_dst), &joint_dst); try_err!(dst.write_all(&buf), &joint_dst); } @@ -1538,8 +1553,8 @@ impl Context { let name = item.name.as_ref().unwrap(); let item_type = item.type_(); let file_name = &item_path(item_type, name); + try_err!(self.shared.ensure_dir(&self.dst), &self.dst); let joint_dst = self.dst.join(file_name); - try_err!(fs::create_dir_all(&self.dst), &self.dst); let mut dst = try_err!(File::create(&joint_dst), &joint_dst); try_err!(dst.write_all(&buf), &joint_dst); From 2c9d452a295c192f3e4762225fc4f4feef6f769c Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Fri, 13 Oct 2017 15:12:13 -0500 Subject: [PATCH 218/365] rustdoc: wrap redirect page writers in a BufWriter --- src/librustdoc/html/render.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ad671e37e69..81dea5121ea 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1562,9 +1562,10 @@ impl Context { // URL for the page. let redir_name = format!("{}.{}.html", name, item_type.name_space()); let redir_dst = self.dst.join(redir_name); - if let Ok(mut redirect_out) = OpenOptions::new().create_new(true) + if let Ok(redirect_out) = OpenOptions::new().create_new(true) .write(true) .open(&redir_dst) { + let mut redirect_out = BufWriter::new(redirect_out); try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst); } @@ -1574,7 +1575,8 @@ impl Context { if item_type == ItemType::Macro { let redir_name = format!("{}.{}!.html", item_type, name); let redir_dst = self.dst.join(redir_name); - let mut redirect_out = try_err!(File::create(&redir_dst), &redir_dst); + let redirect_out = try_err!(File::create(&redir_dst), &redir_dst); + let mut redirect_out = BufWriter::new(redirect_out); try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst); } } From bb4d1caad7f60d095b730fff417e2ac461254600 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Sun, 8 Oct 2017 18:13:37 -0700 Subject: [PATCH 219/365] Pass the full span for method calls --- src/librustc_typeck/check/callee.rs | 3 ++ src/librustc_typeck/check/mod.rs | 32 +++++++---- .../method-call-err-msg.rs | 0 src/test/ui/method-call-err-msg.stderr | 44 +++++++++++++++ src/test/ui/span/missing-unit-argument.rs | 8 +++ src/test/ui/span/missing-unit-argument.stderr | 54 ++++++++++++++----- 6 files changed, 117 insertions(+), 24 deletions(-) rename src/test/{compile-fail => ui}/method-call-err-msg.rs (100%) create mode 100644 src/test/ui/method-call-err-msg.stderr diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7461df8bda5..91ce4511a31 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -271,6 +271,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_sig.output(), fn_sig.inputs()); self.check_argument_types(call_expr.span, + call_expr.span, fn_sig.inputs(), &expected_arg_tys[..], arg_exprs, @@ -298,6 +299,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_sig.inputs()); self.check_argument_types(call_expr.span, + call_expr.span, fn_sig.inputs(), &expected_arg_tys, arg_exprs, @@ -315,6 +317,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { method_callee: MethodCallee<'tcx>) -> Ty<'tcx> { let output_type = self.check_method_argument_types(call_expr.span, + call_expr.span, Ok(method_callee), arg_exprs, TupleArgumentsFlag::TupleArguments, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9c6a4abfbd7..3506fc07112 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2352,6 +2352,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_method_argument_types(&self, sp: Span, + expr_sp: Span, method: Result, ()>, args_no_rcvr: &'gcx [hir::Expr], tuple_arguments: TupleArgumentsFlag, @@ -2371,7 +2372,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)], }; - self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr, + self.check_argument_types(sp, expr_sp, &err_inputs[..], &[], args_no_rcvr, false, tuple_arguments, None); return self.tcx.types.err; } @@ -2384,7 +2385,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { method.sig.output(), &method.sig.inputs()[1..] ); - self.check_argument_types(sp, &method.sig.inputs()[1..], &expected_arg_tys[..], + self.check_argument_types(sp, expr_sp, &method.sig.inputs()[1..], &expected_arg_tys[..], args_no_rcvr, method.sig.variadic, tuple_arguments, self.tcx.hir.span_if_local(method.def_id)); method.sig.output() @@ -2394,6 +2395,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// method calls and overloaded operators. fn check_argument_types(&self, sp: Span, + expr_sp: Span, fn_inputs: &[Ty<'tcx>], expected_arg_tys: &[Ty<'tcx>], args: &'gcx [hir::Expr], @@ -2434,9 +2436,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { sp }; - fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize, - arg_count: usize, error_code: &str, variadic: bool, - def_span: Option, sugg_unit: bool) { + fn parameter_count_error<'tcx>(sess: &Session, + sp: Span, + expr_sp: Span, + expected_count: usize, + arg_count: usize, + error_code: &str, + variadic: bool, + def_span: Option, + sugg_unit: bool) { let mut err = sess.struct_span_err_with_code(sp, &format!("this function takes {}{} parameter{} but {} parameter{} supplied", if variadic {"at least "} else {""}, @@ -2450,12 +2458,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.span_label(def_s, "defined here"); } if sugg_unit { - let sugg_span = sp.end_point(); + let sugg_span = expr_sp.end_point(); // remove closing `)` from the span let sugg_span = sugg_span.with_hi(sugg_span.lo()); err.span_suggestion( sugg_span, - "expected the unit value `()`. You can create one with a pair of parenthesis", + "expected the unit value `()`; create it with empty parentheses", String::from("()")); } else { err.span_label(sp, format!("expected {}{} parameter{}", @@ -2470,7 +2478,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); match tuple_type.sty { ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => { - parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(), + parameter_count_error(tcx.sess, sp_args, expr_sp, arg_types.len(), args.len(), "E0057", false, def_span, false); expected_arg_tys = &[]; self.err_args(args.len()) @@ -2499,7 +2507,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if supplied_arg_count >= expected_arg_count { fn_inputs.to_vec() } else { - parameter_count_error(tcx.sess, sp_args, expected_arg_count, + parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count, supplied_arg_count, "E0060", true, def_span, false); expected_arg_tys = &[]; self.err_args(supplied_arg_count) @@ -2513,7 +2521,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { false }; - parameter_count_error(tcx.sess, sp_args, expected_arg_count, + parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count, supplied_arg_count, "E0061", false, def_span, sugg_unit); expected_arg_tys = &[]; self.err_args(supplied_arg_count) @@ -2866,7 +2874,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; // Call the generic checker. - self.check_method_argument_types(span, method, + self.check_method_argument_types(span, + expr.span, + method, &args[1..], DontTupleArguments, expected) diff --git a/src/test/compile-fail/method-call-err-msg.rs b/src/test/ui/method-call-err-msg.rs similarity index 100% rename from src/test/compile-fail/method-call-err-msg.rs rename to src/test/ui/method-call-err-msg.rs diff --git a/src/test/ui/method-call-err-msg.stderr b/src/test/ui/method-call-err-msg.stderr new file mode 100644 index 00000000000..c39c62daf9e --- /dev/null +++ b/src/test/ui/method-call-err-msg.stderr @@ -0,0 +1,44 @@ +error[E0061]: this function takes 0 parameters but 1 parameter was supplied + --> $DIR/method-call-err-msg.rs:25:12 + | +15 | fn zero(self) -> Foo { self } + | ----------------------------- defined here +... +25 | x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied + | ^ expected 0 parameters + +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/method-call-err-msg.rs:27:7 + | +17 | fn one(self, _: isize) -> Foo { self } + | -------------------------------------- defined here +... +27 | .one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied + | ^^^ expected 1 parameter + +error[E0061]: this function takes 2 parameters but 1 parameter was supplied + --> $DIR/method-call-err-msg.rs:29:11 + | +19 | fn two(self, _: isize, _: isize) -> Foo { self } + | ------------------------------------------------ defined here +... +29 | .two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied + | ^ expected 2 parameters + +error[E0599]: no method named `take` found for type `Foo` in the current scope + --> $DIR/method-call-err-msg.rs:34:7 + | +34 | .take() //~ ERROR no method named `take` found for type `Foo` in the current scope + | ^^^^ + | + = note: the method `take` exists but the following trait bounds were not satisfied: + `&mut Foo : std::iter::Iterator` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `take`, perhaps you need to implement one of them: + candidate #1: `std::collections::hash::Recover` + candidate #2: `std::io::Read` + candidate #3: `std::iter::Iterator` + candidate #4: `alloc::btree::Recover` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/span/missing-unit-argument.rs b/src/test/ui/span/missing-unit-argument.rs index 2cdab5bedc4..ba1a999121c 100644 --- a/src/test/ui/span/missing-unit-argument.rs +++ b/src/test/ui/span/missing-unit-argument.rs @@ -11,9 +11,17 @@ fn foo(():(), ():()) {} fn bar(():()) {} +struct S; +impl S { + fn baz(self, (): ()) { } + fn generic(self, _: T) { } +} + fn main() { let _: Result<(), String> = Ok(); foo(); foo(()); bar(); + S.baz(); + S.generic::<()>(); } diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr index e508a30d182..af558d0ab83 100644 --- a/src/test/ui/span/missing-unit-argument.stderr +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -1,45 +1,73 @@ error[E0061]: this function takes 1 parameter but 0 parameters were supplied - --> $DIR/missing-unit-argument.rs:15:33 + --> $DIR/missing-unit-argument.rs:21:33 | -15 | let _: Result<(), String> = Ok(); +21 | let _: Result<(), String> = Ok(); | ^^^^ | -help: expected the unit value `()`. You can create one with a pair of parenthesis +help: expected the unit value `()`; create it with empty parentheses | -15 | let _: Result<(), String> = Ok(()); +21 | let _: Result<(), String> = Ok(()); | ^^ error[E0061]: this function takes 2 parameters but 0 parameters were supplied - --> $DIR/missing-unit-argument.rs:16:5 + --> $DIR/missing-unit-argument.rs:22:5 | 11 | fn foo(():(), ():()) {} | ----------------------- defined here ... -16 | foo(); +22 | foo(); | ^^^^^ expected 2 parameters error[E0061]: this function takes 2 parameters but 1 parameter was supplied - --> $DIR/missing-unit-argument.rs:17:9 + --> $DIR/missing-unit-argument.rs:23:9 | 11 | fn foo(():(), ():()) {} | ----------------------- defined here ... -17 | foo(()); +23 | foo(()); | ^^ expected 2 parameters error[E0061]: this function takes 1 parameter but 0 parameters were supplied - --> $DIR/missing-unit-argument.rs:18:5 + --> $DIR/missing-unit-argument.rs:24:5 | 12 | fn bar(():()) {} | ---------------- defined here ... -18 | bar(); +24 | bar(); | ^^^^^ | -help: expected the unit value `()`. You can create one with a pair of parenthesis +help: expected the unit value `()`; create it with empty parentheses | -18 | bar(()); +24 | bar(()); | ^^ -error: aborting due to 4 previous errors +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/missing-unit-argument.rs:25:7 + | +16 | fn baz(self, (): ()) { } + | ------------------------ defined here +... +25 | S.baz(); + | ^^^ + | +help: expected the unit value `()`; create it with empty parentheses + | +25 | S.baz(()); + | ^^ + +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/missing-unit-argument.rs:26:7 + | +17 | fn generic(self, _: T) { } + | ----------------------------- defined here +... +26 | S.generic::<()>(); + | ^^^^^^^ + | +help: expected the unit value `()`; create it with empty parentheses + | +26 | S.generic::<()>(()); + | ^^ + +error: aborting due to 6 previous errors From e6115af4bd5f07024e0b73139e1dbcd68c96d9f7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 10 Oct 2017 17:33:19 +0300 Subject: [PATCH 220/365] Implement `dyn Trait` syntax --- src/librustc/hir/lowering.rs | 2 +- src/librustc_passes/ast_validation.rs | 2 +- src/librustc_save_analysis/sig.rs | 2 +- src/libsyntax/ast.rs | 9 ++- src/libsyntax/feature_gate.rs | 7 ++ src/libsyntax/fold.rs | 4 +- src/libsyntax/parse/parser.rs | 66 +++++++++++-------- src/libsyntax/parse/token.rs | 6 ++ src/libsyntax/print/pprust.rs | 5 +- src/libsyntax/visit.rs | 2 +- src/libsyntax_pos/symbol.rs | 9 +-- .../compile-fail/dyn-trait-compatibility.rs | 29 ++++++++ .../compile-fail/feature-gate-dyn-trait.rs | 14 ++++ .../trait-bounds-not-on-struct.rs | 3 + .../parse-fail/trait-object-bad-parens.rs | 2 + src/test/run-pass/dyn-trait.rs | 24 +++++++ src/test/ui/issue-44406.stderr | 4 +- 17 files changed, 149 insertions(+), 41 deletions(-) create mode 100644 src/test/compile-fail/dyn-trait-compatibility.rs create mode 100644 src/test/compile-fail/feature-gate-dyn-trait.rs create mode 100644 src/test/run-pass/dyn-trait.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 64a2ba1fa6f..54aecb4b00f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -705,7 +705,7 @@ impl<'a> LoweringContext<'a> { let expr = self.lower_body(None, |this| this.lower_expr(expr)); hir::TyTypeof(expr) } - TyKind::TraitObject(ref bounds) => { + TyKind::TraitObject(ref bounds, ..) => { let mut lifetime_bound = None; let bounds = bounds.iter().filter_map(|bound| { match *bound { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index efb5b031809..14e33378969 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -152,7 +152,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { err.emit(); }); } - TyKind::TraitObject(ref bounds) => { + TyKind::TraitObject(ref bounds, ..) => { let mut any_lifetime_bounds = false; for bound in bounds { if let RegionTyParamBound(ref lifetime) = *bound { diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index c7e00245d63..47e5ad6c010 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -288,7 +288,7 @@ impl Sig for ast::Ty { }) } } - ast::TyKind::TraitObject(ref bounds) => { + ast::TyKind::TraitObject(ref bounds, ..) => { // FIXME recurse into bounds let nested = pprust::bounds_to_string(bounds); Ok(text_sig(nested)) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 021f96aff8c..f445def9e03 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1419,7 +1419,7 @@ pub enum TyKind { Path(Option, Path), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. - TraitObject(TyParamBounds), + TraitObject(TyParamBounds, TraitObjectSyntax), /// An `impl Bound1 + Bound2 + Bound3` type /// where `Bound` is a trait or a lifetime. ImplTrait(TyParamBounds), @@ -1438,6 +1438,13 @@ pub enum TyKind { Err, } +/// Syntax used to declare a trait object. +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum TraitObjectSyntax { + Dyn, + None, +} + /// Inline assembly dialect. /// /// E.g. `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`` diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a2f29181a20..9060a613bc1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -398,6 +398,9 @@ declare_features! ( // Default match binding modes (RFC 2005) (active, match_default_bindings, "1.22.0", Some(42640)), + + // Trait object syntax with `dyn` prefix + (active, dyn_trait, "1.22.0", Some(44662)), ); declare_features! ( @@ -1417,6 +1420,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, never_type, ty.span, "The `!` type is experimental"); }, + ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => { + gate_feature_post!(&self, dyn_trait, ty.span, + "`dyn Trait` syntax is unstable"); + } _ => {} } visit::walk_ty(self, ty) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 03c47b71d02..d7d491db71f 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -400,8 +400,8 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyKind::Typeof(expr) => { TyKind::Typeof(fld.fold_expr(expr)) } - TyKind::TraitObject(bounds) => { - TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b))) + TyKind::TraitObject(bounds, syntax) => { + TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax) } TyKind::ImplTrait(bounds) => { TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b))) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 04e6cdcfe58..bd400ef6dd6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -33,7 +33,7 @@ use ast::{Stmt, StmtKind}; use ast::{VariantData, StructField}; use ast::StrStyle; use ast::SelfKind; -use ast::{TraitItem, TraitRef}; +use ast::{TraitItem, TraitRef, TraitObjectSyntax}; use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; @@ -364,6 +364,13 @@ fn is_ident_or_underscore(t: &token::Token) -> bool { t.is_ident() || *t == token::Underscore } +// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT`, +// `IDENT<::AssocTy>`, `IDENT(u8, u8) -> u8`. +fn can_continue_type_after_ident(t: &token::Token) -> bool { + t == &token::ModSep || t == &token::Lt || + t == &token::BinOp(token::Shl) || t == &token::OpenDelim(token::Paren) +} + /// Information about the path to a module. pub struct ModulePath { pub name: String, @@ -1428,7 +1435,7 @@ impl<'a> Parser<'a> { TyKind::Path(None, ref path) if maybe_bounds => { self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)? } - TyKind::TraitObject(ref bounds) + TyKind::TraitObject(ref bounds, TraitObjectSyntax::None) if maybe_bounds && bounds.len() == 1 && !trailing_plus => { let path = match bounds[0] { TraitTyParamBound(ref pt, ..) => pt.trait_ref.path.clone(), @@ -1472,6 +1479,35 @@ impl<'a> Parser<'a> { } else if self.eat(&token::Underscore) { // A type to be inferred `_` TyKind::Infer + } else if self.token_is_bare_fn_keyword() { + // Function pointer type + self.parse_ty_bare_fn(Vec::new())? + } else if self.check_keyword(keywords::For) { + // Function pointer type or bound list (trait object type) starting with a poly-trait. + // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` + // `for<'lt> Trait1<'lt> + Trait2 + 'a` + let lo = self.span; + let lifetime_defs = self.parse_late_bound_lifetime_defs()?; + if self.token_is_bare_fn_keyword() { + self.parse_ty_bare_fn(lifetime_defs)? + } else { + let path = self.parse_path(PathStyle::Type)?; + let parse_plus = allow_plus && self.check(&token::BinOp(token::Plus)); + self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)? + } + } else if self.eat_keyword(keywords::Impl) { + // FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511). + TyKind::ImplTrait(self.parse_ty_param_bounds()?) + } else if self.check_keyword(keywords::Dyn) && + self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_ident(t)) { + // FIXME: figure out priority of `+` in `dyn Trait1 + Trait2` (#34511). + self.bump(); // `dyn` + TyKind::TraitObject(self.parse_ty_param_bounds()?, TraitObjectSyntax::Dyn) + } else if self.check(&token::Question) || + self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)) { + // Bound list (trait object type) + TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?, + TraitObjectSyntax::None) } else if self.eat_lt() { // Qualified path let (qself, path) = self.parse_qpath(PathStyle::Type)?; @@ -1493,29 +1529,6 @@ impl<'a> Parser<'a> { TyKind::Path(None, path) } } - } else if self.token_is_bare_fn_keyword() { - // Function pointer type - self.parse_ty_bare_fn(Vec::new())? - } else if self.check_keyword(keywords::For) { - // Function pointer type or bound list (trait object type) starting with a poly-trait. - // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` - // `for<'lt> Trait1<'lt> + Trait2 + 'a` - let lo = self.span; - let lifetime_defs = self.parse_late_bound_lifetime_defs()?; - if self.token_is_bare_fn_keyword() { - self.parse_ty_bare_fn(lifetime_defs)? - } else { - let path = self.parse_path(PathStyle::Type)?; - let parse_plus = allow_plus && self.check(&token::BinOp(token::Plus)); - self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)? - } - } else if self.eat_keyword(keywords::Impl) { - // FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511). - TyKind::ImplTrait(self.parse_ty_param_bounds()?) - } else if self.check(&token::Question) || - self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)){ - // Bound list (trait object type) - TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?) } else { let msg = format!("expected type, found {}", self.this_token_descr()); return Err(self.fatal(&msg)); @@ -1538,7 +1551,7 @@ impl<'a> Parser<'a> { self.bump(); // `+` bounds.append(&mut self.parse_ty_param_bounds()?); } - Ok(TyKind::TraitObject(bounds)) + Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PResult<'a, ()> { @@ -4256,6 +4269,7 @@ impl<'a> Parser<'a> { fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> { let mut bounds = Vec::new(); loop { + // This needs to be syncronized with `Token::can_begin_bound`. let is_bound_start = self.check_path() || self.check_lifetime() || self.check(&token::Question) || self.check_keyword(keywords::For) || diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 4888654fac9..20db87cfc82 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -258,6 +258,12 @@ impl Token { } } + /// Returns `true` if the token can appear at the start of a generic bound. + pub fn can_begin_bound(&self) -> bool { + self.is_path_start() || self.is_lifetime() || self.is_keyword(keywords::For) || + self == &Question || self == &OpenDelim(Paren) + } + /// Returns `true` if the token is any literal pub fn is_lit(&self) -> bool { match *self { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 959dd4ef30f..02f871c58c7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1049,8 +1049,9 @@ impl<'a> State<'a> { ast::TyKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, false)? } - ast::TyKind::TraitObject(ref bounds) => { - self.print_bounds("", &bounds[..])?; + ast::TyKind::TraitObject(ref bounds, syntax) => { + let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn " } else { "" }; + self.print_bounds(prefix, &bounds[..])?; } ast::TyKind::ImplTrait(ref bounds) => { self.print_bounds("impl ", &bounds[..])?; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 05077d42a0b..521c6030eba 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -348,7 +348,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { visitor.visit_ty(ty); visitor.visit_expr(expression) } - TyKind::TraitObject(ref bounds) | + TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 4d3db15ef29..872fc031cfb 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -309,10 +309,11 @@ declare_keywords! { (54, Yield, "yield") // Weak keywords, have special meaning only in specific contexts. - (55, Default, "default") - (56, StaticLifetime, "'static") - (57, Union, "union") - (58, Catch, "catch") + (55, Catch, "catch") + (56, Default, "default") + (57, Dyn, "dyn") + (58, StaticLifetime, "'static") + (59, Union, "union") } // If an interner exists in TLS, return it. Otherwise, prepare a fresh one. diff --git a/src/test/compile-fail/dyn-trait-compatibility.rs b/src/test/compile-fail/dyn-trait-compatibility.rs new file mode 100644 index 00000000000..a7cfda504c7 --- /dev/null +++ b/src/test/compile-fail/dyn-trait-compatibility.rs @@ -0,0 +1,29 @@ +// Copyright 2017 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. + +type A0 = dyn; +//~^ ERROR cannot find type `dyn` in this scope +type A1 = dyn::dyn; +//~^ ERROR Use of undeclared type or module `dyn` +type A2 = dyn; +//~^ ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope +type A3 = dyn<::dyn>; +//~^ ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope +//~| ERROR Use of undeclared type or module `dyn` +type A4 = dyn(dyn, dyn) -> dyn; +//~^ ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope + +fn main() {} diff --git a/src/test/compile-fail/feature-gate-dyn-trait.rs b/src/test/compile-fail/feature-gate-dyn-trait.rs new file mode 100644 index 00000000000..4b3803d019b --- /dev/null +++ b/src/test/compile-fail/feature-gate-dyn-trait.rs @@ -0,0 +1,14 @@ +// 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. + +trait Trait {} +type A = Box; //~ ERROR `dyn Trait` syntax is unstable + +fn main() {} diff --git a/src/test/compile-fail/trait-bounds-not-on-struct.rs b/src/test/compile-fail/trait-bounds-not-on-struct.rs index cabe0fd48ed..6cd43916731 100644 --- a/src/test/compile-fail/trait-bounds-not-on-struct.rs +++ b/src/test/compile-fail/trait-bounds-not-on-struct.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(dyn_trait)] struct Foo; fn foo(_x: Box) { } //~ ERROR expected trait, found struct `Foo` +type A = Box>; //~ ERROR expected trait, found struct `Vec` + fn main() { } diff --git a/src/test/parse-fail/trait-object-bad-parens.rs b/src/test/parse-fail/trait-object-bad-parens.rs index a44c0c3f32f..3e8c140eb19 100644 --- a/src/test/parse-fail/trait-object-bad-parens.rs +++ b/src/test/parse-fail/trait-object-bad-parens.rs @@ -17,4 +17,6 @@ fn main() { //~^ ERROR expected a path on the left-hand side of `+`, not `( Copy + Copy)` let _: Box<(Copy +) + Copy>; //~^ ERROR expected a path on the left-hand side of `+`, not `( Copy)` + let _: Box<(dyn Copy) + Copy>; + //~^ ERROR expected a path on the left-hand side of `+`, not `(dyn Copy)` } diff --git a/src/test/run-pass/dyn-trait.rs b/src/test/run-pass/dyn-trait.rs new file mode 100644 index 00000000000..91930852a57 --- /dev/null +++ b/src/test/run-pass/dyn-trait.rs @@ -0,0 +1,24 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(dyn_trait)] + +use std::fmt::Display; + +static BYTE: u8 = 33; + +fn main() { + let x: &(dyn 'static + Display) = &BYTE; + let y: Box = Box::new(BYTE); + let xstr = format!("{}", x); + let ystr = format!("{}", y); + assert_eq!(xstr, "33"); + assert_eq!(ystr, "33"); +} diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr index e07face24ba..9beae91540a 100644 --- a/src/test/ui/issue-44406.stderr +++ b/src/test/ui/issue-44406.stderr @@ -13,11 +13,11 @@ error: expected type, found keyword `true` 18 | foo!(true); | ^^^^ expecting a type here because of type ascription -error: expected one of `!`, `&&`, `&`, `(`, `*`, `.`, `;`, `<`, `?`, `[`, `_`, `extern`, `fn`, `for`, `impl`, `unsafe`, `}`, an operator, or lifetime, found `true` +error: expected one of `!`, `&&`, `&`, `(`, `*`, `.`, `;`, `<`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, `}`, an operator, or lifetime, found `true` --> $DIR/issue-44406.rs:18:10 | 13 | bar(baz: $rest) - | - expected one of 19 possible tokens here + | - expected one of 20 possible tokens here ... 18 | foo!(true); | ^^^^ unexpected token From 9d373204a5e67c91953f0080d4f93ebdcdcfc402 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Oct 2017 12:53:44 +0300 Subject: [PATCH 221/365] Update rustfmt submodule --- src/tools/rustfmt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 22eb5241c0e..16a478368c8 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 22eb5241c0ee5bb7eaf95e270a2b1500e82bf767 +Subproject commit 16a478368c8dcc0c0ee47372a9f663b23d28b097 From c729e4dca7581fcd060978bcb0d7f98ea4eb6b82 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Oct 2017 15:52:50 +0200 Subject: [PATCH 222/365] Remove terribly useless and problematic margin when searching on mobile --- src/librustdoc/html/static/rustdoc.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 9e2798f1cf7..a132223a051 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -831,6 +831,10 @@ span.since { .toggle-wrapper { height: 1.5em; } + + #search { + margin-left: 0; + } } @media print { From bb9e850246092d3931080ddbac551a0857b28364 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 13 Oct 2017 13:09:35 -0400 Subject: [PATCH 223/365] std: Get rid of hash_offet in RawTable This offset is always zero, and we don't consistently take it into account. This is okay, because it's zero, but if it ever changes we're going to have bugs (e.g. in the `dealloc` call, where we don't take it into account). It's better to remove this for now; if we ever have a need for a nonzero offset we can add it back, and handle it properly when we do so. --- src/libstd/collections/hash/table.rs | 31 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 93929637e2f..527c4ef4592 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -717,26 +717,25 @@ fn calculate_offsets(hashes_size: usize, (pairs_offset, end_of_pairs, oflo) } -// Returns a tuple of (minimum required malloc alignment, hash_offset, +// Returns a tuple of (minimum required malloc alignment, // array_size), from the start of a mallocated array. fn calculate_allocation(hash_size: usize, hash_align: usize, pairs_size: usize, pairs_align: usize) - -> (usize, usize, usize, bool) { - let hash_offset = 0; + -> (usize, usize, bool) { let (_, end_of_pairs, oflo) = calculate_offsets(hash_size, pairs_size, pairs_align); let align = cmp::max(hash_align, pairs_align); - (align, hash_offset, end_of_pairs, oflo) + (align, end_of_pairs, oflo) } #[test] fn test_offset_calculation() { - assert_eq!(calculate_allocation(128, 8, 16, 8), (8, 0, 144, false)); - assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 0, 5, false)); - assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 0, 20, false)); + assert_eq!(calculate_allocation(128, 8, 16, 8), (8, 144, false)); + assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 5, false)); + assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 20, false)); assert_eq!(calculate_offsets(128, 15, 4), (128, 143, false)); assert_eq!(calculate_offsets(3, 2, 4), (4, 6, false)); assert_eq!(calculate_offsets(6, 12, 4), (8, 20, false)); @@ -768,10 +767,10 @@ impl RawTable { // This is great in theory, but in practice getting the alignment // right is a little subtle. Therefore, calculating offsets has been // factored out into a different function. - let (alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size, - align_of::(), - pairs_size, - align_of::<(K, V)>()); + let (alignment, size, oflo) = calculate_allocation(hashes_size, + align_of::(), + pairs_size, + align_of::<(K, V)>()); assert!(!oflo, "capacity overflow"); // One check for overflow that covers calculation and rounding of size. @@ -784,7 +783,7 @@ impl RawTable { let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap()) .unwrap_or_else(|e| Heap.oom(e)); - let hashes = buffer.offset(hash_offset as isize) as *mut HashUint; + let hashes = buffer as *mut HashUint; RawTable { capacity_mask: capacity.wrapping_sub(1), @@ -1183,10 +1182,10 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { let hashes_size = self.capacity() * size_of::(); let pairs_size = self.capacity() * size_of::<(K, V)>(); - let (align, _, size, oflo) = calculate_allocation(hashes_size, - align_of::(), - pairs_size, - align_of::<(K, V)>()); + let (align, size, oflo) = calculate_allocation(hashes_size, + align_of::(), + pairs_size, + align_of::<(K, V)>()); debug_assert!(!oflo, "should be impossible"); From e8e7715bebdd401ebacfabb66928d0f7e4733120 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 13 Oct 2017 13:19:15 -0400 Subject: [PATCH 224/365] std: Set probe length tag on cloned hashmaps This isn't strictly necessary for hashmap cloning to work. The tag is used to hint for an upcoming resize, so it's good to copy this information over. (We can do cleverer things like actually resizing the hashmap when we see the tag, or even cleaning up the entry order, but this requires more thought and might not be worth it) --- src/libstd/collections/hash/table.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 527c4ef4592..7e623a0af17 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -1156,6 +1156,7 @@ impl Clone for RawTable { } new_ht.size = self.size(); + new_ht.set_tag(self.tag()); new_ht } From 1652c582d7357660e0e441c50aa9aa3500d0f475 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sat, 14 Oct 2017 16:35:25 +0100 Subject: [PATCH 225/365] rustbuild: Don't try to build rustdoc API docs with compiler docs rustdoc is built separately to rustc now so the docs would need to be generated separately as well. Also rustdoc doesn't build at stage 1 which prevented the compiler docs being built at stage 1. --- src/bootstrap/doc.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index b9a52a66793..9d24f35c294 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -623,11 +623,9 @@ impl Step for Rustc { compile::rustc_cargo(build, &compiler, target, &mut cargo); if build.config.compiler_docs { - // src/rustc/Cargo.toml contains bin crates called rustc and rustdoc - // which would otherwise overwrite the docs for the real rustc and - // rustdoc lib crates. - cargo.arg("-p").arg("rustc_driver") - .arg("-p").arg("rustdoc"); + // src/rustc/Cargo.toml contains a bin crate called rustc which + // would otherwise overwrite the docs for the real rustc lib crate. + cargo.arg("-p").arg("rustc_driver"); } else { // Like with libstd above if compiler docs aren't enabled then we're not // documenting internal dependencies, so we have a whitelist. From 45bb03f60c38be48b6ec06c95a4c6fa9b5c6ffba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Oct 2017 16:31:48 +0200 Subject: [PATCH 226/365] Save selected search tab --- src/librustdoc/html/static/main.js | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index bccad6c89dc..8c260132902 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -39,6 +39,13 @@ "associatedconstant", "union"]; + // On the search screen, so you remain on the last tab you opened. + // + // 0 for "Types/modules" + // 1 for "As parameters" + // 2 for "As return value" + var currentTab = 0; + function hasClass(elem, className) { if (elem && className && elem.className) { var elemClass = elem.className; @@ -747,7 +754,7 @@ var output = ''; if (array.length > 0) { - output = ``; + output = '
'; var shown = []; array.forEach(function(item) { @@ -801,7 +808,7 @@ }); output += '
'; } else { - output = `
No results :(
` + + output = '
'; @@ -809,6 +816,13 @@ return output; } + function makeTabHeader(tabNb, text) { + if (currentTab === tabNb) { + return '
' + text + '
'; + } + return '
' + text + '
'; + } + function showResults(results) { var output, query = getQuery(); @@ -816,9 +830,10 @@ output = '

Results for ' + escape(query.query) + (query.type ? ' (type: ' + escape(query.type) + ')' : '') + '

' + '
' + - '
Types/modules
' + - '
As parameters
' + - '
As return value
'; + makeTabHeader(0, "Types/modules") + + makeTabHeader(1, "As parameters") + + makeTabHeader(2, "As return value") + + '
'; output += addTab(results['others'], query); output += addTab(results['in_args'], query, false); @@ -1394,6 +1409,9 @@ // In the search display, allows to switch between tabs. function printTab(nb) { + if (nb === 0 || nb === 1 || nb === 2) { + currentTab = nb; + } var nb_copy = nb; onEach(document.getElementById('titles').childNodes, function(elem) { if (nb_copy === 0) { From f44232688e7c70400e5edf9e83a44f1da2317406 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Oct 2017 18:01:14 +0200 Subject: [PATCH 227/365] Save current highlighted item in search tab --- src/librustdoc/html/layout.rs | 2 ++ src/librustdoc/html/static/main.js | 47 +++++++++++++++++--------- src/librustdoc/html/static/rustdoc.css | 2 +- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index d08a7bde71c..93e4af1d620 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -101,6 +101,8 @@ r##"
Move up in search results
Move down in search results
+
+
Switch tab
Go to active search result
+
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 8c260132902..015611db3ff 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -701,41 +701,56 @@ }); var search_input = document.getElementsByClassName('search-input')[0]; - search_input.onkeydown = null; search_input.onkeydown = function(e) { - var actives = []; + // "actives" references the currently highlighted item in each search tab. + // Each array in "actives" represents a tab. + var actives = [[], [], []]; + // "current" is used to know which tab we're looking into. + var current = 0; onEach(document.getElementsByClassName('search-results'), function(e) { - onEach(document.getElementsByClassName('highlighted'), function(e) { - actives.push(e); + onEach(e.getElementsByClassName('highlighted'), function(e) { + actives[current].push(e); }); + current += 1; }); if (e.which === 38) { // up - if (!actives.length || !actives[0].previousElementSibling) { + if (!actives[currentTab].length || + !actives[currentTab][0].previousElementSibling) { return; } - addClass(actives[0].previousElementSibling, 'highlighted'); - removeClass(actives[0], 'highlighted'); + addClass(actives[currentTab][0].previousElementSibling, 'highlighted'); + removeClass(actives[currentTab][0], 'highlighted'); } else if (e.which === 40) { // down - if (!actives.length) { + if (!actives[currentTab].length) { var results = document.getElementsByClassName('search-results'); if (results.length > 0) { - var res = results[0].getElementsByClassName('result'); + var res = results[currentTab].getElementsByClassName('result'); if (res.length > 0) { addClass(res[0], 'highlighted'); } } - } else if (actives[0].nextElementSibling) { - addClass(actives[0].nextElementSibling, 'highlighted'); - removeClass(actives[0], 'highlighted'); + } else if (actives[currentTab][0].nextElementSibling) { + addClass(actives[currentTab][0].nextElementSibling, 'highlighted'); + removeClass(actives[currentTab][0], 'highlighted'); } } else if (e.which === 13) { // return - if (actives.length) { - document.location.href = actives[0].getElementsByTagName('a')[0].href; + if (actives[currentTab].length) { + document.location.href = + actives[currentTab][0].getElementsByTagName('a')[0].href; } - } else if (actives.length > 0) { - removeClass(actives[0], 'highlighted'); + } else if (e.which === 9) { // tab + if (e.shiftKey) { + printTab(currentTab > 0 ? currentTab - 1 : 2); + } else { + printTab(currentTab > 1 ? 0 : currentTab + 1); + } + e.preventDefault(); + } else if (e.which === 16) { // shift + // Does nothing, it's just to avoid losing "focus" on the highlighted element. + } else if (actives[currentTab].length > 0) { + removeClass(actives[currentTab][0], 'highlighted'); } }; } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 9e2798f1cf7..467fab888ab 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -552,7 +552,7 @@ body.blur > :not(#help) { flex: 0 0 auto; box-shadow: 0 0 6px rgba(0,0,0,.2); width: 550px; - height: 330px; + height: 354px; border: 1px solid; } #help dt { From 4df1278c69f6f74f3a58e647ca3a9cd38395ebf3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 15 Sep 2017 12:49:10 -0700 Subject: [PATCH 228/365] rustc: Remove `used_mut_nodes` from `TyCtxt` This updates the borrowck query to return a result, and this result is then used to incrementally check for unused mutable nodes given sets of all the used mutable nodes. Closes #42384 --- src/Cargo.lock | 2 +- src/librustc/lib.rs | 1 + src/librustc/lint/builtin.rs | 9 +- src/librustc/middle/borrowck.rs | 31 +++++ src/librustc/ty/context.rs | 6 - src/librustc/ty/maps/mod.rs | 3 +- src/librustc_borrowck/Cargo.toml | 1 + src/librustc_borrowck/borrowck/check_loans.rs | 3 +- .../borrowck/gather_loans/mod.rs | 6 +- src/librustc_borrowck/borrowck/mod.rs | 43 ++++++- src/librustc_borrowck/borrowck/unused.rs | 118 ++++++++++++++++++ src/librustc_borrowck/lib.rs | 1 + src/librustc_lint/Cargo.toml | 1 - src/librustc_lint/lib.rs | 2 - src/librustc_lint/unused.rs | 89 +------------ src/test/ui/lint/suggestions.stderr | 28 ++--- 16 files changed, 220 insertions(+), 124 deletions(-) create mode 100644 src/librustc/middle/borrowck.rs create mode 100644 src/librustc_borrowck/borrowck/unused.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index fe67a1655f1..3c3223fcade 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1504,6 +1504,7 @@ dependencies = [ "graphviz 0.0.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc_back 0.0.0", "rustc_errors 0.0.0", "rustc_mir 0.0.0", "syntax 0.0.0", @@ -1611,7 +1612,6 @@ version = "0.0.0" dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc_back 0.0.0", "rustc_const_eval 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 015dbbb7aff..ed440849b48 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -106,6 +106,7 @@ pub mod lint; pub mod middle { pub mod allocator; + pub mod borrowck; pub mod expr_use_visitor; pub mod const_val; pub mod cstore; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 5fe75d8ca71..d28963fc726 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -222,6 +222,12 @@ declare_lint! { "unnecessary use of an `unsafe` block" } +declare_lint! { + pub UNUSED_MUT, + Warn, + "detect mut variables which don't need to be mutable" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -263,7 +269,8 @@ impl LintPass for HardwiredLints { PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, LATE_BOUND_LIFETIME_ARGUMENTS, DEPRECATED, - UNUSED_UNSAFE + UNUSED_UNSAFE, + UNUSED_MUT ) } } diff --git a/src/librustc/middle/borrowck.rs b/src/librustc/middle/borrowck.rs new file mode 100644 index 00000000000..c8690422b18 --- /dev/null +++ b/src/librustc/middle/borrowck.rs @@ -0,0 +1,31 @@ +// Copyright 2017 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. + +use ich::StableHashingContext; +use hir::HirId; +use util::nodemap::FxHashSet; + +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, + StableHasherResult}; + +pub struct BorrowCheckResult { + pub used_mut_nodes: FxHashSet, +} + +impl<'gcx> HashStable> for BorrowCheckResult { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + let BorrowCheckResult { + ref used_mut_nodes, + } = *self; + used_mut_nodes.hash_stable(hcx, hasher); + } +} diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 740299b91f1..24ba38cf147 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -898,11 +898,6 @@ pub struct GlobalCtxt<'tcx> { pub inhabitedness_cache: RefCell, DefIdForest>>, - /// Set of nodes which mark locals as mutable which end up getting used at - /// some point. Local variable definitions not in this set can be warned - /// about. - pub used_mut_nodes: RefCell, - /// Caches the results of trait selection. This cache is used /// for things that do not have to do with the parameters in scope. pub selection_cache: traits::SelectionCache<'tcx>, @@ -1185,7 +1180,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { rcache: RefCell::new(FxHashMap()), normalized_cache: RefCell::new(FxHashMap()), inhabitedness_cache: RefCell::new(FxHashMap()), - used_mut_nodes: RefCell::new(NodeSet()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), rvalue_promotable_to_static: RefCell::new(NodeMap()), diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 4b68f5addd2..58405c261ad 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -15,6 +15,7 @@ use hir::def::{Def, Export}; use hir::{self, TraitCandidate, ItemLocalId}; use hir::svh::Svh; use lint; +use middle::borrowck::BorrowCheckResult; use middle::const_val; use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary, ExternBodyNestedBodies}; @@ -183,7 +184,7 @@ define_maps! { <'tcx> [] fn coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (), - [] fn borrowck: BorrowCheck(DefId) -> (), + [] fn borrowck: BorrowCheck(DefId) -> Rc, // FIXME: shouldn't this return a `Result<(), BorrowckErrors>` instead? [] fn mir_borrowck: MirBorrowCheck(DefId) -> (), diff --git a/src/librustc_borrowck/Cargo.toml b/src/librustc_borrowck/Cargo.toml index 25f02537490..4c09a9e003d 100644 --- a/src/librustc_borrowck/Cargo.toml +++ b/src/librustc_borrowck/Cargo.toml @@ -15,5 +15,6 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } graphviz = { path = "../libgraphviz" } rustc = { path = "../librustc" } +rustc_back = { path = "../librustc_back" } rustc_mir = { path = "../librustc_mir" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index fea662e21fa..6ce5afd4bf1 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -770,7 +770,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let lp = opt_loan_path(&assignee_cmt).unwrap(); self.move_data.each_assignment_of(assignment_id, &lp, |assign| { if assignee_cmt.mutbl.is_mutable() { - self.tcx().used_mut_nodes.borrow_mut().insert(local_id); + let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id); + self.bccx.used_mut_nodes.borrow_mut().insert(hir_id); } else { self.bccx.report_reassigned_immutable_variable( assignment_span, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index a58b62ba2a7..1827ddabe4e 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -442,13 +442,13 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { wrapped_path = match current_path.kind { LpVar(local_id) => { if !through_borrow { - self.tcx().used_mut_nodes.borrow_mut().insert(local_id); + let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id); + self.bccx.used_mut_nodes.borrow_mut().insert(hir_id); } None } LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => { - let local_id = self.tcx().hir.hir_to_node_id(var_id); - self.tcx().used_mut_nodes.borrow_mut().insert(local_id); + self.bccx.used_mut_nodes.borrow_mut().insert(var_id); None } LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) | diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index d6f7c2aa887..a324219020b 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -20,6 +20,7 @@ pub use self::MovedValueUseKind::*; use self::InteriorKind::*; +use rustc::hir::HirId; use rustc::hir::map as hir_map; use rustc::hir::map::blocks::FnLikeNode; use rustc::cfg; @@ -27,6 +28,7 @@ use rustc::middle::dataflow::DataFlowContext; use rustc::middle::dataflow::BitwiseOperator; use rustc::middle::dataflow::DataFlowOperator; use rustc::middle::dataflow::KillFrom; +use rustc::middle::borrowck::BorrowCheckResult; use rustc::hir::def_id::{DefId, DefIndex}; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; @@ -37,7 +39,9 @@ use rustc::middle::free_region::RegionRelations; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; +use rustc::util::nodemap::FxHashSet; +use std::cell::RefCell; use std::fmt; use std::rc::Rc; use std::hash::{Hash, Hasher}; @@ -54,6 +58,8 @@ pub mod gather_loans; pub mod move_data; +mod unused; + #[derive(Clone, Copy)] pub struct LoanDataFlowOperator; @@ -79,7 +85,9 @@ pub struct AnalysisData<'a, 'tcx: 'a> { pub move_data: move_data::FlowedMoveData<'a, 'tcx>, } -fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { +fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) + -> Rc +{ debug!("borrowck(body_owner_def_id={:?})", owner_def_id); let owner_id = tcx.hir.as_local_node_id(owner_def_id).unwrap(); @@ -91,7 +99,9 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { // those things (notably the synthesized constructors from // tuple structs/variants) do not have an associated body // and do not need borrowchecking. - return; + return Rc::new(BorrowCheckResult { + used_mut_nodes: FxHashSet(), + }) } _ => { } } @@ -100,7 +110,14 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { let tables = tcx.typeck_tables_of(owner_def_id); let region_scope_tree = tcx.region_scope_tree(owner_def_id); let body = tcx.hir.body(body_id); - let bccx = &mut BorrowckCtxt { tcx, tables, region_scope_tree, owner_def_id, body }; + let mut bccx = BorrowckCtxt { + tcx, + tables, + region_scope_tree, + owner_def_id, + body, + used_mut_nodes: RefCell::new(FxHashSet()), + }; // Eventually, borrowck will always read the MIR, but at the // moment we do not. So, for now, we always force MIR to be @@ -118,14 +135,19 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { if let Some(AnalysisData { all_loans, loans: loan_dfcx, move_data: flowed_moves }) = - build_borrowck_dataflow_data(bccx, false, body_id, + build_borrowck_dataflow_data(&mut bccx, false, body_id, |bccx| { cfg = Some(cfg::CFG::new(bccx.tcx, &body)); cfg.as_mut().unwrap() }) { - check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans, body); + check_loans::check_loans(&mut bccx, &loan_dfcx, &flowed_moves, &all_loans, body); } + unused::check(&mut bccx, body); + + Rc::new(BorrowCheckResult { + used_mut_nodes: bccx.used_mut_nodes.into_inner(), + }) } fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tcx>, @@ -198,7 +220,14 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( let tables = tcx.typeck_tables_of(owner_def_id); let region_scope_tree = tcx.region_scope_tree(owner_def_id); let body = tcx.hir.body(body_id); - let mut bccx = BorrowckCtxt { tcx, tables, region_scope_tree, owner_def_id, body }; + let mut bccx = BorrowckCtxt { + tcx, + tables, + region_scope_tree, + owner_def_id, + body, + used_mut_nodes: RefCell::new(FxHashSet()), + }; let dataflow_data = build_borrowck_dataflow_data(&mut bccx, true, body_id, |_| cfg); (bccx, dataflow_data.unwrap()) @@ -219,6 +248,8 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> { owner_def_id: DefId, body: &'tcx hir::Body, + + used_mut_nodes: RefCell>, } impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> { diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs new file mode 100644 index 00000000000..228824b663d --- /dev/null +++ b/src/librustc_borrowck/borrowck/unused.rs @@ -0,0 +1,118 @@ +// Copyright 2017 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. + +use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; +use rustc::hir::{self, HirId}; +use rustc::lint::builtin::UNUSED_MUT; +use rustc::ty; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; +use rustc_back::slice; +use syntax::ptr::P; + +use borrowck::BorrowckCtxt; + +pub fn check<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, body: &'tcx hir::Body) { + let mut used_mut = bccx.used_mut_nodes.borrow().clone(); + UsedMutFinder { + bccx, + set: &mut used_mut, + }.visit_expr(&body.value); + let mut cx = UnusedMutCx { bccx, used_mut }; + for arg in body.arguments.iter() { + cx.check_unused_mut_pat(slice::ref_slice(&arg.pat)); + } + cx.visit_expr(&body.value); +} + +struct UsedMutFinder<'a, 'tcx: 'a> { + bccx: &'a BorrowckCtxt<'a, 'tcx>, + set: &'a mut FxHashSet, +} + +struct UnusedMutCx<'a, 'tcx: 'a> { + bccx: &'a BorrowckCtxt<'a, 'tcx>, + used_mut: FxHashSet, +} + +impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { + fn check_unused_mut_pat(&self, pats: &[P]) { + let tcx = self.bccx.tcx; + let mut mutables = FxHashMap(); + for p in pats { + p.each_binding(|_, id, span, path1| { + let name = path1.node; + + // Skip anything that looks like `_foo` + if name.as_str().starts_with("_") { + return + } + + // Skip anything that looks like `&foo` or `&mut foo`, only look + // for by-value bindings + let hir_id = tcx.hir.node_to_hir_id(id); + let bm = match self.bccx.tables.pat_binding_modes().get(hir_id) { + Some(&bm) => bm, + None => span_bug!(span, "missing binding mode"), + }; + match bm { + ty::BindByValue(hir::MutMutable) => {} + _ => return, + } + + mutables.entry(name).or_insert(Vec::new()).push((id, hir_id, span)); + }); + } + + for (_name, ids) in mutables { + // If any id for this name was used mutably then consider them all + // ok, so move on to the next + if ids.iter().any(|&(_, ref id, _)| self.used_mut.contains(id)) { + continue + } + + let mut_span = tcx.sess.codemap().span_until_char(ids[0].2, ' '); + + // Ok, every name wasn't used mutably, so issue a warning that this + // didn't need to be mutable. + tcx.struct_span_lint_node(UNUSED_MUT, + ids[0].0, + ids[0].2, + "variable does not need to be mutable") + .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()) + .emit(); + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for UnusedMutCx<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir) + } + + fn visit_arm(&mut self, arm: &hir::Arm) { + self.check_unused_mut_pat(&arm.pats) + } + + fn visit_local(&mut self, local: &hir::Local) { + self.check_unused_mut_pat(slice::ref_slice(&local.pat)); + } +} + +impl<'a, 'tcx> Visitor<'tcx> for UsedMutFinder<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::OnlyBodies(&self.bccx.tcx.hir) + } + + fn visit_nested_body(&mut self, id: hir::BodyId) { + let def_id = self.bccx.tcx.hir.body_owner_def_id(id); + self.set.extend(self.bccx.tcx.borrowck(def_id).used_mut_nodes.iter().cloned()); + self.visit_body(self.bccx.tcx.hir.body(id)); + } +} diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 9bedbfed5db..0a39dc1d8b5 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -22,6 +22,7 @@ #[macro_use] extern crate syntax; extern crate syntax_pos; extern crate rustc_errors as errors; +extern crate rustc_back; // for "clarity", rename the graphviz crate to dot; graphviz within `borrowck` // refers to the borrowck-specific graphviz adapter traits. diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index c3c5461ff7c..cebf52d5af7 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -12,7 +12,6 @@ test = false [dependencies] log = "0.3" rustc = { path = "../librustc" } -rustc_back = { path = "../librustc_back" } rustc_const_eval = { path = "../librustc_const_eval" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index fbf993f4557..4ba7f7aa951 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -38,7 +38,6 @@ extern crate syntax; extern crate rustc; #[macro_use] extern crate log; -extern crate rustc_back; extern crate rustc_const_eval; extern crate syntax_pos; @@ -129,7 +128,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { NonUpperCaseGlobals, NonShorthandFieldPatterns, UnsafeCode, - UnusedMut, UnusedAllocation, MissingCopyImplementations, UnstableFeatures, diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index e2ade19b6e2..a058f84e588 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -11,105 +11,18 @@ use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::adjustment; -use util::nodemap::FxHashMap; use lint::{LateContext, EarlyContext, LintContext, LintArray}; use lint::{LintPass, EarlyLintPass, LateLintPass}; -use std::collections::hash_map::Entry::{Occupied, Vacant}; - use syntax::ast; use syntax::attr; use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType}; -use syntax::symbol::keywords; -use syntax::ptr::P; use syntax::print::pprust; +use syntax::symbol::keywords; use syntax::util::parser; use syntax_pos::Span; -use rustc_back::slice; use rustc::hir; -use rustc::hir::intravisit::FnKind; - -declare_lint! { - pub UNUSED_MUT, - Warn, - "detect mut variables which don't need to be mutable" -} - -#[derive(Copy, Clone)] -pub struct UnusedMut; - -impl UnusedMut { - fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P]) { - // collect all mutable pattern and group their NodeIDs by their Identifier to - // avoid false warnings in match arms with multiple patterns - - let mut mutables = FxHashMap(); - for p in pats { - p.each_binding(|_, id, span, path1| { - let hir_id = cx.tcx.hir.node_to_hir_id(id); - let bm = match cx.tables.pat_binding_modes().get(hir_id) { - Some(&bm) => bm, - None => span_bug!(span, "missing binding mode"), - }; - let name = path1.node; - if let ty::BindByValue(hir::MutMutable) = bm { - if !name.as_str().starts_with("_") { - match mutables.entry(name) { - Vacant(entry) => { - entry.insert(vec![id]); - } - Occupied(mut entry) => { - entry.get_mut().push(id); - } - } - } - } - }); - } - - let used_mutables = cx.tcx.used_mut_nodes.borrow(); - for (_, v) in &mutables { - if !v.iter().any(|e| used_mutables.contains(e)) { - let binding_span = cx.tcx.hir.span(v[0]); - let mut_span = cx.tcx.sess.codemap().span_until_char(binding_span, ' '); - let mut err = cx.struct_span_lint(UNUSED_MUT, - binding_span, - "variable does not need to be mutable"); - err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()); - err.emit(); - } - } - } -} - -impl LintPass for UnusedMut { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_MUT) - } -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedMut { - fn check_arm(&mut self, cx: &LateContext, a: &hir::Arm) { - self.check_unused_mut_pat(cx, &a.pats) - } - - fn check_local(&mut self, cx: &LateContext, l: &hir::Local) { - self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat)); - } - - fn check_fn(&mut self, - cx: &LateContext, - _: FnKind, - _: &hir::FnDecl, - body: &hir::Body, - _: Span, - _: ast::NodeId) { - for a in &body.arguments { - self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat)); - } - } -} declare_lint! { pub UNUSED_MUST_USE, diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index 5b2a4f589f7..9a69c52e6cf 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -14,6 +14,20 @@ warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was | = note: #[warn(deprecated)] on by default +warning: variable does not need to be mutable + --> $DIR/suggestions.rs:17:13 + | +17 | let mut a = (1); // should suggest no `mut`, no parens + | ---^^ + | | + | help: remove this `mut` + | +note: lint level defined here + --> $DIR/suggestions.rs:11:9 + | +11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896 + | ^^^^^^^^^^ + warning: denote infinite loops with `loop { ... }` --> $DIR/suggestions.rs:16:5 | @@ -29,17 +43,3 @@ warning: denote infinite loops with `loop { ... }` | = note: #[warn(while_true)] on by default -warning: variable does not need to be mutable - --> $DIR/suggestions.rs:17:13 - | -17 | let mut a = (1); // should suggest no `mut`, no parens - | ---^^ - | | - | help: remove this `mut` - | -note: lint level defined here - --> $DIR/suggestions.rs:11:9 - | -11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896 - | ^^^^^^^^^^ - From 5acc185ceef4dd2a64726df62ae79895a84d3a1e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Oct 2017 18:35:54 +0200 Subject: [PATCH 229/365] Fix arrow display --- src/librustdoc/html/layout.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index d08a7bde71c..873d978b9cb 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -97,9 +97,9 @@ r##"
Show this help dialog
S
Focus the search field
-
+
Move up in search results
-
+
Move down in search results
Go to active search result
From c6ce067216e7732ac83b94100233c3f55d0ba993 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Oct 2017 18:43:00 +0200 Subject: [PATCH 230/365] Hide help when search bar is focused --- src/librustdoc/html/static/main.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index bccad6c89dc..8f7cd244c2f 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -163,6 +163,20 @@ return String.fromCharCode(c); } + function displayHelp(display, ev) { + if (display === true) { + if (hasClass(help, "hidden")) { + ev.preventDefault(); + removeClass(help, "hidden"); + addClass(document.body, "blur"); + } + } else if (!hasClass(help, "hidden")) { + ev.preventDefault(); + addClass(help, "hidden"); + removeClass(document.body, "blur"); + } + } + function handleShortcut(ev) { if (document.activeElement.tagName === "INPUT") return; @@ -176,9 +190,7 @@ case "Escape": var search = document.getElementById("search"); if (!hasClass(help, "hidden")) { - ev.preventDefault(); - addClass(help, "hidden"); - removeClass(document.body, "blur"); + displayHelp(false, ev); } else if (!hasClass(search, "hidden")) { ev.preventDefault(); addClass(search, "hidden"); @@ -188,6 +200,7 @@ case "s": case "S": + displayHelp(false, ev); ev.preventDefault(); focusSearchBar(); break; @@ -198,10 +211,8 @@ break; case "?": - if (ev.shiftKey && hasClass(help, "hidden")) { - ev.preventDefault(); - removeClass(help, "hidden"); - addClass(document.body, "blur"); + if (ev.shiftKey) { + displayHelp(true, ev); } break; } From 47ea51e4e50a83adaeb872952d5d67eed243ed02 Mon Sep 17 00:00:00 2001 From: Jacob Wahlgren Date: Sat, 14 Oct 2017 21:27:41 +0200 Subject: [PATCH 231/365] Improve E0382 extended help message Mention Clone and refererences, and use more realistic examples (within the constraints of a few lines :). --- src/librustc_mir/diagnostics.rs | 66 ++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 98c5345c69d..0f67f7bf6de 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -320,20 +320,68 @@ Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out of `x` when we set `y`. This is fundamental to Rust's ownership system: outside of workarounds like `Rc`, a value cannot be owned by more than one variable. -If we own the type, the easiest way to address this problem is to implement -`Copy` and `Clone` on it, as shown below. This allows `y` to copy the -information in `x`, while leaving the original version owned by `x`. Subsequent -changes to `x` will not be reflected when accessing `y`. +Sometimes we don't need to move the value. Using a reference, we can let another +function borrow the value without changing its ownership. In the example below, +we don't actually have to move our string to `calculate_length`, we can give it +a reference to it with `&` instead. + +``` +fn main() { + let s1 = String::from("hello"); + + let len = calculate_length(&s1); + + println!("The length of '{}' is {}.", s1, len); +} + +fn calculate_length(s: &String) -> usize { + s.len() +} +``` + +A mutable reference can be created with `&mut`. + +Sometimes we don't want a reference, but a duplicate. All types marked `Clone` +can be duplicated by calling `.clone()`. Subsequent changes to a clone do not +affect the original variable. + +Most types in the standard library are marked `Clone`. The example below +demonstrates using `clone()` on a string. `s1` is first set to "many", and then +copied to `s2`. Then the first character of `s1` is removed, without affecting +`s2`. "any many" is printed to the console. + +``` +fn main() { + let mut s1 = String::from("many"); + let s2 = s1.clone(); + s1.remove(0); + println!("{} {}", s1, s2); +} +``` + +If we control the definition of a type, we can implement `Clone` on it ourselves +with `#[derive(Clone)]`. + +Some types have no ownership semantics at all and are trivial to duplicate. An +example is `i32` and the other number types. We don't have to call `.clone()` to +clone them, because they are marked `Copy` in addition to `Clone`. Implicit +cloning is more convienient in this case. We can mark our own types `Copy` if +all their members also are marked `Copy`. + +In the example below, we implement a `Point` type. Because it only stores two +integers, we opt-out of ownership semantics with `Copy`. Then we can +`let p2 = p1` without `p1` being moved. ``` #[derive(Copy, Clone)] -struct MyStruct { s: u32 } +struct Point { x: i32, y: i32 } fn main() { - let mut x = MyStruct{ s: 5u32 }; - let y = x; - x.s = 6; - println!("{}", x.s); + let mut p1 = Point{ x: -1, y: 2 }; + let p2 = p1; + p1.x = 1; + println!("p1: {}, {}", p1.x, p1.y); + println!("p2: {}, {}", p2.x, p2.y); } ``` From cab99a3f8c8dcdfd9052fd54787d22611ab36edc Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 13 Oct 2017 19:22:33 -0700 Subject: [PATCH 232/365] Fix TcpStream::connect_timeout on linux Linux appears to set POLLOUT when a conection's refused, which is pretty weird. Invert the check to look for an error explicitly. Also add an explict test for this case. Closes #45265. --- src/libstd/net/tcp.rs | 15 +++++++++++++++ src/libstd/sys/unix/net.rs | 13 +++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index b904641a336..4656cc5a7a7 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -1579,6 +1579,21 @@ mod tests { "bad error: {} {:?}", e, e.kind()); } + #[test] + fn connect_timeout_unbound() { + // bind and drop a socket to track down a "probably unassigned" port + let socket = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = socket.local_addr().unwrap(); + drop(socket); + + let timeout = Duration::from_secs(1); + let e = TcpStream::connect_timeout(&addr, timeout).unwrap_err(); + assert!(e.kind() == io::ErrorKind::ConnectionRefused || + e.kind() == io::ErrorKind::TimedOut || + e.kind() == io::ErrorKind::Other, + "bad error: {} {:?}", e, e.kind()); + } + #[test] fn connect_timeout_valid() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index c8019d1c768..e775f857f2b 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -176,11 +176,16 @@ impl Socket { } 0 => {} _ => { - if pollfd.revents & libc::POLLOUT == 0 { - if let Some(e) = self.take_error()? { - return Err(e); - } + // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look + // for POLLHUP rather than read readiness + if pollfd.revents & libc::POLLHUP != 0 { + let e = self.take_error()? + .unwrap_or_else(|| { + io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP") + }); + return Err(e); } + return Ok(()); } } From 6500b3d0699148da8c18d8dbe7339bb017d085ed Mon Sep 17 00:00:00 2001 From: Joe Rattazzi Date: Sat, 14 Oct 2017 16:59:58 -0500 Subject: [PATCH 233/365] Add "Buidling on *nix" sub-header --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 779acb9fab4..4fc003036e9 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Read ["Installation"] from [The Book]. ## Building from Source [building-from-source]: #building-from-source +### Building on *nix 1. Make sure you have installed the dependencies: * `g++` 4.7 or later or `clang++` 3.x or later From b522ee15ce8b4cd419a4f26177694fe3200029be Mon Sep 17 00:00:00 2001 From: matthewjasper Date: Sun, 15 Oct 2017 11:58:32 +0100 Subject: [PATCH 234/365] Check namespaces when resolving associated items in typeck --- src/librustc_typeck/astconv.rs | 8 +++- src/librustc_typeck/check/method/mod.rs | 9 +++-- src/librustc_typeck/check/method/probe.rs | 8 +++- src/librustc_typeck/check/method/suggest.rs | 13 ++++--- src/librustc_typeck/check/mod.rs | 9 ++++- .../coherence/inherent_impls_overlap.rs | 14 ++----- src/librustc_typeck/lib.rs | 1 + src/librustc_typeck/namespace.rs | 39 +++++++++++++++++++ src/test/run-pass/issue-35600.rs | 24 ++++++++++++ src/test/run-pass/issue-44247.rs | 27 +++++++++++++ 10 files changed, 127 insertions(+), 25 deletions(-) create mode 100644 src/librustc_typeck/namespace.rs create mode 100644 src/test/run-pass/issue-35600.rs create mode 100644 src/test/run-pass/issue-44247.rs diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6b7a5b3af96..7c9497badfb 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -18,6 +18,7 @@ use hir; use hir::def::Def; use hir::def_id::DefId; use middle::resolve_lifetime as rl; +use namespace::Namespace; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; @@ -827,8 +828,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_did = bound.0.def_id; let (assoc_ident, def_scope) = tcx.adjust(assoc_name, trait_did, ref_id); - let item = tcx.associated_items(trait_did).find(|i| i.name.to_ident() == assoc_ident) - .expect("missing associated type"); + let item = tcx.associated_items(trait_did).find(|i| { + Namespace::from(i.kind) == Namespace::Type && + i.name.to_ident() == assoc_ident + }) + .expect("missing associated type"); let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound); let ty = self.normalize_ty(span, ty); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 3ddeba9d440..d4eda13c6cd 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -13,6 +13,7 @@ use check::FnCtxt; use hir::def::Def; use hir::def_id::DefId; +use namespace::Namespace; use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; @@ -275,7 +276,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Trait must have a method named `m_name` and it should not have // type parameters or early-bound regions. let tcx = self.tcx; - let method_item = self.associated_item(trait_def_id, m_name).unwrap(); + let method_item = self.associated_item(trait_def_id, m_name, Namespace::Value).unwrap(); let def_id = method_item.def_id; let generics = tcx.generics_of(def_id); assert_eq!(generics.types.len(), 0); @@ -371,10 +372,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Find item with name `item_name` defined in impl/trait `def_id` /// and return it, or `None`, if no such item was defined there. - pub fn associated_item(&self, def_id: DefId, item_name: ast::Name) + pub fn associated_item(&self, def_id: DefId, item_name: ast::Name, ns: Namespace) -> Option { self.tcx.associated_items(def_id) - .find(|item| self.tcx.hygienic_eq(item_name, item.name, def_id)) - + .find(|item| Namespace::from(item.kind) == ns && + self.tcx.hygienic_eq(item_name, item.name, def_id)) } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index a3b196f99d6..78941cb3a56 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -16,6 +16,7 @@ use super::suggest; use check::FnCtxt; use hir::def_id::DefId; use hir::def::Def; +use namespace::Namespace; use rustc::ty::subst::{Subst, Substs}; use rustc::traits::{self, ObligationCause}; use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable}; @@ -1317,11 +1318,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.tcx.associated_items(def_id) .filter(|x| { let dist = lev_distance(&*name.as_str(), &x.name.as_str()); - dist > 0 && dist <= max_dist + Namespace::from(x.kind) == Namespace::Value && dist > 0 + && dist <= max_dist }) .collect() } else { - self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x]) + self.fcx + .associated_item(def_id, name, Namespace::Value) + .map_or(Vec::new(), |x| vec![x]) } } else { self.tcx.associated_items(def_id).collect() diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 90c5297b399..23148406a11 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -17,6 +17,7 @@ use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable}; use hir::def::Def; use hir::def_id::{CRATE_DEF_INDEX, DefId}; use middle::lang_items::FnOnceTraitLangItem; +use namespace::Namespace; use rustc::traits::{Obligation, SelectionContext}; use util::nodemap::FxHashSet; @@ -92,12 +93,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { CandidateSource::ImplSource(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. - let item = self.associated_item(impl_did, item_name) + let item = self.associated_item(impl_did, item_name, Namespace::Value) .or_else(|| { self.associated_item( self.tcx.impl_trait_ref(impl_did).unwrap().def_id, - - item_name + item_name, + Namespace::Value, ) }).unwrap(); let note_span = self.tcx.hir.span_if_local(item.def_id).or_else(|| { @@ -127,7 +128,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } CandidateSource::TraitSource(trait_did) => { - let item = self.associated_item(trait_did, item_name).unwrap(); + let item = self + .associated_item(trait_did, item_name, Namespace::Value) + .unwrap(); let item_span = self.tcx.def_span(item.def_id); span_note!(err, item_span, @@ -402,7 +405,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // implementing a trait would be legal but is rejected // here). (type_is_local || info.def_id.is_local()) - && self.associated_item(info.def_id, item_name).is_some() + && self.associated_item(info.def_id, item_name, Namespace::Value).is_some() }) .collect::>(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9c6a4abfbd7..8aaad11df3f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,6 +88,7 @@ use astconv::AstConv; use hir::def::{Def, CtorKind}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_back::slice::ref_slice; +use namespace::Namespace; use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; @@ -1293,7 +1294,13 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for impl_item in impl_items() { let ty_impl_item = tcx.associated_item(tcx.hir.local_def_id(impl_item.id)); let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id) - .find(|ac| tcx.hygienic_eq(ty_impl_item.name, ac.name, impl_trait_ref.def_id)); + .find(|ac| Namespace::from(&impl_item.node) == Namespace::from(ac.kind) && + tcx.hygienic_eq(ty_impl_item.name, ac.name, impl_trait_ref.def_id)) + .or_else(|| { + // Not compatible, but needed for the error message + tcx.associated_items(impl_trait_ref.def_id) + .find(|ac| tcx.hygienic_eq(ty_impl_item.name, ac.name, impl_trait_ref.def_id)) + }); // Check that impl definition matches trait definition if let Some(ty_trait_item) = ty_trait_item { diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 76dcfe36e4f..1355f711a4b 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use namespace::Namespace; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::traits; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::TyCtxt; pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) { @@ -28,19 +29,10 @@ struct InherentOverlapChecker<'a, 'tcx: 'a> { impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId, overlap: traits::OverlapResult) { - #[derive(Copy, Clone, PartialEq)] - enum Namespace { - Type, - Value, - } let name_and_namespace = |def_id| { let item = self.tcx.associated_item(def_id); - (item.name, match item.kind { - ty::AssociatedKind::Type => Namespace::Type, - ty::AssociatedKind::Const | - ty::AssociatedKind::Method => Namespace::Value, - }) + (item.name, Namespace::from(item.kind)) }; let impl_items1 = self.tcx.associated_item_def_ids(impl1); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 7a6ee73b9b9..1c047ef98d8 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -123,6 +123,7 @@ mod constrained_type_params; mod impl_wf_check; mod coherence; mod variance; +mod namespace; pub struct TypeAndSubsts<'tcx> { substs: &'tcx Substs<'tcx>, diff --git a/src/librustc_typeck/namespace.rs b/src/librustc_typeck/namespace.rs new file mode 100644 index 00000000000..6f0e46b3afe --- /dev/null +++ b/src/librustc_typeck/namespace.rs @@ -0,0 +1,39 @@ +// Copyright 2017 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. + +use rustc::hir; +use rustc::ty; + +// Whether an item exists in the type or value namespace. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Namespace { + Type, + Value, +} + +impl From for Namespace { + fn from(a_kind: ty::AssociatedKind) -> Self { + match a_kind { + ty::AssociatedKind::Type => Namespace::Type, + ty::AssociatedKind::Const | + ty::AssociatedKind::Method => Namespace::Value, + } + } +} + +impl<'a> From <&'a hir::ImplItemKind> for Namespace { + fn from(impl_kind: &'a hir::ImplItemKind) -> Self { + match *impl_kind { + hir::ImplItemKind::Type(..) => Namespace::Type, + hir::ImplItemKind::Const(..) | + hir::ImplItemKind::Method(..) => Namespace::Value, + } + } +} diff --git a/src/test/run-pass/issue-35600.rs b/src/test/run-pass/issue-35600.rs new file mode 100644 index 00000000000..88358eff08d --- /dev/null +++ b/src/test/run-pass/issue-35600.rs @@ -0,0 +1,24 @@ +// Copyright 2017 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. + +trait Foo { + type bar; + fn bar(); +} + +impl Foo for () { + type bar = (); + fn bar() {} +} + +fn main() { + let x: <() as Foo>::bar = (); + <()>::bar(); +} diff --git a/src/test/run-pass/issue-44247.rs b/src/test/run-pass/issue-44247.rs new file mode 100644 index 00000000000..27b0aeaac55 --- /dev/null +++ b/src/test/run-pass/issue-44247.rs @@ -0,0 +1,27 @@ +// Copyright 2017 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. + +trait T { + type X; + const X: Self::X; +} +fn foo() { + let _: X::X = X::X; +} + +trait S { + const X: Self::X; + type X; +} +fn bar() { + let _: X::X = X::X; +} + +fn main() {} From b7d378a94cb5e0f01872f8ce2036357c934bf93b Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 15 Oct 2017 16:59:23 +0200 Subject: [PATCH 235/365] Fix typo in rustdoc book --- src/doc/rustdoc/src/command-line-arguments.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 0f0bda65ce3..bf72a489b5a 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -96,7 +96,7 @@ Using this flag looks like this: $ rustdoc src/lib.rs --crate-name mycrate ``` -By default, `rustodc` assumes that the name of your crate is the same name +By default, `rustdoc` assumes that the name of your crate is the same name as the `.rs` file. `--crate-name` lets you override this assumption with whatever name you choose. @@ -253,7 +253,7 @@ $ rustdoc README.md --html-before-content extra.html ``` This flag takes a list of files, and inserts them inside the `` tag but -before the other content `rustodc` would normally produce in the rendered +before the other content `rustdoc` would normally produce in the rendered documentation. ## `--html-after-content`: include more HTML after the content @@ -266,7 +266,7 @@ $ rustdoc README.md --html-after-content extra.html ``` This flag takes a list of files, and inserts them before the `` tag but -after the other content `rustodc` would normally produce in the rendered +after the other content `rustdoc` would normally produce in the rendered documentation. From fdb3e37126b2d061b2bc1110f649bcd70723eb50 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 15 Oct 2017 17:02:45 +0200 Subject: [PATCH 236/365] Rustdoc book: Add missing headlines Some options were missing headlines, which looked a bit inconsistent. --- src/doc/rustdoc/src/command-line-arguments.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 0f0bda65ce3..d3462c7773a 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -100,7 +100,7 @@ By default, `rustodc` assumes that the name of your crate is the same name as the `.rs` file. `--crate-name` lets you override this assumption with whatever name you choose. -## `-L`/`--library-path`: +## `-L`/`--library-path`: where to look for dependencies Using this flag looks like this: @@ -186,7 +186,7 @@ on documentation tests](documentation-tests.html). See also `--test-args`. -## `--test-args`: +## `--test-args`: pass options to test runner Using this flag looks like this: @@ -199,7 +199,7 @@ For more, see [the chapter on documentation tests](documentation-tests.html). See also `--test`. -## `--target`: +## `--target`: generate documentation for the specified target triple Using this flag looks like this: From 2e1c4cd0f51c28b8cfc003fda67f6641bb4335f2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 11 Oct 2017 11:19:59 -0700 Subject: [PATCH 237/365] rustc: Fix some ThinLTO internalization First the `addPreservedGUID` function forgot to take care of "alias" summaries. I'm not 100% sure what this is but the current code now matches upstream. Next the `computeDeadSymbols` return value wasn't actually being used, but it needed to be used! Together these should... Closes #45195 --- src/librustc_trans/back/lto.rs | 20 ++++++++++++++++++- src/librustc_trans/back/write.rs | 10 ++++++---- src/rustllvm/PassWrapper.cpp | 13 +++++++----- src/test/run-pass/thinlto/auxiliary/dylib.rs | 16 +++++++++++++++ .../auxiliary/thin-lto-inlines-aux.rs | 0 src/test/run-pass/thinlto/dylib-works.rs | 18 +++++++++++++++++ .../{ => thinlto}/thin-lto-inlines.rs | 0 .../{ => thinlto}/thin-lto-inlines2.rs | 0 8 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 src/test/run-pass/thinlto/auxiliary/dylib.rs rename src/test/run-pass/{ => thinlto}/auxiliary/thin-lto-inlines-aux.rs (100%) create mode 100644 src/test/run-pass/thinlto/dylib-works.rs rename src/test/run-pass/{ => thinlto}/thin-lto-inlines.rs (100%) rename src/test/run-pass/{ => thinlto}/thin-lto-inlines2.rs (100%) diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 8f75b891a30..01d3d656dfe 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -130,6 +130,7 @@ pub fn run(cgcx: &CodegenContext, .filter_map(symbol_filter) .collect::>(); timeline.record("whitelist"); + info!("{} symbols to preserve in this crate", symbol_white_list.len()); // If we're performing LTO for the entire crate graph, then for each of our // upstream dependencies, find the corresponding rlib and load the bitcode @@ -437,7 +438,24 @@ fn run_pass_manager(cgcx: &CodegenContext, assert!(!pass.is_null()); llvm::LLVMRustAddPass(pm, pass); - with_llvm_pmb(llmod, config, &mut |b| { + // When optimizing for LTO we don't actually pass in `-O0`, but we force + // it to always happen at least with `-O1`. + // + // With ThinLTO we mess around a lot with symbol visibility in a way + // that will actually cause linking failures if we optimize at O0 which + // notable is lacking in dead code elimination. To ensure we at least + // get some optimizations and correctly link we forcibly switch to `-O1` + // to get dead code elimination. + // + // Note that in general this shouldn't matter too much as you typically + // only turn on ThinLTO when you're compiling with optimizations + // otherwise. + let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); + let opt_level = match opt_level { + llvm::CodeGenOptLevel::None => llvm::CodeGenOptLevel::Less, + level => level, + }; + with_llvm_pmb(llmod, config, opt_level, &mut |b| { if thin { if !llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm) { panic!("this version of LLVM does not support ThinLTO"); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 9d914243ec6..f7e0ad029af 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -217,7 +217,7 @@ pub struct ModuleConfig { passes: Vec, /// Some(level) to optimize at a certain level, or None to run /// absolutely no optimizations (used for the metadata module). - opt_level: Option, + pub opt_level: Option, /// Some(level) to optimize binary size, or None to not affect program size. opt_size: Option, @@ -507,7 +507,8 @@ unsafe fn optimize(cgcx: &CodegenContext, if !config.no_prepopulate_passes { llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); - with_llvm_pmb(llmod, &config, &mut |b| { + let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); + with_llvm_pmb(llmod, &config, opt_level, &mut |b| { llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); }) @@ -1842,16 +1843,17 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { pub unsafe fn with_llvm_pmb(llmod: ModuleRef, config: &ModuleConfig, + opt_level: llvm::CodeGenOptLevel, f: &mut FnMut(llvm::PassManagerBuilderRef)) { // Create the PassManagerBuilder for LLVM. We configure it with // reasonable defaults and prepare it to actually populate the pass // manager. let builder = llvm::LLVMPassManagerBuilderCreate(); - let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone); let inline_threshold = config.inline_threshold; - llvm::LLVMRustConfigurePassManagerBuilder(builder, opt_level, + llvm::LLVMRustConfigurePassManagerBuilder(builder, + opt_level, config.merge_functions, config.vectorize_slp, config.vectorize_loop); diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index e37f048dd47..1287b94159a 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -901,9 +901,7 @@ addPreservedGUID(const ModuleSummaryIndex &Index, } } - GlobalValueSummary *GVSummary = Summary.get(); - if (isa(GVSummary)) { - FunctionSummary *FS = cast(GVSummary); + if (auto *FS = dyn_cast(Summary.get())) { for (auto &Call: FS->calls()) { if (Call.first.isGUID()) { addPreservedGUID(Index, Preserved, Call.first.getGUID()); @@ -916,6 +914,10 @@ addPreservedGUID(const ModuleSummaryIndex &Index, addPreservedGUID(Index, Preserved, GUID); } } + if (auto *AS = dyn_cast(Summary.get())) { + auto GUID = AS->getAliasee().getOriginalName(); + addPreservedGUID(Index, Preserved, GUID); + } } } @@ -963,12 +965,13 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // combined index // // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` - computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols); + auto DeadSymbols = computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols); ComputeCrossModuleImport( Ret->Index, Ret->ModuleToDefinedGVSummaries, Ret->ImportLists, - Ret->ExportLists + Ret->ExportLists, + &DeadSymbols ); // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it diff --git a/src/test/run-pass/thinlto/auxiliary/dylib.rs b/src/test/run-pass/thinlto/auxiliary/dylib.rs new file mode 100644 index 00000000000..cdb3f49cae8 --- /dev/null +++ b/src/test/run-pass/thinlto/auxiliary/dylib.rs @@ -0,0 +1,16 @@ +// Copyright 2017 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. + +// compile-flags: -Z thinlto -C codegen-units=8 + +#[inline] +pub fn foo(b: u8) { + b.to_string(); +} diff --git a/src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs b/src/test/run-pass/thinlto/auxiliary/thin-lto-inlines-aux.rs similarity index 100% rename from src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs rename to src/test/run-pass/thinlto/auxiliary/thin-lto-inlines-aux.rs diff --git a/src/test/run-pass/thinlto/dylib-works.rs b/src/test/run-pass/thinlto/dylib-works.rs new file mode 100644 index 00000000000..3f54519d0d8 --- /dev/null +++ b/src/test/run-pass/thinlto/dylib-works.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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. + +// aux-build:dylib.rs +// min-llvm-version 4.0 + +extern crate dylib; + +fn main() { + dylib::foo(1); +} diff --git a/src/test/run-pass/thin-lto-inlines.rs b/src/test/run-pass/thinlto/thin-lto-inlines.rs similarity index 100% rename from src/test/run-pass/thin-lto-inlines.rs rename to src/test/run-pass/thinlto/thin-lto-inlines.rs diff --git a/src/test/run-pass/thin-lto-inlines2.rs b/src/test/run-pass/thinlto/thin-lto-inlines2.rs similarity index 100% rename from src/test/run-pass/thin-lto-inlines2.rs rename to src/test/run-pass/thinlto/thin-lto-inlines2.rs From 3bd9d62963ec81bc54fd26f5f01758596cb97378 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sun, 15 Oct 2017 19:09:25 +0200 Subject: [PATCH 238/365] aarch64 is not whitelisted for ARM features --- src/librustc_trans/llvm_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs index 448feb5259d..d6cc3004f97 100644 --- a/src/librustc_trans/llvm_util.rs +++ b/src/librustc_trans/llvm_util.rs @@ -89,7 +89,7 @@ pub fn target_features(sess: &Session) -> Vec { let target_machine = create_target_machine(sess); let whitelist = match &*sess.target.target.arch { - "arm" => ARM_WHITELIST, + "arm" | "aarch64" => ARM_WHITELIST, "x86" | "x86_64" => X86_WHITELIST, "hexagon" => HEXAGON_WHITELIST, "powerpc" | "powerpc64" => POWERPC_WHITELIST, From 9e0fc5ccd050201e77483b1efb2e6c76f47496f6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 10 Oct 2017 23:06:22 +0300 Subject: [PATCH 239/365] rustbuild: Support specifying archiver and linker explicitly --- config.toml.example | 11 +++- src/Cargo.lock | 1 - src/bootstrap/bin/rustc.rs | 13 ++--- src/bootstrap/bin/rustdoc.rs | 3 ++ src/bootstrap/builder.rs | 50 +++++++++++++----- src/bootstrap/cc_detect.rs | 52 ++++++++++++++++--- src/bootstrap/check.rs | 8 ++- src/bootstrap/config.rs | 8 ++- src/bootstrap/lib.rs | 23 +++++--- src/bootstrap/native.rs | 7 +++ src/bootstrap/tool.rs | 2 +- src/build_helper/lib.rs | 21 -------- src/liballoc_jemalloc/build.rs | 15 +----- src/librustdoc/lib.rs | 8 ++- src/librustdoc/markdown.rs | 4 +- src/librustdoc/test.rs | 18 +++++-- src/libstd/Cargo.toml | 1 - src/libstd/build.rs | 12 +---- .../run-make/archive-duplicate-names/Makefile | 2 +- .../compiler-rt-works-on-mingw/Makefile | 4 +- src/test/run-make/invalid-library/Makefile | 2 +- src/test/run-make/issue-19371/foo.rs | 7 +-- src/test/run-make/issue-22131/Makefile | 2 +- .../run-make/rustdoc-output-path/Makefile | 2 +- .../run-make/staticlib-blank-lib/Makefile | 4 +- src/test/run-make/tools.mk | 10 +++- src/tools/compiletest/src/common.rs | 2 + src/tools/compiletest/src/main.rs | 6 +++ src/tools/compiletest/src/runtest.rs | 10 +++- 29 files changed, 200 insertions(+), 108 deletions(-) diff --git a/config.toml.example b/config.toml.example index a2f64e6b705..f50543e18a7 100644 --- a/config.toml.example +++ b/config.toml.example @@ -300,7 +300,7 @@ # ============================================================================= [target.x86_64-unknown-linux-gnu] -# C compiler to be used to compiler C code and link Rust code. Note that the +# C compiler to be used to compiler C code. Note that the # default value is platform specific, and if not specified it may also depend on # what platform is crossing to what platform. #cc = "cc" @@ -309,6 +309,15 @@ # This is only used for host targets. #cxx = "c++" +# Archiver to be used to assemble static libraries compiled from C/C++ code. +# Note: an absolute path should be used, otherwise LLVM build will break. +#ar = "ar" + +# Linker to be used to link Rust code. Note that the +# default value is platform specific, and if not specified it may also depend on +# what platform is crossing to what platform. +#linker = "cc" + # Path to the `llvm-config` binary of the installation of a custom LLVM to link # against. Note that if this is specifed we don't compile LLVM at all for this # target. diff --git a/src/Cargo.lock b/src/Cargo.lock index aa5e262e85f..2b95be27ffe 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1994,7 +1994,6 @@ dependencies = [ "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index e91acb21dac..e496ce27f50 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -120,12 +120,6 @@ fn main() { cmd.arg("-L").arg(&root); } - // Pass down extra flags, commonly used to configure `-Clinker` when - // cross compiling. - if let Ok(s) = env::var("RUSTC_FLAGS") { - cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::>()); - } - // Pass down incremental directory, if any. if let Ok(dir) = env::var("RUSTC_INCREMENTAL") { cmd.arg(format!("-Zincremental={}", dir)); @@ -254,6 +248,13 @@ fn main() { } } + // Pass down extra flags, commonly used to configure `-Clinker`. + // Linker options should be set for build scripts as well, + // can't link a build script executable without a linker! + if let Ok(s) = env::var("RUSTC_FLAGS") { + cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::>()); + } + let color = match env::var("RUSTC_COLOR") { Ok(s) => usize::from_str(&s).expect("RUSTC_COLOR should be an integer"), Err(_) => 0, diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index d18512b257d..2105797a830 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -47,6 +47,9 @@ fn main() { if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } + if let Some(linker) = env::var_os("RUSTDOC_LINKER") { + cmd.arg("--linker").arg(linker).arg("-Z").arg("unstable-options"); + } // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick // it up so we can make rustdoc print this into the docs diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 1d63e112ca6..ef4f8f78b0d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -413,13 +413,15 @@ impl<'a> Builder<'a> { pub fn rustdoc_cmd(&self, host: Interned) -> Command { let mut cmd = Command::new(&self.out.join("bootstrap/debug/rustdoc")); let compiler = self.compiler(self.top_stage, host); - cmd - .env("RUSTC_STAGE", compiler.stage.to_string()) - .env("RUSTC_SYSROOT", self.sysroot(compiler)) - .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build)) - .env("CFG_RELEASE_CHANNEL", &self.build.config.channel) - .env("RUSTDOC_REAL", self.rustdoc(host)) - .env("RUSTDOC_CRATE_VERSION", self.build.rust_version()); + cmd.env("RUSTC_STAGE", compiler.stage.to_string()) + .env("RUSTC_SYSROOT", self.sysroot(compiler)) + .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build)) + .env("CFG_RELEASE_CHANNEL", &self.build.config.channel) + .env("RUSTDOC_REAL", self.rustdoc(host)) + .env("RUSTDOC_CRATE_VERSION", self.build.rust_version()); + if let Some(linker) = self.build.linker(host) { + cmd.env("RUSTDOC_LINKER", linker); + } cmd } @@ -485,6 +487,10 @@ impl<'a> Builder<'a> { .env("TEST_MIRI", self.config.test_miri.to_string()) .env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")); + if let Some(linker) = self.build.linker(target) { + cargo.env("RUSTDOC_LINKER", linker); + } + if mode != Mode::Tool { // Tools don't get debuginfo right now, e.g. cargo and rls don't // get compiled with debuginfo. @@ -557,17 +563,35 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); - // Specify some various options for build scripts used throughout - // the build. + // Throughout the build Cargo can execute a number of build scripts + // compiling C/C++ code and we need to pass compilers, archivers, flags, etc + // obtained previously to those build scripts. + // Build scripts use either the `cc` crate or `configure/make` so we pass + // the options through environment variables that are fetched and understood by both. // // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { - cargo.env(format!("CC_{}", target), self.cc(target)) - .env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None - .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); + let cc = self.cc(target); + cargo.env(format!("CC_{}", target), cc) + .env("CC", cc); + + let cflags = self.cflags(target).join(" "); + cargo.env(format!("CFLAGS_{}", target), cflags.clone()) + .env("CFLAGS", cflags.clone()); + + if let Some(ar) = self.ar(target) { + let ranlib = format!("{} s", ar.display()); + cargo.env(format!("AR_{}", target), ar) + .env("AR", ar) + .env(format!("RANLIB_{}", target), ranlib.clone()) + .env("RANLIB", ranlib); + } if let Ok(cxx) = self.cxx(target) { - cargo.env(format!("CXX_{}", target), cxx); + cargo.env(format!("CXX_{}", target), cxx) + .env("CXX", cxx) + .env(format!("CXXFLAGS_{}", target), cflags.clone()) + .env("CXXFLAGS", cflags); } } diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index 08df65c7611..6e3e3c92029 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -31,20 +31,51 @@ //! ever be probed for. Instead the compilers found here will be used for //! everything. +use std::collections::HashSet; +use std::{env, iter}; +use std::path::{Path, PathBuf}; use std::process::Command; -use std::iter; -use build_helper::{cc2ar, output}; +use build_helper::output; use cc; use Build; use config::Target; use cache::Interned; +// The `cc` crate doesn't provide a way to obtain a path to the detected archiver, +// so use some simplified logic here. First we respect the environment variable `AR`, then +// try to infer the archiver path from the C compiler path. +// In the future this logic should be replaced by calling into the `cc` crate. +fn cc2ar(cc: &Path, target: &str) -> Option { + if let Some(ar) = env::var_os("AR") { + Some(PathBuf::from(ar)) + } else if target.contains("msvc") { + None + } else if target.contains("musl") { + Some(PathBuf::from("ar")) + } else if target.contains("openbsd") { + Some(PathBuf::from("ar")) + } else { + let parent = cc.parent().unwrap(); + let file = cc.file_name().unwrap().to_str().unwrap(); + for suffix in &["gcc", "cc", "clang"] { + if let Some(idx) = file.rfind(suffix) { + let mut file = file[..idx].to_owned(); + file.push_str("ar"); + return Some(parent.join(&file)); + } + } + Some(parent.join(file)) + } +} + pub fn find(build: &mut Build) { // For all targets we're going to need a C compiler for building some shims // and such as well as for being a linker for Rust code. - for target in build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build)) { + let targets = build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build)) + .collect::>(); + for target in targets.into_iter() { let mut cfg = cc::Build::new(); cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false) .target(&target).host(&build.build); @@ -57,16 +88,23 @@ pub fn find(build: &mut Build) { } let compiler = cfg.get_compiler(); - let ar = cc2ar(compiler.path(), &target); + let ar = if let ar @ Some(..) = config.and_then(|c| c.ar.clone()) { + ar + } else { + cc2ar(compiler.path(), &target) + }; + build.verbose(&format!("CC_{} = {:?}", &target, compiler.path())); - if let Some(ref ar) = ar { + build.cc.insert(target, compiler); + if let Some(ar) = ar { build.verbose(&format!("AR_{} = {:?}", &target, ar)); + build.ar.insert(target, ar); } - build.cc.insert(target, (compiler, ar)); } // For all host triples we need to find a C++ compiler as well - for host in build.hosts.iter().cloned().chain(iter::once(build.build)) { + let hosts = build.hosts.iter().cloned().chain(iter::once(build.build)).collect::>(); + for host in hosts.into_iter() { let mut cfg = cc::Build::new(); cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true) .target(&host).host(&build.build); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index fb32ab0cb86..d9b0ff4c7a4 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -725,6 +725,9 @@ impl Step for Compiletest { // Avoid depending on rustdoc when we don't need it. if mode == "rustdoc" || mode == "run-make" { cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host)); + if let Some(linker) = build.linker(target) { + cmd.arg("--linker").arg(linker); + } } cmd.arg("--src-base").arg(build.src.join("src/test").join(suite)); @@ -806,6 +809,9 @@ impl Step for Compiletest { .arg("--cflags").arg(build.cflags(target).join(" ")) .arg("--llvm-components").arg(llvm_components.trim()) .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim()); + if let Some(ar) = build.ar(target) { + cmd.arg("--ar").arg(ar); + } } } if suite == "run-make" && !build.config.llvm_enabled { @@ -831,7 +837,7 @@ impl Step for Compiletest { // Note that if we encounter `PATH` we make sure to append to our own `PATH` // rather than stomp over it. if target.contains("msvc") { - for &(ref k, ref v) in build.cc[&target].0.env() { + for &(ref k, ref v) in build.cc[&target].env() { if k != "PATH" { cmd.env(k, v); } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5fb5eb3b7f1..69e0f58f1cd 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -143,6 +143,8 @@ pub struct Target { pub jemalloc: Option, pub cc: Option, pub cxx: Option, + pub ar: Option, + pub linker: Option, pub ndk: Option, pub crt_static: Option, pub musl_root: Option, @@ -282,6 +284,8 @@ struct TomlTarget { jemalloc: Option, cc: Option, cxx: Option, + ar: Option, + linker: Option, android_ndk: Option, crt_static: Option, musl_root: Option, @@ -484,8 +488,10 @@ impl Config { if let Some(ref s) = cfg.android_ndk { target.ndk = Some(env::current_dir().unwrap().join(s)); } - target.cxx = cfg.cxx.clone().map(PathBuf::from); target.cc = cfg.cc.clone().map(PathBuf::from); + target.cxx = cfg.cxx.clone().map(PathBuf::from); + target.ar = cfg.ar.clone().map(PathBuf::from); + target.linker = cfg.linker.clone().map(PathBuf::from); target.crt_static = cfg.crt_static.clone(); target.musl_root = cfg.musl_root.clone().map(PathBuf::from); target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2d721f45578..7c599f91838 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -240,10 +240,11 @@ pub struct Build { lldb_python_dir: Option, // Runtime state filled in later on - // target -> (cc, ar) - cc: HashMap, (cc::Tool, Option)>, - // host -> (cc, ar) + // C/C++ compilers and archiver for all targets + cc: HashMap, cc::Tool>, cxx: HashMap, cc::Tool>, + ar: HashMap, PathBuf>, + // Misc crates: HashMap, Crate>, is_sudo: bool, ci_env: CiEnv, @@ -324,6 +325,7 @@ impl Build { rls_info, cc: HashMap::new(), cxx: HashMap::new(), + ar: HashMap::new(), crates: HashMap::new(), lldb_version: None, lldb_python_dir: None, @@ -612,7 +614,7 @@ impl Build { /// Returns the path to the C compiler for the target specified. fn cc(&self, target: Interned) -> &Path { - self.cc[&target].0.path() + self.cc[&target].path() } /// Returns a list of flags to pass to the C compiler for the target @@ -620,7 +622,7 @@ impl Build { fn cflags(&self, target: Interned) -> Vec { // Filter out -O and /O (the optimization flags) that we picked up from // cc-rs because the build scripts will determine that for themselves. - let mut base = self.cc[&target].0.args().iter() + let mut base = self.cc[&target].args().iter() .map(|s| s.to_string_lossy().into_owned()) .filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) .collect::>(); @@ -644,7 +646,11 @@ impl Build { /// Returns the path to the `ar` archive utility for the target specified. fn ar(&self, target: Interned) -> Option<&Path> { - self.cc[&target].1.as_ref().map(|p| &**p) + self.ar.get(&target).map(|p| &**p) + } + + fn linker(&self, target: Interned) -> Option<&Path> { + self.config.target_config.get(&target).and_then(|c| c.linker.as_ref().map(|p| &**p)) } /// Returns the path to the C++ compiler for the target specified. @@ -667,7 +673,10 @@ impl Build { // than an entry here. let mut base = Vec::new(); - if target != self.config.build && !target.contains("msvc") && + if let Some(linker) = self.linker(target) { + // If linker was explictly provided, force it on all the compiled Rust code. + base.push(format!("-Clinker={}", linker.display())); + } else if target != self.config.build && !target.contains("msvc") && !target.contains("emscripten") { base.push(format!("-Clinker={}", self.cc(target).display())); } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 2c8e5004041..941ea96bbec 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -227,6 +227,13 @@ impl Step for Llvm { cfg.build_arg("-j").build_arg(build.jobs().to_string()); cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" ")); + if let Some(ar) = build.ar(target) { + if ar.is_absolute() { + // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it + // tries to resolve this path in the LLVM build directory. + cfg.define("CMAKE_AR", sanitize_cc(ar)); + } + } }; configure_compilers(&mut cfg); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index e95a5e07436..662c56d728d 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -561,7 +561,7 @@ impl<'a> Builder<'a> { if compiler.host.contains("msvc") { let curpaths = env::var_os("PATH").unwrap_or_default(); let curpaths = env::split_paths(&curpaths).collect::>(); - for &(ref k, ref v) in self.cc[&compiler.host].0.env() { + for &(ref k, ref v) in self.cc[&compiler.host].env() { if k != "PATH" { continue } diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index e81dab70b43..97723e260f6 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -138,27 +138,6 @@ pub fn gnu_target(target: &str) -> String { } } -pub fn cc2ar(cc: &Path, target: &str) -> Option { - if target.contains("msvc") { - None - } else if target.contains("musl") { - Some(PathBuf::from("ar")) - } else if target.contains("openbsd") { - Some(PathBuf::from("ar")) - } else { - let parent = cc.parent().unwrap(); - let file = cc.file_name().unwrap().to_str().unwrap(); - for suffix in &["gcc", "cc", "clang"] { - if let Some(idx) = file.rfind(suffix) { - let mut file = file[..idx].to_owned(); - file.push_str("ar"); - return Some(parent.join(&file)); - } - } - Some(parent.join(file)) - } -} - pub fn make(host: &str) -> PathBuf { if host.contains("bitrig") || host.contains("dragonfly") || host.contains("freebsd") || host.contains("netbsd") || diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 7dd85ddcc79..65e035d4ffd 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -63,15 +63,6 @@ fn main() { _ => return, }; - let compiler = cc::Build::new().get_compiler(); - // only msvc returns None for ar so unwrap is okay - let ar = build_helper::cc2ar(compiler.path(), &target).unwrap(); - let cflags = compiler.args() - .iter() - .map(|s| s.to_str().unwrap()) - .collect::>() - .join(" "); - let mut cmd = Command::new("sh"); cmd.arg(native.src_dir.join("configure") .to_str() @@ -79,8 +70,6 @@ fn main() { .replace("C:\\", "/c/") .replace("\\", "/")) .current_dir(&native.out_dir) - .env("CC", compiler.path()) - .env("EXTRA_CFLAGS", cflags.clone()) // jemalloc generates Makefile deps using GCC's "-MM" flag. This means // that GCC will run the preprocessor, and only the preprocessor, over // jemalloc's source files. If we don't specify CPPFLAGS, then at least @@ -89,9 +78,7 @@ fn main() { // passed to GCC, and then GCC won't define the // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to // select an atomic operation implementation. - .env("CPPFLAGS", cflags.clone()) - .env("AR", &ar) - .env("RANLIB", format!("{} s", ar.display())); + .env("CPPFLAGS", env::var_os("CFLAGS").unwrap_or_default()); if target.contains("ios") { cmd.arg("--disable-tls"); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f8bf00ad73f..890e1169c05 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -246,6 +246,9 @@ pub fn opts() -> Vec { unstable("crate-version", |o| { o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") }), + unstable("linker", |o| { + o.optopt("", "linker", "linker used for building executable test code", "PATH") + }), ] } @@ -357,15 +360,16 @@ pub fn main_args(args: &[String]) -> isize { let playground_url = matches.opt_str("playground-url"); let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); let display_warnings = matches.opt_present("display-warnings"); + let linker = matches.opt_str("linker"); match (should_test, markdown_input) { (true, true) => { return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot, render_type, - display_warnings) + display_warnings, linker) } (true, false) => { return test::run(input, cfgs, libs, externs, test_args, crate_name, maybe_sysroot, - render_type, display_warnings) + render_type, display_warnings, linker) } (false, true) => return markdown::render(input, output.unwrap_or(PathBuf::from("doc")), diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 484285e91f6..fe6bd985bb6 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -142,7 +142,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, /// Run any tests/code examples in the markdown file `input`. pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, mut test_args: Vec, maybe_sysroot: Option, - render_type: RenderType, display_warnings: bool) -> isize { + render_type: RenderType, display_warnings: bool, linker: Option) -> isize { let input_str = match load_string(input) { Ok(s) => s, Err(LoadStringError::ReadFail) => return 1, @@ -154,7 +154,7 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, let mut collector = Collector::new(input.to_string(), cfgs, libs, externs, true, opts, maybe_sysroot, None, Some(input.to_owned()), - render_type); + render_type, linker); if render_type == RenderType::Pulldown { old_find_testable_code(&input_str, &mut collector, DUMMY_SP); find_testable_code(&input_str, &mut collector, DUMMY_SP); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 4b2980bc3a6..8b2c8d2da39 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -61,7 +61,8 @@ pub fn run(input: &str, crate_name: Option, maybe_sysroot: Option, render_type: RenderType, - display_warnings: bool) + display_warnings: bool, + linker: Option) -> isize { let input_path = PathBuf::from(input); let input = config::Input::File(input_path.clone()); @@ -121,7 +122,8 @@ pub fn run(input: &str, maybe_sysroot, Some(codemap), None, - render_type); + render_type, + linker); { let map = hir::map::map_crate(&sess, &*cstore, &mut hir_forest, &defs); @@ -180,7 +182,8 @@ fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec, libs externs: Externs, should_panic: bool, no_run: bool, as_test_harness: bool, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, - maybe_sysroot: Option) { + maybe_sysroot: Option, + linker: Option) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` let test = make_test(test, Some(cratename), as_test_harness, opts); @@ -201,6 +204,7 @@ fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec, libs externs, cg: config::CodegenOptions { prefer_dynamic: true, + linker, .. config::basic_codegen_options() }, test: as_test_harness, @@ -442,13 +446,14 @@ pub struct Collector { filename: Option, // to be removed when hoedown will be removed as well pub render_type: RenderType, + linker: Option, } impl Collector { pub fn new(cratename: String, cfgs: Vec, libs: SearchPaths, externs: Externs, use_headers: bool, opts: TestOptions, maybe_sysroot: Option, codemap: Option>, filename: Option, - render_type: RenderType) -> Collector { + render_type: RenderType, linker: Option) -> Collector { Collector { tests: Vec::new(), old_tests: HashMap::new(), @@ -464,6 +469,7 @@ impl Collector { codemap, filename, render_type, + linker, } } @@ -510,6 +516,7 @@ impl Collector { let cratename = self.cratename.to_string(); let opts = self.opts.clone(); let maybe_sysroot = self.maybe_sysroot.clone(); + let linker = self.linker.clone(); debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { @@ -538,7 +545,8 @@ impl Collector { compile_fail, error_codes, &opts, - maybe_sysroot) + maybe_sysroot, + linker) }) } { Ok(()) => (), diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index c95287390b4..866c0038a7f 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -36,7 +36,6 @@ rustc_tsan = { path = "../librustc_tsan" } [build-dependencies] build_helper = { path = "../build_helper" } -cc = "1.0.1" [features] backtrace = [] diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 7ca762c801a..0e6214ea04f 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -11,7 +11,6 @@ #![deny(warnings)] extern crate build_helper; -extern crate cc; use std::env; use std::process::Command; @@ -77,12 +76,6 @@ fn main() { fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> { let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?; - let compiler = cc::Build::new().get_compiler(); - // only msvc returns None for ar so unwrap is okay - let ar = build_helper::cc2ar(compiler.path(), target).unwrap(); - let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap()) - .collect::>().join(" "); - cflags.push_str(" -fvisibility=hidden"); run(Command::new("sh") .current_dir(&native.out_dir) .arg(native.src_dir.join("configure").to_str().unwrap() @@ -94,10 +87,7 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> { .arg("--disable-host-shared") .arg(format!("--host={}", build_helper::gnu_target(target))) .arg(format!("--build={}", build_helper::gnu_target(host))) - .env("CC", compiler.path()) - .env("AR", &ar) - .env("RANLIB", format!("{} s", ar.display())) - .env("CFLAGS", cflags), + .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"), BuildExpectation::None); run(Command::new(build_helper::make(host)) diff --git a/src/test/run-make/archive-duplicate-names/Makefile b/src/test/run-make/archive-duplicate-names/Makefile index 5202e6dea54..93711c41d79 100644 --- a/src/test/run-make/archive-duplicate-names/Makefile +++ b/src/test/run-make/archive-duplicate-names/Makefile @@ -5,7 +5,7 @@ all: mkdir $(TMPDIR)/b $(call COMPILE_OBJ,$(TMPDIR)/a/foo.o,foo.c) $(call COMPILE_OBJ,$(TMPDIR)/b/foo.o,bar.c) - ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o + $(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o $(RUSTC) foo.rs $(RUSTC) bar.rs $(call RUN,bar) diff --git a/src/test/run-make/compiler-rt-works-on-mingw/Makefile b/src/test/run-make/compiler-rt-works-on-mingw/Makefile index 4ec54f73e67..06d1bb6698e 100644 --- a/src/test/run-make/compiler-rt-works-on-mingw/Makefile +++ b/src/test/run-make/compiler-rt-works-on-mingw/Makefile @@ -3,8 +3,8 @@ ifneq (,$(findstring MINGW,$(UNAME))) ifndef IS_MSVC all: - g++ foo.cpp -c -o $(TMPDIR)/foo.o - ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o + $(CXX) foo.cpp -c -o $(TMPDIR)/foo.o + $(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o $(RUSTC) foo.rs -lfoo -lstdc++ $(call RUN,foo) else diff --git a/src/test/run-make/invalid-library/Makefile b/src/test/run-make/invalid-library/Makefile index 0dbe655b77d..5c9cc993509 100644 --- a/src/test/run-make/invalid-library/Makefile +++ b/src/test/run-make/invalid-library/Makefile @@ -2,5 +2,5 @@ all: touch $(TMPDIR)/rust.metadata.bin - ar crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/rust.metadata.bin + $(AR) crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/rust.metadata.bin $(RUSTC) foo.rs 2>&1 | grep "can't find crate for" diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs index 461df49b468..4db027aaeef 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make/issue-19371/foo.rs @@ -18,7 +18,6 @@ extern crate rustc_errors; extern crate rustc_trans; extern crate syntax; -use rustc::dep_graph::DepGraph; use rustc::session::{build_session, Session}; use rustc::session::config::{basic_options, build_configuration, Input, OutputType, OutputTypes}; @@ -56,6 +55,9 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc) { let mut opts = basic_options(); opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); opts.maybe_sysroot = Some(sysroot); + if let Ok(linker) = std::env::var("RUSTC_LINKER") { + opts.cg.linker = Some(linker); + } let descriptions = Registry::new(&rustc::DIAGNOSTICS); let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader))); @@ -67,8 +69,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc) { fn compile(code: String, output: PathBuf, sysroot: PathBuf) { let (sess, cstore) = basic_sess(sysroot); - let cfg = build_configuration(&sess, HashSet::new()); let control = CompileController::basic(); let input = Input::Str { name: anon_src(), input: code }; - compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control); + let _ = compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control); } diff --git a/src/test/run-make/issue-22131/Makefile b/src/test/run-make/issue-22131/Makefile index 64af91b487b..cb4f1462733 100644 --- a/src/test/run-make/issue-22131/Makefile +++ b/src/test/run-make/issue-22131/Makefile @@ -2,6 +2,6 @@ all: foo.rs $(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs - $(HOST_RPATH_ENV) '$(RUSTDOC)' --test --cfg 'feature="bar"' \ + $(RUSTDOC) --test --cfg 'feature="bar"' \ -L $(TMPDIR) foo.rs |\ grep -q 'foo.rs - foo (line 11) ... ok' diff --git a/src/test/run-make/rustdoc-output-path/Makefile b/src/test/run-make/rustdoc-output-path/Makefile index 4e570718a62..8ce1c699526 100644 --- a/src/test/run-make/rustdoc-output-path/Makefile +++ b/src/test/run-make/rustdoc-output-path/Makefile @@ -1,4 +1,4 @@ -include ../tools.mk all: - $(HOST_RPATH_ENV) '$(RUSTDOC)' -o "$(TMPDIR)/foo/bar/doc" foo.rs + $(RUSTDOC) -o "$(TMPDIR)/foo/bar/doc" foo.rs diff --git a/src/test/run-make/staticlib-blank-lib/Makefile b/src/test/run-make/staticlib-blank-lib/Makefile index 5878eec66ba..92a278825c2 100644 --- a/src/test/run-make/staticlib-blank-lib/Makefile +++ b/src/test/run-make/staticlib-blank-lib/Makefile @@ -1,6 +1,6 @@ -include ../tools.mk all: - ar crus $(TMPDIR)/libfoo.a foo.rs - ar d $(TMPDIR)/libfoo.a foo.rs + $(AR) crus $(TMPDIR)/libfoo.a foo.rs + $(AR) d $(TMPDIR)/libfoo.a foo.rs $(RUSTC) foo.rs diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index 27f235d54d4..c5d5626bf72 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -7,7 +7,13 @@ TARGET_RPATH_ENV = \ RUSTC_ORIGINAL := $(RUSTC) BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)' +BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)' RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS) +RUSTDOC := $(BARE_RUSTDOC) +ifdef RUSTC_LINKER +RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER) +RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options +endif #CC := $(CC) -L $(TMPDIR) HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py @@ -102,13 +108,13 @@ REMOVE_DYLIBS = rm $(TMPDIR)/$(call DYLIB_GLOB,$(1)) REMOVE_RLIBS = rm $(TMPDIR)/$(call RLIB_GLOB,$(1)) %.a: %.o - ar crus $@ $< + $(AR) crus $@ $< ifdef IS_MSVC %.lib: lib%.o $(MSVC_LIB) -out:`cygpath -w $@` $< else %.lib: lib%.o - ar crus $@ $< + $(AR) crus $@ $< endif %.dylib: %.o $(CC) -dynamiclib -Wl,-dylib -o $@ $< diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index cee7e52c7f3..aa98f818f40 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -201,6 +201,8 @@ pub struct Config { pub cc: String, pub cxx: String, pub cflags: String, + pub ar: String, + pub linker: Option, pub llvm_components: String, pub llvm_cxxflags: String, pub nodejs: Option, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 306497da9e3..1701c8a3e43 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -102,6 +102,8 @@ pub fn parse_config(args: Vec ) -> Config { .reqopt("", "cc", "path to a C compiler", "PATH") .reqopt("", "cxx", "path to a C++ compiler", "PATH") .reqopt("", "cflags", "flags for the C compiler", "FLAGS") + .optopt("", "ar", "path to an archiver", "PATH") + .optopt("", "linker", "path to a linker", "PATH") .reqopt("", "llvm-components", "list of LLVM components built in", "LIST") .reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS") .optopt("", "nodejs", "the name of nodejs", "PATH") @@ -198,6 +200,8 @@ pub fn parse_config(args: Vec ) -> Config { cc: matches.opt_str("cc").unwrap(), cxx: matches.opt_str("cxx").unwrap(), cflags: matches.opt_str("cflags").unwrap(), + ar: matches.opt_str("ar").unwrap_or("ar".into()), + linker: matches.opt_str("linker"), llvm_components: matches.opt_str("llvm-components").unwrap(), llvm_cxxflags: matches.opt_str("llvm-cxxflags").unwrap(), nodejs: matches.opt_str("nodejs"), @@ -234,6 +238,8 @@ pub fn log_config(config: &Config) { logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir)); logv(c, format!("adb_device_status: {}", config.adb_device_status)); + logv(c, format!("ar: {}", config.ar)); + logv(c, format!("linker: {:?}", config.linker)); logv(c, format!("verbose: {}", config.verbose)); logv(c, format!("quiet: {}", config.quiet)); logv(c, "\n".to_string()); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 60acc20e692..6d53c70bff6 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1155,6 +1155,9 @@ actual:\n\ .arg("-o").arg(out_dir) .arg(&self.testpaths.file) .args(&self.props.compile_flags); + if let Some(ref linker) = self.config.linker { + rustdoc.arg("--linker").arg(linker).arg("-Z").arg("unstable-options"); + } self.compose_and_run_compiler(rustdoc, None) } @@ -2101,6 +2104,10 @@ actual:\n\ .env("LLVM_COMPONENTS", &self.config.llvm_components) .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags); + if let Some(ref linker) = self.config.linker { + cmd.env("RUSTC_LINKER", linker); + } + // We don't want RUSTFLAGS set from the outside to interfere with // compiler flags set in the test cases: cmd.env_remove("RUSTFLAGS"); @@ -2123,7 +2130,8 @@ actual:\n\ .env("CXX", &self.config.cxx); } else { cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags)) - .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags)); + .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags)) + .env("AR", &self.config.ar); if self.config.target.contains("windows") { cmd.env("IS_WINDOWS", "1"); From 549f8553dc487359b066c6857f7e4996e832d033 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Sun, 15 Oct 2017 14:25:53 -0500 Subject: [PATCH 240/365] Refactor `ensure` and `try_get_with` into `read_node_index` There was a bit of code shared between `try_get_with` and `ensure`, after I added `ensure`. I refactored that shared code into a query-agnostic method called `read_node_index`. The new method `read_node_index` will attempt to find the node index (`DepNodeIndex`) of a query. When `read_node_index` finds the `DepNodeIndex`, it marks the current query as a reader of the node it's requesting the index of. This is used by `try_get_with` and `ensure` as it elides the unimportant (to them) details of if the query is invalidated by previous changed computation (Red) or new and if they had to mark the query green. For both `try_get_with` and `ensure`, they just need to know if they can lookup the results or have to reevaluate. --- src/librustc/dep_graph/graph.rs | 34 +++++++++++++++++++ src/librustc/ty/maps/plumbing.rs | 57 +++++--------------------------- 2 files changed, 43 insertions(+), 48 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 8aff042955c..38a27305c2b 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -427,6 +427,40 @@ impl DepGraph { self.data.as_ref().and_then(|data| data.colors.borrow().get(dep_node).cloned()) } + /// Try to read a node index for the node dep_node. + /// A node will have an index, when it's already been marked green, or when we can mark it + /// green. This function will mark the current task as a reader of the specified node, when + /// the a node index can be found for that node. + pub fn read_node_index(&self, tcx: TyCtxt, dep_node: &DepNode) -> Option { + match self.node_color(dep_node) { + Some(DepNodeColor::Green(dep_node_index)) => { + self.read_index(dep_node_index); + Some(dep_node_index) + } + Some(DepNodeColor::Red) => { + None + } + None => { + // try_mark_green (called below) will panic when full incremental + // compilation is disabled. If that's the case, we can't try to mark nodes + // as green anyway, so we can safely return None here. + if !self.is_fully_enabled() { + return None; + } + match self.try_mark_green(tcx, &dep_node) { + Some(dep_node_index) => { + debug_assert!(tcx.dep_graph.is_green(dep_node_index)); + tcx.dep_graph.read_index(dep_node_index); + Some(dep_node_index) + } + None => { + None + } + } + } + } + } + pub fn try_mark_green(&self, tcx: TyCtxt, dep_node: &DepNode) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index d6eaf6d1bc4..13880b37136 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -309,25 +309,8 @@ macro_rules! define_maps { } if !dep_node.kind.is_input() { - use dep_graph::DepNodeColor; - if let Some(DepNodeColor::Green(dep_node_index)) = tcx.dep_graph - .node_color(&dep_node) { + if let Some(dep_node_index) = tcx.dep_graph.read_node_index(tcx, &dep_node) { profq_msg!(tcx, ProfileQueriesMsg::CacheHit); - tcx.dep_graph.read_index(dep_node_index); - return Self::load_from_disk_and_cache_in_memory(tcx, - key, - span, - dep_node_index) - } - - debug!("ty::queries::{}::try_get_with(key={:?}) - running try_mark_green", - stringify!($name), - key); - - if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, &dep_node) { - debug_assert!(tcx.dep_graph.is_green(dep_node_index)); - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); - tcx.dep_graph.read_index(dep_node_index); return Self::load_from_disk_and_cache_in_memory(tcx, key, span, @@ -357,36 +340,14 @@ macro_rules! define_maps { // Ensuring an "input" or anonymous query makes no sense assert!(!dep_node.kind.is_anon()); assert!(!dep_node.kind.is_input()); - use dep_graph::DepNodeColor; - match tcx.dep_graph.node_color(&dep_node) { - Some(DepNodeColor::Green(dep_node_index)) => { - tcx.dep_graph.read_index(dep_node_index); - } - Some(DepNodeColor::Red) => { - // A DepNodeColor::Red DepNode means that this query was executed - // before. We can not call `dep_graph.read()` here as we don't have - // the DepNodeIndex. Instead, We call the query again to issue the - // appropriate `dep_graph.read()` call. The performance cost this - // introduces should be negligible as we'll immediately hit the - // in-memory cache. - let _ = tcx.$name(key); - } - None => { - // Huh - if !tcx.dep_graph.is_fully_enabled() { - let _ = tcx.$name(key); - return; - } - match tcx.dep_graph.try_mark_green(tcx, &dep_node) { - Some(dep_node_index) => { - debug_assert!(tcx.dep_graph.is_green(dep_node_index)); - tcx.dep_graph.read_index(dep_node_index); - } - None => { - let _ = tcx.$name(key); - } - } - } + if tcx.dep_graph.read_node_index(tcx, &dep_node).is_none() { + // A None return from `read_node_index` means that this is either + // a new dep node or that the dep node has already been marked red. + // Either way, we can't call `dep_graph.read()` as we don't have the + // DepNodeIndex. We must invoke the query itself. The performance cost + // this introduces should be negligible as we'll immediately hit the + // in-memory cache, or another query down the line will. + let _ = tcx.$name(key); } } From 045916603ed55c95169770ed4423d5da18411335 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Sun, 15 Oct 2017 12:00:22 -0700 Subject: [PATCH 241/365] Add test for #40003. --- src/test/run-pass/issue-40003.rs | 186 +++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/test/run-pass/issue-40003.rs diff --git a/src/test/run-pass/issue-40003.rs b/src/test/run-pass/issue-40003.rs new file mode 100644 index 00000000000..103a365af0e --- /dev/null +++ b/src/test/run-pass/issue-40003.rs @@ -0,0 +1,186 @@ +// Copyright 2017 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. + +fn main() { + if false { test(); } +} + +fn test() { + let rx = Err::, u32>(1).into_future(); + + rx.map(|l: Vec| stream::iter(l.into_iter().map(|i| Ok(i)))) + .flatten_stream() + .chunks(50) + .buffer_unordered(5); +} + +use future::{Future, IntoFuture}; +mod future { + use std::result; + + use {stream, Stream}; + + pub trait Future { + type Item; + type Error; + + fn map(self, _: F) -> Map + where F: FnOnce(Self::Item) -> U, + Self: Sized, + { + panic!() + } + + fn flatten_stream(self) -> FlattenStream + where ::Item: stream::Stream, + Self: Sized + { + panic!() + } + } + + pub trait IntoFuture { + type Future: Future; + type Item; + type Error; + fn into_future(self) -> Self::Future; + } + + impl IntoFuture for F { + type Future = F; + type Item = F::Item; + type Error = F::Error; + + fn into_future(self) -> F { + panic!() + } + } + + impl IntoFuture for result::Result { + type Future = FutureResult; + type Item = T; + type Error = E; + + fn into_future(self) -> FutureResult { + panic!() + } + } + + pub struct Map { + _a: (A, F), + } + + impl Future for Map + where A: Future, + F: FnOnce(A::Item) -> U, + { + type Item = U; + type Error = A::Error; + } + + pub struct FlattenStream { + _f: F, + } + + impl Stream for FlattenStream + where F: Future, + ::Item: Stream, + { + type Item = ::Item; + type Error = ::Error; + } + + pub struct FutureResult { + _inner: (T, E), + } + + impl Future for FutureResult { + type Item = T; + type Error = E; + } +} + +mod stream { + use IntoFuture; + + pub trait Stream { + type Item; + type Error; + + fn buffer_unordered(self, amt: usize) -> BufferUnordered + where Self::Item: IntoFuture::Error>, + Self: Sized + { + new(self, amt) + } + + fn chunks(self, _capacity: usize) -> Chunks + where Self: Sized + { + panic!() + } + } + + pub struct IterStream { + _iter: I, + } + + pub fn iter(_: J) -> IterStream + where J: IntoIterator>, + { + panic!() + } + + impl Stream for IterStream + where I: Iterator>, + { + type Item = T; + type Error = E; + } + + pub struct Chunks { + _stream: S + } + + impl Stream for Chunks + where S: Stream + { + type Item = Result::Item>, u32>; + type Error = ::Error; + } + + pub struct BufferUnordered { + _stream: S, + } + + enum Slot { + Next(usize), + _Data { _a: T }, + } + + fn new(_s: S, _amt: usize) -> BufferUnordered + where S: Stream, + S::Item: IntoFuture::Error>, + { + (0..0).map(|_| { + Slot::Next::<::Future>(1) + }).collect::>(); + panic!() + } + + impl Stream for BufferUnordered + where S: Stream, + S::Item: IntoFuture::Error>, + { + type Item = ::Item; + type Error = ::Error; + } +} +use stream::Stream; From 89d9ce4ec3c134ab62e9eea18a9620face8f88b7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 15 Oct 2017 21:39:16 +0300 Subject: [PATCH 242/365] Don't use target's linker when linking build scripts --- src/bootstrap/bin/rustc.rs | 17 +++++++++------- src/bootstrap/bin/rustdoc.rs | 2 +- src/bootstrap/builder.rs | 12 ++++++----- src/bootstrap/check.rs | 13 ++++++------ src/bootstrap/lib.rs | 30 +++++++++------------------- src/tools/compiletest/src/runtest.rs | 3 +++ 6 files changed, 36 insertions(+), 41 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index e496ce27f50..aeeda85e924 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -120,6 +120,11 @@ fn main() { cmd.arg("-L").arg(&root); } + // Override linker if necessary. + if let Ok(target_linker) = env::var("RUSTC_TARGET_LINKER") { + cmd.arg(format!("-Clinker={}", target_linker)); + } + // Pass down incremental directory, if any. if let Ok(dir) = env::var("RUSTC_INCREMENTAL") { cmd.arg(format!("-Zincremental={}", dir)); @@ -246,13 +251,11 @@ fn main() { if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } - } - - // Pass down extra flags, commonly used to configure `-Clinker`. - // Linker options should be set for build scripts as well, - // can't link a build script executable without a linker! - if let Ok(s) = env::var("RUSTC_FLAGS") { - cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::>()); + } else { + // Override linker if necessary. + if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { + cmd.arg(format!("-Clinker={}", host_linker)); + } } let color = match env::var("RUSTC_COLOR") { diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index 2105797a830..4e975adc972 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -47,7 +47,7 @@ fn main() { if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } - if let Some(linker) = env::var_os("RUSTDOC_LINKER") { + if let Some(linker) = env::var_os("RUSTC_TARGET_LINKER") { cmd.arg("--linker").arg(linker).arg("-Z").arg("unstable-options"); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index ef4f8f78b0d..6480b5a619c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -420,7 +420,7 @@ impl<'a> Builder<'a> { .env("RUSTDOC_REAL", self.rustdoc(host)) .env("RUSTDOC_CRATE_VERSION", self.build.rust_version()); if let Some(linker) = self.build.linker(host) { - cmd.env("RUSTDOC_LINKER", linker); + cmd.env("RUSTC_TARGET_LINKER", linker); } cmd } @@ -484,11 +484,13 @@ impl<'a> Builder<'a> { } else { PathBuf::from("/path/to/nowhere/rustdoc/not/required") }) - .env("TEST_MIRI", self.config.test_miri.to_string()) - .env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")); + .env("TEST_MIRI", self.config.test_miri.to_string()); - if let Some(linker) = self.build.linker(target) { - cargo.env("RUSTDOC_LINKER", linker); + if let Some(host_linker) = self.build.linker(compiler.host) { + cargo.env("RUSTC_HOST_LINKER", host_linker); + } + if let Some(target_linker) = self.build.linker(target) { + cargo.env("RUSTC_TARGET_LINKER", target_linker); } if mode != Mode::Tool { diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index d9b0ff4c7a4..d9ee63eef8c 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -725,9 +725,6 @@ impl Step for Compiletest { // Avoid depending on rustdoc when we don't need it. if mode == "rustdoc" || mode == "run-make" { cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host)); - if let Some(linker) = build.linker(target) { - cmd.arg("--linker").arg(linker); - } } cmd.arg("--src-base").arg(build.src.join("src/test").join(suite)); @@ -750,12 +747,14 @@ impl Step for Compiletest { flags.push("-g".to_string()); } - let mut hostflags = build.rustc_flags(compiler.host); - hostflags.extend(flags.clone()); + if let Some(linker) = build.linker(target) { + cmd.arg("--linker").arg(linker); + } + + let hostflags = flags.clone(); cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); - let mut targetflags = build.rustc_flags(target); - targetflags.extend(flags); + let mut targetflags = flags.clone(); targetflags.push(format!("-Lnative={}", build.test_helpers_out(target).display())); cmd.arg("--target-rustcflags").arg(targetflags.join(" ")); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7c599f91838..63dc17910f0 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -649,10 +649,6 @@ impl Build { self.ar.get(&target).map(|p| &**p) } - fn linker(&self, target: Interned) -> Option<&Path> { - self.config.target_config.get(&target).and_then(|c| c.linker.as_ref().map(|p| &**p)) - } - /// Returns the path to the C++ compiler for the target specified. fn cxx(&self, target: Interned) -> Result<&Path, String> { match self.cxx.get(&target) { @@ -663,24 +659,16 @@ impl Build { } } - /// Returns flags to pass to the compiler to generate code for `target`. - fn rustc_flags(&self, target: Interned) -> Vec { - // New flags should be added here with great caution! - // - // It's quite unfortunate to **require** flags to generate code for a - // target, so it should only be passed here if absolutely necessary! - // Most default configuration should be done through target specs rather - // than an entry here. - - let mut base = Vec::new(); - if let Some(linker) = self.linker(target) { - // If linker was explictly provided, force it on all the compiled Rust code. - base.push(format!("-Clinker={}", linker.display())); - } else if target != self.config.build && !target.contains("msvc") && - !target.contains("emscripten") { - base.push(format!("-Clinker={}", self.cc(target).display())); + /// Returns the path to the linker for the given target if it needs to be overriden. + fn linker(&self, target: Interned) -> Option<&Path> { + if let Some(config) = self.config.target_config.get(&target) { + config.linker.as_ref().map(|p| &**p) + } else if target != self.config.build && + !target.contains("msvc") && !target.contains("emscripten") { + Some(self.cc(target)) + } else { + None } - base } /// Returns if this target should statically link the C runtime, if specified diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 6d53c70bff6..d61077643f1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1444,6 +1444,9 @@ actual:\n\ } else { rustc.args(self.split_maybe_args(&self.config.target_rustcflags)); } + if let Some(ref linker) = self.config.linker { + rustc.arg(format!("-Clinker={}", linker)); + } rustc.args(&self.props.compile_flags); From 0577b60832627e774337456ecbb9bfc9dbb0b0fc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 16 Oct 2017 03:20:01 +0300 Subject: [PATCH 243/365] Re-enable linker override for cross-compilation --- src/bootstrap/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 63dc17910f0..6ac919d3fbd 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -661,8 +661,9 @@ impl Build { /// Returns the path to the linker for the given target if it needs to be overriden. fn linker(&self, target: Interned) -> Option<&Path> { - if let Some(config) = self.config.target_config.get(&target) { - config.linker.as_ref().map(|p| &**p) + if let Some(linker) = self.config.target_config.get(&target) + .and_then(|c| c.linker.as_ref()) { + Some(linker) } else if target != self.config.build && !target.contains("msvc") && !target.contains("emscripten") { Some(self.cc(target)) From 696612c02f7e64b8ca5f62c4614d0cb5b20ff9b7 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sun, 15 Oct 2017 19:02:45 -0700 Subject: [PATCH 244/365] don't issue "expected statement after outer attr." after inner attr. While an inner attribute here is in fact erroneous, that error ("inner attribute is not permitted in this context") successfully gets set earlier; this further admonition is nonsensical. Resolves #45296. --- src/libsyntax/parse/parser.rs | 4 ++-- src/test/ui/issue-45296.rs | 15 +++++++++++++++ src/test/ui/issue-45296.stderr | 11 +++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/issue-45296.rs create mode 100644 src/test/ui/issue-45296.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bd400ef6dd6..8fd2bad4e44 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4088,11 +4088,11 @@ impl<'a> Parser<'a> { node: StmtKind::Item(i), }, None => { - let unused_attrs = |attrs: &[_], s: &mut Self| { + let unused_attrs = |attrs: &[Attribute], s: &mut Self| { if !attrs.is_empty() { if s.prev_token_kind == PrevTokenKind::DocComment { s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit(); - } else { + } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) { s.span_err(s.span, "expected statement after outer attribute"); } } diff --git a/src/test/ui/issue-45296.rs b/src/test/ui/issue-45296.rs new file mode 100644 index 00000000000..7a2b4e56d69 --- /dev/null +++ b/src/test/ui/issue-45296.rs @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +fn main() { + let unused = (); + + #![allow(unused_variables)] +} diff --git a/src/test/ui/issue-45296.stderr b/src/test/ui/issue-45296.stderr new file mode 100644 index 00000000000..7bfcac974c5 --- /dev/null +++ b/src/test/ui/issue-45296.stderr @@ -0,0 +1,11 @@ +error: an inner attribute is not permitted in this context + --> $DIR/issue-45296.rs:14:7 + | +14 | #![allow(unused_variables)] + | ^ + | + = note: inner attributes and doc comments, like `#![no_std]` or `//! My crate`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes and doc comments, like `#[test]` and + `/// My function`, annotate the item following them. + +error: aborting due to previous error + From 57f03ea5ff899c6567e18ad9e6b1f45288227340 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Sun, 15 Oct 2017 21:18:08 -0700 Subject: [PATCH 245/365] Mark block exits as reachable if the block can break. --- src/librustc/hir/lowering.rs | 2 +- src/librustc_typeck/check/mod.rs | 7 +++++++ src/test/run-pass/issue-45124.rs | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issue-45124.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 54aecb4b00f..848da9637a2 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2547,7 +2547,7 @@ impl<'a> LoweringContext<'a> { }; // Err(err) => #[allow(unreachable_code)] - // return Carrier::from_error(From::from(err)), + // return Try::from_error(From::from(err)), let err_arm = { let err_ident = self.str_to_ident("err"); let err_local = self.pat_ident(e.span, err_ident); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6e263bdb1ad..0e85ea47d56 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4284,6 +4284,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr) }; + let prev_diverges = self.diverges.get(); let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false, @@ -4333,6 +4334,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }); + if ctxt.may_break { + // If we can break from the block, then the block's exit is always reachable + // (... as long as the entry is reachable) - regardless of the tail of the block. + self.diverges.set(prev_diverges); + } + let mut ty = ctxt.coerce.unwrap().complete(self); if self.has_errors.get() || ty.references_error() { diff --git a/src/test/run-pass/issue-45124.rs b/src/test/run-pass/issue-45124.rs new file mode 100644 index 00000000000..c65823e460b --- /dev/null +++ b/src/test/run-pass/issue-45124.rs @@ -0,0 +1,24 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(catch_expr)] + +fn main() { + let mut a = 0; + let () = { + let _: Result<(), ()> = do catch { + let _ = Err(())?; + return + }; + a += 1; + }; + a += 2; + assert_eq!(a, 3); +} From 6020f3033561076f30062258b92a146b26a0e322 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Mon, 16 Oct 2017 13:33:43 +0200 Subject: [PATCH 246/365] introduce a whitelist for aarch64 --- src/librustc_trans/llvm_util.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs index d6cc3004f97..4fe726364f2 100644 --- a/src/librustc_trans/llvm_util.rs +++ b/src/librustc_trans/llvm_util.rs @@ -73,6 +73,8 @@ unsafe fn configure_llvm(sess: &Session) { const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"]; +const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0"]; + const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0", "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0", "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0", @@ -89,7 +91,8 @@ pub fn target_features(sess: &Session) -> Vec { let target_machine = create_target_machine(sess); let whitelist = match &*sess.target.target.arch { - "arm" | "aarch64" => ARM_WHITELIST, + "arm" => ARM_WHITELIST, + "aarch64" => AARCH64_WHITELIST, "x86" | "x86_64" => X86_WHITELIST, "hexagon" => HEXAGON_WHITELIST, "powerpc" | "powerpc64" => POWERPC_WHITELIST, From a5673de454a330df075834732861080ad6f9c124 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 7 Sep 2017 16:39:15 -0400 Subject: [PATCH 247/365] refactor inhabitedness to have clearer public entry points --- src/librustc/ty/inhabitedness/mod.rs | 112 +++++++++++++++++---- src/librustc/ty/sty.rs | 49 --------- src/librustc_const_eval/_match.rs | 12 +-- src/librustc_const_eval/check_match.rs | 2 +- src/librustc_mir/build/matches/simplify.rs | 11 +- 5 files changed, 100 insertions(+), 86 deletions(-) diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index a829814e090..9dc1b19c0f1 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -10,7 +10,7 @@ use util::nodemap::{FxHashMap, FxHashSet}; use ty::context::TyCtxt; -use ty::{AdtDef, VariantDef, FieldDef, TyS}; +use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS}; use ty::{DefId, Substs}; use ty::{AdtKind, Visibility}; use ty::TypeVariants::*; @@ -62,13 +62,81 @@ mod def_id_forest; // This code should only compile in modules where the uninhabitedness of Foo is // visible. +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + /// Checks whether a type is visibly uninhabited from a particular module. + /// # Example + /// ```rust + /// enum Void {} + /// mod a { + /// pub mod b { + /// pub struct SecretlyUninhabited { + /// _priv: !, + /// } + /// } + /// } + /// + /// mod c { + /// pub struct AlsoSecretlyUninhabited { + /// _priv: Void, + /// } + /// mod d { + /// } + /// } + /// + /// struct Foo { + /// x: a::b::SecretlyUninhabited, + /// y: c::AlsoSecretlyUninhabited, + /// } + /// ``` + /// In this code, the type `Foo` will only be visibly uninhabited inside the + /// modules b, c and d. This effects pattern-matching on `Foo` or types that + /// contain `Foo`. + /// + /// # Example + /// ```rust + /// let foo_result: Result = ... ; + /// let Ok(t) = foo_result; + /// ``` + /// This code should only compile in modules where the uninhabitedness of Foo is + /// visible. + pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool { + let forest = ty.uninhabited_from(&mut FxHashMap(), self); + + // To check whether this type is uninhabited at all (not just from the + // given node) you could check whether the forest is empty. + // ``` + // forest.is_empty() + // ``` + forest.contains(self, module) + } + + pub fn is_enum_variant_uninhabited_from(self, + module: DefId, + variant: &'tcx VariantDef, + substs: &'tcx Substs<'tcx>) + -> bool + { + let adt_kind = AdtKind::Enum; + variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).contains(self, module) + } + + pub fn is_variant_uninhabited_from_all_modules(self, + variant: &'tcx VariantDef, + substs: &'tcx Substs<'tcx>, + adt_kind: AdtKind) + -> bool + { + !variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).is_empty() + } +} + impl<'a, 'gcx, 'tcx> AdtDef { /// Calculate the forest of DefIds from which this adt is visibly uninhabited. - pub fn uninhabited_from( - &self, - visited: &mut FxHashMap>>, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - substs: &'tcx Substs<'tcx>) -> DefIdForest + fn uninhabited_from( + &self, + visited: &mut FxHashMap>>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>) -> DefIdForest { DefIdForest::intersection(tcx, self.variants.iter().map(|v| { v.uninhabited_from(visited, tcx, substs, self.adt_kind()) @@ -78,12 +146,12 @@ impl<'a, 'gcx, 'tcx> AdtDef { impl<'a, 'gcx, 'tcx> VariantDef { /// Calculate the forest of DefIds from which this variant is visibly uninhabited. - pub fn uninhabited_from( - &self, - visited: &mut FxHashMap>>, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - substs: &'tcx Substs<'tcx>, - adt_kind: AdtKind) -> DefIdForest + fn uninhabited_from( + &self, + visited: &mut FxHashMap>>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>, + adt_kind: AdtKind) -> DefIdForest { match adt_kind { AdtKind::Union => { @@ -107,12 +175,12 @@ impl<'a, 'gcx, 'tcx> VariantDef { impl<'a, 'gcx, 'tcx> FieldDef { /// Calculate the forest of DefIds from which this field is visibly uninhabited. - pub fn uninhabited_from( - &self, - visited: &mut FxHashMap>>, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - substs: &'tcx Substs<'tcx>, - is_enum: bool) -> DefIdForest + fn uninhabited_from( + &self, + visited: &mut FxHashMap>>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>, + is_enum: bool) -> DefIdForest { let mut data_uninhabitedness = move || { self.ty(tcx, substs).uninhabited_from(visited, tcx) @@ -138,10 +206,10 @@ impl<'a, 'gcx, 'tcx> FieldDef { impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// Calculate the forest of DefIds from which this type is visibly uninhabited. - pub fn uninhabited_from( - &self, - visited: &mut FxHashMap>>, - tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest + fn uninhabited_from( + &self, + visited: &mut FxHashMap>>, + tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest { match tcx.lift_to_global(&self) { Some(global_ty) => { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 10e1286465d..064627c21bf 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -24,7 +24,6 @@ use std::cmp::Ordering; use syntax::abi; use syntax::ast::{self, Name}; use syntax::symbol::keywords; -use util::nodemap::FxHashMap; use serialize; @@ -1070,54 +1069,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - /// Checks whether a type is visibly uninhabited from a particular module. - /// # Example - /// ```rust - /// enum Void {} - /// mod a { - /// pub mod b { - /// pub struct SecretlyUninhabited { - /// _priv: !, - /// } - /// } - /// } - /// - /// mod c { - /// pub struct AlsoSecretlyUninhabited { - /// _priv: Void, - /// } - /// mod d { - /// } - /// } - /// - /// struct Foo { - /// x: a::b::SecretlyUninhabited, - /// y: c::AlsoSecretlyUninhabited, - /// } - /// ``` - /// In this code, the type `Foo` will only be visibly uninhabited inside the - /// modules b, c and d. This effects pattern-matching on `Foo` or types that - /// contain `Foo`. - /// - /// # Example - /// ```rust - /// let foo_result: Result = ... ; - /// let Ok(t) = foo_result; - /// ``` - /// This code should only compile in modules where the uninhabitedness of Foo is - /// visible. - pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { - let mut visited = FxHashMap::default(); - let forest = self.uninhabited_from(&mut visited, tcx); - - // To check whether this type is uninhabited at all (not just from the - // given node) you could check whether the forest is empty. - // ``` - // forest.is_empty() - // ``` - forest.contains(tcx, module) - } - pub fn is_primitive(&self) -> bool { match self.sty { TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true, diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index b836b71e74b..08f3b0a4c5f 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -25,7 +25,7 @@ use pattern::{PatternFoldable, PatternFolder}; use rustc::hir::def_id::DefId; use rustc::hir::RangeEnd; -use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::mir::Field; use rustc::util::common::ErrorReported; @@ -202,7 +202,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { if self.tcx.sess.features.borrow().never_type { - ty.is_uninhabited_from(self.module, self.tcx) + self.tcx.is_ty_uninhabited_from(self.module, ty) } else { false } @@ -210,13 +210,11 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { fn is_variant_uninhabited(&self, variant: &'tcx ty::VariantDef, - substs: &'tcx ty::subst::Substs<'tcx>) -> bool + substs: &'tcx ty::subst::Substs<'tcx>) + -> bool { if self.tcx.sess.features.borrow().never_type { - let forest = variant.uninhabited_from( - &mut FxHashMap::default(), self.tcx, substs, AdtKind::Enum - ); - forest.contains(self.tcx, self.module) + self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs) } else { false } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 0339969f2b4..a9eda3c2f69 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -192,7 +192,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let module = self.tcx.hir.get_module_parent(scrut.id); if inlined_arms.is_empty() { let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type { - pat_ty.is_uninhabited_from(module, self.tcx) + self.tcx.is_ty_uninhabited_from(module, pat_ty) } else { self.conservative_is_uninhabited(pat_ty) }; diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 6e3eef57352..f7d15d91188 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -26,7 +26,6 @@ use build::{BlockAnd, BlockAndExtension, Builder}; use build::matches::{Binding, MatchPair, Candidate}; use hair::*; use rustc::mir::*; -use rustc_data_structures::fx::FxHashMap; use std::mem; @@ -102,12 +101,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if self.hir.tcx().sess.features.borrow().never_type { let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| { i == variant_index || { - let mut visited = FxHashMap::default(); - let node_set = v.uninhabited_from(&mut visited, - self.hir.tcx(), - substs, - adt_def.adt_kind()); - !node_set.is_empty() + let adt_kind = adt_def.adt_kind(); + self.hir.tcx().is_variant_uninhabited_from_all_modules(v, + substs, + adt_kind) } }); if irrefutable { From 25014b5379143f975e62407180f082daac0ddaed Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 16 Oct 2017 13:16:04 +0200 Subject: [PATCH 248/365] rustc_data_structures: Add implementation of 128 bit SipHash. --- src/libcore/hash/sip.rs | 1 + src/librustc_data_structures/lib.rs | 1 + src/librustc_data_structures/sip128.rs | 533 +++++++++++++++++++++++++ 3 files changed, 535 insertions(+) create mode 100644 src/librustc_data_structures/sip128.rs diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 91fd01b36d4..d82de082da6 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -72,6 +72,7 @@ struct Hasher { } #[derive(Debug, Clone, Copy)] +#[repr(C)] struct State { // v0, v2 and v1, v3 show up in pairs in the algorithm, // and simd implementations of SipHash will use vectors diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 47061883425..1277123d700 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -54,6 +54,7 @@ pub mod graph; pub mod indexed_set; pub mod indexed_vec; pub mod obligation_forest; +pub mod sip128; pub mod snapshot_map; pub mod snapshot_vec; pub mod stable_hasher; diff --git a/src/librustc_data_structures/sip128.rs b/src/librustc_data_structures/sip128.rs new file mode 100644 index 00000000000..1f0b0d9cbfb --- /dev/null +++ b/src/librustc_data_structures/sip128.rs @@ -0,0 +1,533 @@ +// Copyright 2012-2015 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 is a copy of `core::hash::sip` adapted to providing 128 bit hashes. + +use std::cmp; +use std::hash::Hasher; +use std::slice; +use std::ptr; +use std::mem; + +#[derive(Debug, Clone)] +pub struct SipHasher128 { + k0: u64, + k1: u64, + length: usize, // how many bytes we've processed + state: State, // hash State + tail: u64, // unprocessed bytes le + ntail: usize, // how many bytes in tail are valid +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +struct State { + // v0, v2 and v1, v3 show up in pairs in the algorithm, + // and simd implementations of SipHash will use vectors + // of v02 and v13. By placing them in this order in the struct, + // the compiler can pick up on just a few simd optimizations by itself. + v0: u64, + v2: u64, + v1: u64, + v3: u64, +} + +macro_rules! compress { + ($state:expr) => ({ + compress!($state.v0, $state.v1, $state.v2, $state.v3) + }); + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => + ({ + $v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0; + $v0 = $v0.rotate_left(32); + $v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2; + $v2 = $v2.rotate_left(32); + }); +} + +/// Load an integer of the desired type from a byte stream, in LE order. Uses +/// `copy_nonoverlapping` to let the compiler generate the most efficient way +/// to load it from a possibly unaligned address. +/// +/// Unsafe because: unchecked indexing at i..i+size_of(int_ty) +macro_rules! load_int_le { + ($buf:expr, $i:expr, $int_ty:ident) => + ({ + debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); + let mut data = 0 as $int_ty; + ptr::copy_nonoverlapping($buf.get_unchecked($i), + &mut data as *mut _ as *mut u8, + mem::size_of::<$int_ty>()); + data.to_le() + }); +} + +/// Load an u64 using up to 7 bytes of a byte slice. +/// +/// Unsafe because: unchecked indexing at start..start+len +#[inline] +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + debug_assert!(len < 8); + let mut i = 0; // current byte index (from LSB) in the output u64 + let mut out = 0; + if i + 3 < len { + out = load_int_le!(buf, start + i, u32) as u64; + i += 4; + } + if i + 1 < len { + out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8); + i += 2 + } + if i < len { + out |= (*buf.get_unchecked(start + i) as u64) << (i * 8); + i += 1; + } + debug_assert_eq!(i, len); + out +} + + +impl SipHasher128 { + #[inline] + pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher128 { + let mut state = SipHasher128 { + k0: key0, + k1: key1, + length: 0, + state: State { + v0: 0, + v1: 0, + v2: 0, + v3: 0, + }, + tail: 0, + ntail: 0, + }; + state.reset(); + state + } + + #[inline] + fn reset(&mut self) { + self.length = 0; + self.state.v0 = self.k0 ^ 0x736f6d6570736575; + self.state.v1 = self.k1 ^ 0x646f72616e646f6d; + self.state.v2 = self.k0 ^ 0x6c7967656e657261; + self.state.v3 = self.k1 ^ 0x7465646279746573; + self.ntail = 0; + + // This is only done in the 128 bit version: + self.state.v1 ^= 0xee; + } + + // Specialized write function that is only valid for buffers with len <= 8. + // It's used to force inlining of write_u8 and write_usize, those would normally be inlined + // except for composite types (that includes slices and str hashing because of delimiter). + // Without this extra push the compiler is very reluctant to inline delimiter writes, + // degrading performance substantially for the most common use cases. + #[inline] + fn short_write(&mut self, msg: &[u8]) { + debug_assert!(msg.len() <= 8); + let length = msg.len(); + self.length += length; + + let needed = 8 - self.ntail; + let fill = cmp::min(length, needed); + if fill == 8 { + self.tail = unsafe { load_int_le!(msg, 0, u64) }; + } else { + self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail); + if length < needed { + self.ntail += length; + return; + } + } + self.state.v3 ^= self.tail; + Sip24Rounds::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + + // Buffered tail is now flushed, process new input. + self.ntail = length - needed; + self.tail = unsafe { u8to64_le(msg, needed, self.ntail) }; + } + + #[inline(always)] + fn short_write_gen(&mut self, x: T) { + let bytes = unsafe { + slice::from_raw_parts(&x as *const T as *const u8, mem::size_of::()) + }; + self.short_write(bytes); + } + + #[inline] + pub fn finish128(mut self) -> (u64, u64) { + let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail; + + self.state.v3 ^= b; + Sip24Rounds::c_rounds(&mut self.state); + self.state.v0 ^= b; + + self.state.v2 ^= 0xee; + Sip24Rounds::d_rounds(&mut self.state); + let _0 = self.state.v0 ^ self.state.v1 ^ self.state.v2 ^ self.state.v3; + + self.state.v1 ^= 0xdd; + Sip24Rounds::d_rounds(&mut self.state); + let _1 = self.state.v0 ^ self.state.v1 ^ self.state.v2 ^ self.state.v3; + (_0, _1) + } +} + +impl Hasher for SipHasher128 { + #[inline] + fn write_u8(&mut self, i: u8) { + self.short_write_gen(i); + } + + #[inline] + fn write_u16(&mut self, i: u16) { + self.short_write_gen(i); + } + + #[inline] + fn write_u32(&mut self, i: u32) { + self.short_write_gen(i); + } + + #[inline] + fn write_u64(&mut self, i: u64) { + self.short_write_gen(i); + } + + #[inline] + fn write_usize(&mut self, i: usize) { + self.short_write_gen(i); + } + + #[inline] + fn write_i8(&mut self, i: i8) { + self.short_write_gen(i); + } + + #[inline] + fn write_i16(&mut self, i: i16) { + self.short_write_gen(i); + } + + #[inline] + fn write_i32(&mut self, i: i32) { + self.short_write_gen(i); + } + + #[inline] + fn write_i64(&mut self, i: i64) { + self.short_write_gen(i); + } + + #[inline] + fn write_isize(&mut self, i: isize) { + self.short_write_gen(i); + } + + #[inline] + fn write(&mut self, msg: &[u8]) { + let length = msg.len(); + self.length += length; + + let mut needed = 0; + + if self.ntail != 0 { + needed = 8 - self.ntail; + self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail; + if length < needed { + self.ntail += length; + return + } else { + self.state.v3 ^= self.tail; + Sip24Rounds::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + self.ntail = 0; + } + } + + // Buffered tail is now flushed, process new input. + let len = length - needed; + let left = len & 0x7; + + let mut i = needed; + while i < len - left { + let mi = unsafe { load_int_le!(msg, i, u64) }; + + self.state.v3 ^= mi; + Sip24Rounds::c_rounds(&mut self.state); + self.state.v0 ^= mi; + + i += 8; + } + + self.tail = unsafe { u8to64_le(msg, i, left) }; + self.ntail = left; + } + + fn finish(&self) -> u64 { + panic!("SipHasher128 cannot provide valid 64 bit hashes") + } +} + +#[derive(Debug, Clone, Default)] +struct Sip24Rounds; + +impl Sip24Rounds { + #[inline] + fn c_rounds(state: &mut State) { + compress!(state); + compress!(state); + } + + #[inline] + fn d_rounds(state: &mut State) { + compress!(state); + compress!(state); + compress!(state); + compress!(state); + } +} + +#[cfg(test)] +mod test { + use std::hash::{Hash, Hasher}; + use std::{slice, mem}; + use super::SipHasher128; + + // Hash just the bytes of the slice, without length prefix + struct Bytes<'a>(&'a [u8]); + + impl<'a> Hash for Bytes<'a> { + #[allow(unused_must_use)] + fn hash(&self, state: &mut H) { + for byte in self.0 { + state.write_u8(*byte); + } + } + } + + fn hash_with(mut st: SipHasher128, x: &T) -> (u64, u64) { + x.hash(&mut st); + st.finish128() + } + + fn hash(x: &T) -> (u64, u64) { + hash_with(SipHasher128::new_with_keys(0, 0), x) + } + + const TEST_VECTOR : [[u8; 16]; 64] = [ + [0xa3,0x81,0x7f,0x04,0xba,0x25,0xa8,0xe6,0x6d,0xf6,0x72,0x14,0xc7,0x55,0x02,0x93], + [0xda,0x87,0xc1,0xd8,0x6b,0x99,0xaf,0x44,0x34,0x76,0x59,0x11,0x9b,0x22,0xfc,0x45], + [0x81,0x77,0x22,0x8d,0xa4,0xa4,0x5d,0xc7,0xfc,0xa3,0x8b,0xde,0xf6,0x0a,0xff,0xe4], + [0x9c,0x70,0xb6,0x0c,0x52,0x67,0xa9,0x4e,0x5f,0x33,0xb6,0xb0,0x29,0x85,0xed,0x51], + [0xf8,0x81,0x64,0xc1,0x2d,0x9c,0x8f,0xaf,0x7d,0x0f,0x6e,0x7c,0x7b,0xcd,0x55,0x79], + [0x13,0x68,0x87,0x59,0x80,0x77,0x6f,0x88,0x54,0x52,0x7a,0x07,0x69,0x0e,0x96,0x27], + [0x14,0xee,0xca,0x33,0x8b,0x20,0x86,0x13,0x48,0x5e,0xa0,0x30,0x8f,0xd7,0xa1,0x5e], + [0xa1,0xf1,0xeb,0xbe,0xd8,0xdb,0xc1,0x53,0xc0,0xb8,0x4a,0xa6,0x1f,0xf0,0x82,0x39], + [0x3b,0x62,0xa9,0xba,0x62,0x58,0xf5,0x61,0x0f,0x83,0xe2,0x64,0xf3,0x14,0x97,0xb4], + [0x26,0x44,0x99,0x06,0x0a,0xd9,0xba,0xab,0xc4,0x7f,0x8b,0x02,0xbb,0x6d,0x71,0xed], + [0x00,0x11,0x0d,0xc3,0x78,0x14,0x69,0x56,0xc9,0x54,0x47,0xd3,0xf3,0xd0,0xfb,0xba], + [0x01,0x51,0xc5,0x68,0x38,0x6b,0x66,0x77,0xa2,0xb4,0xdc,0x6f,0x81,0xe5,0xdc,0x18], + [0xd6,0x26,0xb2,0x66,0x90,0x5e,0xf3,0x58,0x82,0x63,0x4d,0xf6,0x85,0x32,0xc1,0x25], + [0x98,0x69,0xe2,0x47,0xe9,0xc0,0x8b,0x10,0xd0,0x29,0x93,0x4f,0xc4,0xb9,0x52,0xf7], + [0x31,0xfc,0xef,0xac,0x66,0xd7,0xde,0x9c,0x7e,0xc7,0x48,0x5f,0xe4,0x49,0x49,0x02], + [0x54,0x93,0xe9,0x99,0x33,0xb0,0xa8,0x11,0x7e,0x08,0xec,0x0f,0x97,0xcf,0xc3,0xd9], + [0x6e,0xe2,0xa4,0xca,0x67,0xb0,0x54,0xbb,0xfd,0x33,0x15,0xbf,0x85,0x23,0x05,0x77], + [0x47,0x3d,0x06,0xe8,0x73,0x8d,0xb8,0x98,0x54,0xc0,0x66,0xc4,0x7a,0xe4,0x77,0x40], + [0xa4,0x26,0xe5,0xe4,0x23,0xbf,0x48,0x85,0x29,0x4d,0xa4,0x81,0xfe,0xae,0xf7,0x23], + [0x78,0x01,0x77,0x31,0xcf,0x65,0xfa,0xb0,0x74,0xd5,0x20,0x89,0x52,0x51,0x2e,0xb1], + [0x9e,0x25,0xfc,0x83,0x3f,0x22,0x90,0x73,0x3e,0x93,0x44,0xa5,0xe8,0x38,0x39,0xeb], + [0x56,0x8e,0x49,0x5a,0xbe,0x52,0x5a,0x21,0x8a,0x22,0x14,0xcd,0x3e,0x07,0x1d,0x12], + [0x4a,0x29,0xb5,0x45,0x52,0xd1,0x6b,0x9a,0x46,0x9c,0x10,0x52,0x8e,0xff,0x0a,0xae], + [0xc9,0xd1,0x84,0xdd,0xd5,0xa9,0xf5,0xe0,0xcf,0x8c,0xe2,0x9a,0x9a,0xbf,0x69,0x1c], + [0x2d,0xb4,0x79,0xae,0x78,0xbd,0x50,0xd8,0x88,0x2a,0x8a,0x17,0x8a,0x61,0x32,0xad], + [0x8e,0xce,0x5f,0x04,0x2d,0x5e,0x44,0x7b,0x50,0x51,0xb9,0xea,0xcb,0x8d,0x8f,0x6f], + [0x9c,0x0b,0x53,0xb4,0xb3,0xc3,0x07,0xe8,0x7e,0xae,0xe0,0x86,0x78,0x14,0x1f,0x66], + [0xab,0xf2,0x48,0xaf,0x69,0xa6,0xea,0xe4,0xbf,0xd3,0xeb,0x2f,0x12,0x9e,0xeb,0x94], + [0x06,0x64,0xda,0x16,0x68,0x57,0x4b,0x88,0xb9,0x35,0xf3,0x02,0x73,0x58,0xae,0xf4], + [0xaa,0x4b,0x9d,0xc4,0xbf,0x33,0x7d,0xe9,0x0c,0xd4,0xfd,0x3c,0x46,0x7c,0x6a,0xb7], + [0xea,0x5c,0x7f,0x47,0x1f,0xaf,0x6b,0xde,0x2b,0x1a,0xd7,0xd4,0x68,0x6d,0x22,0x87], + [0x29,0x39,0xb0,0x18,0x32,0x23,0xfa,0xfc,0x17,0x23,0xde,0x4f,0x52,0xc4,0x3d,0x35], + [0x7c,0x39,0x56,0xca,0x5e,0xea,0xfc,0x3e,0x36,0x3e,0x9d,0x55,0x65,0x46,0xeb,0x68], + [0x77,0xc6,0x07,0x71,0x46,0xf0,0x1c,0x32,0xb6,0xb6,0x9d,0x5f,0x4e,0xa9,0xff,0xcf], + [0x37,0xa6,0x98,0x6c,0xb8,0x84,0x7e,0xdf,0x09,0x25,0xf0,0xf1,0x30,0x9b,0x54,0xde], + [0xa7,0x05,0xf0,0xe6,0x9d,0xa9,0xa8,0xf9,0x07,0x24,0x1a,0x2e,0x92,0x3c,0x8c,0xc8], + [0x3d,0xc4,0x7d,0x1f,0x29,0xc4,0x48,0x46,0x1e,0x9e,0x76,0xed,0x90,0x4f,0x67,0x11], + [0x0d,0x62,0xbf,0x01,0xe6,0xfc,0x0e,0x1a,0x0d,0x3c,0x47,0x51,0xc5,0xd3,0x69,0x2b], + [0x8c,0x03,0x46,0x8b,0xca,0x7c,0x66,0x9e,0xe4,0xfd,0x5e,0x08,0x4b,0xbe,0xe7,0xb5], + [0x52,0x8a,0x5b,0xb9,0x3b,0xaf,0x2c,0x9c,0x44,0x73,0xcc,0xe5,0xd0,0xd2,0x2b,0xd9], + [0xdf,0x6a,0x30,0x1e,0x95,0xc9,0x5d,0xad,0x97,0xae,0x0c,0xc8,0xc6,0x91,0x3b,0xd8], + [0x80,0x11,0x89,0x90,0x2c,0x85,0x7f,0x39,0xe7,0x35,0x91,0x28,0x5e,0x70,0xb6,0xdb], + [0xe6,0x17,0x34,0x6a,0xc9,0xc2,0x31,0xbb,0x36,0x50,0xae,0x34,0xcc,0xca,0x0c,0x5b], + [0x27,0xd9,0x34,0x37,0xef,0xb7,0x21,0xaa,0x40,0x18,0x21,0xdc,0xec,0x5a,0xdf,0x89], + [0x89,0x23,0x7d,0x9d,0xed,0x9c,0x5e,0x78,0xd8,0xb1,0xc9,0xb1,0x66,0xcc,0x73,0x42], + [0x4a,0x6d,0x80,0x91,0xbf,0x5e,0x7d,0x65,0x11,0x89,0xfa,0x94,0xa2,0x50,0xb1,0x4c], + [0x0e,0x33,0xf9,0x60,0x55,0xe7,0xae,0x89,0x3f,0xfc,0x0e,0x3d,0xcf,0x49,0x29,0x02], + [0xe6,0x1c,0x43,0x2b,0x72,0x0b,0x19,0xd1,0x8e,0xc8,0xd8,0x4b,0xdc,0x63,0x15,0x1b], + [0xf7,0xe5,0xae,0xf5,0x49,0xf7,0x82,0xcf,0x37,0x90,0x55,0xa6,0x08,0x26,0x9b,0x16], + [0x43,0x8d,0x03,0x0f,0xd0,0xb7,0xa5,0x4f,0xa8,0x37,0xf2,0xad,0x20,0x1a,0x64,0x03], + [0xa5,0x90,0xd3,0xee,0x4f,0xbf,0x04,0xe3,0x24,0x7e,0x0d,0x27,0xf2,0x86,0x42,0x3f], + [0x5f,0xe2,0xc1,0xa1,0x72,0xfe,0x93,0xc4,0xb1,0x5c,0xd3,0x7c,0xae,0xf9,0xf5,0x38], + [0x2c,0x97,0x32,0x5c,0xbd,0x06,0xb3,0x6e,0xb2,0x13,0x3d,0xd0,0x8b,0x3a,0x01,0x7c], + [0x92,0xc8,0x14,0x22,0x7a,0x6b,0xca,0x94,0x9f,0xf0,0x65,0x9f,0x00,0x2a,0xd3,0x9e], + [0xdc,0xe8,0x50,0x11,0x0b,0xd8,0x32,0x8c,0xfb,0xd5,0x08,0x41,0xd6,0x91,0x1d,0x87], + [0x67,0xf1,0x49,0x84,0xc7,0xda,0x79,0x12,0x48,0xe3,0x2b,0xb5,0x92,0x25,0x83,0xda], + [0x19,0x38,0xf2,0xcf,0x72,0xd5,0x4e,0xe9,0x7e,0x94,0x16,0x6f,0xa9,0x1d,0x2a,0x36], + [0x74,0x48,0x1e,0x96,0x46,0xed,0x49,0xfe,0x0f,0x62,0x24,0x30,0x16,0x04,0x69,0x8e], + [0x57,0xfc,0xa5,0xde,0x98,0xa9,0xd6,0xd8,0x00,0x64,0x38,0xd0,0x58,0x3d,0x8a,0x1d], + [0x9f,0xec,0xde,0x1c,0xef,0xdc,0x1c,0xbe,0xd4,0x76,0x36,0x74,0xd9,0x57,0x53,0x59], + [0xe3,0x04,0x0c,0x00,0xeb,0x28,0xf1,0x53,0x66,0xca,0x73,0xcb,0xd8,0x72,0xe7,0x40], + [0x76,0x97,0x00,0x9a,0x6a,0x83,0x1d,0xfe,0xcc,0xa9,0x1c,0x59,0x93,0x67,0x0f,0x7a], + [0x58,0x53,0x54,0x23,0x21,0xf5,0x67,0xa0,0x05,0xd5,0x47,0xa4,0xf0,0x47,0x59,0xbd], + [0x51,0x50,0xd1,0x77,0x2f,0x50,0x83,0x4a,0x50,0x3e,0x06,0x9a,0x97,0x3f,0xbd,0x7c], + ]; + + // Test vector from reference implementation + #[test] + fn test_siphash_2_4_test_vector() { + let k0 = 0x_07_06_05_04_03_02_01_00; + let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; + + let mut input: Vec = Vec::new(); + + for i in 0 .. 64 { + let out = hash_with(SipHasher128::new_with_keys(k0, k1), + &Bytes(&input[..])); + let expected = ( + ((TEST_VECTOR[i][0] as u64) << 0) | + ((TEST_VECTOR[i][1] as u64) << 8) | + ((TEST_VECTOR[i][2] as u64) << 16) | + ((TEST_VECTOR[i][3] as u64) << 24) | + ((TEST_VECTOR[i][4] as u64) << 32) | + ((TEST_VECTOR[i][5] as u64) << 40) | + ((TEST_VECTOR[i][6] as u64) << 48) | + ((TEST_VECTOR[i][7] as u64) << 56), + + ((TEST_VECTOR[i][8] as u64) << 0) | + ((TEST_VECTOR[i][9] as u64) << 8) | + ((TEST_VECTOR[i][10] as u64) << 16) | + ((TEST_VECTOR[i][11] as u64) << 24) | + ((TEST_VECTOR[i][12] as u64) << 32) | + ((TEST_VECTOR[i][13] as u64) << 40) | + ((TEST_VECTOR[i][14] as u64) << 48) | + ((TEST_VECTOR[i][15] as u64) << 56), + ); + + assert_eq!(out, expected); + input.push(i as u8); + } + } + + #[test] #[cfg(target_arch = "arm")] + fn test_hash_usize() { + let val = 0xdeadbeef_deadbeef_u64; + assert!(hash(&(val as u64)) != hash(&(val as usize))); + assert_eq!(hash(&(val as u32)), hash(&(val as usize))); + } + #[test] #[cfg(target_arch = "x86_64")] + fn test_hash_usize() { + let val = 0xdeadbeef_deadbeef_u64; + assert_eq!(hash(&(val as u64)), hash(&(val as usize))); + assert!(hash(&(val as u32)) != hash(&(val as usize))); + } + #[test] #[cfg(target_arch = "x86")] + fn test_hash_usize() { + let val = 0xdeadbeef_deadbeef_u64; + assert!(hash(&(val as u64)) != hash(&(val as usize))); + assert_eq!(hash(&(val as u32)), hash(&(val as usize))); + } + + #[test] + fn test_hash_idempotent() { + let val64 = 0xdeadbeef_deadbeef_u64; + assert_eq!(hash(&val64), hash(&val64)); + let val32 = 0xdeadbeef_u32; + assert_eq!(hash(&val32), hash(&val32)); + } + + #[test] + fn test_hash_no_bytes_dropped_64() { + let val = 0xdeadbeef_deadbeef_u64; + + assert!(hash(&val) != hash(&zero_byte(val, 0))); + assert!(hash(&val) != hash(&zero_byte(val, 1))); + assert!(hash(&val) != hash(&zero_byte(val, 2))); + assert!(hash(&val) != hash(&zero_byte(val, 3))); + assert!(hash(&val) != hash(&zero_byte(val, 4))); + assert!(hash(&val) != hash(&zero_byte(val, 5))); + assert!(hash(&val) != hash(&zero_byte(val, 6))); + assert!(hash(&val) != hash(&zero_byte(val, 7))); + + fn zero_byte(val: u64, byte: usize) -> u64 { + assert!(byte < 8); + val & !(0xff << (byte * 8)) + } + } + + #[test] + fn test_hash_no_bytes_dropped_32() { + let val = 0xdeadbeef_u32; + + assert!(hash(&val) != hash(&zero_byte(val, 0))); + assert!(hash(&val) != hash(&zero_byte(val, 1))); + assert!(hash(&val) != hash(&zero_byte(val, 2))); + assert!(hash(&val) != hash(&zero_byte(val, 3))); + + fn zero_byte(val: u32, byte: usize) -> u32 { + assert!(byte < 4); + val & !(0xff << (byte * 8)) + } + } + + #[test] + fn test_hash_no_concat_alias() { + let s = ("aa", "bb"); + let t = ("aabb", ""); + let u = ("a", "abb"); + + assert!(s != t && t != u); + assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u)); + + let u = [1, 0, 0, 0]; + let v = (&u[..1], &u[1..3], &u[3..]); + let w = (&u[..], &u[4..4], &u[4..4]); + + assert!(v != w); + assert!(hash(&v) != hash(&w)); + } + + #[test] + fn test_write_short_works() { + let test_usize = 0xd0c0b0a0usize; + let mut h1 = SipHasher128::new_with_keys(0, 0); + h1.write_usize(test_usize); + h1.write(b"bytes"); + h1.write(b"string"); + h1.write_u8(0xFFu8); + h1.write_u8(0x01u8); + let mut h2 = SipHasher128::new_with_keys(0, 0); + h2.write(unsafe { + slice::from_raw_parts(&test_usize as *const _ as *const u8, + mem::size_of::()) + }); + h2.write(b"bytes"); + h2.write(b"string"); + h2.write(&[0xFFu8, 0x01u8]); + assert_eq!(h1.finish128(), h2.finish128()); + } + +} From 74ebad4b63ce2ccaa6051b60031a6597ee4468ec Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 16 Oct 2017 14:06:07 +0200 Subject: [PATCH 249/365] Use SipHasher128 in StableHasher. --- src/librustc/ich/fingerprint.rs | 15 +-- src/librustc_data_structures/lib.rs | 1 + src/librustc_data_structures/stable_hasher.rs | 119 ++++++++++-------- 3 files changed, 70 insertions(+), 65 deletions(-) diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs index 2391b61253a..f3bb3b38566 100644 --- a/src/librustc/ich/fingerprint.rs +++ b/src/librustc/ich/fingerprint.rs @@ -9,8 +9,6 @@ // except according to those terms. use rustc_data_structures::stable_hasher; -use std::mem; -use std::slice; #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)] pub struct Fingerprint(u64, u64); @@ -54,16 +52,9 @@ impl ::std::fmt::Display for Fingerprint { } impl stable_hasher::StableHasherResult for Fingerprint { - fn finish(mut hasher: stable_hasher::StableHasher) -> Self { - let hash_bytes: &[u8] = hasher.finalize(); - - assert!(hash_bytes.len() >= mem::size_of::() * 2); - let hash_bytes: &[u64] = unsafe { - slice::from_raw_parts(hash_bytes.as_ptr() as *const u64, 2) - }; - - // The bytes returned bytes the Blake2B hasher are always little-endian. - Fingerprint(u64::from_le(hash_bytes[0]), u64::from_le(hash_bytes[1])) + fn finish(hasher: stable_hasher::StableHasher) -> Self { + let (_0, _1) = hasher.finalize(); + Fingerprint(_0, _1) } } diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 1277123d700..3a20343033c 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -28,6 +28,7 @@ #![feature(fn_traits)] #![feature(unsize)] #![feature(i128_type)] +#![feature(i128)] #![feature(conservative_impl_trait)] #![feature(specialization)] diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 9aba48c5bef..3e526900110 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -11,16 +11,7 @@ use std::hash::{Hash, Hasher, BuildHasher}; use std::marker::PhantomData; use std::mem; -use blake2b::Blake2bHasher; -use rustc_serialize::leb128; - -fn write_unsigned_leb128_to_buf(buf: &mut [u8; 16], value: u64) -> usize { - leb128::write_unsigned_leb128_to(value as u128, |i, v| buf[i] = v) -} - -fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize { - leb128::write_signed_leb128_to(value as i128, |i, v| buf[i] = v) -} +use sip128::SipHasher128; /// When hashing something that ends up affecting properties like symbol names. We /// want these symbol names to be calculated independent of other factors like @@ -41,7 +32,7 @@ fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize { /// and allows for variable output lengths through its type /// parameter. pub struct StableHasher { - state: Blake2bHasher, + state: SipHasher128, bytes_hashed: u64, width: PhantomData, } @@ -59,7 +50,7 @@ pub trait StableHasherResult: Sized { impl StableHasher { pub fn new() -> Self { StableHasher { - state: Blake2bHasher::new(mem::size_of::(), &[]), + state: SipHasher128::new_with_keys(0, 0), bytes_hashed: 0, width: PhantomData, } @@ -71,57 +62,59 @@ impl StableHasher { } impl StableHasherResult for [u8; 20] { - fn finish(mut hasher: StableHasher) -> Self { - let mut result: [u8; 20] = [0; 20]; - result.copy_from_slice(hasher.state.finalize()); - result + fn finish(hasher: StableHasher) -> Self { + let (_0, _1) = hasher.finalize(); + + [ + (_0 >> 0) as u8, + (_0 >> 8) as u8, + (_0 >> 16) as u8, + (_0 >> 24) as u8, + (_0 >> 32) as u8, + (_0 >> 40) as u8, + (_0 >> 48) as u8, + (_0 >> 56) as u8, + + 17, + 33, + 47, + 3, + + (_1 >> 0) as u8, + (_1 >> 8) as u8, + (_1 >> 16) as u8, + (_1 >> 24) as u8, + (_1 >> 32) as u8, + (_1 >> 40) as u8, + (_1 >> 48) as u8, + (_1 >> 56) as u8, + ] } } impl StableHasherResult for u128 { - fn finish(mut hasher: StableHasher) -> Self { - let hash_bytes: &[u8] = hasher.finalize(); - assert!(hash_bytes.len() >= mem::size_of::()); - - unsafe { - ::std::ptr::read_unaligned(hash_bytes.as_ptr() as *const u128) - } + fn finish(hasher: StableHasher) -> Self { + let (_0, _1) = hasher.finalize(); + (_0 as u128) | ((_1 as u128) << 64) } } impl StableHasherResult for u64 { - fn finish(mut hasher: StableHasher) -> Self { - hasher.state.finalize(); - hasher.state.finish() + fn finish(hasher: StableHasher) -> Self { + hasher.finalize().0 } } impl StableHasher { #[inline] - pub fn finalize(&mut self) -> &[u8] { - self.state.finalize() + pub fn finalize(self) -> (u64, u64) { + self.state.finish128() } #[inline] pub fn bytes_hashed(&self) -> u64 { self.bytes_hashed } - - #[inline] - fn write_uleb128(&mut self, value: u64) { - let mut buf = [0; 16]; - let len = write_unsigned_leb128_to_buf(&mut buf, value); - self.state.write(&buf[..len]); - self.bytes_hashed += len as u64; - } - - #[inline] - fn write_ileb128(&mut self, value: i64) { - let mut buf = [0; 16]; - let len = write_signed_leb128_to_buf(&mut buf, value); - self.state.write(&buf[..len]); - self.bytes_hashed += len as u64; - } } // For the non-u8 integer cases we leb128 encode them first. Because small @@ -129,7 +122,7 @@ impl StableHasher { // bytes hashed, which is good because blake2b is expensive. impl Hasher for StableHasher { fn finish(&self) -> u64 { - panic!("use StableHasher::finish instead"); + panic!("use StableHasher::finalize instead"); } #[inline] @@ -146,22 +139,32 @@ impl Hasher for StableHasher { #[inline] fn write_u16(&mut self, i: u16) { - self.write_uleb128(i as u64); + self.state.write_u16(i.to_le()); + self.bytes_hashed += 2; } #[inline] fn write_u32(&mut self, i: u32) { - self.write_uleb128(i as u64); + self.state.write_u32(i.to_le()); + self.bytes_hashed += 4; } #[inline] fn write_u64(&mut self, i: u64) { - self.write_uleb128(i); + self.state.write_u64(i.to_le()); + self.bytes_hashed += 8; + } + + #[inline] + fn write_u128(&mut self, i: u128) { + self.state.write_u128(i.to_le()); + self.bytes_hashed += 16; } #[inline] fn write_usize(&mut self, i: usize) { - self.write_uleb128(i as u64); + self.state.write_usize(i.to_le()); + self.bytes_hashed += ::std::mem::size_of::() as u64; } #[inline] @@ -172,22 +175,32 @@ impl Hasher for StableHasher { #[inline] fn write_i16(&mut self, i: i16) { - self.write_ileb128(i as i64); + self.state.write_i16(i.to_le()); + self.bytes_hashed += 2; } #[inline] fn write_i32(&mut self, i: i32) { - self.write_ileb128(i as i64); + self.state.write_i32(i.to_le()); + self.bytes_hashed += 4; } #[inline] fn write_i64(&mut self, i: i64) { - self.write_ileb128(i); + self.state.write_i64(i.to_le()); + self.bytes_hashed += 8; + } + + #[inline] + fn write_i128(&mut self, i: i128) { + self.state.write_i128(i.to_le()); + self.bytes_hashed += 16; } #[inline] fn write_isize(&mut self, i: isize) { - self.write_ileb128(i as i64); + self.state.write_isize(i.to_le()); + self.bytes_hashed += ::std::mem::size_of::() as u64; } } From 10e289e19131b5339ef1a2e001ae0cfcf330c1b0 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 16 Oct 2017 14:43:36 +0200 Subject: [PATCH 250/365] Make debuginfo::UniqueTypeId use 128 bit hash. --- src/librustc_data_structures/stable_hasher.rs | 31 ------------------- src/librustc_trans/debuginfo/metadata.rs | 7 ++--- 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 3e526900110..831e113016f 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -61,37 +61,6 @@ impl StableHasher { } } -impl StableHasherResult for [u8; 20] { - fn finish(hasher: StableHasher) -> Self { - let (_0, _1) = hasher.finalize(); - - [ - (_0 >> 0) as u8, - (_0 >> 8) as u8, - (_0 >> 16) as u8, - (_0 >> 24) as u8, - (_0 >> 32) as u8, - (_0 >> 40) as u8, - (_0 >> 48) as u8, - (_0 >> 56) as u8, - - 17, - 33, - 47, - 3, - - (_1 >> 0) as u8, - (_1 >> 8) as u8, - (_1 >> 16) as u8, - (_1 >> 24) as u8, - (_1 >> 32) as u8, - (_1 >> 40) as u8, - (_1 >> 48) as u8, - (_1 >> 56) as u8, - ] - } -} - impl StableHasherResult for u128 { fn finish(hasher: StableHasher) -> Self { let (_0, _1) = hasher.finalize(); diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 8a89bfee4ac..201d7867764 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -30,7 +30,7 @@ use rustc::ty::fold::TypeVisitor; use rustc::ty::subst::Substs; use rustc::ty::util::TypeIdHasher; use rustc::hir; -use rustc_data_structures::ToHex; +use rustc::ich::Fingerprint; use {type_of, machine, monomorphize}; use common::{self, CrateContext}; use type_::Type; @@ -146,11 +146,10 @@ impl<'tcx> TypeMap<'tcx> { // The hasher we are using to generate the UniqueTypeId. We want // something that provides more than the 64 bits of the DefaultHasher. - - let mut type_id_hasher = TypeIdHasher::<[u8; 20]>::new(cx.tcx()); + let mut type_id_hasher = TypeIdHasher::::new(cx.tcx()); type_id_hasher.visit_ty(type_); - let unique_type_id = type_id_hasher.finish().to_hex(); + let key = self.unique_id_interner.intern(&unique_type_id); self.type_to_unique_id.insert(type_, UniqueTypeId(key)); From 90f6bc0bc7689ae33f0b5c953f5f026ec39994cd Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 16 Oct 2017 14:25:33 +0000 Subject: [PATCH 251/365] turn link to RFC 1751 into a markdown link --- src/librustc_borrowck/borrowck/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index fb70a6c3e84..b877c5a9cbc 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -781,7 +781,7 @@ the base path, it will still be considered freezable. -**FIXME(https://github.com/rust-lang/rfcs/issues/1751) +**FIXME [RFC 1751](https://github.com/rust-lang/rfcs/issues/1751) Restrictions against mutating the base pointer.** When an `&mut` pointer is frozen or claimed, we currently pass along the restriction against MUTATE to the base pointer. I do not believe this From 978349ea434c09a3e2355b86b5e7fd6b1a1a502a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Oct 2017 08:25:58 -0700 Subject: [PATCH 252/365] ci: Update Travis OSX builders Looks like Travis [has announced][blog] that our current `xcode8.2` image is being deprecated and the recommended Xcode 7 image is `xcode7.3`. This updates us to these ahead of time to make sure we can shake out any bugs, if any. [blog]: https://blog.travis-ci.com/2017-10-16-a-new-default-os-x-image-is-coming --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 139f06ec570..88be81be755 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ matrix: NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 os: osx - osx_image: xcode7 + osx_image: xcode7.3 if: branch = auto # macOS builders. These are placed near the beginning because they are very @@ -57,7 +57,7 @@ matrix: NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 os: osx - osx_image: xcode8.2 + osx_image: xcode8.3 if: branch = auto - env: > @@ -71,7 +71,7 @@ matrix: NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 os: osx - osx_image: xcode8.2 + osx_image: xcode8.3 if: branch = auto # OSX builders producing releases. These do not run the full test suite and @@ -91,7 +91,7 @@ matrix: NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 os: osx - osx_image: xcode7 + osx_image: xcode7.3 if: branch = auto - env: > @@ -105,7 +105,7 @@ matrix: NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1 os: osx - osx_image: xcode7 + osx_image: xcode7.3 if: branch = auto # Linux builders, remaining docker images From 27b6c9174d15872ec708d278ec98bcd9eb8fe0ef Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 16 Oct 2017 17:32:38 +0200 Subject: [PATCH 253/365] Update crate hashes in mir-opt test after changing hash algorithm. --- src/test/mir-opt/validate_1.rs | 4 ++-- src/test/mir-opt/validate_4.rs | 12 ++++++------ src/test/mir-opt/validate_5.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index 5a31be8bd50..22788d7a898 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -30,7 +30,7 @@ fn main() { // END RUST SOURCE // START rustc.node12.EraseRegions.after.mir // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[8cd8]::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[8cd8]::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[e36f]::{{impl}}[0]::foo[0] }, BrAnon(0)) Test, _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:5) => validate_1[e36f]::{{impl}}[0]::foo[0] }, BrAnon(1)) mut i32]); // ... // return; // } @@ -62,7 +62,7 @@ fn main() { // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[e36f]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[e36f]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _3 = _2; // StorageLive(_4); diff --git a/src/test/mir-opt/validate_4.rs b/src/test/mir-opt/validate_4.rs index bcb21c60b26..d2852cf5226 100644 --- a/src/test/mir-opt/validate_4.rs +++ b/src/test/mir-opt/validate_4.rs @@ -51,8 +51,8 @@ fn main() { // fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[8cd8]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[e36f]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_4[e36f]::write_42[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(22)], _2: *mut i32]); // StorageLive(_3); // _3 = _2; // (*_3) = const 23i32; @@ -65,8 +65,8 @@ fn main() { // fn test(_1: &ReErased mut i32) -> () { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[8cd8]::test[0] }, BrAnon(0)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[8cd8]::test[0] }, BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[e36f]::test[0] }, BrAnon(0)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_4[e36f]::test[0] }, BrAnon(0)) mut i32]); // ... // _3 = const write_42(_4) -> bb1; // } @@ -81,8 +81,8 @@ fn main() { // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[e36f]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[e36f]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[e36f]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[e36f]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // ... // _0 = const write_42(_4) -> bb1; diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index 44280539c41..98c553d6b35 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -37,7 +37,7 @@ fn main() { // fn test(_1: &ReErased mut i32) -> () { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_5[8cd8]::test[0] }, BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:4) => validate_5[e36f]::test[0] }, BrAnon(0)) mut i32]); // ... // Validate(Release, [_3: bool, _4: *mut i32]); // _3 = const write_42(_4) -> bb1; @@ -49,7 +49,7 @@ fn main() { // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[8cd8]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[e36f]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[e36f]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]); // StorageLive(_3); // _3 = _2; // StorageLive(_4); From 5050dadfc616b090d396deed9a4652a85c5f6f04 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 Sep 2017 13:04:17 -0700 Subject: [PATCH 254/365] rustbuild: Allow setting rls/rustfmt to "broken" This commit enables configuring the RLS/rustfmt tools to the "broken" state and actually get it past CI. The main changes here were to update all dist-related code to handle the situation where the RLS isn't available. This in turn involved a homegrown preprocessor-like-function to edit the configuration files we pass to the various combined installer tools. --- src/bootstrap/dist.rs | 196 ++++++++++++++----------- src/bootstrap/toolstate.rs | 7 + src/etc/installer/exe/rust.iss | 4 + src/etc/installer/msi/rust.wxs | 4 + src/etc/installer/pkg/Distribution.xml | 6 + src/tools/toolstate.toml | 1 - 6 files changed, 129 insertions(+), 89 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index b57661715cc..02dfa04d920 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1035,7 +1035,7 @@ pub struct Rls { } impl Step for Rls { - type Output = PathBuf; + type Output = Option; const ONLY_BUILD_TARGETS: bool = true; const ONLY_HOSTS: bool = true; @@ -1050,12 +1050,17 @@ impl Step for Rls { }); } - fn run(self, builder: &Builder) -> PathBuf { + fn run(self, builder: &Builder) -> Option { let build = builder.build; let stage = self.stage; let target = self.target; assert!(build.config.extended); + if !builder.config.toolstate.rls.testing() { + println!("skipping Dist RLS stage{} ({})", stage, target); + return None + } + println!("Dist RLS stage{} ({})", stage, target); let src = build.src.join("src/tools/rls"); let release_num = build.release_num("rls"); @@ -1102,7 +1107,7 @@ impl Step for Rls { .arg("--component-name=rls-preview"); build.run(&mut cmd); - distdir(build).join(format!("{}-{}.tar.gz", name, target)) + Some(distdir(build).join(format!("{}-{}.tar.gz", name, target))) } } @@ -1202,8 +1207,12 @@ impl Step for Extended { // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering // the std files during uninstall. To do this ensure that rustc comes // before rust-std in the list below. - let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer, - analysis_installer, std_installer]; + let mut tarballs = Vec::new(); + tarballs.push(rustc_installer); + tarballs.push(cargo_installer); + tarballs.extend(rls_installer.clone()); + tarballs.push(analysis_installer); + tarballs.push(std_installer); if build.config.docs { tarballs.push(docs_installer); } @@ -1245,35 +1254,38 @@ impl Step for Extended { } rtf.push_str("}"); + fn filter(contents: &str, marker: &str) -> String { + let start = format!("tool-{}-start", marker); + let end = format!("tool-{}-end", marker); + let mut lines = Vec::new(); + let mut omitted = false; + for line in contents.lines() { + if line.contains(&start) { + omitted = true; + } else if line.contains(&end) { + omitted = false; + } else if !omitted { + lines.push(line); + } + } + + lines.join("\n") + } + + let xform = |p: &Path| { + let mut contents = String::new(); + t!(t!(File::open(p)).read_to_string(&mut contents)); + if rls_installer.is_none() { + contents = filter(&contents, "rls"); + } + let ret = tmp.join(p.file_name().unwrap()); + t!(t!(File::create(&ret)).write_all(contents.as_bytes())); + return ret + }; + if target.contains("apple-darwin") { let pkg = tmp.join("pkg"); let _ = fs::remove_dir_all(&pkg); - t!(fs::create_dir_all(pkg.join("rustc"))); - t!(fs::create_dir_all(pkg.join("cargo"))); - t!(fs::create_dir_all(pkg.join("rust-docs"))); - t!(fs::create_dir_all(pkg.join("rust-std"))); - t!(fs::create_dir_all(pkg.join("rls"))); - t!(fs::create_dir_all(pkg.join("rust-analysis"))); - - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)), - &pkg.join("rustc")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)), - &pkg.join("cargo")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)), - &pkg.join("rust-docs")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)), - &pkg.join("rust-std")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)), - &pkg.join("rls")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)), - &pkg.join("rust-analysis")); - - install(&etc.join("pkg/postinstall"), &pkg.join("rustc"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("cargo"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("rust-docs"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("rust-std"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("rls"), 0o755); - install(&etc.join("pkg/postinstall"), &pkg.join("rust-analysis"), 0o755); let pkgbuild = |component: &str| { let mut cmd = Command::new("pkgbuild"); @@ -1283,12 +1295,23 @@ impl Step for Extended { .arg(pkg.join(component).with_extension("pkg")); build.run(&mut cmd); }; - pkgbuild("rustc"); - pkgbuild("cargo"); - pkgbuild("rust-docs"); - pkgbuild("rust-std"); - pkgbuild("rls"); - pkgbuild("rust-analysis"); + + let prepare = |name: &str| { + t!(fs::create_dir_all(pkg.join(name))); + cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)), + &pkg.join(name)); + install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755); + pkgbuild(name); + }; + prepare("rustc"); + prepare("cargo"); + prepare("rust-docs"); + prepare("rust-std"); + prepare("rust-analysis"); + + if rls_installer.is_some() { + prepare("rls"); + } // create an 'uninstall' package install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); @@ -1298,7 +1321,7 @@ impl Step for Extended { t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes())); install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644); let mut cmd = Command::new("productbuild"); - cmd.arg("--distribution").arg(etc.join("pkg/Distribution.xml")) + cmd.arg("--distribution").arg(xform(&etc.join("pkg/Distribution.xml"))) .arg("--resources").arg(pkg.join("res")) .arg(distdir(build).join(format!("{}-{}.pkg", pkgname(build, "rust"), @@ -1310,46 +1333,34 @@ impl Step for Extended { if target.contains("windows") { let exe = tmp.join("exe"); let _ = fs::remove_dir_all(&exe); - t!(fs::create_dir_all(exe.join("rustc"))); - t!(fs::create_dir_all(exe.join("cargo"))); - t!(fs::create_dir_all(exe.join("rls"))); - t!(fs::create_dir_all(exe.join("rust-analysis"))); - t!(fs::create_dir_all(exe.join("rust-docs"))); - t!(fs::create_dir_all(exe.join("rust-std"))); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)) - .join("rustc"), - &exe.join("rustc")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)) - .join("cargo"), - &exe.join("cargo")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)) - .join("rust-docs"), - &exe.join("rust-docs")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)) - .join(format!("rust-std-{}", target)), - &exe.join("rust-std")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls-preview"), - &exe.join("rls")); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)) - .join(format!("rust-analysis-{}", target)), - &exe.join("rust-analysis")); - - t!(fs::remove_file(exe.join("rustc/manifest.in"))); - t!(fs::remove_file(exe.join("cargo/manifest.in"))); - t!(fs::remove_file(exe.join("rust-docs/manifest.in"))); - t!(fs::remove_file(exe.join("rust-std/manifest.in"))); - t!(fs::remove_file(exe.join("rls/manifest.in"))); - t!(fs::remove_file(exe.join("rust-analysis/manifest.in"))); + let prepare = |name: &str| { + t!(fs::create_dir_all(exe.join(name))); + let dir = if name == "rust-std" || name == "rust-analysis" { + format!("{}-{}", name, target) + } else if name == "rls" { + "rls-preview".to_string() + } else { + name.to_string() + }; + cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)) + .join(dir), + &exe.join(name)); + t!(fs::remove_file(exe.join(name).join("manifest.in"))); + }; + prepare("rustc"); + prepare("cargo"); + prepare("rust-analysis"); + prepare("rust-docs"); + prepare("rust-std"); + if rls_installer.is_some() { + prepare("rls"); + } if target.contains("windows-gnu") { - t!(fs::create_dir_all(exe.join("rust-mingw"))); - cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-mingw"), target)) - .join("rust-mingw"), - &exe.join("rust-mingw")); - t!(fs::remove_file(exe.join("rust-mingw/manifest.in"))); + prepare("rust-mingw"); } - install(&etc.join("exe/rust.iss"), &exe, 0o644); + install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644); install(&etc.join("exe/modpath.iss"), &exe, 0o644); install(&etc.join("exe/upgrade.iss"), &exe, 0o644); install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); @@ -1413,16 +1424,18 @@ impl Step for Extended { .arg("-dr").arg("Std") .arg("-var").arg("var.StdDir") .arg("-out").arg(exe.join("StdGroup.wxs"))); - build.run(Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rls") - .args(&heat_flags) - .arg("-cg").arg("RlsGroup") - .arg("-dr").arg("Rls") - .arg("-var").arg("var.RlsDir") - .arg("-out").arg(exe.join("RlsGroup.wxs")) - .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); + if rls_installer.is_some() { + build.run(Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rls") + .args(&heat_flags) + .arg("-cg").arg("RlsGroup") + .arg("-dr").arg("Rls") + .arg("-var").arg("var.RlsDir") + .arg("-out").arg(exe.join("RlsGroup.wxs")) + .arg("-t").arg(etc.join("msi/remove-duplicates.xsl"))); + } build.run(Command::new(&heat) .current_dir(&exe) .arg("dir") @@ -1456,26 +1469,30 @@ impl Step for Extended { .arg("-dDocsDir=rust-docs") .arg("-dCargoDir=cargo") .arg("-dStdDir=rust-std") - .arg("-dRlsDir=rls") .arg("-dAnalysisDir=rust-analysis") .arg("-arch").arg(&arch) .arg("-out").arg(&output) .arg(&input); add_env(build, &mut cmd, target); + if rls_installer.is_some() { + cmd.arg("-dRlsDir=rls"); + } if target.contains("windows-gnu") { cmd.arg("-dGccDir=rust-mingw"); } build.run(&mut cmd); }; - candle(&etc.join("msi/rust.wxs")); + candle(&xform(&etc.join("msi/rust.wxs"))); candle(&etc.join("msi/ui.wxs")); candle(&etc.join("msi/rustwelcomedlg.wxs")); candle("RustcGroup.wxs".as_ref()); candle("DocsGroup.wxs".as_ref()); candle("CargoGroup.wxs".as_ref()); candle("StdGroup.wxs".as_ref()); - candle("RlsGroup.wxs".as_ref()); + if rls_installer.is_some() { + candle("RlsGroup.wxs".as_ref()); + } candle("AnalysisGroup.wxs".as_ref()); if target.contains("windows-gnu") { @@ -1499,10 +1516,13 @@ impl Step for Extended { .arg("DocsGroup.wixobj") .arg("CargoGroup.wixobj") .arg("StdGroup.wixobj") - .arg("RlsGroup.wixobj") .arg("AnalysisGroup.wixobj") .current_dir(&exe); + if rls_installer.is_some() { + cmd.arg("RlsGroup.wixobj"); + } + if target.contains("windows-gnu") { cmd.arg("GccGroup.wixobj"); } diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 8a113f6b4d2..328cbf0e5d7 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -31,6 +31,13 @@ impl ToolState { BuildExpectation::Failing } } + + pub fn testing(&self) -> bool { + match *self { + ToolState::Testing => true, + _ => false, + } + } } impl Default for ToolState { diff --git a/src/etc/installer/exe/rust.iss b/src/etc/installer/exe/rust.iss index e7d4ec61946..c22d60b6c5d 100644 --- a/src/etc/installer/exe/rust.iss +++ b/src/etc/installer/exe/rust.iss @@ -46,7 +46,9 @@ Name: gcc; Description: "Linker and platform libraries"; Types: full Name: docs; Description: "HTML documentation"; Types: full Name: cargo; Description: "Cargo, the Rust package manager"; Types: full Name: std; Description: "The Rust Standard Library"; Types: full +// tool-rls-start Name: rls; Description: "RLS, the Rust Language Server" +// tool-rls-end [Files] Source: "rustc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust @@ -56,8 +58,10 @@ Source: "rust-mingw/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Source: "rust-docs/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: docs Source: "cargo/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: cargo Source: "rust-std/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: std +// tool-rls-start Source: "rls/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls Source: "rust-analysis/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rls +// tool-rls-end [Code] const diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs index 258291cbb72..d95b096d732 100644 --- a/src/etc/installer/msi/rust.wxs +++ b/src/etc/installer/msi/rust.wxs @@ -170,8 +170,10 @@ + + @@ -275,6 +277,7 @@ + + diff --git a/src/etc/installer/pkg/Distribution.xml b/src/etc/installer/pkg/Distribution.xml index f138a1a3154..077ee175116 100644 --- a/src/etc/installer/pkg/Distribution.xml +++ b/src/etc/installer/pkg/Distribution.xml @@ -16,7 +16,9 @@ + + @@ -62,6 +64,7 @@ > + + rustc.pkg cargo.pkg rust-docs.pkg rust-std.pkg + rls.pkg + rust-analysis.pkg uninstall.pkg Date: Wed, 11 Oct 2017 22:34:20 -0700 Subject: [PATCH 255/365] remove an obsolete FIXME comment This comment made sense when it was introduced in fbef2417. It does not make sense in its current context, where the referred-to guard is no longer present. This being an item under the fabulous metabug #44366. --- src/librustc_lint/builtin.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7f331418d42..06bc716f024 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -894,7 +894,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, sp, "function cannot return without recurring"); - // FIXME #19668: these could be span_lint_note's instead of this manual guard. // offer some help to the programmer. for call in &self_call_spans { db.span_note(*call, "recursive call site"); From f98939c6fd73e0cb776b7ddbc732827b04a4b2a3 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Wed, 11 Oct 2017 23:06:45 -0700 Subject: [PATCH 256/365] code suggestion for non-shorthand field patterns lint We also edit the lint description to clarify that this is different from the struct field init shorthand. --- src/librustc_lint/builtin.rs | 14 +++++++++----- src/libsyntax/codemap.rs | 11 +++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 06bc716f024..5f58e96efba 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -153,7 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers { declare_lint! { NON_SHORTHAND_FIELD_PATTERNS, Warn, - "using `Struct { x: x }` instead of `Struct { x }`" + "using `Struct { x: x }` instead of `Struct { x }` in a pattern" } #[derive(Copy, Clone)] @@ -174,11 +174,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns { } if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node { if ident.node == fieldpat.node.name { - cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, + let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, - &format!("the `{}:` in this pattern is redundant and can \ - be removed", - ident.node)) + &format!("the `{}:` in this pattern is redundant", + ident.node)); + let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':'); + err.span_suggestion_short(subspan, + "remove this", + format!("{}", ident.node)); + err.emit(); } } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index efaa5e5e3da..dd46903bb88 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -471,6 +471,17 @@ impl CodeMap { } } + /// Given a `Span`, try to get a shorter span ending just after the first + /// occurrence of `char` `c`. + pub fn span_through_char(&self, sp: Span, c: char) -> Span { + if let Ok(snippet) = self.span_to_snippet(sp) { + if let Some(offset) = snippet.find(c) { + return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32)); + } + } + sp + } + pub fn def_span(&self, sp: Span) -> Span { self.span_until_char(sp, '{') } From 38e5a964f2c90d46dfa8dff17a2ce251e7465da1 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Wed, 11 Oct 2017 23:08:48 -0700 Subject: [PATCH 257/365] code suggestions for no-mangle lints At reviewer's suggestion, we remove the function/static name from the main lint message. While we're correspondingly adjusting the expectations of a compile-fail test, we remove an obsolete FIXME comment, another quantum of progress towards resolving the fabulous metabug #44366. --- src/librustc_lint/builtin.rs | 50 +++++++++++++------ .../issue-43106-gating-of-builtin-attrs.rs | 2 +- .../compile-fail/lint-unexported-no-mangle.rs | 5 +- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 5f58e96efba..bc2a1f08441 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -44,7 +44,7 @@ use std::collections::HashSet; use syntax::ast; use syntax::attr; use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes}; -use syntax_pos::{Span, SyntaxContext}; +use syntax_pos::{BytePos, Span, SyntaxContext}; use syntax::symbol::keywords; use rustc::hir::{self, PatKind}; @@ -1133,35 +1133,55 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(.., ref generics, _) => { - if attr::contains_name(&it.attrs, "no_mangle") && - !attr::contains_name(&it.attrs, "linkage") { + if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") { + if attr::contains_name(&it.attrs, "linkage") { + return; + } if !cx.access_levels.is_reachable(it.id) { - let msg = format!("function {} is marked #[no_mangle], but not exported", - it.name); - cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg); + let msg = "function is marked #[no_mangle], but not exported"; + let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg); + let insertion_span = it.span.with_hi(it.span.lo()); + err.span_suggestion(insertion_span, + "try making it public", + "pub ".to_owned()); + err.emit(); } if generics.is_type_parameterized() { - cx.span_lint(NO_MANGLE_GENERIC_ITEMS, - it.span, - "functions generic over types must be mangled"); + let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, + it.span, + "functions generic over \ + types must be mangled"); + err.span_suggestion_short(no_mangle_attr.span, + "remove this attribute", + "".to_owned()); + err.emit(); } } } hir::ItemStatic(..) => { if attr::contains_name(&it.attrs, "no_mangle") && !cx.access_levels.is_reachable(it.id) { - let msg = format!("static {} is marked #[no_mangle], but not exported", - it.name); - cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg); + let msg = "static is marked #[no_mangle], but not exported"; + let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg); + let insertion_span = it.span.with_hi(it.span.lo()); + err.span_suggestion(insertion_span, + "try making it public", + "pub ".to_owned()); + err.emit(); } } hir::ItemConst(..) => { if attr::contains_name(&it.attrs, "no_mangle") { // Const items do not refer to a particular location in memory, and therefore // don't have anything to attach a symbol to - let msg = "const items should never be #[no_mangle], consider instead using \ - `pub static`"; - cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg); + let msg = "const items should never be #[no_mangle]"; + let mut err = cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg); + // `const` is 5 chars + let const_span = it.span.with_hi(BytePos(it.span.lo().0 + 5)); + err.span_suggestion(const_span, + "try a static value", + "pub static".to_owned()); + err.emit(); } } _ => {} diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 06b87206669..ab2fe02bb14 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs @@ -424,7 +424,7 @@ mod no_mangle { mod inner { #![no_mangle="3500"] } #[no_mangle = "3500"] fn f() { } - //~^ WARN function f is marked #[no_mangle], but not exported + //~^ WARN function is marked #[no_mangle], but not exported #[no_mangle = "3500"] struct S; diff --git a/src/test/compile-fail/lint-unexported-no-mangle.rs b/src/test/compile-fail/lint-unexported-no-mangle.rs index 216fcf93535..cd64dfa7a47 100644 --- a/src/test/compile-fail/lint-unexported-no-mangle.rs +++ b/src/test/compile-fail/lint-unexported-no-mangle.rs @@ -10,9 +10,8 @@ // compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics -// FIXME(#19495) no_mangle'ing main ICE's. #[no_mangle] -fn foo() { //~ ERROR function foo is marked #[no_mangle], but not exported +fn foo() { //~ ERROR function is marked #[no_mangle], but not exported } #[allow(dead_code)] @@ -31,7 +30,7 @@ pub static BAR: u64 = 1; #[allow(dead_code)] #[no_mangle] -static PRIVATE_BAR: u64 = 1; //~ ERROR static PRIVATE_BAR is marked #[no_mangle], but not exported +static PRIVATE_BAR: u64 = 1; //~ ERROR static is marked #[no_mangle], but not exported fn main() { From f01ee857a301e203ab960b50c85ac0c370eb1adc Mon Sep 17 00:00:00 2001 From: toidiu Date: Tue, 26 Sep 2017 00:36:38 -0400 Subject: [PATCH 258/365] return an empty inferred_outlives_of --- src/librustc_typeck/collect.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 25a37a2c48c..9a66f07cba4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1329,10 +1329,21 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( }) } +//todo +fn inferred_outlives_of<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, + _def_id: DefId) + -> Vec> { + Vec::new() +} + fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::GenericPredicates<'tcx> { - explicit_predicates_of(tcx, def_id) + let explicit = explicit_predicates_of(tcx, def_id); + ty::GenericPredicates { + parent: explicit.parent, + predicates: [&explicit.predicates[..], &inferred_outlives_of(tcx, def_id)[..]].concat() + } } fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, From 32b968ce443a840b51e605e8a29408aa903aa6bf Mon Sep 17 00:00:00 2001 From: toidiu Date: Tue, 26 Sep 2017 00:48:32 -0400 Subject: [PATCH 259/365] add inferred_outlives_of query --- src/librustc/ty/maps/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 58405c261ad..e14a77ea93b 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -121,6 +121,9 @@ define_maps! { <'tcx> /// (inferred) variance. [] fn variances_of: ItemVariances(DefId) -> Rc>, + /// Maps from def-id of a type to its (inferred) outlives. + [] fn inferred_outlives_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, + /// Maps from an impl/trait def-id to a list of the def-ids of its items [] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc>, From 7c8a7221a4e3d926c419e1d681db450835733aef Mon Sep 17 00:00:00 2001 From: toidiu Date: Wed, 27 Sep 2017 20:18:41 -0400 Subject: [PATCH 260/365] create a seperate module for outlives. added a query for inferred_outlives. setup some files for upcoming tests --- src/librustc/ty/maps/mod.rs | 2 +- src/librustc_typeck/collect.rs | 9 +----- src/librustc_typeck/lib.rs | 8 ++++++ src/librustc_typeck/outlives/mod.rs | 22 +++++++++++++++ src/librustc_typeck/outlives/test.rs | 41 ++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 src/librustc_typeck/outlives/mod.rs create mode 100644 src/librustc_typeck/outlives/test.rs diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index e14a77ea93b..d13de98df28 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -122,7 +122,7 @@ define_maps! { <'tcx> [] fn variances_of: ItemVariances(DefId) -> Rc>, /// Maps from def-id of a type to its (inferred) outlives. - [] fn inferred_outlives_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, + [] fn inferred_outlives_of: PredicatesOfItem(DefId) -> Vec>, /// Maps from an impl/trait def-id to a list of the def-ids of its items [] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc>, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9a66f07cba4..a5b3f8cb806 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1329,20 +1329,13 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( }) } -//todo -fn inferred_outlives_of<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, - _def_id: DefId) - -> Vec> { - Vec::new() -} - fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::GenericPredicates<'tcx> { let explicit = explicit_predicates_of(tcx, def_id); ty::GenericPredicates { parent: explicit.parent, - predicates: [&explicit.predicates[..], &inferred_outlives_of(tcx, def_id)[..]].concat() + predicates: [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat() } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 1c047ef98d8..9cf954cecc9 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -50,6 +50,8 @@ independently: - variance: variance inference +- outlives: outlives inference + - check: walks over function bodies and type checks them, inferring types for local variables, type parameters, etc as necessary. @@ -122,6 +124,7 @@ mod collect; mod constrained_type_params; mod impl_wf_check; mod coherence; +mod outlives; mod variance; mod namespace; @@ -316,6 +319,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) variance::test::test_variance(tcx)); })?; +// tcx.sess.track_errors(|| { +// time(time_passes, "outlives testing", || +// outlives::test::test_inferred_outlives(tcx)); +// })?; + time(time_passes, "wf checking", || check::check_wf_new(tcx))?; time(time_passes, "item-types checking", || check::check_item_types(tcx))?; diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs new file mode 100644 index 00000000000..d496ed0e46d --- /dev/null +++ b/src/librustc_typeck/outlives/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2013 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. + +use rustc::hir::def_id::DefId; +use rustc::ty::{self, TyCtxt}; + +/// Code to write unit test for outlives. +pub mod test; + +//todo +pub fn inferred_outlives_of<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, + _def_id: DefId) + -> Vec> { + Vec::new() +} diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs new file mode 100644 index 00000000000..0d45fc58637 --- /dev/null +++ b/src/librustc_typeck/outlives/test.rs @@ -0,0 +1,41 @@ +// Copyright 2013 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. + +//use rustc::hir; +//use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::ty::TyCtxt; + +//pub fn test_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { +// tcx.hir.krate().visit_all_item_likes(&mut OutlivesTest { tcx }); +//} + +struct OutlivesTest<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx> +} + +//impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> { +// fn visit_item(&mut self, item: &'tcx hir::Item) { +// let item_def_id = self.tcx.hir.local_def_id(item.id); +// +// // For unit testing: check for a special "rustc_outlives" +// // attribute and report an error with various results if found. +// if self.tcx.has_attr(item_def_id, "rustc_outlives") { +// let outlives_of = self.tcx.outlives_of(item_def_id); +// span_err!(self.tcx.sess, +// item.span, +// E0208, +// "{:?}", +// outlives_of); +// } +// } +// +// fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { } +// fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } +//} From ba1efa3b61759384fc39ad262cffb0a007b87f95 Mon Sep 17 00:00:00 2001 From: toidiu Date: Wed, 27 Sep 2017 21:01:48 -0400 Subject: [PATCH 261/365] added components for testing. added outlives test to the check_crate function of librustc_typeck --- src/librustc_typeck/diagnostics.rs | 1 + src/librustc_typeck/lib.rs | 9 +++--- src/librustc_typeck/outlives/mod.rs | 11 +++++-- src/librustc_typeck/outlives/test.rs | 48 ++++++++++++++-------------- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 8df97355574..5f741029731 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4679,4 +4679,5 @@ register_diagnostics! { E0627, // yield statement outside of generator literal E0632, // cannot provide explicit type parameters when `impl Trait` is used in // argument position. + E0628, // infer outlives } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9cf954cecc9..ea4ce64e487 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -289,6 +289,7 @@ pub fn provide(providers: &mut Providers) { coherence::provide(providers); check::provide(providers); variance::provide(providers); + outlives::provide(providers); } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) @@ -319,10 +320,10 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) variance::test::test_variance(tcx)); })?; -// tcx.sess.track_errors(|| { -// time(time_passes, "outlives testing", || -// outlives::test::test_inferred_outlives(tcx)); -// })?; + tcx.sess.track_errors(|| { + time(time_passes, "outlives testing", || + outlives::test::test_inferred_outlives(tcx)); + })?; time(time_passes, "wf checking", || check::check_wf_new(tcx))?; diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index d496ed0e46d..1127028cbc8 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -10,13 +10,20 @@ use rustc::hir::def_id::DefId; use rustc::ty::{self, TyCtxt}; +use rustc::ty::maps::Providers; /// Code to write unit test for outlives. pub mod test; +pub fn provide(providers: &mut Providers) { + *providers = Providers { + inferred_outlives_of, + ..*providers + }; +} + //todo -pub fn inferred_outlives_of<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, - _def_id: DefId) +fn inferred_outlives_of<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, _def_id: DefId) -> Vec> { Vec::new() } diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs index 0d45fc58637..665b3d57d91 100644 --- a/src/librustc_typeck/outlives/test.rs +++ b/src/librustc_typeck/outlives/test.rs @@ -8,34 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//use rustc::hir; -//use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir; +use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::TyCtxt; -//pub fn test_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { -// tcx.hir.krate().visit_all_item_likes(&mut OutlivesTest { tcx }); -//} +pub fn test_inferred_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + tcx.hir.krate().visit_all_item_likes(&mut OutlivesTest { tcx }); +} struct OutlivesTest<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } -//impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> { -// fn visit_item(&mut self, item: &'tcx hir::Item) { -// let item_def_id = self.tcx.hir.local_def_id(item.id); -// -// // For unit testing: check for a special "rustc_outlives" -// // attribute and report an error with various results if found. -// if self.tcx.has_attr(item_def_id, "rustc_outlives") { -// let outlives_of = self.tcx.outlives_of(item_def_id); -// span_err!(self.tcx.sess, -// item.span, -// E0208, -// "{:?}", -// outlives_of); -// } -// } -// -// fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { } -// fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } -//} +impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> { + fn visit_item(&mut self, item: &'tcx hir::Item) { + let item_def_id = self.tcx.hir.local_def_id(item.id); + + // For unit testing: check for a special "rustc_outlives" + // attribute and report an error with various results if found. + if self.tcx.has_attr(item_def_id, "rustc_outlives") { + let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id); + span_err!(self.tcx.sess, + item.span, + E0628, + "{:?}", + inferred_outlives_of); + } + } + + fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { } + fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { } +} From c021e5303f7db901a962b7c650ad5b2206801d9c Mon Sep 17 00:00:00 2001 From: toidiu Date: Wed, 27 Sep 2017 21:20:44 -0400 Subject: [PATCH 262/365] add a test case dont duplicate error codes choose unlikely error code specify error pattern in test --- src/librustc_typeck/diagnostics.rs | 2 +- src/librustc_typeck/lib.rs | 10 ++++---- src/librustc_typeck/outlives/test.rs | 2 +- .../compile-fail/outlives-associated-types.rs | 24 +++++++++++++++++++ 4 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/outlives-associated-types.rs diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 5f741029731..8f91d07b53f 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4676,8 +4676,8 @@ register_diagnostics! { E0588, // packed struct cannot transitively contain a `[repr(align)]` struct E0592, // duplicate definitions with name `{}` // E0613, // Removed (merged with E0609) + E0640, // infer outlives E0627, // yield statement outside of generator literal E0632, // cannot provide explicit type parameters when `impl Trait` is used in // argument position. - E0628, // infer outlives } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index ea4ce64e487..49ba0499f78 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -305,6 +305,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) })?; + tcx.sess.track_errors(|| { + time(time_passes, "outlives testing", || + outlives::test::test_inferred_outlives(tcx)); + })?; + tcx.sess.track_errors(|| { time(time_passes, "impl wf inference", || impl_wf_check::impl_wf_check(tcx)); @@ -320,11 +325,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) variance::test::test_variance(tcx)); })?; - tcx.sess.track_errors(|| { - time(time_passes, "outlives testing", || - outlives::test::test_inferred_outlives(tcx)); - })?; - time(time_passes, "wf checking", || check::check_wf_new(tcx))?; time(time_passes, "item-types checking", || check::check_item_types(tcx))?; diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs index 665b3d57d91..196e6605494 100644 --- a/src/librustc_typeck/outlives/test.rs +++ b/src/librustc_typeck/outlives/test.rs @@ -30,7 +30,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> { let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id); span_err!(self.tcx.sess, item.span, - E0628, + E0640, "{:?}", inferred_outlives_of); } diff --git a/src/test/compile-fail/outlives-associated-types.rs b/src/test/compile-fail/outlives-associated-types.rs new file mode 100644 index 00000000000..f742ca81bcc --- /dev/null +++ b/src/test/compile-fail/outlives-associated-types.rs @@ -0,0 +1,24 @@ +// Copyright 2015 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 that the outlives computation runs for now... + +#![feature(rustc_attrs)] + +//todo add all the test cases +// https://github.com/rust-lang/rfcs/blob/master/text/2093-infer-outlives.md#example-1-a-reference + +#[rustc_outlives] +struct Direct<'a, T> { + // inferred: `T: 'a` + field: &'a T //~ ERROR generic reference may outlive the data it points to +} + +fn main() { } From fe5cb1a5174f6054d03b6d95f84ff8808e2c89de Mon Sep 17 00:00:00 2001 From: toidiu Date: Sun, 8 Oct 2017 14:45:19 -0400 Subject: [PATCH 263/365] add error to the correct line in unit test --- src/test/compile-fail/outlives-associated-types.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/compile-fail/outlives-associated-types.rs b/src/test/compile-fail/outlives-associated-types.rs index f742ca81bcc..778394c9fc8 100644 --- a/src/test/compile-fail/outlives-associated-types.rs +++ b/src/test/compile-fail/outlives-associated-types.rs @@ -16,9 +16,8 @@ // https://github.com/rust-lang/rfcs/blob/master/text/2093-infer-outlives.md#example-1-a-reference #[rustc_outlives] -struct Direct<'a, T> { - // inferred: `T: 'a` - field: &'a T //~ ERROR generic reference may outlive the data it points to +struct Direct<'a, T> { //~ ERROR 19:1: 21:2: [] [E0640] + field: &'a T } fn main() { } From ce754ba4767efcb5ee73246d780da95a379c27f8 Mon Sep 17 00:00:00 2001 From: toidiu Date: Tue, 10 Oct 2017 22:54:59 -0400 Subject: [PATCH 264/365] add a new dep node for outlives --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/ty/maps/mod.rs | 2 +- src/librustc/ty/maps/plumbing.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 4600cdbc692..92bbb745bb2 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -476,6 +476,7 @@ define_dep_nodes!( <'tcx> [] TypeOfItem(DefId), [] GenericsOfItem(DefId), [] PredicatesOfItem(DefId), + [] InferredOutlivesOf(DefId), [] SuperPredicatesOfItem(DefId), [] TraitDefOfItem(DefId), [] AdtDefOfItem(DefId), diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index d13de98df28..f54391ebb07 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -122,7 +122,7 @@ define_maps! { <'tcx> [] fn variances_of: ItemVariances(DefId) -> Rc>, /// Maps from def-id of a type to its (inferred) outlives. - [] fn inferred_outlives_of: PredicatesOfItem(DefId) -> Vec>, + [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Vec>, /// Maps from an impl/trait def-id to a list of the def-ids of its items [] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Rc>, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index d6eaf6d1bc4..69a9a258d81 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -736,6 +736,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::TypeOfItem => { force!(type_of, def_id!()); } DepKind::GenericsOfItem => { force!(generics_of, def_id!()); } DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); } + DepKind::InferredOutlivesOf => { force!(outlives_of, def_id!()); } DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); } DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); } DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); } From 98c6e0a02deb3b5efe1c06d1028502f45672a66e Mon Sep 17 00:00:00 2001 From: toidiu Date: Wed, 11 Oct 2017 10:18:57 -0400 Subject: [PATCH 265/365] fix function name --- src/librustc/ty/maps/plumbing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 69a9a258d81..4e301342ee0 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -736,7 +736,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::TypeOfItem => { force!(type_of, def_id!()); } DepKind::GenericsOfItem => { force!(generics_of, def_id!()); } DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); } - DepKind::InferredOutlivesOf => { force!(outlives_of, def_id!()); } + DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); } DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); } DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); } DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); } From 8e6ed1203b777747bb435c7eb11272ccf252cd52 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 12 Oct 2017 00:42:52 -0700 Subject: [PATCH 266/365] bolster UI test converage for lint suggestions --- src/test/ui/lint/suggestions.rs | 17 +++++++ src/test/ui/lint/suggestions.stderr | 79 ++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 12 deletions(-) diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs index 874124a7d36..e078056ab5e 100644 --- a/src/test/ui/lint/suggestions.rs +++ b/src/test/ui/lint/suggestions.rs @@ -11,10 +11,27 @@ #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896 #![feature(no_debug)] +#[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub` +#[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const` + +#[no_mangle] // should suggest removal (generics can't be no-mangle) +pub fn defiant(_t: T) {} + +#[no_mangle] +fn rio_grande() {} // should suggest `pub` + +struct Equinox { + warp_factor: f32, +} + #[no_debug] // should suggest removal of deprecated attribute fn main() { while true { // should suggest `loop` let mut a = (1); // should suggest no `mut`, no parens + let d = Equinox { warp_factor: 9.975 }; + match d { + Equinox { warp_factor: warp_factor } => {} // should suggest shorthand + } println!("{}", a); } } diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index 9a69c52e6cf..7a498b56413 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -1,23 +1,23 @@ warning: unnecessary parentheses around assigned value - --> $DIR/suggestions.rs:17:21 + --> $DIR/suggestions.rs:30:21 | -17 | let mut a = (1); // should suggest no `mut`, no parens +30 | let mut a = (1); // should suggest no `mut`, no parens | ^^^ help: remove these parentheses | = note: #[warn(unused_parens)] on by default warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721 - --> $DIR/suggestions.rs:14:1 + --> $DIR/suggestions.rs:27:1 | -14 | #[no_debug] // should suggest removal of deprecated attribute +27 | #[no_debug] // should suggest removal of deprecated attribute | ^^^^^^^^^^^ help: remove this attribute | = note: #[warn(deprecated)] on by default warning: variable does not need to be mutable - --> $DIR/suggestions.rs:17:13 + --> $DIR/suggestions.rs:30:13 | -17 | let mut a = (1); // should suggest no `mut`, no parens +30 | let mut a = (1); // should suggest no `mut`, no parens | ---^^ | | | help: remove this `mut` @@ -28,18 +28,73 @@ note: lint level defined here 11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896 | ^^^^^^^^^^ -warning: denote infinite loops with `loop { ... }` - --> $DIR/suggestions.rs:16:5 +warning: static is marked #[no_mangle], but not exported + --> $DIR/suggestions.rs:14:14 | -16 | while true { // should suggest `loop` +14 | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub` + | -^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: try making it public: `pub ` + | + = note: #[warn(private_no_mangle_statics)] on by default + +error: const items should never be #[no_mangle] + --> $DIR/suggestions.rs:15:14 + | +15 | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const` + | -----^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + | + = note: #[deny(no_mangle_const_items)] on by default + +warning: functions generic over types must be mangled + --> $DIR/suggestions.rs:18:1 + | +17 | #[no_mangle] // should suggest removal (generics can't be no-mangle) + | ------------ help: remove this attribute +18 | pub fn defiant(_t: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(no_mangle_generic_items)] on by default + +warning: function is marked #[no_mangle], but not exported + --> $DIR/suggestions.rs:21:1 + | +21 | fn rio_grande() {} // should suggest `pub` + | -^^^^^^^^^^^^^^^^^ + | | + | help: try making it public: `pub ` + | + = note: #[warn(private_no_mangle_fns)] on by default + +warning: denote infinite loops with `loop { ... }` + --> $DIR/suggestions.rs:29:5 + | +29 | while true { // should suggest `loop` | ^--------- | | | _____help: use `loop` | | -17 | | let mut a = (1); // should suggest no `mut`, no parens -18 | | println!("{}", a); -19 | | } +30 | | let mut a = (1); // should suggest no `mut`, no parens +31 | | let d = Equinox { warp_factor: 9.975 }; +32 | | match d { +... | +35 | | println!("{}", a); +36 | | } | |_____^ | = note: #[warn(while_true)] on by default +warning: the `warp_factor:` in this pattern is redundant + --> $DIR/suggestions.rs:33:23 + | +33 | Equinox { warp_factor: warp_factor } => {} // should suggest shorthand + | ------------^^^^^^^^^^^^ + | | + | help: remove this + | + = note: #[warn(non_shorthand_field_patterns)] on by default + +error: aborting due to previous error + From 11b2b08ba9bdf7d3759666a3b05711b0a6c20484 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 16 Oct 2017 21:41:10 +0200 Subject: [PATCH 267/365] Display rustdoc pulldown switch warnings everytime --- src/librustdoc/html/render.rs | 49 ++++++++++++++++------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3c789cb3a15..d538428a7e9 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1826,37 +1826,32 @@ fn render_markdown(w: &mut fmt::Formatter, prefix: &str, scx: &SharedContext) -> fmt::Result { - // We only emit warnings if the user has opted-in to Pulldown rendering. - let output = if render_type == RenderType::Pulldown { - // Save the state of USED_ID_MAP so it only gets updated once even - // though we're rendering twice. - let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone()); - let hoedown_output = format!("{}", Markdown(md_text, RenderType::Hoedown)); - USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map); - let pulldown_output = format!("{}", Markdown(md_text, RenderType::Pulldown)); - let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output); - differences.retain(|s| { - match *s { - html_diff::Difference::NodeText { ref elem_text, - ref opposite_elem_text, - .. } - if elem_text.split_whitespace().eq(opposite_elem_text.split_whitespace()) => { - false - } - _ => true, + // Save the state of USED_ID_MAP so it only gets updated once even + // though we're rendering twice. + let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone()); + let hoedown_output = format!("{}", Markdown(md_text, RenderType::Hoedown)); + USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map); + let pulldown_output = format!("{}", Markdown(md_text, RenderType::Pulldown)); + let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output); + differences.retain(|s| { + match *s { + html_diff::Difference::NodeText { ref elem_text, + ref opposite_elem_text, + .. } + if elem_text.split_whitespace().eq(opposite_elem_text.split_whitespace()) => { + false } - }); - - if !differences.is_empty() { - scx.markdown_warnings.borrow_mut().push((span, md_text.to_owned(), differences)); + _ => true, } + }); - pulldown_output - } else { - format!("{}", Markdown(md_text, RenderType::Hoedown)) - }; + if !differences.is_empty() { + scx.markdown_warnings.borrow_mut().push((span, md_text.to_owned(), differences)); + } - write!(w, "
{}{}
", prefix, output) + write!(w, "
{}{}
", + prefix, + if render_type == RenderType::Pulldown { pulldown_output } else { hoedown_output }) } fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink, From 094c2ae16ce6f78b99d0e69c1084a2c14f0ad59f Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 16 Oct 2017 22:53:25 +0300 Subject: [PATCH 268/365] revert change to function_sections for windows --- src/librustc_back/target/windows_base.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index 21b8c4e082e..e6aa745d54e 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -64,7 +64,8 @@ pub fn opts() -> TargetOptions { ]); TargetOptions { - function_sections: true, + // FIXME(#13846) this should be enabled for windows + function_sections: false, linker: "gcc".to_string(), dynamic_linking: true, executables: true, From 68311bdf2bcddea8012fd9cec24357feaf771fd0 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 16 Oct 2017 12:45:24 -0700 Subject: [PATCH 269/365] Bump the minimum LLVM to 3.9 Old LLVM bugs are reportedly cropping up harder, but 3.9 seems to be OK. Fixes #45277. --- .travis.yml | 2 +- .../{x86_64-gnu-llvm-3.7 => x86_64-gnu-llvm-3.9}/Dockerfile | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) rename src/ci/docker/{x86_64-gnu-llvm-3.7 => x86_64-gnu-llvm-3.9}/Dockerfile (72%) diff --git a/.travis.yml b/.travis.yml index 139f06ec570..e97f9d9251f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ matrix: fast_finish: true include: # Images used in testing PR and try-build should be run first. - - env: IMAGE=x86_64-gnu-llvm-3.7 RUST_BACKTRACE=1 + - env: IMAGE=x86_64-gnu-llvm-3.9 RUST_BACKTRACE=1 if: type = pull_request OR branch = auto - env: IMAGE=dist-x86_64-linux DEPLOY=1 diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile similarity index 72% rename from src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile rename to src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile index e832a2445ba..6b818604898 100644 --- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-3.9/Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - llvm-3.7-tools \ + llvm-3.9-tools \ libedit-dev \ zlib1g-dev \ xz-utils @@ -19,7 +19,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh +# using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-3.7 + --llvm-root=/usr/lib/llvm-3.9 \ + --enable-llvm-link-shared ENV RUST_CHECK_TARGET check From 7538a9b8afc42abfdc01afb4481a63dc3840f2ee Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 16 Oct 2017 12:48:01 -0700 Subject: [PATCH 270/365] Update the codegen/mainsubprogram tests to min-llvm 4.0 The necessary changes were only in upstream LLVM in 4.0, but they were for a while backported to Rust LLVM. Now that Rust LLVM is also 4.0, we can make the test conditional here more accurate. --- src/test/codegen/mainsubprogram.rs | 7 +++---- src/test/codegen/mainsubprogramstart.rs | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/test/codegen/mainsubprogram.rs b/src/test/codegen/mainsubprogram.rs index 657f4b662f7..f0508bc90f2 100644 --- a/src/test/codegen/mainsubprogram.rs +++ b/src/test/codegen/mainsubprogram.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// The minimum LLVM version is set to 3.8, but really this test -// depends on a patch that is was committed to upstream LLVM before -// 4.0; and also backported to the Rust LLVM fork. +// This test depends on a patch that was committed to upstream LLVM +// before 4.0, formerly backported to the Rust LLVM fork. // ignore-tidy-linelength // ignore-windows // ignore-macos -// min-llvm-version 3.8 +// min-llvm-version 4.0 // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/mainsubprogramstart.rs b/src/test/codegen/mainsubprogramstart.rs index cd34a1670dc..8325318f9af 100644 --- a/src/test/codegen/mainsubprogramstart.rs +++ b/src/test/codegen/mainsubprogramstart.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// The minimum LLVM version is set to 3.8, but really this test -// depends on a patch that is was committed to upstream LLVM before -// 4.0; and also backported to the Rust LLVM fork. +// This test depends on a patch that was committed to upstream LLVM +// before 4.0, formerly backported to the Rust LLVM fork. // ignore-tidy-linelength // ignore-windows // ignore-macos -// min-llvm-version 3.8 +// min-llvm-version 4.0 // compile-flags: -g -C no-prepopulate-passes From 6f33108e4d13c018368fb7fd3c337718de89925e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 16 Oct 2017 12:57:37 -0700 Subject: [PATCH 271/365] bootstrap: update and enable the LLVM version-check While the `config.toml.example` comments say "we automatically check the version by default," we actually didn't. That check was badly out of date, only allowing 3.5, 3.6, or 3.7. This it now updated to the new 3.9 minimum requirement, and truly enabled by default. --- config.toml.example | 2 +- src/bootstrap/config.rs | 1 + src/bootstrap/native.rs | 11 +++++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/config.toml.example b/config.toml.example index f50543e18a7..261fe205387 100644 --- a/config.toml.example +++ b/config.toml.example @@ -35,7 +35,7 @@ # If an external LLVM root is specified, we automatically check the version by # default to make sure it's within the range that we're expecting, but setting # this flag will indicate that this version check should not be done. -#version-check = false +#version-check = true # Link libstdc++ statically into the librustc_llvm instead of relying on a # dynamic version to be available. diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 69e0f58f1cd..d6c83e3acfc 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -299,6 +299,7 @@ impl Config { let mut config = Config::default(); config.llvm_enabled = true; config.llvm_optimize = true; + config.llvm_version_check = true; config.use_jemalloc = true; config.backtrace = true; config.rust_optimize = true; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 941ea96bbec..c37b1dad4c6 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -259,11 +259,14 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { let mut cmd = Command::new(llvm_config); let version = output(cmd.arg("--version")); - if version.starts_with("3.5") || version.starts_with("3.6") || - version.starts_with("3.7") { - return + let mut parts = version.split('.').take(2) + .filter_map(|s| s.parse::().ok()); + if let (Some(major), Some(minor)) = (parts.next(), parts.next()) { + if major > 3 || (major == 3 && minor >= 9) { + return + } } - panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version) + panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version) } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] From 5c26509405681aa54d57577085810101ed6ac54e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 8 Sep 2017 09:58:53 -0400 Subject: [PATCH 272/365] restructure the public inhabitedness APIs and remove the cache The cache was broken anyhow and this computation doesn't look that expensive. These public accessors could potentially become queries, but we'd have to add some more complex logic around lift. I'd prefer to have some test cases to profile with before doing that. Fixes #44402. --- src/librustc/ty/context.rs | 4 -- src/librustc/ty/inhabitedness/mod.rs | 51 ++++++++-------------- src/librustc/ty/mod.rs | 15 +++++++ src/librustc_mir/build/matches/simplify.rs | 5 +-- src/test/run-pass/issue-44402.rs | 36 +++++++++++++++ 5 files changed, 70 insertions(+), 41 deletions(-) create mode 100644 src/test/run-pass/issue-44402.rs diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 24ba38cf147..c2e881255f2 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -43,7 +43,6 @@ use ty::RegionKind; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; use ty::TypeVariants::*; use ty::layout::{Layout, TargetDataLayout}; -use ty::inhabitedness::DefIdForest; use ty::maps; use ty::steal::Steal; use ty::BindingMode; @@ -896,8 +895,6 @@ pub struct GlobalCtxt<'tcx> { // FIXME dep tracking -- should be harmless enough pub normalized_cache: RefCell, Ty<'tcx>>>, - pub inhabitedness_cache: RefCell, DefIdForest>>, - /// Caches the results of trait selection. This cache is used /// for things that do not have to do with the parameters in scope. pub selection_cache: traits::SelectionCache<'tcx>, @@ -1179,7 +1176,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { mir_passes, rcache: RefCell::new(FxHashMap()), normalized_cache: RefCell::new(FxHashMap()), - inhabitedness_cache: RefCell::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), rvalue_promotable_to_static: RefCell::new(NodeMap()), diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 9dc1b19c0f1..34e9084662a 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -100,14 +100,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// This code should only compile in modules where the uninhabitedness of Foo is /// visible. pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool { - let forest = ty.uninhabited_from(&mut FxHashMap(), self); - // To check whether this type is uninhabited at all (not just from the // given node) you could check whether the forest is empty. // ``` // forest.is_empty() // ``` - forest.contains(self, module) + self.ty_inhabitedness_forest(ty).contains(self, module) + } + + fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest { + ty.uninhabited_from(&mut FxHashMap(), self) } pub fn is_enum_variant_uninhabited_from(self, @@ -116,17 +118,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { substs: &'tcx Substs<'tcx>) -> bool { - let adt_kind = AdtKind::Enum; - variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).contains(self, module) + self.variant_inhabitedness_forest(variant, substs).contains(self, module) } pub fn is_variant_uninhabited_from_all_modules(self, variant: &'tcx VariantDef, - substs: &'tcx Substs<'tcx>, - adt_kind: AdtKind) + substs: &'tcx Substs<'tcx>) -> bool { - !variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).is_empty() + !self.variant_inhabitedness_forest(variant, substs).is_empty() + } + + fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: &'tcx Substs<'tcx>) + -> DefIdForest { + // Determine the ADT kind: + let adt_def_id = self.adt_def_id_of_variant(variant); + let adt_kind = self.adt_def(adt_def_id).adt_kind(); + + // Compute inhabitedness forest: + variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind) } } @@ -210,31 +220,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { &self, visited: &mut FxHashMap>>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest - { - match tcx.lift_to_global(&self) { - Some(global_ty) => { - { - let cache = tcx.inhabitedness_cache.borrow(); - if let Some(forest) = cache.get(&global_ty) { - return forest.clone(); - } - } - let forest = global_ty.uninhabited_from_inner(visited, tcx); - let mut cache = tcx.inhabitedness_cache.borrow_mut(); - cache.insert(global_ty, forest.clone()); - forest - }, - None => { - let forest = self.uninhabited_from_inner(visited, tcx); - forest - }, - } - } - - fn uninhabited_from_inner( - &self, - visited: &mut FxHashMap>>, - tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest { match self.sty { TyAdt(def, substs) => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c4f526d8014..35969361544 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -18,6 +18,7 @@ pub use self::fold::TypeFoldable; use hir::{map as hir_map, FreevarMap, TraitMap}; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; +use hir::map::DefPathData; use ich::StableHashingContext; use middle::const_val::ConstVal; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; @@ -2232,6 +2233,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + /// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part. + pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId { + let def_key = self.def_key(variant_def.did); + match def_key.disambiguated_data.data { + // for enum variants and tuple structs, the def-id of the ADT itself + // is the *parent* of the variant + DefPathData::EnumVariant(..) | DefPathData::StructCtor => + DefId { krate: variant_def.did.krate, index: def_key.parent.unwrap() }, + + // otherwise, for structs and unions, they share a def-id + _ => variant_def.did, + } + } + pub fn item_name(self, id: DefId) -> InternedString { if let Some(id) = self.hir.as_local_node_id(id) { self.hir.name(id).as_str() diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index f7d15d91188..9b3f16f1ab4 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -101,10 +101,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if self.hir.tcx().sess.features.borrow().never_type { let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| { i == variant_index || { - let adt_kind = adt_def.adt_kind(); - self.hir.tcx().is_variant_uninhabited_from_all_modules(v, - substs, - adt_kind) + self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs) } }); if irrefutable { diff --git a/src/test/run-pass/issue-44402.rs b/src/test/run-pass/issue-44402.rs new file mode 100644 index 00000000000..244aa65a3d5 --- /dev/null +++ b/src/test/run-pass/issue-44402.rs @@ -0,0 +1,36 @@ +// 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. + +#![feature(never_type)] + +// Regression test for inhabitedness check. The old +// cache used to cause us to incorrectly decide +// that `test_b` was invalid. + +struct Foo { + field1: !, + field2: Option<&'static Bar>, +} + +struct Bar { + field1: &'static Foo +} + +fn test_a() { + let x: Option = None; + match x { None => () } +} + +fn test_b() { + let x: Option = None; + match x { None => () } +} + +fn main() { } From 807e157b4cff0bcedb91abe482b876ea1ac3b1e0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 8 Sep 2017 12:14:38 -0400 Subject: [PATCH 273/365] invoke const only on body-ids --- src/librustc_passes/consts.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 547d63fc3d4..54c656e3a51 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -53,6 +53,23 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use std::collections::hash_map::Entry; use std::cmp::Ordering; +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + for &body_id in &tcx.hir.krate().body_ids { + let visitor = &mut CheckCrateVisitor { + tcx, + tables: &ty::TypeckTables::empty(None), + in_fn: false, + in_static: false, + promotable: false, + mut_rvalue_borrows: NodeSet(), + param_env: ty::ParamEnv::empty(Reveal::UserFacing), + identity_substs: Substs::empty(), + }; + visitor.visit_nested_body(body_id); + } + tcx.sess.abort_if_errors(); +} + struct CheckCrateVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, in_fn: bool, @@ -513,20 +530,6 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp } } -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - tcx.hir.krate().visit_all_item_likes(&mut CheckCrateVisitor { - tcx, - tables: &ty::TypeckTables::empty(None), - in_fn: false, - in_static: false, - promotable: false, - mut_rvalue_borrows: NodeSet(), - param_env: ty::ParamEnv::empty(Reveal::UserFacing), - identity_substs: Substs::empty(), - }.as_deep_visitor()); - tcx.sess.abort_if_errors(); -} - impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { fn consume(&mut self, _consume_id: ast::NodeId, From 0f568e2f347f27c72ca5853a7b13aa599c31b612 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 11 Sep 2017 13:09:14 -0400 Subject: [PATCH 274/365] convert constant promotion into a query --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/middle/expr_use_visitor.rs | 22 +++- src/librustc/middle/mem_categorization.rs | 40 ++++++- src/librustc/ty/context.rs | 4 - src/librustc/ty/maps/config.rs | 14 ++- src/librustc/ty/maps/mod.rs | 3 +- src/librustc_borrowck/borrowck/check_loans.rs | 8 +- .../borrowck/gather_loans/mod.rs | 8 +- src/librustc_const_eval/check_match.rs | 2 +- src/librustc_driver/driver.rs | 3 +- src/librustc_metadata/astencode.rs | 5 +- src/librustc_passes/consts.rs | 103 ++++++++++++------ src/librustc_passes/lib.rs | 6 + 13 files changed, 165 insertions(+), 54 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 4600cdbc692..08acc22114b 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -553,6 +553,7 @@ define_dep_nodes!( <'tcx> [] LookupDeprecationEntry(DefId), [] ItemBodyNestedBodies(DefId), [] ConstIsRvaluePromotableToStatic(DefId), + [] RvaluePromotableMap(DefId), [] ImplParent(DefId), [] TraitOfItem(DefId), [] IsExportedSymbol(DefId), diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index b036b145a96..e62cc2a658a 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -27,10 +27,11 @@ use middle::region; use ty::{self, TyCtxt, adjustment}; use hir::{self, PatKind}; - +use std::rc::Rc; use syntax::ast; use syntax::ptr::P; use syntax_pos::Span; +use util::nodemap::ItemLocalMap; /////////////////////////////////////////////////////////////////////////// // The Delegate trait @@ -262,15 +263,30 @@ macro_rules! return_if_err { } impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { + /// Creates the ExprUseVisitor, configuring it with the various options provided: + /// + /// - `delegate` -- who receives the callbacks + /// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`) + /// - `region_scope_tree` --- region scope tree for the code being analyzed + /// - `tables` --- typeck results for the code being analyzed + /// - `rvalue_promotable_map` --- if you care about rvalue promotion, then provide + /// the map here (it can be computed with `tcx.rvalue_promotable_map(def_id)`). + /// `None` means that rvalues will be given more conservative lifetimes. + /// + /// See also `with_infer`, which is used *during* typeck. pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, region_scope_tree: &'a region::ScopeTree, - tables: &'a ty::TypeckTables<'tcx>) + tables: &'a ty::TypeckTables<'tcx>, + rvalue_promotable_map: Option>>) -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::new(tcx, region_scope_tree, tables), + mc: mc::MemCategorizationContext::new(tcx, + region_scope_tree, + tables, + rvalue_promotable_map), delegate, param_env, } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c973881c980..3ef7ee4d6b0 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -86,6 +86,7 @@ use syntax_pos::Span; use std::fmt; use std::rc::Rc; +use util::nodemap::ItemLocalMap; #[derive(Clone, PartialEq)] pub enum Categorization<'tcx> { @@ -285,6 +286,7 @@ pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub region_scope_tree: &'a region::ScopeTree, pub tables: &'a ty::TypeckTables<'tcx>, + rvalue_promotable_map: Option>>, infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>, } @@ -392,21 +394,46 @@ impl MutabilityCategory { impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, region_scope_tree: &'a region::ScopeTree, - tables: &'a ty::TypeckTables<'tcx>) + tables: &'a ty::TypeckTables<'tcx>, + rvalue_promotable_map: Option>>) -> MemCategorizationContext<'a, 'tcx, 'tcx> { - MemCategorizationContext { tcx, region_scope_tree, tables, infcx: None } + MemCategorizationContext { + tcx, + region_scope_tree, + tables, + rvalue_promotable_map, + infcx: None + } } } impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { + /// Creates a `MemCategorizationContext` during type inference. + /// This is used during upvar analysis and a few other places. + /// Because the typeck tables are not yet complete, the results + /// from the analysis must be used with caution: + /// + /// - rvalue promotions are not known, so the lifetimes of + /// temporaries may be overly conservative; + /// - similarly, as the results of upvar analysis are not yet + /// known, the results around upvar accesses may be incorrect. pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>) -> MemCategorizationContext<'a, 'gcx, 'tcx> { + let tcx = infcx.tcx; + + // Subtle: we can't do rvalue promotion analysis until the + // typeck false is complete, which means that you can't trust + // the rvalue lifetimes that result, but that's ok, since we + // don't need to know those during type inference. + let rvalue_promotable_map = None; + MemCategorizationContext { - tcx: infcx.tcx, + tcx, region_scope_tree, tables, + rvalue_promotable_map, infcx: Some(infcx), } } @@ -871,8 +898,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span: Span, expr_ty: Ty<'tcx>) -> cmt<'tcx> { - let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned() - .unwrap_or(false); + let hir_id = self.tcx.hir.node_to_hir_id(id); + let promotable = self.rvalue_promotable_map.as_ref().map(|m| m[&hir_id.local_id]) + .unwrap_or(false); // Always promote `[T; 0]` (even when e.g. borrowed mutably). let promotable = match expr_ty.sty { @@ -887,7 +915,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let re = if promotable { self.tcx.types.re_static } else { - self.temporary_scope(self.tcx.hir.node_to_hir_id(id).local_id) + self.temporary_scope(hir_id.local_id) }; let ret = self.cat_rvalue(id, span, re, expr_ty); debug!("cat_rvalue_node ret {:?}", ret); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c2e881255f2..3ba7dc68f9b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -904,9 +904,6 @@ pub struct GlobalCtxt<'tcx> { /// Merge this with `selection_cache`? pub evaluation_cache: traits::EvaluationCache<'tcx>, - /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime. - pub rvalue_promotable_to_static: RefCell>, - /// The definite name of the current crate after taking into account /// attributes, commandline parameters, etc. pub crate_name: Symbol, @@ -1178,7 +1175,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { normalized_cache: RefCell::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), - rvalue_promotable_to_static: RefCell::new(NodeMap()), crate_name: Symbol::intern(crate_name), data_layout, layout_interner: RefCell::new(FxHashSet()), diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 137039598a5..2279dff1335 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -29,7 +29,12 @@ pub(super) trait QueryDescription: QueryConfig { impl> QueryDescription for M { default fn describe(tcx: TyCtxt, def_id: DefId) -> String { - format!("processing `{}`", tcx.item_path_str(def_id)) + if !tcx.sess.verbose() { + format!("processing `{}`", tcx.item_path_str(def_id)) + } else { + let name = unsafe { ::std::intrinsics::type_name::() }; + format!("processing `{}` applied to `{:?}`", name, def_id) + } } } @@ -214,6 +219,13 @@ impl<'tcx> QueryDescription for queries::const_is_rvalue_promotable_to_static<'t } } +impl<'tcx> QueryDescription for queries::rvalue_promotable_map<'tcx> { + fn describe(tcx: TyCtxt, def_id: DefId) -> String { + format!("checking which parts of `{}` are promotable to static", + tcx.item_path_str(def_id)) + } +} + impl<'tcx> QueryDescription for queries::is_mir_available<'tcx> { fn describe(tcx: TyCtxt, def_id: DefId) -> String { format!("checking if item is mir available: `{}`", diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 58405c261ad..07807429bfb 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -37,7 +37,7 @@ use ty::{self, CrateInherentImpls, Ty, TyCtxt}; use ty::layout::{Layout, LayoutError}; use ty::steal::Steal; use ty::subst::Substs; -use util::nodemap::{DefIdSet, DefIdMap}; +use util::nodemap::{DefIdSet, DefIdMap, ItemLocalMap}; use util::common::{profq_msg, ProfileQueriesMsg}; use rustc_data_structures::indexed_set::IdxSetBuf; @@ -228,6 +228,7 @@ define_maps! { <'tcx> [] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool, [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies, [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, + [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Rc>, [] fn is_mir_available: IsMirAvailable(DefId) -> bool, [] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>) -> Rc)>>>, diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 6ce5afd4bf1..266fe406d01 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -206,7 +206,13 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans, param_env, }; - euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, param_env, &bccx.region_scope_tree, bccx.tables) + let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id); + euv::ExprUseVisitor::new(&mut clcx, + bccx.tcx, + param_env, + &bccx.region_scope_tree, + bccx.tables, + Some(rvalue_promotable_map)) .consume_body(body); } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 1827ddabe4e..859f32f5bfc 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -48,7 +48,13 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_error_collector: move_error::MoveErrorCollector::new(), }; - euv::ExprUseVisitor::new(&mut glcx, bccx.tcx, param_env, &bccx.region_scope_tree, bccx.tables) + let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id); + euv::ExprUseVisitor::new(&mut glcx, + bccx.tcx, + param_env, + &bccx.region_scope_tree, + bccx.tables, + Some(rvalue_promotable_map)) .consume_body(bccx.body); glcx.report_potential_errors(); diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index a9eda3c2f69..e6a04c9c57a 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -526,7 +526,7 @@ fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { let mut checker = MutationChecker { cx, }; - ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables) + ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables, None) .walk_expr(guard); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ad6f7fbf111..7dbf93da385 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -38,7 +38,7 @@ use rustc_typeck as typeck; use rustc_privacy; use rustc_plugin::registry::Registry; use rustc_plugin as plugin; -use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats}; +use rustc_passes::{self, ast_validation, no_asm, loops, consts, static_recursion, hir_stats}; use rustc_const_eval::{self, check_match}; use super::Compilation; use ::DefaultTransCrate; @@ -973,6 +973,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, traits::provide(&mut local_providers); reachable::provide(&mut local_providers); rustc_const_eval::provide(&mut local_providers); + rustc_passes::provide(&mut local_providers); middle::region::provide(&mut local_providers); cstore::provide_local(&mut local_providers); lint::provide(&mut local_providers); diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index d9ab2562eff..722d0cad238 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -56,7 +56,8 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> { }; let lazy_body = self.lazy(body); - let tables = self.tcx.body_tables(body_id); + let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id); + let tables = self.tcx.typeck_tables_of(body_owner_def_id); let lazy_tables = self.lazy(tables); let mut visitor = NestedBodyCollector { @@ -67,7 +68,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> { let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found); let rvalue_promotable_to_static = - self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id]; + self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id); self.lazy(&Ast { body: lazy_body, diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 54c656e3a51..d3202ba4ab5 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -39,37 +39,79 @@ use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; use rustc::mir::transform::MirSource; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::maps::{queries, Providers}; use rustc::ty::subst::Substs; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; -use rustc::util::nodemap::NodeSet; +use rustc::util::nodemap::{ItemLocalMap, NodeSet}; use rustc::lint::builtin::CONST_ERR; - use rustc::hir::{self, PatKind, RangeEnd}; +use std::rc::Rc; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use std::collections::hash_map::Entry; use std::cmp::Ordering; +pub fn provide(providers: &mut Providers) { + *providers = Providers { + rvalue_promotable_map, + const_is_rvalue_promotable_to_static, + ..*providers + }; +} + pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { for &body_id in &tcx.hir.krate().body_ids { - let visitor = &mut CheckCrateVisitor { - tcx, - tables: &ty::TypeckTables::empty(None), - in_fn: false, - in_static: false, - promotable: false, - mut_rvalue_borrows: NodeSet(), - param_env: ty::ParamEnv::empty(Reveal::UserFacing), - identity_substs: Substs::empty(), - }; - visitor.visit_nested_body(body_id); + let def_id = tcx.hir.body_owner_def_id(body_id); + tcx.const_is_rvalue_promotable_to_static(def_id); } tcx.sess.abort_if_errors(); } +fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> bool +{ + assert!(def_id.is_local()); + + let node_id = tcx.hir.as_local_node_id(def_id) + .expect("rvalue_promotable_map invoked with non-local def-id"); + let body_id = tcx.hir.body_owned_by(node_id); + let body_hir_id = tcx.hir.node_to_hir_id(body_id.node_id); + tcx.rvalue_promotable_map(def_id).contains_key(&body_hir_id.local_id) +} + +fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> Rc> +{ + let outer_def_id = tcx.closure_base_def_id(def_id); + if outer_def_id != def_id { + return tcx.rvalue_promotable_map(outer_def_id); + } + + let mut visitor = CheckCrateVisitor { + tcx, + tables: &ty::TypeckTables::empty(None), + in_fn: false, + in_static: false, + promotable: false, + mut_rvalue_borrows: NodeSet(), + param_env: ty::ParamEnv::empty(Reveal::UserFacing), + identity_substs: Substs::empty(), + result_map: ItemLocalMap(), + }; + + // `def_id` should be a `Body` owner + let node_id = tcx.hir.as_local_node_id(def_id) + .expect("rvalue_promotable_map invoked with non-local def-id"); + let body_id = tcx.hir.body_owned_by(node_id); + visitor.visit_nested_body(body_id); + + Rc::new(visitor.result_map) +} + struct CheckCrateVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, in_fn: bool, @@ -79,6 +121,7 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> { param_env: ty::ParamEnv<'tcx>, identity_substs: &'tcx Substs<'tcx>, tables: &'a ty::TypeckTables<'tcx>, + result_map: ItemLocalMap, } impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { @@ -126,18 +169,11 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + // note that we *do* visit nested bodies, because we override `visit_nested_body` below NestedVisitorMap::None } fn visit_nested_body(&mut self, body_id: hir::BodyId) { - match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body_id.node_id) { - Entry::Occupied(_) => return, - Entry::Vacant(entry) => { - // Prevent infinite recursion on re-entry. - entry.insert(false); - } - } - let item_id = self.tcx.hir.body_owner(body_id); let item_def_id = self.tcx.hir.local_def_id(item_id); @@ -168,7 +204,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { let tcx = self.tcx; let param_env = self.param_env; let region_scope_tree = self.tcx.region_scope_tree(item_def_id); - euv::ExprUseVisitor::new(self, tcx, param_env, ®ion_scope_tree, self.tables) + euv::ExprUseVisitor::new(self, tcx, param_env, ®ion_scope_tree, self.tables, None) .consume_body(body); self.visit_body(body); @@ -287,7 +323,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { } } - self.tcx.rvalue_promotable_to_static.borrow_mut().insert(ex.id, self.promotable); + self.result_map.insert(ex.hir_id.local_id, self.promotable); self.promotable &= outer; } } @@ -388,16 +424,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node let promotable = if v.tcx.trait_of_item(did).is_some() { // Don't peek inside trait associated constants. false - } else if let Some(node_id) = v.tcx.hir.as_local_node_id(did) { - match v.tcx.hir.maybe_body_owned_by(node_id) { - Some(body) => { - v.visit_nested_body(body); - v.tcx.rvalue_promotable_to_static.borrow()[&body.node_id] - } - None => false - } } else { - v.tcx.const_is_rvalue_promotable_to_static(did) + queries::const_is_rvalue_promotable_to_static::try_get(v.tcx, e.span, did) + .unwrap_or_else(|mut err| { + // A cycle between constants ought to be reported elsewhere. + err.cancel(); + v.tcx.sess.delay_span_bug( + e.span, + &format!("cycle encountered during const qualification: {:?}", + did)); + false + }) }; // Just in case the type is more specific than the definition, diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 28b99e1185b..9a150abea66 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -33,6 +33,8 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc_errors as errors; +use rustc::ty::maps::Providers; + mod diagnostics; pub mod ast_validation; @@ -44,3 +46,7 @@ pub mod no_asm; pub mod static_recursion; __build_diagnostic_array! { librustc_passes, DIAGNOSTICS } + +pub fn provide(providers: &mut Providers) { + consts::provide(providers); +} From 47449ea513955f278e8838a132a0c71655c54abf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 21 Sep 2017 13:46:38 -0400 Subject: [PATCH 275/365] add a function for testing if a ty is uninhabited from all modules Desired by miri. --- src/librustc/ty/inhabitedness/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 34e9084662a..0072512464a 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -108,6 +108,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.ty_inhabitedness_forest(ty).contains(self, module) } + pub fn is_ty_uninhabited_from_all_modules(self, ty: Ty<'tcx>) -> bool { + !self.ty_inhabitedness_forest(ty).is_empty() + } + fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest { ty.uninhabited_from(&mut FxHashMap(), self) } From 09caa12a51cb61a9841ac072103b6300aa5fb1fd Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 21 Sep 2017 13:46:52 -0400 Subject: [PATCH 276/365] add some tips to CONTRIBUTING.md to help with debugging this problem --- CONTRIBUTING.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a86742d7bd4..d67a74f681e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -360,8 +360,10 @@ git add path/to/submodule outside the submodule. -It can also be more convenient during development to set `submodules = false` -in the `config.toml` to prevent `x.py` from resetting to the original branch. +In order to prepare your PR, you can run the build locally by doing +`./x.py build src/tools/TOOL`. If you will be editing the sources +there, you may wish to set `submodules = false` in the `config.toml` +to prevent `x.py` from resetting to the original branch. ## Writing Documentation [writing-documentation]: #writing-documentation From 165cbce1ccb34cd643297ccf1e710c7e8ed95c14 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 22 Sep 2017 04:35:25 -0400 Subject: [PATCH 277/365] fix nits --- src/librustc/middle/mem_categorization.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3ef7ee4d6b0..f6d90c03ce0 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -424,7 +424,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let tcx = infcx.tcx; // Subtle: we can't do rvalue promotion analysis until the - // typeck false is complete, which means that you can't trust + // typeck phase is complete, which means that you can't trust // the rvalue lifetimes that result, but that's ok, since we // don't need to know those during type inference. let rvalue_promotable_map = None; From 0ae18a18b48850dc3e45ab1a09b243b6c61c265e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Oct 2017 16:07:47 -0400 Subject: [PATCH 278/365] bump up the recursion limit --- src/librustc/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index ed440849b48..64fe4626d6e 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -60,7 +60,7 @@ #![cfg_attr(stage0, feature(const_fn))] #![cfg_attr(not(stage0), feature(const_atomic_bool_new))] -#![recursion_limit="256"] +#![recursion_limit="512"] extern crate arena; #[macro_use] extern crate bitflags; From cefaaf21ee2dad6e615c5b2905d2bf9750547ce8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Oct 2017 00:19:25 +0200 Subject: [PATCH 279/365] Remove duplicated word --- src/libstd/sys/windows/ext/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index d58a3505154..a532163f61e 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -393,8 +393,8 @@ pub trait MetadataExt { /// to. For a directory, the structure specifies when the directory was /// created. /// - /// If the underlying filesystem does not support the last write time - /// time, the returned value is 0. + /// If the underlying filesystem does not support the last write time, + /// the returned value is 0. /// /// # Examples /// From 229bee3c38376b99d7d483e20fa97ec774e8a2bd Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Mon, 16 Oct 2017 17:18:02 -0500 Subject: [PATCH 280/365] Rename `read_node_index` to `try_mark_green_and_read` in plumbing This should limit the availability of `try_mark_green_and_read` making it harder to abuse. --- src/librustc/dep_graph/graph.rs | 34 -------------------------- src/librustc/ty/maps/plumbing.rs | 42 +++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 38a27305c2b..8aff042955c 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -427,40 +427,6 @@ impl DepGraph { self.data.as_ref().and_then(|data| data.colors.borrow().get(dep_node).cloned()) } - /// Try to read a node index for the node dep_node. - /// A node will have an index, when it's already been marked green, or when we can mark it - /// green. This function will mark the current task as a reader of the specified node, when - /// the a node index can be found for that node. - pub fn read_node_index(&self, tcx: TyCtxt, dep_node: &DepNode) -> Option { - match self.node_color(dep_node) { - Some(DepNodeColor::Green(dep_node_index)) => { - self.read_index(dep_node_index); - Some(dep_node_index) - } - Some(DepNodeColor::Red) => { - None - } - None => { - // try_mark_green (called below) will panic when full incremental - // compilation is disabled. If that's the case, we can't try to mark nodes - // as green anyway, so we can safely return None here. - if !self.is_fully_enabled() { - return None; - } - match self.try_mark_green(tcx, &dep_node) { - Some(dep_node_index) => { - debug_assert!(tcx.dep_graph.is_green(dep_node_index)); - tcx.dep_graph.read_index(dep_node_index); - Some(dep_node_index) - } - None => { - None - } - } - } - } - } - pub fn try_mark_green(&self, tcx: TyCtxt, dep_node: &DepNode) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 13880b37136..be12f443782 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -12,7 +12,7 @@ //! that generate the actual methods on tcx which find and execute the //! provider, manage the caches, and so forth. -use dep_graph::{DepNodeIndex, DepNode, DepKind}; +use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor}; use errors::{Diagnostic, DiagnosticBuilder}; use ty::{TyCtxt}; use ty::maps::Query; // NB: actually generated by the macros in this file @@ -133,6 +133,40 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Ok(result) } + + /// Try to read a node index for the node dep_node. + /// A node will have an index, when it's already been marked green, or when we can mark it + /// green. This function will mark the current task as a reader of the specified node, when + /// the a node index can be found for that node. + pub(super) fn try_mark_green_and_read(self, dep_node: &DepNode) -> Option { + match self.dep_graph.node_color(dep_node) { + Some(DepNodeColor::Green(dep_node_index)) => { + self.dep_graph.read_index(dep_node_index); + Some(dep_node_index) + } + Some(DepNodeColor::Red) => { + None + } + None => { + // try_mark_green (called below) will panic when full incremental + // compilation is disabled. If that's the case, we can't try to mark nodes + // as green anyway, so we can safely return None here. + if !self.dep_graph.is_fully_enabled() { + return None; + } + match self.dep_graph.try_mark_green(self, &dep_node) { + Some(dep_node_index) => { + debug_assert!(self.dep_graph.is_green(dep_node_index)); + self.dep_graph.read_index(dep_node_index); + Some(dep_node_index) + } + None => { + None + } + } + } + } + } } // If enabled, send a message to the profile-queries thread @@ -309,7 +343,7 @@ macro_rules! define_maps { } if !dep_node.kind.is_input() { - if let Some(dep_node_index) = tcx.dep_graph.read_node_index(tcx, &dep_node) { + if let Some(dep_node_index) = tcx.try_mark_green_and_read(&dep_node) { profq_msg!(tcx, ProfileQueriesMsg::CacheHit); return Self::load_from_disk_and_cache_in_memory(tcx, key, @@ -340,8 +374,8 @@ macro_rules! define_maps { // Ensuring an "input" or anonymous query makes no sense assert!(!dep_node.kind.is_anon()); assert!(!dep_node.kind.is_input()); - if tcx.dep_graph.read_node_index(tcx, &dep_node).is_none() { - // A None return from `read_node_index` means that this is either + if tcx.try_mark_green_and_read(&dep_node).is_none() { + // A None return from `try_mark_green_and_read` means that this is either // a new dep node or that the dep node has already been marked red. // Either way, we can't call `dep_graph.read()` as we don't have the // DepNodeIndex. We must invoke the query itself. The performance cost From 56f5a19e4561434919ecda627c5409a3b16ba1d0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Oct 2017 12:29:14 -0700 Subject: [PATCH 281/365] Update ThinLTO for LLVM 5 --- src/rustllvm/PassWrapper.cpp | 39 +++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 1287b94159a..c7d966fcdfd 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -26,11 +26,13 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #if LLVM_VERSION_GE(4, 0) -#include "llvm/Object/ModuleSummaryIndexObjectFile.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/LTO/LTO.h" +#if LLVM_VERSION_LE(4, 0) +#include "llvm/Object/ModuleSummaryIndexObjectFile.h" +#endif #endif #include "llvm-c/Transforms/PassManagerBuilder.h" @@ -888,6 +890,28 @@ addPreservedGUID(const ModuleSummaryIndex &Index, return; Preserved.insert(GUID); +#if LLVM_VERSION_GE(5, 0) + auto Info = Index.getValueInfo(GUID); + if (!Info) { + return; + } + for (auto &Summary : Info.getSummaryList()) { + for (auto &Ref : Summary->refs()) { + addPreservedGUID(Index, Preserved, Ref.getGUID()); + } + + GlobalValueSummary *GVSummary = Summary.get(); + if (isa(GVSummary)) { + FunctionSummary *FS = cast(GVSummary); + for (auto &Call: FS->calls()) { + addPreservedGUID(Index, Preserved, Call.first.getGUID()); + } + for (auto &GUID: FS->type_tests()) { + addPreservedGUID(Index, Preserved, GUID); + } + } + } +#else auto SummaryList = Index.findGlobalValueSummaryList(GUID); if (SummaryList == Index.end()) return; @@ -919,6 +943,7 @@ addPreservedGUID(const ModuleSummaryIndex &Index, addPreservedGUID(Index, Preserved, GUID); } } +#endif } // The main entry point for creating the global ThinLTO analysis. The structure @@ -939,6 +964,12 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, Ret->ModuleMap[module->identifier] = mem_buffer; +#if LLVM_VERSION_GE(5, 0) + if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) { + LLVMRustSetLastError(toString(std::move(Err)).c_str()); + return nullptr; + } +#else Expected> ObjOrErr = object::ModuleSummaryIndexObjectFile::create(mem_buffer); if (!ObjOrErr) { @@ -947,6 +978,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, } auto Index = (*ObjOrErr)->takeIndex(); Ret->Index.mergeFrom(std::move(Index), i); +#endif } // Collect for each module the list of function it defines (GUID -> Summary) @@ -981,8 +1013,13 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, StringMap> ResolvedODR; DenseMap PrevailingCopy; for (auto &I : Ret->Index) { +#if LLVM_VERSION_GE(5, 0) + if (I.second.SummaryList.size() > 1) + PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList); +#else if (I.second.size() > 1) PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second); +#endif } auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) { const auto &Prevailing = PrevailingCopy.find(GUID); From cbe41168e07852d976e6aa334de7b2ef0eab6c95 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Tue, 17 Oct 2017 15:01:49 +0900 Subject: [PATCH 282/365] bootstrap: Avoid fetching jemalloc if it's disabled Fix #45300 --- src/bootstrap/bootstrap.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 842144ff1ea..c441dc9acb8 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -648,7 +648,8 @@ class RustBuild(object): if not ((module.endswith("llvm") and self.get_toml('llvm-config')) or (module.endswith("jemalloc") and - self.get_toml('jemalloc')))] + (self.get_toml('use-jemalloc') == "false" or + self.get_toml('jemalloc'))))] run(["git", "submodule", "update", "--init", "--recursive"] + submodules, cwd=self.rust_root, verbose=self.verbose) From 8528508aa0850fa8286fb73503fb93263edaa976 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Tue, 17 Oct 2017 08:29:29 +0200 Subject: [PATCH 283/365] Update array documentation for Clone trait changes --- src/libstd/primitive_docs.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 1edb35d8fe7..9e1da318242 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -284,7 +284,6 @@ mod prim_pointer { } /// Arrays of sizes from 0 to 32 (inclusive) implement the following traits if /// the element type allows it: /// -/// - [`Clone`][clone] (only if `T: `[`Copy`][copy]) /// - [`Debug`][debug] /// - [`IntoIterator`][intoiterator] (implemented for `&[T; N]` and `&mut [T; N]`) /// - [`PartialEq`][partialeq], [`PartialOrd`][partialord], [`Eq`][eq], [`Ord`][ord] @@ -299,8 +298,10 @@ mod prim_pointer { } /// entirely different types. As a stopgap, trait implementations are /// statically generated up to size 32. /// -/// Arrays of *any* size are [`Copy`][copy] if the element type is [`Copy`][copy]. This -/// works because the [`Copy`][copy] trait is specially known to the compiler. +/// Arrays of *any* size are [`Copy`][copy] if the element type is [`Copy`][copy] +/// and [`Clone`][clone] if the element type is [`Clone`][clone]. This works +/// because [`Copy`][copy] and [`Clone`][clone] traits are specially known +/// to the compiler. /// /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on /// an array. Indeed, this provides most of the API for working with arrays. From a50fe312dc9fec9f9fc3576bc244ef2517ac8f4a Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Tue, 17 Oct 2017 11:02:25 +0200 Subject: [PATCH 284/365] Docs: a LocalKey might start in the Valid state --- src/libstd/thread/local.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index a53c76a333a..cb18eed8ee5 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -325,7 +325,10 @@ impl LocalKey { /// /// Once the initialization expression succeeds, the key transitions to the /// `Valid` state which will guarantee that future calls to [`with`] will - /// succeed within the thread. + /// succeed within the thread. Some keys might skip the `Uninitialized` + /// state altogether and start in the `Valid` state as an optimization + /// (e.g. keys initialized with a constant expression), but no guarantees + /// are made. /// /// When a thread exits, each key will be destroyed in turn, and as keys are /// destroyed they will enter the `Destroyed` state just before the From a151d37401b20d235eac1d862579dbbaa4ccea13 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 17 Oct 2017 15:20:22 +0300 Subject: [PATCH 285/365] fix generator drop caching Fixes #45328. --- src/librustc_mir/build/scope.rs | 35 ++++++++++++++++++++++++------- src/test/run-pass/dynamic-drop.rs | 24 ++++++++++++++++++++- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 03273419432..b88b61f1818 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -154,6 +154,11 @@ struct CachedBlock { unwind: Option, /// The cached block for unwinds during cleanups-on-generator-drop path + /// + /// This is split from the standard unwind path here to prevent drop + /// elaboration from creating drop flags that would have to be captured + /// by the generator. I'm not sure how important this optimization is, + /// but it is here. generator_drop: Option, } @@ -217,13 +222,26 @@ impl<'tcx> Scope<'tcx> { /// Should always be run for all inner scopes when a drop is pushed into some scope enclosing a /// larger extent of code. /// - /// `unwind` controls whether caches for the unwind branch are also invalidated. - fn invalidate_cache(&mut self, unwind: bool) { + /// `storage_only` controls whether to invalidate only drop paths run `StorageDead`. + /// `this_scope_only` controls whether to invalidate only drop paths that refer to the current + /// top-of-scope (as opposed to dependent scopes). + fn invalidate_cache(&mut self, storage_only: bool, this_scope_only: bool) { + // FIXME: maybe do shared caching of `cached_exits` etc. to handle functions + // with lots of `try!`? + + // cached exits drop storage and refer to the top-of-scope self.cached_exits.clear(); - if !unwind { return; } - for dropdata in &mut self.drops { - if let DropKind::Value { ref mut cached_block } = dropdata.kind { - cached_block.invalidate(); + + if !storage_only { + // the current generator drop ignores storage but refers to top-of-scope + self.cached_generator_drop = None; + } + + if !storage_only && !this_scope_only { + for dropdata in &mut self.drops { + if let DropKind::Value { ref mut cached_block } = dropdata.kind { + cached_block.invalidate(); + } } } } @@ -672,8 +690,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // invalidating caches of each scope visited. This way bare minimum of the // caches gets invalidated. i.e. if a new drop is added into the middle scope, the // cache of outer scpoe stays intact. - let invalidate_unwind = needs_drop && !this_scope; - scope.invalidate_cache(invalidate_unwind); + scope.invalidate_cache(!needs_drop, this_scope); if this_scope { if let DropKind::Value { .. } = drop_kind { scope.needs_cleanup = true; @@ -942,5 +959,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, target = block } + debug!("build_diverge_scope({:?}, {:?}) = {:?}", scope, span, target); + target } diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index 1aba47af1e9..d8b6dbe48f1 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(untagged_unions)] +#![feature(generators, generator_trait, untagged_unions)] use std::cell::{Cell, RefCell}; +use std::ops::Generator; use std::panic; use std::usize; @@ -161,6 +162,21 @@ fn vec_simple(a: &Allocator) { let _x = vec![a.alloc(), a.alloc(), a.alloc(), a.alloc()]; } +fn generator(a: &Allocator, run_count: usize) { + assert!(run_count < 4); + + let mut gen = || { + (a.alloc(), + yield a.alloc(), + a.alloc(), + yield a.alloc() + ); + }; + for _ in 0..run_count { + gen.resume(); + } +} + #[allow(unreachable_code)] fn vec_unreachable(a: &Allocator) { let _x = vec![a.alloc(), a.alloc(), a.alloc(), return]; @@ -228,5 +244,11 @@ fn main() { run_test(|a| field_assignment(a, false)); run_test(|a| field_assignment(a, true)); + // FIXME: fix leaks on panics + run_test_nopanic(|a| generator(a, 0)); + run_test_nopanic(|a| generator(a, 1)); + run_test_nopanic(|a| generator(a, 2)); + run_test_nopanic(|a| generator(a, 3)); + run_test_nopanic(|a| union1(a)); } From b3ea6e5fc548fd03f1902f9abfe4e3f11d426d39 Mon Sep 17 00:00:00 2001 From: bgermann Date: Tue, 17 Oct 2017 15:53:18 +0200 Subject: [PATCH 286/365] Make Solaris builder compatible with Solaris 10 retry Unfortunately, #45255 does not quite cut it, so use a different approach to have Solaris 10 compatibility by tricking libbacktrace's autoconf tests. The sysroot download routine is slightly changed, too. --- .../docker/cross2/build-solaris-toolchain.sh | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/ci/docker/cross2/build-solaris-toolchain.sh b/src/ci/docker/cross2/build-solaris-toolchain.sh index 935cbe5d61b..29d1d4414f2 100755 --- a/src/ci/docker/cross2/build-solaris-toolchain.sh +++ b/src/ci/docker/cross2/build-solaris-toolchain.sh @@ -38,37 +38,38 @@ cd solaris dpkg --add-architecture $APT_ARCH apt-get update -apt-get download \ - libc:$APT_ARCH \ +apt-get download $(apt-cache depends --recurse --no-replaces \ libc-dev:$APT_ARCH \ - libm:$APT_ARCH \ libm-dev:$APT_ARCH \ - libpthread:$APT_ARCH \ libpthread-dev:$APT_ARCH \ - libresolv:$APT_ARCH \ libresolv-dev:$APT_ARCH \ - librt:$APT_ARCH \ librt-dev:$APT_ARCH \ - libsocket:$APT_ARCH \ libsocket-dev:$APT_ARCH \ system-crt:$APT_ARCH \ - system-header:$APT_ARCH + system-header:$APT_ARCH \ + | grep "^\w") for deb in *$APT_ARCH.deb; do dpkg -x $deb . done -# Strip Solaris 11 functions that are optionally used by libbacktrace. +# Remove Solaris 11 functions that are optionally used by libbacktrace. # This is for Solaris 10 compatibility. -$ARCH-sun-solaris2.10-strip -N dl_iterate_phdr -N strnlen lib/$LIB_ARCH/libc.so +rm usr/include/link.h +patch -p0 << 'EOF' +--- usr/include/string.h 2017-10-09 03:15:04.000000000 +0200 ++++ usr/include/string10.h 2017-10-16 11:27:26.498764422 +0200 +@@ -93 +92,0 @@ +-extern size_t strnlen(const char *, size_t); +EOF mkdir /usr/local/$ARCH-sun-solaris2.10/usr mv usr/include /usr/local/$ARCH-sun-solaris2.10/usr/include mv usr/lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.10/lib mv lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.10/lib -ln -s /usr/local/$ARCH-sun-solaris2.10/usr/include /usr/local/$ARCH-sun-solaris2.10/sys-include -ln -s /usr/local/$ARCH-sun-solaris2.10/usr/include /usr/local/$ARCH-sun-solaris2.10/include +ln -s usr/include /usr/local/$ARCH-sun-solaris2.10/sys-include +ln -s usr/include /usr/local/$ARCH-sun-solaris2.10/include cd .. rm -rf solaris @@ -97,8 +98,7 @@ hide_output ../gcc-$GCC/configure \ --disable-libada \ --disable-libsanitizer \ --disable-libquadmath-support \ - --disable-lto \ - --with-sysroot=/usr/local/$ARCH-sun-solaris2.10 + --disable-lto hide_output make -j10 hide_output make install From 12873006f65ecc2aab1604bf857a42680939b245 Mon Sep 17 00:00:00 2001 From: Havvy Date: Tue, 10 Oct 2017 11:25:09 -0700 Subject: [PATCH 287/365] List of all lang items in unstable book. --- .../src/language-features/lang-items.md | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index ecbc860e25c..0137a052a62 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -227,3 +227,95 @@ A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_ flag is set in the options of the compilation target. It allows customizing the process of resuming unwind at the end of the landing pads. The language item's name is `eh_unwind_resume`. + +## List of all language items + +This is a list of all language items in Rust along with where they are located in +the source code. + +- Primitives + - `i8`: `libcore/num/mod.rs` + - `i16`: `libcore/num/mod.rs` + - `i32`: `libcore/num/mod.rs` + - `i64`: `libcore/num/mod.rs` + - `i128`: `libcore/num/mod.rs` + - `isize`: `libcore/num/mod.rs` + - `u8`: `libcore/num/mod.rs` + - `u16`: `libcore/num/mod.rs` + - `u32`: `libcore/num/mod.rs` + - `u64`: `libcore/num/mod.rs` + - `u128`: `libcore/num/mod.rs` + - `usize`: `libcore/num/mod.rs` + - `f32`: `libstd/f32.rs` + - `f64`: `libstd/f64.rs` + - `char`: `libstd_unicode/char.rs` + - `slice`: `liballoc/slice.rs` + - `str`: `liballoc/str.rs` + - `const_ptr`: `libcore/ptr.rs` + - `mut_ptr`: `libcore/ptr.rs` + - `unsafe_cell`: `libcore/cell.rs` +- Runtime + - `start`: `libstd/rt.rs` + - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) + - `eh_personality`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU) + - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) + - `eh_unwind_resume`: `libpanic_unwind/seh64_gnu.rs` (SEH64 GNU) + - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC) + - `msvc_try_filter`: `libpanic_unwind/seh.rs` (SEH) + - `panic`: `libcore/panicking.rs` + - `panic_bounds_check`: `libcore/panicking.rs` + - `panic_fmt`: `libcore/panicking.rs` + - `panic_fmt`: `libstd/panicking.rs` +- Allocations + - `owned_box`: `liballoc/boxed.rs` + - `exchange_malloc`: `liballoc/heap.rs` + - `box_free`: `liballoc/heap.rs` +- Operands + - `not`: `libcore/ops/bit.rs` + - `bitand`: `libcore/ops/bit.rs` + - `bitor`: `libcore/ops/bit.rs` + - `bitxor`: `libcore/ops/bit.rs` + - `shl`: `libcore/ops/bit.rs` + - `shr`: `libcore/ops/bit.rs` + - `bitand_assign`: `libcore/ops/bit.rs` + - `bitor_assign`: `libcore/ops/bit.rs` + - `bitxor_assign`: `libcore/ops/bit.rs` + - `shl_assign`: `libcore/ops/bit.rs` + - `shr_assign`: `libcore/ops/bit.rs` + - `deref`: `libcore/ops/deref.rs` + - `deref_mut`: `libcore/ops/deref.rs` + - `index`: `libcore/ops/index.rs` + - `index_mut`: `libcore/ops/index.rs` + - `add`: `libcore/ops/arith.rs` + - `sub`: `libcore/ops/arith.rs` + - `mul`: `libcore/ops/arith.rs` + - `div`: `libcore/ops/arith.rs` + - `rem`: `libcore/ops/arith.rs` + - `neg`: `libcore/ops/arith.rs` + - `add_assign`: `libcore/ops/arith.rs` + - `sub_assign`: `libcore/ops/arith.rs` + - `mul_assign`: `libcore/ops/arith.rs` + - `div_assign`: `libcore/ops/arith.rs` + - `rem_assign`: `libcore/ops/arith.rs` + - `eq`: `libcore/cmp.rs` + - `ord`: `libcore/cmp.rs` +- Functions + - `fn`: `libcore/ops/function.rs` + - `fn_mut`: `libcore/ops/function.rs` + - `fn_once`: `libcore/ops/function.rs` + - `generator_state`: `libcore/ops/generator.rs` + - `generator`: `libcore/ops/generator.rs` +- Other + - `coerce_unsized`: `libcore/ops/unsize.rs` + - `drop`: `libcore/ops/drop.rs` + - `drop_in_place`: `libcore/ptr.rs` + - `clone`: `libcore/clone.rs` + - `copy`: `libcore/marker.rs` + - `send`: `libcore/marker.rs` + - `sized`: `libcore/marker.rs` + - `unsize`: `libcore/marker.rs` + - `sync`: `libcore/marker.rs` + - `phantom_data`: `libcore/marker.rs` + - `freeze`: `libcore/marker.rs` + - `debug_trait`: `libcore/fmt/mod.rs` + - `non_zero`: `libcore/nonzero.rs` \ No newline at end of file From 0597bdabff5b8ee2d966c90b1836d67631327787 Mon Sep 17 00:00:00 2001 From: bgermann Date: Tue, 17 Oct 2017 16:39:15 +0200 Subject: [PATCH 288/365] Remove tabs --- src/ci/docker/cross2/build-solaris-toolchain.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/cross2/build-solaris-toolchain.sh b/src/ci/docker/cross2/build-solaris-toolchain.sh index 29d1d4414f2..71ab998aab2 100755 --- a/src/ci/docker/cross2/build-solaris-toolchain.sh +++ b/src/ci/docker/cross2/build-solaris-toolchain.sh @@ -57,8 +57,8 @@ done # This is for Solaris 10 compatibility. rm usr/include/link.h patch -p0 << 'EOF' ---- usr/include/string.h 2017-10-09 03:15:04.000000000 +0200 -+++ usr/include/string10.h 2017-10-16 11:27:26.498764422 +0200 +--- usr/include/string.h ++++ usr/include/string10.h @@ -93 +92,0 @@ -extern size_t strnlen(const char *, size_t); EOF From 4adf6aed697f2d3915fdcc0ee3c5387f9d833dc5 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Mon, 28 Aug 2017 19:30:45 -0400 Subject: [PATCH 289/365] Deprecate several flags in rustdoc Part of #44136 Upgrades cargo due to https://github.com/rust-lang/cargo/pull/4451 --- src/librustdoc/lib.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 890e1169c05..90952588c55 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -275,6 +275,9 @@ pub fn main_args(args: &[String]) -> isize { // Check for unstable options. nightly_options::check_nightly_options(&matches, &opts()); + // check for deprecated options + check_deprecated_options(&matches); + if matches.opt_present("h") || matches.opt_present("help") { usage("rustdoc"); return 0; @@ -550,3 +553,22 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { }); rx.recv().unwrap() } + +/// Prints deprecation warnings for deprecated options +fn check_deprecated_options(matches: &getopts::Matches) { + let deprecated_flags = [ + "input-format", + "output-format", + "plugin-path", + "plugins", + "no-defaults", + "passes", + ]; + + for flag in deprecated_flags.into_iter() { + if matches.opt_present(flag) { + eprintln!("WARNING: the '{}' flag is considered deprecated", flag); + eprintln!("WARNING: please see https://github.com/rust-lang/rust/issues/44136"); + } + } +} From aad8787586a46fc8eb2a89260fafd8598d378b67 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Thu, 21 Sep 2017 14:10:07 -0400 Subject: [PATCH 290/365] Create a new flag, --document-private-items Fixes #44136 --- src/librustdoc/lib.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 90952588c55..20da99a6b13 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -170,6 +170,9 @@ pub fn opts() -> Vec { stable("no-default", |o| { o.optflag("", "no-defaults", "don't run the default passes") }), + stable("document-private-items", |o| { + o.optflag("", "document-private-items", "document private items") + }), stable("test", |o| o.optflag("", "test", "run code examples as tests")), stable("test-args", |o| { o.optmulti("", "test-args", "arguments to pass to the test runner", @@ -461,6 +464,18 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { let mut passes = matches.opt_strs("passes"); let mut plugins = matches.opt_strs("plugins"); + // We hardcode in the passes here, as this is a new flag and we + // are generally deprecating passes. + if matches.opt_present("document-private-items") { + default_passes = false; + + passes = vec![ + String::from("strip-hidden"), + String::from("collapse-docs"), + String::from("unindent-comments"), + ]; + } + // First, parse the crate and extract all relevant information. let mut paths = SearchPaths::new(); for s in &matches.opt_strs("L") { @@ -571,4 +586,8 @@ fn check_deprecated_options(matches: &getopts::Matches) { eprintln!("WARNING: please see https://github.com/rust-lang/rust/issues/44136"); } } + + if matches.opt_present("no-defaults") { + eprintln!("WARNING: (you may want to use --document-private-items)"); + } } From b8f981a149ddbfdfa943d05a30710bafdf2f9522 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 16 Oct 2017 10:45:23 -0300 Subject: [PATCH 291/365] Generate FirstStatementIndex using newtype_index macro --- src/librustc/ich/impls_ty.rs | 2 +- src/librustc/middle/region.rs | 27 +++++---------------- src/librustc_data_structures/indexed_vec.rs | 4 +-- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f719ce15092..50f7e4ba176 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -518,7 +518,7 @@ impl_stable_hash_for!(enum ty::cast::CastKind { FnPtrAddrCast }); -impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { idx }); +impl_stable_hash_for!(tuple_struct ::middle::region::FirstStatementIndex { idx }); impl_stable_hash_for!(struct ::middle::region::Scope { id, code }); impl<'gcx> ToStableHashKey> for region::Scope { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index b909ee9f93b..1d18c465179 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -156,26 +156,11 @@ pub struct BlockRemainder { pub first_statement_index: FirstStatementIndex, } -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, - RustcDecodable, Copy)] -pub struct FirstStatementIndex { pub idx: u32 } - -impl Idx for FirstStatementIndex { - fn new(idx: usize) -> Self { - assert!(idx <= SCOPE_DATA_REMAINDER_MAX as usize); - FirstStatementIndex { idx: idx as u32 } - } - - fn index(self) -> usize { - self.idx as usize - } -} - -impl fmt::Debug for FirstStatementIndex { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.index(), formatter) - } -} +newtype_index!(FirstStatementIndex + { + DEBUG_NAME = "", + MAX = SCOPE_DATA_REMAINDER_MAX, + }); impl From for Scope { #[inline] @@ -208,7 +193,7 @@ impl Scope { SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id), idx => ScopeData::Remainder(BlockRemainder { block: self.id, - first_statement_index: FirstStatementIndex { idx } + first_statement_index: FirstStatementIndex::new(idx as usize) }) } } diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 6c5a37aa1e5..1d1b367de20 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -65,7 +65,7 @@ macro_rules! newtype_index { (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]) => ( #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)] - pub struct $type(u32); + pub struct $type(pub u32); impl Idx for $type { fn new(value: usize) -> Self { @@ -99,7 +99,7 @@ macro_rules! newtype_index { // Replace existing default for max (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr] MAX = $max:expr, $($tokens:tt)*) => ( - newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $(tokens)*); + newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*); ); // Replace existing default for debug_name From 0e67d1735858d6c1bb8d1b9005cd371d31fdfd2c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 17 Oct 2017 11:24:46 -0400 Subject: [PATCH 292/365] make `erase_regions` use a query instead of an ad-hoc cache --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/ty/context.rs | 4 -- src/librustc/ty/erase_regions.rs | 79 ++++++++++++++++++++++++++++++ src/librustc/ty/fold.rs | 61 ----------------------- src/librustc/ty/maps/config.rs | 6 +++ src/librustc/ty/maps/mod.rs | 9 ++++ src/librustc/ty/maps/plumbing.rs | 2 + src/librustc/ty/mod.rs | 2 + 8 files changed, 99 insertions(+), 65 deletions(-) create mode 100644 src/librustc/ty/erase_regions.rs diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 08acc22114b..ae3157e81a0 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -609,6 +609,7 @@ define_dep_nodes!( <'tcx> [] PostorderCnums, [] HasCloneClosures(CrateNum), [] HasCopyClosures(CrateNum), + [] EraseRegionsTy { ty: Ty<'tcx> }, [] Freevars(DefId), [] MaybeUnusedTraitImport(DefId), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 3ba7dc68f9b..3d5e8ea583c 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -892,9 +892,6 @@ pub struct GlobalCtxt<'tcx> { // Internal cache for metadata decoding. No need to track deps on this. pub rcache: RefCell>>, - // FIXME dep tracking -- should be harmless enough - pub normalized_cache: RefCell, Ty<'tcx>>>, - /// Caches the results of trait selection. This cache is used /// for things that do not have to do with the parameters in scope. pub selection_cache: traits::SelectionCache<'tcx>, @@ -1172,7 +1169,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { maps: maps::Maps::new(providers), mir_passes, rcache: RefCell::new(FxHashMap()), - normalized_cache: RefCell::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), crate_name: Symbol::intern(crate_name), diff --git a/src/librustc/ty/erase_regions.rs b/src/librustc/ty/erase_regions.rs new file mode 100644 index 00000000000..4f8fca67949 --- /dev/null +++ b/src/librustc/ty/erase_regions.rs @@ -0,0 +1,79 @@ +// Copyright 2017 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. + +use ty::{self, Ty, TyCtxt}; +use ty::fold::{TypeFolder, TypeFoldable}; + +pub(super) fn provide(providers: &mut ty::maps::Providers) { + *providers = ty::maps::Providers { + erase_regions_ty, + ..*providers + }; +} + +fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + // NB: use `super_fold_with` here. If we used `fold_with`, it + // could invoke the `erase_regions_ty` query recursively. + ty.super_fold_with(&mut RegionEraserVisitor { tcx }) +} + +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + /// Returns an equivalent value with all free regions removed (note + /// that late-bound regions remain, because they are important for + /// subtyping, but they are anonymized and normalized as well).. + pub fn erase_regions(self, value: &T) -> T + where T : TypeFoldable<'tcx> + { + let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }); + debug!("erase_regions({:?}) = {:?}", value, value1); + value1 + } +} + +struct RegionEraserVisitor<'a, 'gcx: 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, +} + +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { + self.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) { + self.tcx.erase_regions_ty(ty_lifted) + } else { + ty.super_fold_with(self) + } + } + + fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + where T : TypeFoldable<'tcx> + { + let u = self.tcx.anonymize_late_bound_regions(t); + u.super_fold_with(self) + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + // because late-bound regions affect subtyping, we can't + // erase the bound/free distinction, but we can replace + // all free regions with 'erased. + // + // Note that we *CAN* replace early-bound regions -- the + // type system never "sees" those, they get substituted + // away. In trans, they will always be erased to 'erased + // whenever a substitution occurs. + match *r { + ty::ReLateBound(..) => r, + _ => self.tcx.types.re_erased + } + } +} + diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 543e8f3e2f0..edd4329fa41 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -444,67 +444,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { } } -/////////////////////////////////////////////////////////////////////////// -// Region eraser - -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - /// Returns an equivalent value with all free regions removed (note - /// that late-bound regions remain, because they are important for - /// subtyping, but they are anonymized and normalized as well).. - pub fn erase_regions(self, value: &T) -> T - where T : TypeFoldable<'tcx> - { - let value1 = value.fold_with(&mut RegionEraser(self)); - debug!("erase_regions({:?}) = {:?}", - value, value1); - return value1; - - struct RegionEraser<'a, 'gcx: 'a+'tcx, 'tcx: 'a>(TyCtxt<'a, 'gcx, 'tcx>); - - impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraser<'a, 'gcx, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.0 } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let Some(u) = self.tcx().normalized_cache.borrow().get(&ty).cloned() { - return u; - } - - // FIXME(eddyb) should local contexts have a cache too? - if let Some(ty_lifted) = self.tcx().lift_to_global(&ty) { - let tcx = self.tcx().global_tcx(); - let t_norm = ty_lifted.super_fold_with(&mut RegionEraser(tcx)); - tcx.normalized_cache.borrow_mut().insert(ty_lifted, t_norm); - t_norm - } else { - ty.super_fold_with(self) - } - } - - fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder - where T : TypeFoldable<'tcx> - { - let u = self.tcx().anonymize_late_bound_regions(t); - u.super_fold_with(self) - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - // because late-bound regions affect subtyping, we can't - // erase the bound/free distinction, but we can replace - // all free regions with 'erased. - // - // Note that we *CAN* replace early-bound regions -- the - // type system never "sees" those, they get substituted - // away. In trans, they will always be erased to 'erased - // whenever a substitution occurs. - match *r { - ty::ReLateBound(..) => r, - _ => self.tcx().types.re_erased - } - } - } - } -} - /////////////////////////////////////////////////////////////////////////// // Region shifter // diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 2279dff1335..8f8cda0e0f1 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -75,6 +75,12 @@ impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> { } } +impl<'tcx> QueryDescription for queries::erase_regions_ty<'tcx> { + fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String { + format!("erasing regions from `{:?}`", ty) + } +} + impl<'tcx> QueryDescription for queries::type_param_predicates<'tcx> { fn describe(tcx: TyCtxt, (_, def_id): (DefId, DefId)) -> String { let id = tcx.hir.as_local_node_id(def_id).unwrap(); diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 07807429bfb..95192dc5bae 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -341,12 +341,21 @@ define_maps! { <'tcx> [] fn has_copy_closures: HasCopyClosures(CrateNum) -> bool, [] fn has_clone_closures: HasCloneClosures(CrateNum) -> bool, + + // Erases regions from `ty` to yield a new type. + // Normally you would just use `tcx.erase_regions(&value)`, + // however, which uses this query as a kind of cache. + [] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>, } ////////////////////////////////////////////////////////////////////// // These functions are little shims used to find the dep-node for a // given query when there is not a *direct* mapping: +fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> { + DepConstructor::EraseRegionsTy { ty } +} + fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { DepConstructor::TypeParamPredicates { item_id, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index d6eaf6d1bc4..3fc9d854f29 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -701,6 +701,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::CompileCodegenUnit | DepKind::FulfillObligation | DepKind::VtableMethods | + DepKind::EraseRegionsTy | // These are just odd DepKind::Null | @@ -773,6 +774,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::ConstIsRvaluePromotableToStatic => { force!(const_is_rvalue_promotable_to_static, def_id!()); } + DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); } DepKind::ImplParent => { force!(impl_parent, def_id!()); } DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); } DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 35969361544..129c81c5cd6 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -90,6 +90,7 @@ pub mod adjustment; pub mod binding; pub mod cast; pub mod error; +mod erase_regions; pub mod fast_reject; pub mod fold; pub mod inhabitedness; @@ -2575,6 +2576,7 @@ fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn provide(providers: &mut ty::maps::Providers) { util::provide(providers); context::provide(providers); + erase_regions::provide(providers); *providers = ty::maps::Providers { associated_item, associated_item_def_ids, From 7715f97279fe343c4dc78609b51b75cb0433a8b3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 16 Oct 2017 17:36:59 -0400 Subject: [PATCH 293/365] break clippy --- src/tools/toolstate.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml index b03e4f05641..186522262dd 100644 --- a/src/tools/toolstate.toml +++ b/src/tools/toolstate.toml @@ -26,7 +26,7 @@ miri = "Broken" # ping @Manishearth @llogiq @mcarton @oli-obk -clippy = "Compiling" +clippy = "Broken" # ping @nrc rls = "Testing" From a6ca84a38340bdbf3c02ba4c7970c9289e5bc946 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 17 Oct 2017 21:37:18 +0300 Subject: [PATCH 294/365] look past the next drop for the drop panic target The previous code would leak data on a drop panic if the immediate next drop was a StorageDead that was followed by another drop. --- src/librustc_mir/build/scope.rs | 16 +++++++--------- src/test/run-pass/dynamic-drop.rs | 22 +++++++++++++++++----- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index b88b61f1818..772438d5252 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -836,24 +836,22 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, generator_drop: bool) -> BlockAnd<()> { debug!("build_scope_drops({:?} -> {:?})", block, scope); - let mut iter = scope.drops.iter().rev().peekable(); + let mut iter = scope.drops.iter().rev(); while let Some(drop_data) = iter.next() { let source_info = scope.source_info(drop_data.span); match drop_data.kind { DropKind::Value { .. } => { // Try to find the next block with its cached block // for us to diverge into in case the drop panics. - let on_diverge = iter.peek().iter().filter_map(|dd| { + let on_diverge = iter.clone().filter_map(|dd| { match dd.kind { - DropKind::Value { cached_block } => { - let result = cached_block.get(generator_drop); - if result.is_none() { - span_bug!(drop_data.span, "cached block not present?") - } - result - }, + DropKind::Value { cached_block } => Some(cached_block), DropKind::Storage => None } + }).map(|cached_block| { + cached_block + .get(generator_drop) + .unwrap_or_else(|| span_bug!(drop_data.span, "cached block not present?")) }).next(); // If there’s no `cached_block`s within current scope, // we must look for one in the enclosing scope. diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index d8b6dbe48f1..483dbb356ce 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -177,6 +177,17 @@ fn generator(a: &Allocator, run_count: usize) { } } +fn mixed_drop_and_nondrop(a: &Allocator) { + // check that destructor panics handle drop + // and non-drop blocks in the same scope correctly. + // + // Surprisingly enough, this used to not work. + let (x, y, z); + x = a.alloc(); + y = 5; + z = a.alloc(); +} + #[allow(unreachable_code)] fn vec_unreachable(a: &Allocator) { let _x = vec![a.alloc(), a.alloc(), a.alloc(), return]; @@ -244,11 +255,12 @@ fn main() { run_test(|a| field_assignment(a, false)); run_test(|a| field_assignment(a, true)); - // FIXME: fix leaks on panics - run_test_nopanic(|a| generator(a, 0)); - run_test_nopanic(|a| generator(a, 1)); - run_test_nopanic(|a| generator(a, 2)); - run_test_nopanic(|a| generator(a, 3)); + run_test(|a| generator(a, 0)); + run_test(|a| generator(a, 1)); + run_test(|a| generator(a, 2)); + run_test(|a| generator(a, 3)); + + run_test(|a| mixed_drop_and_nondrop(a)); run_test_nopanic(|a| union1(a)); } From 045ce183cc6f34ec8315b2a99d22b9563c714a08 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Tue, 17 Oct 2017 13:54:46 -0400 Subject: [PATCH 295/365] modify tests to use new flag --- src/test/rustdoc/empty-mod-private.rs | 2 +- src/test/rustdoc/issue-15347.rs | 2 +- src/test/rustdoc/pub-method.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/rustdoc/empty-mod-private.rs b/src/test/rustdoc/empty-mod-private.rs index 6b86af62a66..6c6af19be88 100644 --- a/src/test/rustdoc/empty-mod-private.rs +++ b/src/test/rustdoc/empty-mod-private.rs @@ -9,7 +9,7 @@ // except according to those terms. // ignore-tidy-linelength -// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports +// compile-flags: --document-private-items // @has 'empty_mod_private/index.html' '//a[@href="foo/index.html"]' 'foo' // @has 'empty_mod_private/sidebar-items.js' 'foo' diff --git a/src/test/rustdoc/issue-15347.rs b/src/test/rustdoc/issue-15347.rs index 266a3089194..c50df6edd48 100644 --- a/src/test/rustdoc/issue-15347.rs +++ b/src/test/rustdoc/issue-15347.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--no-defaults --passes collapse-docs --passes unindent-comments +// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments // @has issue_15347/fn.foo.html #[doc(hidden)] diff --git a/src/test/rustdoc/pub-method.rs b/src/test/rustdoc/pub-method.rs index 5998734e4a2..24d566e082e 100644 --- a/src/test/rustdoc/pub-method.rs +++ b/src/test/rustdoc/pub-method.rs @@ -9,7 +9,7 @@ // except according to those terms. // ignore-tidy-linelength -// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports +// compile-flags: --document-private-items #![crate_name = "foo"] From da7aab6e51fd06ea6628324b3be5ab88a4abda4f Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Tue, 17 Oct 2017 20:11:03 -0500 Subject: [PATCH 296/365] added examples of closures --- src/liballoc/str.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 830128f2b9f..3e273a67000 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -959,13 +959,15 @@ impl str { /// assert_eq!(s.find("Léopard"), Some(13)); /// ``` /// - /// More complex patterns with closures: + /// More complex patterns using point-free style and closures: /// /// ``` /// let s = "Löwe 老虎 Léopard"; /// /// assert_eq!(s.find(char::is_whitespace), Some(5)); /// assert_eq!(s.find(char::is_lowercase), Some(1)); + /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5)); + /// assert_eq!(s.find(|c: char| c.is_lowercase()), Some(1)); /// ``` /// /// Not finding the pattern: From d9ecdfe3a7a579b9ec89355168f13760c670d4d4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 Oct 2017 18:45:42 -0700 Subject: [PATCH 297/365] test: Update Emscripten failures/passing All tests should now have annotation for *why* they're ignored on emscripten. A few tests no longer need such an annotation as well! Closes #41299 --- src/ci/docker/asmjs/Dockerfile | 8 ++++---- src/test/compile-fail/macro-expanded-include/test.rs | 2 +- src/test/run-pass/asm-concat-src.rs | 2 +- src/test/run-pass/command-before-exec.rs | 2 +- src/test/run-pass/command-exec.rs | 3 ++- src/test/run-pass/core-run-destroy.rs | 2 +- src/test/run-pass/env-args-reverse-iterator.rs | 2 +- src/test/run-pass/env-funky-keys.rs | 2 +- src/test/run-pass/env-home-dir.rs | 2 +- src/test/run-pass/extern-pass-empty.rs | 2 +- src/test/run-pass/fds-are-cloexec.rs | 2 +- src/test/run-pass/format-no-std.rs | 2 +- src/test/run-pass/generator/smoke.rs | 2 +- src/test/run-pass/i128.rs | 2 +- src/test/run-pass/issue-10626.rs | 2 +- src/test/run-pass/issue-13304.rs | 3 ++- src/test/run-pass/issue-14456.rs | 2 +- src/test/run-pass/issue-14940.rs | 2 +- src/test/run-pass/issue-16272.rs | 2 +- src/test/run-pass/issue-20091.rs | 3 ++- src/test/run-pass/issue-2190-1.rs | 2 +- src/test/run-pass/issue-24313.rs | 2 +- src/test/run-pass/issue-28950.rs | 2 +- src/test/run-pass/issue-29485.rs | 2 +- src/test/run-pass/issue-29663.rs | 2 -- src/test/run-pass/issue-30490.rs | 2 +- src/test/run-pass/issue-33770.rs | 2 +- src/test/run-pass/linkage1.rs | 2 +- src/test/run-pass/multi-panic.rs | 2 +- src/test/run-pass/no-stdio.rs | 2 +- src/test/run-pass/out-of-stack.rs | 2 +- src/test/run-pass/packed-struct-layout.rs | 2 -- src/test/run-pass/packed-tuple-struct-layout.rs | 2 -- .../panic-runtime/abort-link-to-unwinding-crates.rs | 2 +- src/test/run-pass/panic-runtime/abort.rs | 2 +- src/test/run-pass/panic-runtime/lto-abort.rs | 2 +- src/test/run-pass/panic-runtime/lto-unwind.rs | 2 +- src/test/run-pass/process-envs.rs | 2 +- src/test/run-pass/process-exit.rs | 2 +- src/test/run-pass/process-remove-from-env.rs | 2 +- src/test/run-pass/process-spawn-with-unicode-params.rs | 2 +- src/test/run-pass/process-status-inherits-stdin.rs | 3 ++- src/test/run-pass/running-with-no-runtime.rs | 2 +- src/test/run-pass/signal-exit-status.rs | 2 +- src/test/run-pass/sigpipe-should-be-ignored.rs | 2 +- src/test/run-pass/simd-intrinsic-generic-cast.rs | 3 ++- src/test/run-pass/stack-probes-lto.rs | 2 +- src/test/run-pass/stack-probes.rs | 2 +- src/test/run-pass/stdio-is-blocking.rs | 2 +- src/test/run-pass/thinlto/thin-lto-inlines.rs | 2 +- src/test/run-pass/thinlto/thin-lto-inlines2.rs | 2 +- src/test/run-pass/try-wait.rs | 2 +- src/test/run-pass/u128.rs | 2 +- src/test/run-pass/vec-macro-no-std.rs | 2 +- src/test/run-pass/wait-forked-but-failed-child.rs | 2 +- 55 files changed, 60 insertions(+), 61 deletions(-) diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index 28caf1fb57a..c0bf689e39d 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -16,6 +16,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + ENV PATH=$PATH:/emsdk-portable ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/ ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/ @@ -28,7 +31,4 @@ ENV TARGETS=asmjs-unknown-emscripten ENV RUST_CONFIGURE_ARGS --target=$TARGETS -ENV SCRIPT python2.7 ../x.py test --target $TARGETS - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh +ENV SCRIPT python2.7 ../x.py test --target $TARGETS src/test/run-pass diff --git a/src/test/compile-fail/macro-expanded-include/test.rs b/src/test/compile-fail/macro-expanded-include/test.rs index bcc2c10653f..4afb61ab76c 100644 --- a/src/test/compile-fail/macro-expanded-include/test.rs +++ b/src/test/compile-fail/macro-expanded-include/test.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no asm! support #![feature(asm, rustc_attrs)] #![allow(unused)] diff --git a/src/test/run-pass/asm-concat-src.rs b/src/test/run-pass/asm-concat-src.rs index fb257bf7b50..0380ccbdea4 100644 --- a/src/test/run-pass/asm-concat-src.rs +++ b/src/test/run-pass/asm-concat-src.rs @@ -9,7 +9,7 @@ // except according to those terms. // pretty-expanded FIXME #23616 -// ignore-emscripten +// ignore-emscripten no asm #![feature(asm)] diff --git a/src/test/run-pass/command-before-exec.rs b/src/test/run-pass/command-before-exec.rs index 5b83ce48e5d..9e782cca218 100644 --- a/src/test/run-pass/command-before-exec.rs +++ b/src/test/run-pass/command-before-exec.rs @@ -9,7 +9,7 @@ // except according to those terms. // ignore-windows - this is a unix-specific test -// ignore-emscripten +// ignore-emscripten no processes #![feature(process_exec, libc)] diff --git a/src/test/run-pass/command-exec.rs b/src/test/run-pass/command-exec.rs index 5be9b97aac7..e378f55dffa 100644 --- a/src/test/run-pass/command-exec.rs +++ b/src/test/run-pass/command-exec.rs @@ -10,7 +10,8 @@ // ignore-windows - this is a unix-specific test // ignore-pretty issue #37199 -// ignore-emscripten +// ignore-emscripten no processes + #![feature(process_exec)] use std::env; diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 22fbeb2d5d0..863f3cf30e9 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -9,7 +9,7 @@ // except according to those terms. // compile-flags:--test -// ignore-emscripten +// ignore-emscripten no processes // NB: These tests kill child processes. Valgrind sees these children as leaking // memory, which makes for some *confusing* logs. That's why these are here diff --git a/src/test/run-pass/env-args-reverse-iterator.rs b/src/test/run-pass/env-args-reverse-iterator.rs index 89af1db7c78..dddf1ae0546 100644 --- a/src/test/run-pass/env-args-reverse-iterator.rs +++ b/src/test/run-pass/env-args-reverse-iterator.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes use std::env::args; use std::process::Command; diff --git a/src/test/run-pass/env-funky-keys.rs b/src/test/run-pass/env-funky-keys.rs index 8b4a633d613..86ffaf1e24f 100644 --- a/src/test/run-pass/env-funky-keys.rs +++ b/src/test/run-pass/env-funky-keys.rs @@ -12,7 +12,7 @@ // ignore-android // ignore-windows -// ignore-emscripten +// ignore-emscripten no execve // no-prefer-dynamic #![feature(libc)] diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs index bcb0c62d9fe..3693e86ba24 100644 --- a/src/test/run-pass/env-home-dir.rs +++ b/src/test/run-pass/env-home-dir.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten env vars don't work? #![feature(path)] diff --git a/src/test/run-pass/extern-pass-empty.rs b/src/test/run-pass/extern-pass-empty.rs index 2606c928680..f4ee3b6e9e8 100644 --- a/src/test/run-pass/extern-pass-empty.rs +++ b/src/test/run-pass/extern-pass-empty.rs @@ -12,7 +12,7 @@ // pretty-expanded FIXME #23616 // ignore-msvc -// ignore-emscripten +// ignore-emscripten emcc asserts on an empty struct as an argument #[repr(C)] struct TwoU8s { diff --git a/src/test/run-pass/fds-are-cloexec.rs b/src/test/run-pass/fds-are-cloexec.rs index a1b7d42a196..f55876115c0 100644 --- a/src/test/run-pass/fds-are-cloexec.rs +++ b/src/test/run-pass/fds-are-cloexec.rs @@ -10,7 +10,7 @@ // ignore-windows // ignore-android -// ignore-emscripten +// ignore-emscripten no processes // ignore-haiku #![feature(libc)] diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs index 9e8a3218518..e23accfcc23 100644 --- a/src/test/run-pass/format-no-std.rs +++ b/src/test/run-pass/format-no-std.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten missing rust_begin_unwind +// ignore-emscripten no no_std executables #![feature(lang_items, start, alloc)] #![no_std] diff --git a/src/test/run-pass/generator/smoke.rs b/src/test/run-pass/generator/smoke.rs index e9bdfbf28ea..8693964665d 100644 --- a/src/test/run-pass/generator/smoke.rs +++ b/src/test/run-pass/generator/smoke.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no threads support // compile-flags: --test #![feature(generators, generator_trait)] diff --git a/src/test/run-pass/i128.rs b/src/test/run-pass/i128.rs index 7c14d34b0ee..5369b138b0d 100644 --- a/src/test/run-pass/i128.rs +++ b/src/test/run-pass/i128.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten i128 doesn't work #![feature(i128_type, test)] diff --git a/src/test/run-pass/issue-10626.rs b/src/test/run-pass/issue-10626.rs index b350bd1a4cc..e9d37817ee2 100644 --- a/src/test/run-pass/issue-10626.rs +++ b/src/test/run-pass/issue-10626.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes // Make sure that if a process doesn't have its stdio/stderr descriptors set up // that we don't die in a large ball of fire diff --git a/src/test/run-pass/issue-13304.rs b/src/test/run-pass/issue-13304.rs index 5a743d7b547..9214d6b04bd 100644 --- a/src/test/run-pass/issue-13304.rs +++ b/src/test/run-pass/issue-13304.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes + #![feature(io, process_capture)] use std::env; diff --git a/src/test/run-pass/issue-14456.rs b/src/test/run-pass/issue-14456.rs index 513ab91489c..2edb45cc1c4 100644 --- a/src/test/run-pass/issue-14456.rs +++ b/src/test/run-pass/issue-14456.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes #![feature(io, process_capture)] diff --git a/src/test/run-pass/issue-14940.rs b/src/test/run-pass/issue-14940.rs index ffe6b646794..588fa63cfdf 100644 --- a/src/test/run-pass/issue-14940.rs +++ b/src/test/run-pass/issue-14940.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes use std::env; use std::process::Command; diff --git a/src/test/run-pass/issue-16272.rs b/src/test/run-pass/issue-16272.rs index f86be2d7c99..cd02cbf3dad 100644 --- a/src/test/run-pass/issue-16272.rs +++ b/src/test/run-pass/issue-16272.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes use std::process::Command; use std::env; diff --git a/src/test/run-pass/issue-20091.rs b/src/test/run-pass/issue-20091.rs index 1ee47a69d0c..c8ba5dbd84c 100644 --- a/src/test/run-pass/issue-20091.rs +++ b/src/test/run-pass/issue-20091.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes + #![feature(std_misc, os)] #[cfg(unix)] diff --git a/src/test/run-pass/issue-2190-1.rs b/src/test/run-pass/issue-2190-1.rs index 39375703514..8cc23c883ed 100644 --- a/src/test/run-pass/issue-2190-1.rs +++ b/src/test/run-pass/issue-2190-1.rs @@ -9,7 +9,7 @@ // except according to those terms. // pretty-expanded FIXME #23616 -// ignore-emscripten +// ignore-emscripten no threads use std::thread::Builder; diff --git a/src/test/run-pass/issue-24313.rs b/src/test/run-pass/issue-24313.rs index 9b2b474351d..ad385ee78e0 100644 --- a/src/test/run-pass/issue-24313.rs +++ b/src/test/run-pass/issue-24313.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no threads use std::thread; use std::env; diff --git a/src/test/run-pass/issue-28950.rs b/src/test/run-pass/issue-28950.rs index a70c2b3ae1b..4e4530789c8 100644 --- a/src/test/run-pass/issue-28950.rs +++ b/src/test/run-pass/issue-28950.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no threads // compile-flags: -O // Tests that the `vec!` macro does not overflow the stack when it is diff --git a/src/test/run-pass/issue-29485.rs b/src/test/run-pass/issue-29485.rs index 9252762d1bd..828b495d408 100644 --- a/src/test/run-pass/issue-29485.rs +++ b/src/test/run-pass/issue-29485.rs @@ -9,7 +9,7 @@ // except according to those terms. // aux-build:issue-29485.rs -// ignore-emscripten +// ignore-emscripten no threads #[feature(recover)] diff --git a/src/test/run-pass/issue-29663.rs b/src/test/run-pass/issue-29663.rs index cf925662fc3..9a77be049fe 100644 --- a/src/test/run-pass/issue-29663.rs +++ b/src/test/run-pass/issue-29663.rs @@ -10,8 +10,6 @@ // write_volatile causes an LLVM assert with composite types -// ignore-emscripten See #41299: probably a bad optimization - #![feature(volatile)] use std::ptr::{read_volatile, write_volatile}; diff --git a/src/test/run-pass/issue-30490.rs b/src/test/run-pass/issue-30490.rs index 7658abc00c5..4296107dd45 100644 --- a/src/test/run-pass/issue-30490.rs +++ b/src/test/run-pass/issue-30490.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes // Previously libstd would set stdio descriptors of a child process // by `dup`ing the requested descriptors to inherit directly into the diff --git a/src/test/run-pass/issue-33770.rs b/src/test/run-pass/issue-33770.rs index 76728a0d354..38062700707 100644 --- a/src/test/run-pass/issue-33770.rs +++ b/src/test/run-pass/issue-33770.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes use std::process::{Command, Stdio}; use std::env; diff --git a/src/test/run-pass/linkage1.rs b/src/test/run-pass/linkage1.rs index 591610e88b1..f12a233f493 100644 --- a/src/test/run-pass/linkage1.rs +++ b/src/test/run-pass/linkage1.rs @@ -10,7 +10,7 @@ // ignore-windows // ignore-macos -// ignore-emscripten +// ignore-emscripten doesn't support this linkage // aux-build:linkage1.rs #![feature(linkage)] diff --git a/src/test/run-pass/multi-panic.rs b/src/test/run-pass/multi-panic.rs index 86fe06b1765..c15b40d4dda 100644 --- a/src/test/run-pass/multi-panic.rs +++ b/src/test/run-pass/multi-panic.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes fn check_for_no_backtrace(test: std::process::Output) { assert!(!test.status.success()); diff --git a/src/test/run-pass/no-stdio.rs b/src/test/run-pass/no-stdio.rs index 85c63e184fe..7b6b711315a 100644 --- a/src/test/run-pass/no-stdio.rs +++ b/src/test/run-pass/no-stdio.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes // ignore-android #![feature(libc)] diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index 7e70c4a7ab3..485335a2d80 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -10,7 +10,7 @@ // ignore-android: FIXME (#20004) // ignore-musl -// ignore-emscripten +// ignore-emscripten no processes #![feature(asm)] #![feature(libc)] diff --git a/src/test/run-pass/packed-struct-layout.rs b/src/test/run-pass/packed-struct-layout.rs index d1e05e5a018..a4a0055785f 100644 --- a/src/test/run-pass/packed-struct-layout.rs +++ b/src/test/run-pass/packed-struct-layout.rs @@ -7,8 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten Not sure what's happening here. - use std::mem; diff --git a/src/test/run-pass/packed-tuple-struct-layout.rs b/src/test/run-pass/packed-tuple-struct-layout.rs index ee4eb86ed0d..18f7eff280a 100644 --- a/src/test/run-pass/packed-tuple-struct-layout.rs +++ b/src/test/run-pass/packed-tuple-struct-layout.rs @@ -7,8 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten - use std::mem; diff --git a/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs b/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs index ebbb00a4a9f..d1fdc8afa65 100644 --- a/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs +++ b/src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs @@ -11,7 +11,7 @@ // compile-flags:-C panic=abort // aux-build:exit-success-if-unwind.rs // no-prefer-dynamic -// ignore-emscripten Function not implemented +// ignore-emscripten no processes extern crate exit_success_if_unwind; diff --git a/src/test/run-pass/panic-runtime/abort.rs b/src/test/run-pass/panic-runtime/abort.rs index 3ba3bd61c2e..bb541b29d7c 100644 --- a/src/test/run-pass/panic-runtime/abort.rs +++ b/src/test/run-pass/panic-runtime/abort.rs @@ -10,7 +10,7 @@ // compile-flags:-C panic=abort // no-prefer-dynamic -// ignore-emscripten Function not implemented. +// ignore-emscripten no processes use std::process::Command; use std::env; diff --git a/src/test/run-pass/panic-runtime/lto-abort.rs b/src/test/run-pass/panic-runtime/lto-abort.rs index e4cd4e809a4..59e9474aab2 100644 --- a/src/test/run-pass/panic-runtime/lto-abort.rs +++ b/src/test/run-pass/panic-runtime/lto-abort.rs @@ -10,7 +10,7 @@ // compile-flags:-C lto -C panic=abort // no-prefer-dynamic -// ignore-emscripten Function not implemented. +// ignore-emscripten no processes use std::process::Command; use std::env; diff --git a/src/test/run-pass/panic-runtime/lto-unwind.rs b/src/test/run-pass/panic-runtime/lto-unwind.rs index 768b88fd09e..6d28b8d12f6 100644 --- a/src/test/run-pass/panic-runtime/lto-unwind.rs +++ b/src/test/run-pass/panic-runtime/lto-unwind.rs @@ -10,7 +10,7 @@ // compile-flags:-C lto -C panic=unwind // no-prefer-dynamic -// ignore-emscripten Function not implemented. +// ignore-emscripten no processes use std::process::Command; use std::env; diff --git a/src/test/run-pass/process-envs.rs b/src/test/run-pass/process-envs.rs index b3785d898ba..1622517198a 100644 --- a/src/test/run-pass/process-envs.rs +++ b/src/test/run-pass/process-envs.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes use std::process::Command; use std::env; diff --git a/src/test/run-pass/process-exit.rs b/src/test/run-pass/process-exit.rs index a5d408448a0..5abc06b75e1 100644 --- a/src/test/run-pass/process-exit.rs +++ b/src/test/run-pass/process-exit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes use std::env; use std::process::{self, Command, Stdio}; diff --git a/src/test/run-pass/process-remove-from-env.rs b/src/test/run-pass/process-remove-from-env.rs index b7f296a65c2..7a9b431d570 100644 --- a/src/test/run-pass/process-remove-from-env.rs +++ b/src/test/run-pass/process-remove-from-env.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes use std::process::Command; use std::env; diff --git a/src/test/run-pass/process-spawn-with-unicode-params.rs b/src/test/run-pass/process-spawn-with-unicode-params.rs index 550c6d6ab67..7b854207263 100644 --- a/src/test/run-pass/process-spawn-with-unicode-params.rs +++ b/src/test/run-pass/process-spawn-with-unicode-params.rs @@ -16,7 +16,7 @@ // non-ASCII characters. The child process ensures all the strings are // intact. -// ignore-emscripten +// ignore-emscripten no processes use std::io::prelude::*; use std::io; diff --git a/src/test/run-pass/process-status-inherits-stdin.rs b/src/test/run-pass/process-status-inherits-stdin.rs index ff389bec899..5ea48a4ff33 100644 --- a/src/test/run-pass/process-status-inherits-stdin.rs +++ b/src/test/run-pass/process-status-inherits-stdin.rs @@ -7,7 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten Function not implemented. + +// ignore-emscripten no processes use std::env; use std::io; diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs index f81c3f2e99d..6f696c1c9ce 100644 --- a/src/test/run-pass/running-with-no-runtime.rs +++ b/src/test/run-pass/running-with-no-runtime.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten spawning processes is not supported #![feature(start)] diff --git a/src/test/run-pass/signal-exit-status.rs b/src/test/run-pass/signal-exit-status.rs index 8a2bbc83c42..0f6832acec8 100644 --- a/src/test/run-pass/signal-exit-status.rs +++ b/src/test/run-pass/signal-exit-status.rs @@ -9,7 +9,7 @@ // except according to those terms. // ignore-windows -// ignore-emscripten +// ignore-emscripten no processes use std::env; use std::process::Command; diff --git a/src/test/run-pass/sigpipe-should-be-ignored.rs b/src/test/run-pass/sigpipe-should-be-ignored.rs index 5aa4faa1365..465feb4b779 100644 --- a/src/test/run-pass/sigpipe-should-be-ignored.rs +++ b/src/test/run-pass/sigpipe-should-be-ignored.rs @@ -11,7 +11,7 @@ // Be sure that when a SIGPIPE would have been received that the entire process // doesn't die in a ball of fire, but rather it's gracefully handled. -// ignore-emscripten +// ignore-emscripten no processes use std::env; use std::io::prelude::*; diff --git a/src/test/run-pass/simd-intrinsic-generic-cast.rs b/src/test/run-pass/simd-intrinsic-generic-cast.rs index ede2325b51c..ed2786edf3a 100644 --- a/src/test/run-pass/simd-intrinsic-generic-cast.rs +++ b/src/test/run-pass/simd-intrinsic-generic-cast.rs @@ -7,7 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten linking with emcc failed + +// ignore-emscripten FIXME(#45351) hits an LLVM assert #![feature(repr_simd, platform_intrinsics, concat_idents, test)] #![allow(non_camel_case_types)] diff --git a/src/test/run-pass/stack-probes-lto.rs b/src/test/run-pass/stack-probes-lto.rs index f49320e4da4..78a1019578e 100644 --- a/src/test/run-pass/stack-probes-lto.rs +++ b/src/test/run-pass/stack-probes-lto.rs @@ -11,7 +11,7 @@ // ignore-arm // ignore-aarch64 // ignore-wasm -// ignore-emscripten +// ignore-emscripten no processes // ignore-musl FIXME #31506 // ignore-pretty // no-system-llvm diff --git a/src/test/run-pass/stack-probes.rs b/src/test/run-pass/stack-probes.rs index 1d66cb60207..bb9471e1b48 100644 --- a/src/test/run-pass/stack-probes.rs +++ b/src/test/run-pass/stack-probes.rs @@ -11,7 +11,7 @@ // ignore-arm // ignore-aarch64 // ignore-wasm -// ignore-emscripten +// ignore-emscripten no processes // ignore-musl FIXME #31506 // no-system-llvm diff --git a/src/test/run-pass/stdio-is-blocking.rs b/src/test/run-pass/stdio-is-blocking.rs index 448bb7de772..cce1077202c 100644 --- a/src/test/run-pass/stdio-is-blocking.rs +++ b/src/test/run-pass/stdio-is-blocking.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes use std::env; use std::io::prelude::*; diff --git a/src/test/run-pass/thinlto/thin-lto-inlines.rs b/src/test/run-pass/thinlto/thin-lto-inlines.rs index 3135a682d86..7a71dd2bc51 100644 --- a/src/test/run-pass/thinlto/thin-lto-inlines.rs +++ b/src/test/run-pass/thinlto/thin-lto-inlines.rs @@ -10,7 +10,7 @@ // compile-flags: -Z thinlto -C codegen-units=8 -O // min-llvm-version 4.0 -// ignore-emscripten +// ignore-emscripten can't inspect instructions on emscripten // We want to assert here that ThinLTO will inline across codegen units. There's // not really a great way to do that in general so we sort of hack around it by diff --git a/src/test/run-pass/thinlto/thin-lto-inlines2.rs b/src/test/run-pass/thinlto/thin-lto-inlines2.rs index ed899d2b115..0e8ad08a5f6 100644 --- a/src/test/run-pass/thinlto/thin-lto-inlines2.rs +++ b/src/test/run-pass/thinlto/thin-lto-inlines2.rs @@ -12,7 +12,7 @@ // aux-build:thin-lto-inlines-aux.rs // min-llvm-version 4.0 // no-prefer-dynamic -// ignore-emscripten +// ignore-emscripten can't inspect instructions on emscripten // We want to assert here that ThinLTO will inline across codegen units. There's // not really a great way to do that in general so we sort of hack around it by diff --git a/src/test/run-pass/try-wait.rs b/src/test/run-pass/try-wait.rs index be87b7b3c87..0ee2cb9238c 100644 --- a/src/test/run-pass/try-wait.rs +++ b/src/test/run-pass/try-wait.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes #![feature(process_try_wait)] diff --git a/src/test/run-pass/u128.rs b/src/test/run-pass/u128.rs index b16f6c7b6af..bf506a71250 100644 --- a/src/test/run-pass/u128.rs +++ b/src/test/run-pass/u128.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten u128 not supported #![feature(i128_type, test)] diff --git a/src/test/run-pass/vec-macro-no-std.rs b/src/test/run-pass/vec-macro-no-std.rs index f21027afac3..56ff9cb2477 100644 --- a/src/test/run-pass/vec-macro-no-std.rs +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten missing rust_begin_unwind +// ignore-emscripten no no_std executables #![feature(lang_items, start, libc, alloc)] #![no_std] diff --git a/src/test/run-pass/wait-forked-but-failed-child.rs b/src/test/run-pass/wait-forked-but-failed-child.rs index 1d1c83cf12a..744f2989bcf 100644 --- a/src/test/run-pass/wait-forked-but-failed-child.rs +++ b/src/test/run-pass/wait-forked-but-failed-child.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-emscripten +// ignore-emscripten no processes #![feature(libc)] From f61394f0bd9c7d5951d2f70207177ff5a6b038fa Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 21 Sep 2017 22:18:47 -0400 Subject: [PATCH 298/365] Lifting Generics from MethodSig to TraitItem and ImplItem since we want to support generics in each variant of TraitItem and ImplItem --- src/librustc/hir/lowering.rs | 10 +++---- src/librustc_resolve/lib.rs | 7 +++-- src/librustc_save_analysis/dump_visitor.rs | 9 ++++-- src/librustc_save_analysis/sig.rs | 6 ++-- src/libsyntax/ast.rs | 3 +- src/libsyntax/ext/placeholders.rs | 5 ++-- src/libsyntax/fold.rs | 3 +- src/libsyntax/parse/parser.rs | 32 +++++++++++----------- src/libsyntax/print/pprust.rs | 7 +++-- src/libsyntax/visit.rs | 6 ++-- src/libsyntax_ext/deriving/generic/mod.rs | 3 +- 11 files changed, 51 insertions(+), 40 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 54aecb4b00f..f3363bde6e7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1548,7 +1548,7 @@ impl<'a> LoweringContext<'a> { } TraitItemKind::Method(ref sig, None) => { let names = this.lower_fn_args_to_names(&sig.decl); - hir::TraitItemKind::Method(this.lower_method_sig(sig), + hir::TraitItemKind::Method(this.lower_method_sig(&i.generics, sig), hir::TraitMethod::Required(names)) } TraitItemKind::Method(ref sig, Some(ref body)) => { @@ -1556,7 +1556,7 @@ impl<'a> LoweringContext<'a> { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) }); - hir::TraitItemKind::Method(this.lower_method_sig(sig), + hir::TraitItemKind::Method(this.lower_method_sig(&i.generics, sig), hir::TraitMethod::Provided(body_id)) } TraitItemKind::Type(ref bounds, ref default) => { @@ -1615,7 +1615,7 @@ impl<'a> LoweringContext<'a> { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) }); - hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id) + hir::ImplItemKind::Method(this.lower_method_sig(&i.generics, sig), body_id) } ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -1727,9 +1727,9 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { + fn lower_method_sig(&mut self, generics: &Generics, sig: &MethodSig) -> hir::MethodSig { hir::MethodSig { - generics: self.lower_generics(&sig.generics), + generics: self.lower_generics(generics), abi: sig.abi, unsafety: self.lower_unsafety(sig.unsafety), constness: self.lower_constness(sig.constness), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4aab43cbec7..8d546a66ef5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -723,7 +723,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { ItemRibKind } FnKind::Method(_, sig, _, _) => { - self.visit_generics(&sig.generics); MethodRibKind(!sig.decl.has_self()) } FnKind::Closure(_) => ClosureRibKind(node_id), @@ -1864,6 +1863,7 @@ impl<'a> Resolver<'a> { for trait_item in trait_items { this.check_proc_macro_attrs(&trait_item.attrs); + this.visit_generics(&trait_item.generics); match trait_item.node { TraitItemKind::Const(ref ty, ref default) => { @@ -1880,7 +1880,7 @@ impl<'a> Resolver<'a> { } TraitItemKind::Method(ref sig, _) => { let type_parameters = - HasTypeParameters(&sig.generics, + HasTypeParameters(&trait_item.generics, MethodRibKind(!sig.decl.has_self())); this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) @@ -2075,6 +2075,7 @@ impl<'a> Resolver<'a> { this.with_current_self_type(self_type, |this| { for impl_item in impl_items { this.check_proc_macro_attrs(&impl_item.attrs); + this.visit_generics(&impl_item.generics); this.resolve_visibility(&impl_item.vis); match impl_item.node { ImplItemKind::Const(..) => { @@ -2097,7 +2098,7 @@ impl<'a> Resolver<'a> { // We also need a new scope for the method- // specific type parameters. let type_parameters = - HasTypeParameters(&sig.generics, + HasTypeParameters(&impl_item.generics, MethodRibKind(!sig.decl.has_self())); this.with_type_parameter_rib(type_parameters, |this| { visit::walk_impl_item(this, impl_item); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 3e730cf8365..c57d5305d80 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -354,23 +354,24 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { body: Option<&'l ast::Block>, id: ast::NodeId, name: ast::Ident, + generics: &'l ast::Generics, vis: ast::Visibility, span: Span) { debug!("process_method: {}:{}", id, name); if let Some(mut method_data) = self.save_ctxt.get_method_data(id, name.name, span) { - let sig_str = ::make_signature(&sig.decl, &sig.generics); + let sig_str = ::make_signature(&sig.decl, &generics); if body.is_some() { self.nest_tables(id, |v| { v.process_formals(&sig.decl.inputs, &method_data.qualname) }); } - self.process_generic_params(&sig.generics, span, &method_data.qualname, id); + self.process_generic_params(&generics, span, &method_data.qualname, id); method_data.value = sig_str; - method_data.sig = sig::method_signature(id, name, sig, &self.save_ctxt); + method_data.sig = sig::method_signature(id, name, generics, sig, &self.save_ctxt); self.dumper.dump_def(vis == ast::Visibility::Public, method_data); } @@ -1007,6 +1008,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { body.as_ref().map(|x| &**x), trait_item.id, trait_item.ident, + &trait_item.generics, ast::Visibility::Public, trait_item.span); } @@ -1066,6 +1068,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { Some(body), impl_item.id, impl_item.ident, + &impl_item.generics, impl_item.vis.clone(), impl_item.span); } diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 47e5ad6c010..88f574d513b 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -77,13 +77,14 @@ pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext) -> Option Option { if !scx.config.signatures { return None; } - make_method_signature(id, ident, m, scx).ok() + make_method_signature(id, ident, generics, m, scx).ok() } pub fn assoc_const_signature(id: NodeId, @@ -895,6 +896,7 @@ fn make_assoc_const_signature(id: NodeId, fn make_method_signature(id: NodeId, ident: ast::Ident, + generics: &ast::Generics, m: &ast::MethodSig, scx: &SaveContext) -> Result { @@ -915,7 +917,7 @@ fn make_method_signature(id: NodeId, let mut sig = name_and_generics(text, 0, - &m.generics, + generics, id, ident, scx)?; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f445def9e03..b985ac78056 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1178,7 +1178,6 @@ pub struct MethodSig { pub constness: Spanned, pub abi: Abi, pub decl: P, - pub generics: Generics, } /// Represents an item declaration within a trait declaration, @@ -1190,6 +1189,7 @@ pub struct TraitItem { pub id: NodeId, pub ident: Ident, pub attrs: Vec, + pub generics: Generics, pub node: TraitItemKind, pub span: Span, /// See `Item::tokens` for what this is @@ -1211,6 +1211,7 @@ pub struct ImplItem { pub vis: Visibility, pub defaultness: Defaultness, pub attrs: Vec, + pub generics: Generics, pub node: ImplItemKind, pub span: Span, /// See `Item::tokens` for what this is diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 4fc2b92d3cd..2f5b386346b 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -32,6 +32,7 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { let ident = keywords::Invalid.ident(); let attrs = Vec::new(); + let generics = ast::Generics::default(); let vis = ast::Visibility::Inherited; let span = DUMMY_SP; let expr_placeholder = || P(ast::Expr { @@ -49,12 +50,12 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { tokens: None, }))), ExpansionKind::TraitItems => Expansion::TraitItems(SmallVector::one(ast::TraitItem { - id, span, ident, attrs, + id, span, ident, attrs, generics, node: ast::TraitItemKind::Macro(mac_placeholder()), tokens: None, })), ExpansionKind::ImplItems => Expansion::ImplItems(SmallVector::one(ast::ImplItem { - id, span, ident, vis, attrs, + id, span, ident, vis, attrs, generics, node: ast::ImplItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index d7d491db71f..518386a2ad2 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -943,6 +943,7 @@ pub fn noop_fold_trait_item(i: TraitItem, folder: &mut T) id: folder.new_id(i.id), ident: folder.fold_ident(i.ident), attrs: fold_attrs(i.attrs, folder), + generics: folder.fold_generics(i.generics), node: match i.node { TraitItemKind::Const(ty, default) => { TraitItemKind::Const(folder.fold_ty(ty), @@ -972,6 +973,7 @@ pub fn noop_fold_impl_item(i: ImplItem, folder: &mut T) vis: folder.fold_vis(i.vis), ident: folder.fold_ident(i.ident), attrs: fold_attrs(i.attrs, folder), + generics: folder.fold_generics(i.generics), defaultness: i.defaultness, node: match i.node { ast::ImplItemKind::Const(ty, expr) => { @@ -1074,7 +1076,6 @@ pub fn noop_fold_foreign_item(ni: ForeignItem, folder: &mut T) -> For pub fn noop_fold_method_sig(sig: MethodSig, folder: &mut T) -> MethodSig { MethodSig { - generics: folder.fold_generics(sig.generics), abi: sig.abi, unsafety: sig.unsafety, constness: sig.constness, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8fd2bad4e44..b0ed4c4e0ee 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1287,10 +1287,10 @@ impl<'a> Parser<'a> { mut attrs: Vec) -> PResult<'a, TraitItem> { let lo = self.span; - let (name, node) = if self.eat_keyword(keywords::Type) { + let (name, node, generics) = if self.eat_keyword(keywords::Type) { let TyParam {ident, bounds, default, ..} = self.parse_ty_param(vec![])?; self.expect(&token::Semi)?; - (ident, TraitItemKind::Type(bounds, default)) + (ident, TraitItemKind::Type(bounds, default), ast::Generics::default()) } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let ident = self.parse_ident()?; @@ -1305,7 +1305,7 @@ impl<'a> Parser<'a> { self.expect(&token::Semi)?; None }; - (ident, TraitItemKind::Const(ty, default)) + (ident, TraitItemKind::Const(ty, default), ast::Generics::default()) } else if self.token.is_path_start() { // trait item macro. // code copied from parse_macro_use_or_failure... abstraction! @@ -1328,7 +1328,7 @@ impl<'a> Parser<'a> { } let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts }); - (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac)) + (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) } else { let (constness, unsafety, abi) = self.parse_fn_front_matter()?; @@ -1341,13 +1341,12 @@ impl<'a> Parser<'a> { // definition... p.parse_arg_general(false) })?; - generics.where_clause = self.parse_where_clause()?; + let sig = ast::MethodSig { unsafety, constness, decl: d, - generics, abi, }; @@ -1370,13 +1369,14 @@ impl<'a> Parser<'a> { return Err(self.fatal(&format!("expected `;` or `{{`, found `{}`", token_str))); } }; - (ident, ast::TraitItemKind::Method(sig, body)) + (ident, ast::TraitItemKind::Method(sig, body), generics) }; Ok(TraitItem { id: ast::DUMMY_NODE_ID, ident: name, attrs, + generics, node, span: lo.to(self.prev_span), tokens: None, @@ -4901,12 +4901,12 @@ impl<'a> Parser<'a> { let lo = self.span; let vis = self.parse_visibility(false)?; let defaultness = self.parse_defaultness()?; - let (name, node) = if self.eat_keyword(keywords::Type) { + let (name, node, generics) = if self.eat_keyword(keywords::Type) { let name = self.parse_ident()?; self.expect(&token::Eq)?; let typ = self.parse_ty()?; self.expect(&token::Semi)?; - (name, ast::ImplItemKind::Type(typ)) + (name, ast::ImplItemKind::Type(typ), ast::Generics::default()) } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let name = self.parse_ident()?; @@ -4915,11 +4915,11 @@ impl<'a> Parser<'a> { self.expect(&token::Eq)?; let expr = self.parse_expr()?; self.expect(&token::Semi)?; - (name, ast::ImplItemKind::Const(typ, expr)) + (name, ast::ImplItemKind::Const(typ, expr), ast::Generics::default()) } else { - let (name, inner_attrs, node) = self.parse_impl_method(&vis, at_end)?; + let (name, inner_attrs, generics, node) = self.parse_impl_method(&vis, at_end)?; attrs.extend(inner_attrs); - (name, node) + (name, node, generics) }; Ok(ImplItem { @@ -4929,6 +4929,7 @@ impl<'a> Parser<'a> { vis, defaultness, attrs, + generics, node, tokens: None, }) @@ -4986,7 +4987,7 @@ impl<'a> Parser<'a> { /// Parse a method or a macro invocation in a trait impl. fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool) - -> PResult<'a, (Ident, Vec, ast::ImplItemKind)> { + -> PResult<'a, (Ident, Vec, ast::Generics, ast::ImplItemKind)> { // code copied from parse_macro_use_or_failure... abstraction! if self.token.is_path_start() { // Method macro. @@ -5013,7 +5014,7 @@ impl<'a> Parser<'a> { } let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts }); - Ok((keywords::Invalid.ident(), vec![], ast::ImplItemKind::Macro(mac))) + Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(), ast::ImplItemKind::Macro(mac))) } else { let (constness, unsafety, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; @@ -5022,8 +5023,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - Ok((ident, inner_attrs, ast::ImplItemKind::Method(ast::MethodSig { - generics, + Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(ast::MethodSig { abi, unsafety, constness, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 02f871c58c7..b9a7fa04a06 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1525,6 +1525,7 @@ impl<'a> State<'a> { pub fn print_method_sig(&mut self, ident: ast::Ident, + generics: &ast::Generics, m: &ast::MethodSig, vis: &ast::Visibility) -> io::Result<()> { @@ -1533,7 +1534,7 @@ impl<'a> State<'a> { m.constness.node, m.abi, Some(ident), - &m.generics, + &generics, vis) } @@ -1553,7 +1554,7 @@ impl<'a> State<'a> { if body.is_some() { self.head("")?; } - self.print_method_sig(ti.ident, sig, &ast::Visibility::Inherited)?; + self.print_method_sig(ti.ident, &ti.generics, sig, &ast::Visibility::Inherited)?; if let Some(ref body) = *body { self.nbsp()?; self.print_block_with_attrs(body, &ti.attrs)?; @@ -1592,7 +1593,7 @@ impl<'a> State<'a> { } ast::ImplItemKind::Method(ref sig, ref body) => { self.head("")?; - self.print_method_sig(ii.ident, sig, &ii.vis)?; + self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis)?; self.nbsp()?; self.print_block_with_attrs(body, &ii.attrs)?; } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 521c6030eba..e74296c06a9 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -543,8 +543,7 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl walk_fn_decl(visitor, declaration); visitor.visit_block(body); } - FnKind::Method(_, sig, _, body) => { - visitor.visit_generics(&sig.generics); + FnKind::Method(_, _, _, body) => { walk_fn_decl(visitor, declaration); visitor.visit_block(body); } @@ -558,13 +557,13 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) { visitor.visit_ident(trait_item.span, trait_item.ident); walk_list!(visitor, visit_attribute, &trait_item.attrs); + visitor.visit_generics(&trait_item.generics); match trait_item.node { TraitItemKind::Const(ref ty, ref default) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, default); } TraitItemKind::Method(ref sig, None) => { - visitor.visit_generics(&sig.generics); walk_fn_decl(visitor, &sig.decl); } TraitItemKind::Method(ref sig, Some(ref body)) => { @@ -585,6 +584,7 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt visitor.visit_vis(&impl_item.vis); visitor.visit_ident(impl_item.span, impl_item.ident); walk_list!(visitor, visit_attribute, &impl_item.attrs); + visitor.visit_generics(&impl_item.generics); match impl_item.node { ImplItemKind::Const(ref ty, ref expr) => { visitor.visit_ty(ty); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 5c1ca19d635..18897047538 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -506,6 +506,7 @@ impl<'a> TraitDef<'a> { vis: ast::Visibility::Inherited, defaultness: ast::Defaultness::Final, attrs: Vec::new(), + generics: Generics::default(), node: ast::ImplItemKind::Type(type_def.to_ty(cx, self.span, type_ident, generics)), tokens: None, } @@ -921,12 +922,12 @@ impl<'a> MethodDef<'a> { ast::ImplItem { id: ast::DUMMY_NODE_ID, attrs: self.attributes.clone(), + generics: fn_generics, span: trait_.span, vis: ast::Visibility::Inherited, defaultness: ast::Defaultness::Final, ident: method_ident, node: ast::ImplItemKind::Method(ast::MethodSig { - generics: fn_generics, abi, unsafety, constness: From e03447dae36022a0155718a8b089fed1204ac39a Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 21 Sep 2017 22:22:33 -0400 Subject: [PATCH 299/365] Fixed tidy errors --- src/libsyntax/parse/parser.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b0ed4c4e0ee..07fa2a4d1a7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4987,7 +4987,8 @@ impl<'a> Parser<'a> { /// Parse a method or a macro invocation in a trait impl. fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool) - -> PResult<'a, (Ident, Vec, ast::Generics, ast::ImplItemKind)> { + -> PResult<'a, (Ident, Vec, ast::Generics, + ast::ImplItemKind)> { // code copied from parse_macro_use_or_failure... abstraction! if self.token.is_path_start() { // Method macro. @@ -5014,7 +5015,8 @@ impl<'a> Parser<'a> { } let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts }); - Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(), ast::ImplItemKind::Macro(mac))) + Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(), + ast::ImplItemKind::Macro(mac))) } else { let (constness, unsafety, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; From 892e4689efb163ab220ee353b15b70833b9baeb0 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Mon, 25 Sep 2017 12:23:43 -0400 Subject: [PATCH 300/365] Removed redundant generics visits --- src/librustc_resolve/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8d546a66ef5..2e5c9e35346 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1863,7 +1863,6 @@ impl<'a> Resolver<'a> { for trait_item in trait_items { this.check_proc_macro_attrs(&trait_item.attrs); - this.visit_generics(&trait_item.generics); match trait_item.node { TraitItemKind::Const(ref ty, ref default) => { @@ -2075,7 +2074,6 @@ impl<'a> Resolver<'a> { this.with_current_self_type(self_type, |this| { for impl_item in impl_items { this.check_proc_macro_attrs(&impl_item.attrs); - this.visit_generics(&impl_item.generics); this.resolve_visibility(&impl_item.vis); match impl_item.node { ImplItemKind::Const(..) => { From bb301446050900f2e9bbb0d465fd8615fbd0e7e6 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Mon, 25 Sep 2017 17:24:20 -0400 Subject: [PATCH 301/365] Lifted generics into TraitItem and ImplItem from MethodSig -- HIR now matches AST --- src/librustc/hir/intravisit.rs | 8 ++-- src/librustc/hir/lowering.rs | 11 ++--- src/librustc/hir/mod.rs | 3 +- src/librustc/hir/print.rs | 9 ++-- src/librustc/ich/impls_hir.rs | 7 +++- src/librustc/middle/reachable.rs | 11 +++-- src/librustc/middle/resolve_lifetime.rs | 4 +- src/librustc_typeck/check/compare_method.rs | 14 +++---- src/librustc_typeck/collect.rs | 46 ++++----------------- 9 files changed, 42 insertions(+), 71 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 1755b3bca05..d99d7cd897b 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -780,9 +780,7 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<' FnKind::ItemFn(_, generics, ..) => { visitor.visit_generics(generics); } - FnKind::Method(_, sig, ..) => { - visitor.visit_generics(&sig.generics); - } + FnKind::Method(..) | FnKind::Closure(_) => {} } } @@ -802,6 +800,7 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { visitor.visit_name(trait_item.span, trait_item.name); walk_list!(visitor, visit_attribute, &trait_item.attrs); + visitor.visit_generics(&trait_item.generics); match trait_item.node { TraitItemKind::Const(ref ty, default) => { visitor.visit_id(trait_item.id); @@ -810,7 +809,6 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } TraitItemKind::Method(ref sig, TraitMethod::Required(ref names)) => { visitor.visit_id(trait_item.id); - visitor.visit_generics(&sig.generics); visitor.visit_fn_decl(&sig.decl); for name in names { visitor.visit_name(name.span, name.node); @@ -852,6 +850,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt ref vis, ref defaultness, ref attrs, + ref generics, ref node, span } = *impl_item; @@ -860,6 +859,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt visitor.visit_vis(vis); visitor.visit_defaultness(defaultness); walk_list!(visitor, visit_attribute, attrs); + visitor.visit_generics(generics); match *node { ImplItemKind::Const(ref ty, body) => { visitor.visit_id(impl_item.id); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f3363bde6e7..81da69a575c 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1539,6 +1539,7 @@ impl<'a> LoweringContext<'a> { hir_id, name: this.lower_ident(i.ident), attrs: this.lower_attrs(&i.attrs), + generics: this.lower_generics(&i.generics), node: match i.node { TraitItemKind::Const(ref ty, ref default) => { hir::TraitItemKind::Const(this.lower_ty(ty), @@ -1548,7 +1549,7 @@ impl<'a> LoweringContext<'a> { } TraitItemKind::Method(ref sig, None) => { let names = this.lower_fn_args_to_names(&sig.decl); - hir::TraitItemKind::Method(this.lower_method_sig(&i.generics, sig), + hir::TraitItemKind::Method(this.lower_method_sig(sig), hir::TraitMethod::Required(names)) } TraitItemKind::Method(ref sig, Some(ref body)) => { @@ -1556,7 +1557,7 @@ impl<'a> LoweringContext<'a> { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) }); - hir::TraitItemKind::Method(this.lower_method_sig(&i.generics, sig), + hir::TraitItemKind::Method(this.lower_method_sig(sig), hir::TraitMethod::Provided(body_id)) } TraitItemKind::Type(ref bounds, ref default) => { @@ -1603,6 +1604,7 @@ impl<'a> LoweringContext<'a> { hir_id, name: this.lower_ident(i.ident), attrs: this.lower_attrs(&i.attrs), + generics: this.lower_generics(&i.generics), vis: this.lower_visibility(&i.vis, None), defaultness: this.lower_defaultness(i.defaultness, true /* [1] */), node: match i.node { @@ -1615,7 +1617,7 @@ impl<'a> LoweringContext<'a> { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) }); - hir::ImplItemKind::Method(this.lower_method_sig(&i.generics, sig), body_id) + hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id) } ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -1727,9 +1729,8 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_method_sig(&mut self, generics: &Generics, sig: &MethodSig) -> hir::MethodSig { + fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { hir::MethodSig { - generics: self.lower_generics(generics), abi: sig.abi, unsafety: self.lower_unsafety(sig.unsafety), constness: self.lower_constness(sig.constness), diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 5ad0ff04c1b..fb3fc8a2da4 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1295,7 +1295,6 @@ pub struct MethodSig { pub constness: Constness, pub abi: Abi, pub decl: P, - pub generics: Generics, } // The bodies for items are stored "out of line", in a separate @@ -1316,6 +1315,7 @@ pub struct TraitItem { pub name: Name, pub hir_id: HirId, pub attrs: HirVec, + pub generics: Generics, pub node: TraitItemKind, pub span: Span, } @@ -1360,6 +1360,7 @@ pub struct ImplItem { pub vis: Visibility, pub defaultness: Defaultness, pub attrs: HirVec, + pub generics: Generics, pub node: ImplItemKind, pub span: Span, } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 7287e599b29..4eee9cbfc2d 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -880,6 +880,7 @@ impl<'a> State<'a> { pub fn print_method_sig(&mut self, name: ast::Name, m: &hir::MethodSig, + generics: &hir::Generics, vis: &hir::Visibility, arg_names: &[Spanned], body_id: Option) @@ -889,7 +890,7 @@ impl<'a> State<'a> { m.constness, m.abi, Some(name), - &m.generics, + generics, vis, arg_names, body_id) @@ -905,12 +906,12 @@ impl<'a> State<'a> { self.print_associated_const(ti.name, &ty, default, &hir::Inherited)?; } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => { - self.print_method_sig(ti.name, sig, &hir::Inherited, arg_names, None)?; + self.print_method_sig(ti.name, sig, &ti.generics, &hir::Inherited, arg_names, None)?; self.s.word(";")?; } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { self.head("")?; - self.print_method_sig(ti.name, sig, &hir::Inherited, &[], Some(body))?; + self.print_method_sig(ti.name, sig, &ti.generics, &hir::Inherited, &[], Some(body))?; self.nbsp()?; self.end()?; // need to close a box self.end()?; // need to close a box @@ -938,7 +939,7 @@ impl<'a> State<'a> { } hir::ImplItemKind::Method(ref sig, body) => { self.head("")?; - self.print_method_sig(ii.name, sig, &ii.vis, &[], Some(body))?; + self.print_method_sig(ii.name, sig, &ii.generics, &ii.vis, &[], Some(body))?; self.nbsp()?; self.end()?; // need to close a box self.end()?; // need to close a box diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index c0fae8bf8bd..994f0bd16b1 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -232,8 +232,7 @@ impl_stable_hash_for!(struct hir::MethodSig { unsafety, constness, abi, - decl, - generics + decl }); impl_stable_hash_for!(struct hir::TypeBinding { @@ -709,6 +708,7 @@ impl<'gcx> HashStable> for hir::TraitItem { hir_id: _, name, ref attrs, + ref generics, ref node, span } = *self; @@ -716,6 +716,7 @@ impl<'gcx> HashStable> for hir::TraitItem { hcx.hash_hir_item_like(attrs, |hcx| { name.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); + generics.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher); }); @@ -744,6 +745,7 @@ impl<'gcx> HashStable> for hir::ImplItem { ref vis, defaultness, ref attrs, + ref generics, ref node, span } = *self; @@ -753,6 +755,7 @@ impl<'gcx> HashStable> for hir::ImplItem { vis.hash_stable(hcx, hasher); defaultness.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); + generics.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher); }); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index bb6213cb5fa..2037bc01a5b 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -58,11 +58,10 @@ fn item_might_be_inlined(item: &hir::Item) -> bool { } fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - sig: &hir::MethodSig, impl_item: &hir::ImplItem, impl_src: DefId) -> bool { if attr::requests_inline(&impl_item.attrs) || - generics_require_inlining(&sig.generics) { + generics_require_inlining(&impl_item.generics) { return true } if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) { @@ -176,8 +175,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Some(hir_map::NodeImplItem(impl_item)) => { match impl_item.node { hir::ImplItemKind::Const(..) => true, - hir::ImplItemKind::Method(ref sig, _) => { - if generics_require_inlining(&sig.generics) || + hir::ImplItemKind::Method(..) => { + if generics_require_inlining(&impl_item.generics) || attr::requests_inline(&impl_item.attrs) { true } else { @@ -293,9 +292,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ImplItemKind::Const(_, body) => { self.visit_nested_body(body); } - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Method(_, body) => { let did = self.tcx.hir.get_parent_did(search_item); - if method_might_be_inlined(self.tcx, sig, impl_item, did) { + if method_might_be_inlined(self.tcx, impl_item, did) { self.visit_nested_body(body) } } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index d0c5460fa97..dc912f1c1b6 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -412,7 +412,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { if let hir::TraitItemKind::Method(ref sig, _) = trait_item.node { self.visit_early_late( Some(self.hir_map.get_parent(trait_item.id)), - &sig.decl, &sig.generics, + &sig.decl, &trait_item.generics, |this| intravisit::walk_trait_item(this, trait_item)) } else { intravisit::walk_trait_item(self, trait_item); @@ -423,7 +423,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { self.visit_early_late( Some(self.hir_map.get_parent(impl_item.id)), - &sig.decl, &sig.generics, + &sig.decl, &impl_item.generics, |this| intravisit::walk_impl_item(this, impl_item)) } else { intravisit::walk_impl_item(self, impl_item); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index b21d4888612..554a858bcc1 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -568,15 +568,11 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let num_trait_m_type_params = trait_m_generics.types.len(); if num_impl_m_type_params != num_trait_m_type_params { let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap(); - let span = match tcx.hir.expect_impl_item(impl_m_node_id).node { - ImplItemKind::Method(ref impl_m_sig, _) => { - if impl_m_sig.generics.is_parameterized() { - impl_m_sig.generics.span - } else { - impl_m_span - } - } - _ => bug!("{:?} is not a method", impl_m), + let impl_m_item = tcx.hir.expect_impl_item(impl_m_node_id); + let span = if impl_m_item.generics.is_parameterized() { + impl_m_item.generics.span + } else { + impl_m_span }; let mut err = struct_span_err!(tcx.sess, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a5b3f8cb806..68ba1b4c44c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -261,19 +261,9 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); let ast_generics = match tcx.hir.get(item_node_id) { - NodeTraitItem(item) => { - match item.node { - TraitItemKind::Method(ref sig, _) => &sig.generics, - _ => return result - } - } + NodeTraitItem(item) => &item.generics, - NodeImplItem(item) => { - match item.node { - ImplItemKind::Method(ref sig, _) => &sig.generics, - _ => return result - } - } + NodeImplItem(item) => &item.generics, NodeItem(item) => { match item.node { @@ -818,12 +808,12 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match node { hir_map::NodeTraitItem(item) => match item.node { hir::TraitItemKind::Method(ref sig, _) => - has_late_bound_regions(tcx, &sig.generics, &sig.decl), + has_late_bound_regions(tcx, &item.generics, &sig.decl), _ => None, }, hir_map::NodeImplItem(item) => match item.node { hir::ImplItemKind::Method(ref sig, _) => - has_late_bound_regions(tcx, &sig.generics, &sig.decl), + has_late_bound_regions(tcx, &item.generics, &sig.decl), _ => None, }, hir_map::NodeForeignItem(item) => match item.node { @@ -881,19 +871,9 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let no_generics = hir::Generics::empty(); let ast_generics = match node { - NodeTraitItem(item) => { - match item.node { - TraitItemKind::Method(ref sig, _) => &sig.generics, - _ => &no_generics - } - } + NodeTraitItem(item) => &item.generics, - NodeImplItem(item) => { - match item.node { - ImplItemKind::Method(ref sig, _) => &sig.generics, - _ => &no_generics - } - } + NodeImplItem(item) => &item.generics, NodeItem(item) => { match item.node { @@ -1353,19 +1333,9 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let icx = ItemCtxt::new(tcx, def_id); let no_generics = hir::Generics::empty(); let ast_generics = match node { - NodeTraitItem(item) => { - match item.node { - TraitItemKind::Method(ref sig, _) => &sig.generics, - _ => &no_generics - } - } + NodeTraitItem(item) => &item.generics, - NodeImplItem(item) => { - match item.node { - ImplItemKind::Method(ref sig, _) => &sig.generics, - _ => &no_generics - } - } + NodeImplItem(item) => &item.generics, NodeItem(item) => { match item.node { From 2095ac1e2714f5fa8f25de1e8574dd541514277c Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Mon, 25 Sep 2017 18:36:28 -0400 Subject: [PATCH 302/365] Fixed tidy errors --- src/librustc/hir/print.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 4eee9cbfc2d..b4614873550 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -906,12 +906,14 @@ impl<'a> State<'a> { self.print_associated_const(ti.name, &ty, default, &hir::Inherited)?; } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => { - self.print_method_sig(ti.name, sig, &ti.generics, &hir::Inherited, arg_names, None)?; + self.print_method_sig(ti.name, sig, &ti.generics, &hir::Inherited, arg_names, + None)?; self.s.word(";")?; } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { self.head("")?; - self.print_method_sig(ti.name, sig, &ti.generics, &hir::Inherited, &[], Some(body))?; + self.print_method_sig(ti.name, sig, &ti.generics, &hir::Inherited, &[], + Some(body))?; self.nbsp()?; self.end()?; // need to close a box self.end()?; // need to close a box From b43db76d36d6205ebaf5b2b6c260ac23f74733dc Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 26 Sep 2017 01:17:04 -0400 Subject: [PATCH 303/365] Fixing rustdoc --- src/librustdoc/clean/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e217978648e..63e3c7edb95 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1140,13 +1140,13 @@ pub struct Method { pub abi: Abi, } -impl<'a> Clean for (&'a hir::MethodSig, hir::BodyId) { +impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) { fn clean(&self, cx: &DocContext) -> Method { Method { - generics: self.0.generics.clean(cx), + generics: self.1.clean(cx), unsafety: self.0.unsafety, constness: self.0.constness, - decl: (&*self.0.decl, self.1).clean(cx), + decl: (&*self.0.decl, self.2).clean(cx), abi: self.0.abi } } @@ -1379,13 +1379,13 @@ impl Clean for hir::TraitItem { default.map(|e| print_const_expr(cx, e))) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { - MethodItem((sig, body).clean(cx)) + MethodItem((sig, &self.generics, body).clean(cx)) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { TyMethodItem(TyMethod { unsafety: sig.unsafety.clone(), decl: (&*sig.decl, &names[..]).clean(cx), - generics: sig.generics.clean(cx), + generics: self.generics.clean(cx), abi: sig.abi }) } @@ -1414,7 +1414,7 @@ impl Clean for hir::ImplItem { Some(print_const_expr(cx, expr))) } hir::ImplItemKind::Method(ref sig, body) => { - MethodItem((sig, body).clean(cx)) + MethodItem((sig, &self.generics, body).clean(cx)) } hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef { type_: ty.clean(cx), From 86ae34900f68903006913f374a7860e25c502057 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 10 Oct 2017 16:38:43 -0400 Subject: [PATCH 304/365] Updated to latest rustfmt-nightly --- src/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 328ce353e2a..0b708dc7cc8 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1358,10 +1358,10 @@ dependencies = [ "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.2.7", - "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.2.8", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.2.7" +version = "0.2.8" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", From 14c426da99b06c35aa820b2d6845134d09dbe2c3 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 10 Oct 2017 17:56:24 -0400 Subject: [PATCH 305/365] Removed Generics from FnKind::ItemFn in libsyntax --- src/librustc_resolve/lib.rs | 3 +-- src/libsyntax/feature_gate.rs | 4 ++-- src/libsyntax/visit.rs | 8 ++++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2e5c9e35346..88404953266 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -718,8 +718,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { _: Span, node_id: NodeId) { let rib_kind = match function_kind { - FnKind::ItemFn(_, generics, ..) => { - self.visit_generics(generics); + FnKind::ItemFn(..) => { ItemRibKind } FnKind::Method(_, sig, _, _) => { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9060a613bc1..326f8cef6b3 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1526,7 +1526,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { span: Span, _node_id: NodeId) { // check for const fn declarations - if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) = + if let FnKind::ItemFn(_, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) = fn_kind { gate_feature_post!(&self, const_fn, span, "const fn is unstable"); } @@ -1536,7 +1536,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // point. match fn_kind { - FnKind::ItemFn(_, _, _, _, abi, _, _) | + FnKind::ItemFn(_, _, _, abi, _, _) | FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => { self.check_abi(abi, span); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index e74296c06a9..078a63cba20 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -31,7 +31,7 @@ use codemap::Spanned; #[derive(Copy, Clone, PartialEq, Eq)] pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() - ItemFn(Ident, &'a Generics, Unsafety, Spanned, Abi, &'a Visibility, &'a Block), + ItemFn(Ident, Unsafety, Spanned, Abi, &'a Visibility, &'a Block), /// fn foo(&self) Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block), @@ -247,7 +247,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_expr(expr); } ItemKind::Fn(ref declaration, unsafety, constness, abi, ref generics, ref body) => { - visitor.visit_fn(FnKind::ItemFn(item.ident, generics, unsafety, + visitor.visit_generics(generics); + visitor.visit_fn(FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), declaration, item.span, @@ -538,8 +539,7 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl where V: Visitor<'a>, { match kind { - FnKind::ItemFn(_, generics, _, _, _, _, body) => { - visitor.visit_generics(generics); + FnKind::ItemFn(_, _, _, _, _, body) => { walk_fn_decl(visitor, declaration); visitor.visit_block(body); } From 693687187e48b687dd158ad7f52eab7a744918d8 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Wed, 11 Oct 2017 02:35:48 -0400 Subject: [PATCH 306/365] Revert "Updated to latest rustfmt-nightly" This reverts commit a49157dc30bf7a163200b10d63a71b005a1376e3. --- src/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 0b708dc7cc8..328ce353e2a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1358,10 +1358,10 @@ dependencies = [ "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.2.8", - "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.2.7", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.2.8" +version = "0.2.7" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", From 60bff8ce93d2b43a8d53ffc4454e58f53e012475 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 17 Oct 2017 22:15:34 -0400 Subject: [PATCH 307/365] Marking the tools as broken --- src/tools/toolstate.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml index e62597c5216..9dd420c1458 100644 --- a/src/tools/toolstate.toml +++ b/src/tools/toolstate.toml @@ -26,10 +26,10 @@ miri = "Broken" # ping @Manishearth @llogiq @mcarton @oli-obk -clippy = "Compiling" +clippy = "Broken" # ping @nrc -rls = "Testing" +rls = "Broken" # ping @nrc -rustfmt = "Testing" +rustfmt = "Broken" From bd4907d534a1894e28a1f3cf672022e29eabf194 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sat, 7 Oct 2017 21:53:43 -0400 Subject: [PATCH 308/365] Documenting the process for when rustfmt/rls breakk because of your changes --- CONTRIBUTING.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a86742d7bd4..c6c62a8c7b4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -363,6 +363,44 @@ outside the submodule. It can also be more convenient during development to set `submodules = false` in the `config.toml` to prevent `x.py` from resetting to the original branch. +#### Breaking rustfmt or rls + +Rust's build system also builds the +[RLS](https://github.com/rust-lang-nursery/rls) +and [rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools +break because of your changes, you may run into a sort of "chicken and egg" +problem. Both tools rely on the latest compiler to be built so you can't update +them until the changes you are making to the compiler land. In the meantime, you +can't land your changes to the compiler because the build won't pass until those +tools are fixed. + +That means that, in the default state, you can't update the compiler without +fixing rustfmt and rls first. + +When this happens, follow these steps: + +1. First, if it doesn't exist already, create a `config.toml` by copying + `config.toml.example` in the root directory of the Rust repository. + Set `submodules = false` in the `[build]` section. This will prevent `x.py` + from resetting to the original branch after you make your changes. +2. Run `./x.py test src/tools/rustfmt`. Fix any errors in the submodule itself + (the `src/tools/rustfmt` directory) until it works. +3. Run `./x.py test src/tools/rls`. Fix any errors in the submodule itself + (the `src/tools/rls` directory) until it works. +4. Make a commit for `rustfmt`, if necessary, and send a PR to the master + branch of rust-lang-nursery/rustfmt +5. Do the same, if necessary for the RLS +6. A maintainer of rls/rustfmt will **not** merge the PR. The PR can't be + merged because CI will be broken. Instead a new branch will be created, + and the PR will be pushed to the branch (the PR is left open) +7. On your branch, update the rls/rustfmt submodules to these branches +8. Commit the changes, update your PR to rust-lang/rust +9. Wait for the branch to merge +10. Wait for a nightly +11. A maintainer of rls/rustfmt will merge the original PRs to rls/rustfmt +12. Eventually the rls/rustfmt submodules will get re-updated back to the + master branch + ## Writing Documentation [writing-documentation]: #writing-documentation From 3f90c3a2cfb458c94d514345e701696d74d988c8 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 10 Oct 2017 16:31:43 -0400 Subject: [PATCH 309/365] Added a section about updating submodules The process for updating rustfmt is quite involved because of the way everything is configured. This section covers the steps for updating rustfmt and rationale behind them. --- CONTRIBUTING.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c6c62a8c7b4..34789f144f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -364,6 +364,7 @@ It can also be more convenient during development to set `submodules = false` in the `config.toml` to prevent `x.py` from resetting to the original branch. #### Breaking rustfmt or rls +[breaking-rustfmt-or-rls]: #breaking-rustfmt-or-rls Rust's build system also builds the [RLS](https://github.com/rust-lang-nursery/rls) @@ -382,7 +383,9 @@ When this happens, follow these steps: 1. First, if it doesn't exist already, create a `config.toml` by copying `config.toml.example` in the root directory of the Rust repository. Set `submodules = false` in the `[build]` section. This will prevent `x.py` - from resetting to the original branch after you make your changes. + from resetting to the original branch after you make your changes. If you + need to [update any submodules to their latest versions][updating-submodules], + see the section of this file about that for more information. 2. Run `./x.py test src/tools/rustfmt`. Fix any errors in the submodule itself (the `src/tools/rustfmt` directory) until it works. 3. Run `./x.py test src/tools/rls`. Fix any errors in the submodule itself @@ -401,6 +404,65 @@ When this happens, follow these steps: 12. Eventually the rls/rustfmt submodules will get re-updated back to the master branch +#### Updating submodules +[updating-submodules]: #updating-submodules + +These instructions are specific to updating `rustfmt`, however they may apply +to the other submodules as well. Please help by improving these instructions +if you find any discrepencies or special cases that need to be addressed. + +To update the `rustfmt` submodule, start by running the appropriate +[`git submodule` command](https://git-scm.com/book/en/v2/Git-Tools-Submodules). +For example, to update to the latest commit on the remote master branch, +you may want to run: +``` +git submodule update --remote src/tools/rustfmt +``` +If you run `./x.py build` now, and you are lucky, it may just work. If you see +an error message about patches that did not resolve to any crates, you will need +to complete a few more steps which are outlined with their rationale below. + +*(This error may change in the future to include more information.)* +``` +error: failed to resolve patches for `https://github.com/rust-lang-nursery/rustfmt` + +Caused by: + patch for `rustfmt-nightly` in `https://github.com/rust-lang-nursery/rustfmt` did not resolve to any crates +failed to run: ~/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path ~/rust/src/bootstrap/Cargo.toml +``` + +If you haven't used the `[patch]` +section of `Cargo.toml` before, there is [some relevant documentation about it +in the cargo docs](http://doc.crates.io/manifest.html#the-patch-section). In +addition to that, you should read the +[Overriding dependencies](http://doc.crates.io/specifying-dependencies.html#overriding-dependencies) +section of the documentation as well. + +Specifically, the following [section in Overriding dependencies](http://doc.crates.io/specifying-dependencies.html#testing-a-bugfix) reveals what the problem is: + +> Next up we need to ensure that our lock file is updated to use this new version of uuid so our project uses the locally checked out copy instead of one from crates.io. The way [patch] works is that it'll load the dependency at ../path/to/uuid and then whenever crates.io is queried for versions of uuid it'll also return the local version. +> +> This means that the version number of the local checkout is significant and will affect whether the patch is used. Our manifest declared uuid = "1.0" which means we'll only resolve to >= 1.0.0, < 2.0.0, and Cargo's greedy resolution algorithm also means that we'll resolve to the maximum version within that range. Typically this doesn't matter as the version of the git repository will already be greater or match the maximum version published on crates.io, but it's important to keep this in mind! + +This says that when we updated the submodule, the version number in our +`src/tools/rustfmt/Cargo.toml` changed. The new version is different from +the version in `Cargo.lock`, so the build can no longer continue. + +To resolve this, we need to update `Cargo.lock`. Luckily, cargo provides a +command to do this easily. + +First, go into the `src/` directory since that is where `Cargo.toml` is in +the rust repository. Then run, `cargo update -p rustfmt-nightly` to solve +the problem. + +``` +$ cd src +$ cargo update -p rustfmt-nightly +``` + +This should change the version listed in `src/Cargo.lock` to the new version you updated +the submodule to. Running `./x.py build` should work now. + ## Writing Documentation [writing-documentation]: #writing-documentation From 790604adad9fd02b92c59d1f937edb902a58b036 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 17 Oct 2017 22:51:10 -0400 Subject: [PATCH 310/365] Updating the instructions for when a tool breaks to use the new toolstate feature --- CONTRIBUTING.md | 70 ++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 34789f144f4..0f6cba7a95e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -363,46 +363,56 @@ outside the submodule. It can also be more convenient during development to set `submodules = false` in the `config.toml` to prevent `x.py` from resetting to the original branch. -#### Breaking rustfmt or rls -[breaking-rustfmt-or-rls]: #breaking-rustfmt-or-rls +#### Breaking Tools Built With The Compiler +[breaking-tools-built-with-the-compiler]: #breaking-tools-built-with-the-compiler -Rust's build system also builds the -[RLS](https://github.com/rust-lang-nursery/rls) -and [rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools +Rust's build system builds a number of tools that make use of the +internals of the compiler. This includes clippy, +[RLS](https://github.com/rust-lang-nursery/rls) and +[rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools break because of your changes, you may run into a sort of "chicken and egg" -problem. Both tools rely on the latest compiler to be built so you can't update -them until the changes you are making to the compiler land. In the meantime, you -can't land your changes to the compiler because the build won't pass until those -tools are fixed. +problem. These tools rely on the latest compiler to be built so you can't update +them to reflect your changes to the compiler until those changes are merged into +the compiler. At the same time, you can't get your changes merged into the compiler +because the rust-lang/rust build won't pass until those tools build and pass their +tests. -That means that, in the default state, you can't update the compiler without -fixing rustfmt and rls first. +That means that, in the default state, you can't update the compiler without first +fixing rustfmt, rls and the other tools that the compiler builds. -When this happens, follow these steps: +Luckily, a feature was [added to Rust's build](https://github.com/rust-lang/rust/pull/45243) +to make all of this easy to handle. The idea is that you mark the tools as "broken", +so that the rust-lang/rust build passes without trying to build them, then land the change +in the compiler, wait for a nightly, and go update the tools that you broke. Once you're done +and the tools are working again, you go back in the compiler and change the tools back +from "broken". -1. First, if it doesn't exist already, create a `config.toml` by copying +This should avoid a bunch of synchronization dances and is also much easier on contributors as +there's no need to block on rls/rustfmt/other tools changes going upstream. + +Here are those same steps in detail: + +1. (optional) First, if it doesn't exist already, create a `config.toml` by copying `config.toml.example` in the root directory of the Rust repository. Set `submodules = false` in the `[build]` section. This will prevent `x.py` from resetting to the original branch after you make your changes. If you need to [update any submodules to their latest versions][updating-submodules], see the section of this file about that for more information. -2. Run `./x.py test src/tools/rustfmt`. Fix any errors in the submodule itself - (the `src/tools/rustfmt` directory) until it works. -3. Run `./x.py test src/tools/rls`. Fix any errors in the submodule itself - (the `src/tools/rls` directory) until it works. -4. Make a commit for `rustfmt`, if necessary, and send a PR to the master - branch of rust-lang-nursery/rustfmt -5. Do the same, if necessary for the RLS -6. A maintainer of rls/rustfmt will **not** merge the PR. The PR can't be - merged because CI will be broken. Instead a new branch will be created, - and the PR will be pushed to the branch (the PR is left open) -7. On your branch, update the rls/rustfmt submodules to these branches -8. Commit the changes, update your PR to rust-lang/rust -9. Wait for the branch to merge -10. Wait for a nightly -11. A maintainer of rls/rustfmt will merge the original PRs to rls/rustfmt -12. Eventually the rls/rustfmt submodules will get re-updated back to the - master branch +2. (optional) Run `./x.py test src/tools/rustfmt` (substituting the submodule + that broke for `rustfmt`). Fix any errors in the submodule (and possibly others). +3. (optional) Make commits for your changes and send them to upstream repositories as a PR. +4. (optional) Maintainers of these submodules will **not** merge the PR. The PR can't be + merged because CI will be broken. You'll want to write a message on the PR referencing + your change, and how the PR should be merged once your change makes it into a nightly. +5. Update `src/tools/toolstate.toml` to indicate that the tool in question is "broken", + that will disable building it on CI. See the documentation in that file for the exact + configuration values you can use. +6. Commit the changes to `src/tools/toolstate.toml`, **do not update submodules in your commit**, + and then update the PR you have for rust-lang/rust. +7. Wait for your PR to merge. +8. Wait for a nightly +9. (optional) Help land your PR on the upstream repository now that your changes are in nightly. +10. (optional) Send a PR to rust-lang/rust updating the submodule, reverting `src/tools/toolstate.toml` back to a "building" or "testing" state. #### Updating submodules [updating-submodules]: #updating-submodules From 2a889eb945cdae95fce33fbeb1b79093c456cadd Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Tue, 17 Oct 2017 23:51:27 -0500 Subject: [PATCH 311/365] added non trivial examples of closures for str::find --- src/liballoc/str.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 3e273a67000..895607ff8d4 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -966,8 +966,8 @@ impl str { /// /// assert_eq!(s.find(char::is_whitespace), Some(5)); /// assert_eq!(s.find(char::is_lowercase), Some(1)); - /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5)); - /// assert_eq!(s.find(|c: char| c.is_lowercase()), Some(1)); + /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1)); + /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4)); /// ``` /// /// Not finding the pattern: From 9fda05c0bc1c6611e8c6102c46c39a7af847ff08 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 17 Oct 2017 23:03:50 -0700 Subject: [PATCH 312/365] rustdoc: add a primitive page for "unit" In `src/libstd/primitive_docs.rs`, a `#[doc(primitive = "unit")]` section has sat long neglected. This patch teaches rustdoc to recognize "unit", and steals its trait implementations away from the tuple page. --- src/librustdoc/clean/mod.rs | 17 +++++++++++++++-- src/librustdoc/html/format.rs | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e217978648e..ad171c4babb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -238,6 +238,7 @@ impl Clean for CrateNum { if prim.is_some() { break; } + // FIXME: should warn on unknown primitives? } } } @@ -1627,6 +1628,7 @@ pub enum PrimitiveType { Slice, Array, Tuple, + Unit, RawPointer, Reference, Fn, @@ -1662,7 +1664,11 @@ impl Type { Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p), Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice), Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array), - Tuple(..) => Some(PrimitiveType::Tuple), + Tuple(ref tys) => if tys.is_empty() { + Some(PrimitiveType::Unit) + } else { + Some(PrimitiveType::Tuple) + }, RawPointer(..) => Some(PrimitiveType::RawPointer), BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference), BareFunction(..) => Some(PrimitiveType::Fn), @@ -1708,7 +1714,11 @@ impl GetDefId for Type { BorrowedRef { type_: box Generic(..), .. } => Primitive(PrimitiveType::Reference).def_id(), BorrowedRef { ref type_, .. } => type_.def_id(), - Tuple(..) => Primitive(PrimitiveType::Tuple).def_id(), + Tuple(ref tys) => if tys.is_empty() { + Primitive(PrimitiveType::Unit).def_id() + } else { + Primitive(PrimitiveType::Tuple).def_id() + }, BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(), Slice(..) => Primitive(PrimitiveType::Slice).def_id(), Array(..) => Primitive(PrimitiveType::Array).def_id(), @@ -1742,6 +1752,7 @@ impl PrimitiveType { "array" => Some(PrimitiveType::Array), "slice" => Some(PrimitiveType::Slice), "tuple" => Some(PrimitiveType::Tuple), + "unit" => Some(PrimitiveType::Unit), "pointer" => Some(PrimitiveType::RawPointer), "reference" => Some(PrimitiveType::Reference), "fn" => Some(PrimitiveType::Fn), @@ -1772,6 +1783,7 @@ impl PrimitiveType { Array => "array", Slice => "slice", Tuple => "tuple", + Unit => "unit", RawPointer => "pointer", Reference => "reference", Fn => "fn", @@ -2693,6 +2705,7 @@ fn build_deref_target_impls(cx: &DocContext, Slice => tcx.lang_items().slice_impl(), Array => tcx.lang_items().slice_impl(), Tuple => None, + Unit => None, RawPointer => tcx.lang_items().const_ptr_impl(), Reference => None, Fn => None, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6303fd662bf..18d6b1cc1e0 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -614,7 +614,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } clean::Tuple(ref typs) => { match &typs[..] { - &[] => primitive_link(f, PrimitiveType::Tuple, "()"), + &[] => primitive_link(f, PrimitiveType::Unit, "()"), &[ref one] => { primitive_link(f, PrimitiveType::Tuple, "(")?; //carry f.alternate() into this display w/o branching manually From 6bfecd41cc29a5faec964f2dc252443d5fda4293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Thu, 14 Sep 2017 22:09:09 +0200 Subject: [PATCH 313/365] Avoid unnecessary allocas for indirect function arguments The extra alloca was only necessary because it made LLVM implicitly handle the necessary deref to get to the actual value. The same happens for indirect arguments that have the byval attribute. But the Rust ABI does not use the byval attribute and so we need to manually add the deref operation to the debuginfo. --- src/librustc_trans/abi.rs | 4 ++++ src/librustc_trans/mir/mod.rs | 29 ++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index c3b6ede24b0..6df40c34ec5 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -113,6 +113,10 @@ impl ArgAttributes { self } + pub fn contains(&self, attr: ArgAttribute) -> bool { + self.regular.contains(attr) + } + pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { unsafe { self.regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 5206ad74e20..d5d44bfa7ba 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -23,7 +23,7 @@ use builder::Builder; use common::{self, CrateContext, Funclet}; use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext}; use monomorphize::Instance; -use abi::FnType; +use abi::{ArgAttribute, FnType}; use type_of; use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span}; @@ -378,6 +378,10 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, None }; + let deref_op = unsafe { + [llvm::LLVMRustDIBuilderCreateOpDeref()] + }; + mir.args_iter().enumerate().map(|(arg_index, local)| { let arg_decl = &mir.local_decls[local]; let arg_ty = mircx.monomorphize(&arg_decl.ty); @@ -432,10 +436,9 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let arg = &mircx.fn_ty.args[idx]; idx += 1; - let llval = if arg.is_indirect() && bcx.sess().opts.debuginfo != FullDebugInfo { + let llval = if arg.is_indirect() { // Don't copy an indirect argument to an alloca, the caller - // already put it in a temporary alloca and gave it up, unless - // we emit extra-debug-info, which requires local allocas :(. + // already put it in a temporary alloca and gave it up // FIXME: lifetimes if arg.pad.is_some() { llarg_idx += 1; @@ -444,8 +447,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, llarg_idx += 1; llarg } else if !lvalue_locals.contains(local.index()) && - !arg.is_indirect() && arg.cast.is_none() && - arg_scope.is_none() { + arg.cast.is_none() && arg_scope.is_none() { if arg.is_ignore() { return LocalRef::new_operand(bcx.ccx, arg_ty); } @@ -510,13 +512,26 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, arg_scope.map(|scope| { // Is this a regular argument? if arg_index > 0 || mir.upvar_decls.is_empty() { + // The Rust ABI passes indirect variables using a pointer and a manual copy, so we + // need to insert a deref here, but the C ABI uses a pointer and a copy using the + // byval attribute, for which LLVM does the deref itself, so we must not add it. + let variable_access = if arg.is_indirect() && + !arg.attrs.contains(ArgAttribute::ByVal) { + VariableAccess::IndirectVariable { + alloca: llval, + address_operations: &deref_op, + } + } else { + VariableAccess::DirectVariable { alloca: llval } + }; + declare_local( bcx, &mircx.debug_context, arg_decl.name.unwrap_or(keywords::Invalid.name()), arg_ty, scope, - VariableAccess::DirectVariable { alloca: llval }, + variable_access, VariableKind::ArgumentVariable(arg_index + 1), DUMMY_SP ); From 0caba178dfd5983403564de82a7d11184c7964e2 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 18 Oct 2017 13:54:36 +0300 Subject: [PATCH 314/365] run EndRegion when unwinding otherwise-empty scopes Improves #44832 borrowck-overloaded-index-move-index.rs - fixed borrowck-multiple-captures.rs - still ICE borrowck-issue-2657-1.rs - fixed borrowck-loan-blocks-move.rs - fixed borrowck-move-from-subpath-of-borrowed-path.rs - fixed borrowck-mut-borrow-linear-errors.rs - still ICE borrowck-no-cycle-in-exchange-heap.rs - fixed borrowck-unary-move.rs - fixed borrowck-loan-blocks-move-cc.rs - fixed borrowck-vec-pattern-element-loan.rs - still broken --- src/librustc_mir/build/scope.rs | 104 ++++++++++-------- .../borrowck/borrowck-unary-move.rs | 7 +- 2 files changed, 66 insertions(+), 45 deletions(-) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 772438d5252..c0d17a1590f 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -131,6 +131,9 @@ pub struct Scope<'tcx> { /// The cache for drop chain on "generator drop" exit. cached_generator_drop: Option, + + /// The cache for drop chain on "unwind" exit. + cached_unwind: CachedBlock, } #[derive(Debug)] @@ -233,8 +236,10 @@ impl<'tcx> Scope<'tcx> { self.cached_exits.clear(); if !storage_only { - // the current generator drop ignores storage but refers to top-of-scope + // the current generator drop and unwind ignore + // storage but refer to top-of-scope self.cached_generator_drop = None; + self.cached_unwind.invalidate(); } if !storage_only && !this_scope_only { @@ -246,26 +251,6 @@ impl<'tcx> Scope<'tcx> { } } - /// Returns the cached entrypoint for diverging exit from this scope. - /// - /// Precondition: the caches must be fully filled (i.e. diverge_cleanup is called) in order for - /// this method to work correctly. - fn cached_block(&self, generator_drop: bool) -> Option { - let mut drops = self.drops.iter().rev().filter_map(|data| { - match data.kind { - DropKind::Value { cached_block } => { - Some(cached_block.get(generator_drop)) - } - DropKind::Storage => None - } - }); - if let Some(cached_block) = drops.next() { - Some(cached_block.expect("drop cache is not filled")) - } else { - None - } - } - /// Given a span and this scope's visibility scope, make a SourceInfo. fn source_info(&self, span: Span) -> SourceInfo { SourceInfo { @@ -374,7 +359,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { needs_cleanup: false, drops: vec![], cached_generator_drop: None, - cached_exits: FxHashMap() + cached_exits: FxHashMap(), + cached_unwind: CachedBlock::default(), }); } @@ -500,15 +486,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { TerminatorKind::Goto { target: b }); b }; + + // End all regions for scopes out of which we are breaking. + self.cfg.push_end_region(self.hir.tcx(), block, src_info, scope.region_scope); + unpack!(block = build_scope_drops(&mut self.cfg, scope, rest, block, self.arg_count, true)); - - // End all regions for scopes out of which we are breaking. - self.cfg.push_end_region(self.hir.tcx(), block, src_info, scope.region_scope); } self.cfg.terminate(block, src_info, TerminatorKind::GeneratorDrop); @@ -841,23 +828,45 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, let source_info = scope.source_info(drop_data.span); match drop_data.kind { DropKind::Value { .. } => { - // Try to find the next block with its cached block - // for us to diverge into in case the drop panics. + // Try to find the next block with its cached block for us to + // diverge into, either a previous block in this current scope or + // the top of the previous scope. + // + // If it wasn't for EndRegion, we could just chain all the DropData + // together and pick the first DropKind::Value. Please do that + // when we replace EndRegion with NLL. let on_diverge = iter.clone().filter_map(|dd| { match dd.kind { DropKind::Value { cached_block } => Some(cached_block), DropKind::Storage => None } - }).map(|cached_block| { - cached_block - .get(generator_drop) - .unwrap_or_else(|| span_bug!(drop_data.span, "cached block not present?")) - }).next(); - // If there’s no `cached_block`s within current scope, - // we must look for one in the enclosing scope. - let on_diverge = on_diverge.or_else(|| { - earlier_scopes.iter().rev().flat_map(|s| s.cached_block(generator_drop)).next() + }).next().or_else(|| { + if earlier_scopes.iter().any(|scope| scope.needs_cleanup) { + // If *any* scope requires cleanup code to be run, + // we must use the cached unwind from the *topmost* + // scope, to ensure all EndRegions from surrounding + // scopes are executed before the drop code runs. + Some(earlier_scopes.last().unwrap().cached_unwind) + } else { + // We don't need any further cleanup, so return None + // to avoid creating a landing pad. We can skip + // EndRegions because all local regions end anyway + // when the function unwinds. + // + // This is an important optimization because LLVM is + // terrible at optimizing landing pads. FIXME: I think + // it would be cleaner and better to do this optimization + // in SimplifyCfg instead of here. + None + } }); + + let on_diverge = on_diverge.map(|cached_block| { + cached_block.get(generator_drop).unwrap_or_else(|| { + span_bug!(drop_data.span, "cached block not present?") + }) + }); + let next = cfg.start_new_block(); cfg.terminate(block, source_info, TerminatorKind::Drop { location: drop_data.location.clone(), @@ -948,14 +957,21 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, }; } - // Finally, push the EndRegion block, used by mir-borrowck. (Block - // becomes trivial goto after pass that removes all EndRegions.) - { - let block = cfg.start_new_cleanup_block(); - cfg.push_end_region(tcx, block, source_info(span), scope.region_scope); - cfg.terminate(block, source_info(span), TerminatorKind::Goto { target: target }); - target = block - } + // Finally, push the EndRegion block, used by mir-borrowck, and set + // `cached_unwind` to point to it (Block becomes trivial goto after + // pass that removes all EndRegions). + target = { + let cached_block = scope.cached_unwind.ref_mut(generator_drop); + if let Some(cached_block) = *cached_block { + cached_block + } else { + let block = cfg.start_new_cleanup_block(); + cfg.push_end_region(tcx, block, source_info(span), scope.region_scope); + cfg.terminate(block, source_info(span), TerminatorKind::Goto { target: target }); + *cached_block = Some(block); + block + } + }; debug!("build_diverge_scope({:?}, {:?}) = {:?}", scope, span, target); diff --git a/src/test/compile-fail/borrowck/borrowck-unary-move.rs b/src/test/compile-fail/borrowck/borrowck-unary-move.rs index 5b5c5f4da91..6cab5a8bf60 100644 --- a/src/test/compile-fail/borrowck/borrowck-unary-move.rs +++ b/src/test/compile-fail/borrowck/borrowck-unary-move.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength +// revisions: ast mir +//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir fn foo(x: Box) -> isize { let y = &*x; - free(x); //~ ERROR cannot move out of `x` because it is borrowed + free(x); //[ast]~ ERROR cannot move out of `x` because it is borrowed + //[mir]~^ ERROR cannot move out of `x` because it is borrowed (Ast) + //[mir]~| ERROR cannot move out of `x` because it is borrowed (Mir) *y } From 3541ffb668c3b908aa5e3b6ba8a890d56a8360a7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 Oct 2017 13:08:13 -0700 Subject: [PATCH 315/365] rustc: Add `_imp_` symbols later in compilation On MSVC targets rustc will add symbols prefixed with `_imp_` to LLVM modules to "emulate" dllexported statics as that workaround is still in place after #27438 hasn't been solved otherwise. These statics, however, were getting gc'd by ThinLTO accidentally which later would cause linking failures. This commit updates the location we add such symbols to happen just before codegen to ensure that (a) they're not eliminated by the optimizer and (b) the optimizer doesn't even worry about them. Closes #45347 --- src/librustc_trans/back/write.rs | 61 ++++++++++++++++++- src/librustc_trans/base.rs | 52 +--------------- .../thinlto/auxiliary/msvc-imp-present.rs | 21 +++++++ src/test/run-pass/thinlto/msvc-imp-present.rs | 31 ++++++++++ 4 files changed, 115 insertions(+), 50 deletions(-) create mode 100644 src/test/run-pass/thinlto/auxiliary/msvc-imp-present.rs create mode 100644 src/test/run-pass/thinlto/msvc-imp-present.rs diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index f7e0ad029af..f8dbe68dba9 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -12,6 +12,8 @@ use back::lto; use back::link::{self, get_linker, remove}; use back::linker::LinkerInfo; use back::symbol_export::ExportedSymbols; +use base; +use consts; use rustc_incremental::{save_trans_partition, in_incr_comp_dir}; use rustc::dep_graph::DepGraph; use rustc::middle::cstore::{LinkMeta, EncodedMetadata}; @@ -35,12 +37,13 @@ use syntax::attr; use syntax::ext::hygiene::Mark; use syntax_pos::MultiSpan; use syntax_pos::symbol::Symbol; +use type_::Type; use context::{is_pie_binary, get_reloc_model}; use jobserver::{Client, Acquired}; use rustc_demangle; use std::any::Any; -use std::ffi::CString; +use std::ffi::{CString, CStr}; use std::fs; use std::io; use std::io::Write; @@ -315,6 +318,8 @@ pub struct CodegenContext { metadata_module_config: Arc, allocator_module_config: Arc, pub tm_factory: Arc Result + Send + Sync>, + pub msvc_imps_needed: bool, + pub target_pointer_width: String, // Number of cgus excluding the allocator/metadata modules pub total_cgus: usize, @@ -586,6 +591,10 @@ unsafe fn codegen(cgcx: &CodegenContext, let module_name = Some(&module_name[..]); let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); + if cgcx.msvc_imps_needed { + create_msvc_imps(cgcx, llcx, llmod); + } + // A codegen-specific pass manager is used to generate object // files for an LLVM module. // @@ -1300,6 +1309,8 @@ fn start_executing_work(tcx: TyCtxt, allocator_module_config: allocator_config, tm_factory: target_machine_factory(tcx.sess), total_cgus, + msvc_imps_needed: msvc_imps_needed(tcx), + target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(), }; // This is the "main loop" of parallel work happening for parallel codegen. @@ -2133,3 +2144,51 @@ pub fn submit_translated_module_to_llvm(tcx: TyCtxt, cost, }))); } + +fn msvc_imps_needed(tcx: TyCtxt) -> bool { + tcx.sess.target.target.options.is_like_msvc && + tcx.sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) +} + +// Create a `__imp_ = &symbol` global for every public static `symbol`. +// This is required to satisfy `dllimport` references to static data in .rlibs +// when using MSVC linker. We do this only for data, as linker can fix up +// code references on its own. +// See #26591, #27438 +fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) { + if !cgcx.msvc_imps_needed { + return + } + // The x86 ABI seems to require that leading underscores are added to symbol + // names, so we need an extra underscore on 32-bit. There's also a leading + // '\x01' here which disables LLVM's symbol mangling (e.g. no extra + // underscores added in front). + let prefix = if cgcx.target_pointer_width == "32" { + "\x01__imp__" + } else { + "\x01__imp_" + }; + unsafe { + let i8p_ty = Type::i8p_llcx(llcx); + let globals = base::iter_globals(llmod) + .filter(|&val| { + llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage && + llvm::LLVMIsDeclaration(val) == 0 + }) + .map(move |val| { + let name = CStr::from_ptr(llvm::LLVMGetValueName(val)); + let mut imp_name = prefix.as_bytes().to_vec(); + imp_name.extend(name.to_bytes()); + let imp_name = CString::new(imp_name).unwrap(); + (imp_name, val) + }) + .collect::>(); + for (imp_name, val) in globals { + let imp = llvm::LLVMAddGlobal(llmod, + i8p_ty.to_ref(), + imp_name.as_ptr() as *const _); + llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty)); + llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); + } + } +} diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 6b53b5b6411..7bc33a88956 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -78,7 +78,7 @@ use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet, DefIdSet}; use CrateInfo; use std::any::Any; -use std::ffi::{CStr, CString}; +use std::ffi::CString; use std::str; use std::sync::Arc; use std::time::{Instant, Duration}; @@ -812,47 +812,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, return (metadata_llcx, metadata_llmod, metadata, hashes); } -// Create a `__imp_ = &symbol` global for every public static `symbol`. -// This is required to satisfy `dllimport` references to static data in .rlibs -// when using MSVC linker. We do this only for data, as linker can fix up -// code references on its own. -// See #26591, #27438 -fn create_imps(sess: &Session, - llvm_module: &ModuleLlvm) { - // The x86 ABI seems to require that leading underscores are added to symbol - // names, so we need an extra underscore on 32-bit. There's also a leading - // '\x01' here which disables LLVM's symbol mangling (e.g. no extra - // underscores added in front). - let prefix = if sess.target.target.target_pointer_width == "32" { - "\x01__imp__" - } else { - "\x01__imp_" - }; - unsafe { - let exported: Vec<_> = iter_globals(llvm_module.llmod) - .filter(|&val| { - llvm::LLVMRustGetLinkage(val) == - llvm::Linkage::ExternalLinkage && - llvm::LLVMIsDeclaration(val) == 0 - }) - .collect(); - - let i8p_ty = Type::i8p_llcx(llvm_module.llcx); - for val in exported { - let name = CStr::from_ptr(llvm::LLVMGetValueName(val)); - let mut imp_name = prefix.as_bytes().to_vec(); - imp_name.extend(name.to_bytes()); - let imp_name = CString::new(imp_name).unwrap(); - let imp = llvm::LLVMAddGlobal(llvm_module.llmod, - i8p_ty.to_ref(), - imp_name.as_ptr() as *const _); - llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty)); - llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); - } - } -} - -struct ValueIter { +pub struct ValueIter { cur: ValueRef, step: unsafe extern "C" fn(ValueRef) -> ValueRef, } @@ -871,7 +831,7 @@ impl Iterator for ValueIter { } } -fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter { +pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter { unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), @@ -1437,12 +1397,6 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tm: create_target_machine(ccx.sess()), }; - // Adjust exported symbols for MSVC dllimport - if ccx.sess().target.target.options.is_like_msvc && - ccx.sess().crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) { - create_imps(ccx.sess(), &llvm_module); - } - ModuleTranslation { name: cgu_name, source: ModuleSource::Translated(llvm_module), diff --git a/src/test/run-pass/thinlto/auxiliary/msvc-imp-present.rs b/src/test/run-pass/thinlto/auxiliary/msvc-imp-present.rs new file mode 100644 index 00000000000..eff7802a245 --- /dev/null +++ b/src/test/run-pass/thinlto/auxiliary/msvc-imp-present.rs @@ -0,0 +1,21 @@ +// Copyright 2017 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. + +// no-prefer-dynamic +// compile-flags: -Z thinlto -C codegen-units=8 -C prefer-dynamic + +#![crate_type = "rlib"] +#![crate_type = "dylib"] + +pub static A: u32 = 43; + +pub mod a { + pub static A: u32 = 43; +} diff --git a/src/test/run-pass/thinlto/msvc-imp-present.rs b/src/test/run-pass/thinlto/msvc-imp-present.rs new file mode 100644 index 00000000000..8329c7032f1 --- /dev/null +++ b/src/test/run-pass/thinlto/msvc-imp-present.rs @@ -0,0 +1,31 @@ +// Copyright 2017 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. + +// aux-build:msvc-imp-present.rs +// compile-flags: -Z thinlto -C codegen-units=8 +// min-llvm-version: 4.0 +// no-prefer-dynamic + +// On MSVC we have a "hack" where we emit symbols that look like `_imp_$name` +// for all exported statics. This is done because we apply `dllimport` to all +// imported constants and this allows everything to actually link correctly. +// +// The ThinLTO passes aggressively remove symbols if they can, and this test +// asserts that the ThinLTO passes don't remove these compiler-generated +// `_imp_*` symbols. The external library that we link in here is compiled with +// ThinLTO and multiple codegen units and has a few exported constants. Note +// that we also namely compile the library as both a dylib and an rlib, but we +// link the rlib to ensure that we assert those generated symbols exist. + +extern crate msvc_imp_present as bar; + +fn main() { + println!("{}", bar::A); +} From 6309a475f912f8237cba57458bc598c2fc8fc90b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 18 Oct 2017 07:54:35 -0700 Subject: [PATCH 316/365] Remove two obsolete min-llvm-version tests --- src/test/codegen/abi-x86-interrupt.rs | 1 - src/test/run-pass/issue-36023.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/test/codegen/abi-x86-interrupt.rs b/src/test/codegen/abi-x86-interrupt.rs index 838cd4bf6d7..e0b37cb2f32 100644 --- a/src/test/codegen/abi-x86-interrupt.rs +++ b/src/test/codegen/abi-x86-interrupt.rs @@ -14,7 +14,6 @@ // ignore-arm // ignore-aarch64 -// min-llvm-version 3.8 // compile-flags: -C no-prepopulate-passes diff --git a/src/test/run-pass/issue-36023.rs b/src/test/run-pass/issue-36023.rs index 53a8a403b64..f6c03b384f2 100644 --- a/src/test/run-pass/issue-36023.rs +++ b/src/test/run-pass/issue-36023.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// min-llvm-version 3.9 - use std::ops::Deref; fn main() { From b5e2451f62391223cd9db7d025bf3a1d67713adc Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 18 Oct 2017 11:21:36 -0400 Subject: [PATCH 317/365] make `erase_regions_ty` query anonymous --- src/librustc/dep_graph/dep_node.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index f9e902b9105..6993ef3768a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -610,7 +610,14 @@ define_dep_nodes!( <'tcx> [] PostorderCnums, [] HasCloneClosures(CrateNum), [] HasCopyClosures(CrateNum), - [] EraseRegionsTy { ty: Ty<'tcx> }, + + // This query is not expected to have inputs -- as a result, it's + // not a good candidate for "replay" because it's essentially a + // pure function of its input (and hence the expectation is that + // no caller would be green **apart** from just this + // query). Making it anonymous avoids hashing the result, which + // may save a bit of time. + [anon] EraseRegionsTy { ty: Ty<'tcx> }, [] Freevars(DefId), [] MaybeUnusedTraitImport(DefId), From 55c01736cbabc8e4541b814ae8149173b8028651 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 18 Oct 2017 11:43:17 -0700 Subject: [PATCH 318/365] std: Update randomness implementation on Windows This commit updates the OS random number generator on Windows to match the upstream implementation in the `rand` crate. First proposed in rust-lang-nursery/rand#111 this implementation uses a "private" API of `RtlGenRandom`. Despite the [documentation][dox] indicating this is a private function its widespread use in Chromium and Firefox as well as [comments] from Microsoft internally indicates that it's highly unlikely to break. Another motivation for switching this is to also attempt to make progress on #44911. It may be the case that this function succeeds while the previous implementation may fail in "weird" scenarios. [dox]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx [comments]: https://github.com/rust-lang-nursery/rand/issues/111#issuecomment-316140155 --- src/libstd/sys/windows/c.rs | 18 +++------------- src/libstd/sys/windows/rand.rs | 38 +++++++--------------------------- 2 files changed, 10 insertions(+), 46 deletions(-) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 762e39809cc..39e00270233 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -37,7 +37,6 @@ pub type BOOL = c_int; pub type BYTE = u8; pub type BOOLEAN = BYTE; pub type GROUP = c_uint; -pub type LONG_PTR = isize; pub type LARGE_INTEGER = c_longlong; pub type LONG = c_long; pub type UINT = c_uint; @@ -46,7 +45,6 @@ pub type USHORT = c_ushort; pub type SIZE_T = usize; pub type WORD = u16; pub type CHAR = c_char; -pub type HCRYPTPROV = LONG_PTR; pub type ULONG_PTR = usize; pub type ULONG = c_ulong; #[cfg(target_arch = "x86_64")] @@ -288,10 +286,6 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c; #[cfg(feature = "backtrace")] pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664; -pub const PROV_RSA_FULL: DWORD = 1; -pub const CRYPT_SILENT: DWORD = 64; -pub const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000; - pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0; pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; @@ -1136,15 +1130,6 @@ extern "system" { pub fn GetProcAddress(handle: HMODULE, name: LPCSTR) -> *mut c_void; pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; - pub fn CryptAcquireContextA(phProv: *mut HCRYPTPROV, - pszContainer: LPCSTR, - pszProvider: LPCSTR, - dwProvType: DWORD, - dwFlags: DWORD) -> BOOL; - pub fn CryptGenRandom(hProv: HCRYPTPROV, - dwLen: DWORD, - pbBuffer: *mut BYTE) -> BOOL; - pub fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL; pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); @@ -1175,6 +1160,9 @@ extern "system" { writefds: *mut fd_set, exceptfds: *mut fd_set, timeout: *const timeval) -> c_int; + + #[link_name = "SystemFunction036"] + pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; } // Functions that aren't available on every version of Windows that we support, diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs index 10e3d45f9d5..f66b0a3bdc3 100644 --- a/src/libstd/sys/windows/rand.rs +++ b/src/libstd/sys/windows/rand.rs @@ -14,25 +14,12 @@ use mem; use rand::Rng; use sys::c; -pub struct OsRng { - hcryptprov: c::HCRYPTPROV -} +pub struct OsRng; impl OsRng { /// Create a new `OsRng`. pub fn new() -> io::Result { - let mut hcp = 0; - let ret = unsafe { - c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR, - c::PROV_RSA_FULL, - c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT) - }; - - if ret == 0 { - Err(io::Error::last_os_error()) - } else { - Ok(OsRng { hcryptprov: hcp }) - } + Ok(OsRng) } } @@ -42,18 +29,19 @@ impl Rng for OsRng { self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } + fn next_u64(&mut self) -> u64 { let mut v = [0; 8]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } + fn fill_bytes(&mut self, v: &mut [u8]) { - // CryptGenRandom takes a DWORD (u32) for the length so we need to + // RtlGenRandom takes an ULONG (u32) for the length so we need to // split up the buffer. - for slice in v.chunks_mut(::max_value() as usize) { + for slice in v.chunks_mut(::max_value() as usize) { let ret = unsafe { - c::CryptGenRandom(self.hcryptprov, slice.len() as c::DWORD, - slice.as_mut_ptr()) + c::RtlGenRandom(slice.as_mut_ptr(), slice.len() as c::ULONG) }; if ret == 0 { panic!("couldn't generate random bytes: {}", @@ -62,15 +50,3 @@ impl Rng for OsRng { } } } - -impl Drop for OsRng { - fn drop(&mut self) { - let ret = unsafe { - c::CryptReleaseContext(self.hcryptprov, 0) - }; - if ret == 0 { - panic!("couldn't release context: {}", - io::Error::last_os_error()); - } - } -} From 0d6923d1b58ca325daf97cc9617651e812b14c54 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 19 Oct 2017 06:00:15 +0900 Subject: [PATCH 319/365] Remove --enable-rustbuild config option from example --- 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 6eb074605fc..7c257682e4a 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -129,7 +129,7 @@ configure your directory to use this build, like so: # configure to use local rust instead of downloading a beta. # `--local-rust-root` is optional here. If elided, we will # use whatever rustc we find on your PATH. -> configure --enable-rustbuild --local-rust-root=~/.cargo/ --enable-local-rebuild +> configure --local-rust-root=~/.cargo/ --enable-local-rebuild ``` After that, you can use the `--incremental` flag to actually do From e11abd15419b513500da07cf22e2b36ceb9b35a1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 19 Oct 2017 06:02:13 +0900 Subject: [PATCH 320/365] Fix typos --- src/bootstrap/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 7c257682e4a..9ff681ac680 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -129,14 +129,14 @@ configure your directory to use this build, like so: # configure to use local rust instead of downloading a beta. # `--local-rust-root` is optional here. If elided, we will # use whatever rustc we find on your PATH. -> configure --local-rust-root=~/.cargo/ --enable-local-rebuild +> ./configure --local-rust-root=~/.cargo/ --enable-local-rebuild ``` After that, you can use the `--incremental` flag to actually do incremental builds: ``` -> ../x.py build --incremental +> ./x.py build --incremental ``` The `--incremental` flag will store incremental compilation artifacts From 0dde8cdd40437f26bccfcbbf73a0dfa720702d2f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 19 Oct 2017 06:22:32 +0900 Subject: [PATCH 321/365] Allow passing a path with tilde --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c441dc9acb8..0ab4c79e3b2 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -532,7 +532,7 @@ class RustBuild(object): """ config = self.get_toml(program) if config: - return config + return os.path.expanduser(config) return os.path.join(self.bin_root(), "bin", "{}{}".format( program, self.exe_suffix())) From 0fcd3e7b07e0f50a75f50b2e7dc935ae06fc5abd Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Mon, 16 Oct 2017 11:40:47 -0600 Subject: [PATCH 322/365] Make sure to clear out the stageN-{rustc,std,tools} directories. We copy built tool binaries into a dedicated directory to avoid deleting them, stageN-tools-bin. These aren't ever cleared out by code, since there should be no reason to do so, and we'll simply overwrite them as necessary. When clearing out the stageN-{std,rustc,tools} directories, make sure to delete both Cargo directories -- per-target and build scripts. This ensures that changing libstd doesn't cause problems due to build scripts not being rebuilt, even though they should be. --- src/bootstrap/builder.rs | 2 +- src/bootstrap/compile.rs | 23 ++++++++------------- src/bootstrap/lib.rs | 13 ++++++++++-- src/bootstrap/tool.rs | 44 +++++++++++++++++++++++++++++----------- src/bootstrap/util.rs | 21 +++++++++++++++++-- 5 files changed, 72 insertions(+), 31 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6480b5a619c..dee4999879c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -612,7 +612,7 @@ impl<'a> Builder<'a> { // Set this for all builds to make sure doc builds also get it. cargo.env("CFG_RELEASE_CHANNEL", &self.build.config.channel); - if self.is_verbose() { + if self.is_very_verbose() { cargo.arg("-v"); } // FIXME: cargo bench does not accept `--release` diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b1c630a8de9..f837371bebe 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -29,7 +29,7 @@ use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use serde_json; -use util::{exe, libdir, is_dylib, copy}; +use util::{exe, libdir, is_dylib, copy, read_stamp_file}; use {Build, Compiler, Mode}; use native; use tool; @@ -102,7 +102,7 @@ impl Step for Std { copy_musl_third_party_objects(build, target, &libdir); } - let out_dir = build.cargo_out(compiler, Mode::Libstd, target); + let out_dir = build.stage_out(compiler, Mode::Libstd); build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build"); std_cargo(build, &compiler, target, &mut cargo); @@ -354,7 +354,7 @@ impl Step for Test { let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); println!("Building stage{} test artifacts ({} -> {})", compiler.stage, &compiler.host, target); - let out_dir = build.cargo_out(compiler, Mode::Libtest, target); + let out_dir = build.stage_out(compiler, Mode::Libtest); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build"); test_cargo(build, &compiler, target, &mut cargo); @@ -480,8 +480,9 @@ impl Step for Rustc { println!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, &compiler.host, target); - let out_dir = build.cargo_out(compiler, Mode::Librustc, target); - build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target)); + let stage_out = builder.stage_out(compiler, Mode::Librustc); + build.clear_if_dirty(&stage_out, &libstd_stamp(build, compiler, target)); + build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build"); rustc_cargo(build, &compiler, target, &mut cargo); @@ -757,15 +758,7 @@ impl Step for Assemble { /// `sysroot_dst` provided. fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) { t!(fs::create_dir_all(&sysroot_dst)); - let mut contents = Vec::new(); - t!(t!(File::open(stamp)).read_to_end(&mut contents)); - // This is the method we use for extracting paths from the stamp file passed to us. See - // run_cargo for more information (in this file). - for part in contents.split(|b| *b == 0) { - if part.is_empty() { - continue - } - let path = Path::new(t!(str::from_utf8(part))); + for path in read_stamp_file(stamp) { copy(&path, &sysroot_dst.join(path.file_name().unwrap())); } } @@ -938,6 +931,8 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { let max = max.unwrap(); let max_path = max_path.unwrap(); if stamp_contents == new_contents && max <= stamp_mtime { + build.verbose(&format!("not updating {:?}; contents equal and {} <= {}", + stamp, max, stamp_mtime)); return } if max > stamp_mtime { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 6ac919d3fbd..479283b3595 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -385,16 +385,19 @@ impl Build { /// Clear out `dir` if `input` is newer. /// /// After this executes, it will also ensure that `dir` exists. - fn clear_if_dirty(&self, dir: &Path, input: &Path) { + fn clear_if_dirty(&self, dir: &Path, input: &Path) -> bool { let stamp = dir.join(".stamp"); + let mut cleared = false; if mtime(&stamp) < mtime(input) { self.verbose(&format!("Dirty - {}", dir.display())); let _ = fs::remove_dir_all(dir); + cleared = true; } else if stamp.exists() { - return + return cleared; } t!(fs::create_dir_all(dir)); t!(File::create(stamp)); + cleared } /// Get the space-separated set of activated features for the standard @@ -435,6 +438,12 @@ impl Build { if self.config.rust_optimize {"release"} else {"debug"} } + fn tools_dir(&self, compiler: Compiler) -> PathBuf { + let out = self.out.join(&*compiler.host).join(format!("stage{}-tools-bin", compiler.stage)); + t!(fs::create_dir_all(&out)); + out + } + /// Get the directory for incremental by-products when using the /// given compiler. fn incremental_dir(&self, compiler: Compiler) -> PathBuf { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 662c56d728d..bdbef3a943b 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -38,24 +38,40 @@ impl Step for CleanTools { run.never() } - /// Build a tool in `src/tools` - /// - /// This will build the specified tool with the specified `host` compiler in - /// `stage` into the normal cargo output directory. fn run(self, builder: &Builder) { let build = builder.build; let compiler = self.compiler; let target = self.target; let mode = self.mode; - let stamp = match mode { - Mode::Libstd => libstd_stamp(build, compiler, target), - Mode::Libtest => libtest_stamp(build, compiler, target), - Mode::Librustc => librustc_stamp(build, compiler, target), - _ => panic!(), + // This is for the original compiler, but if we're forced to use stage 1, then + // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since + // we copy the libs forward. + let tools_dir = build.stage_out(compiler, Mode::Tool); + let compiler = if builder.force_use_stage1(compiler, target) { + builder.compiler(1, compiler.host) + } else { + compiler }; - let out_dir = build.cargo_out(compiler, Mode::Tool, target); - build.clear_if_dirty(&out_dir, &stamp); + + for &cur_mode in &[Mode::Libstd, Mode::Libtest, Mode::Librustc] { + let stamp = match cur_mode { + Mode::Libstd => libstd_stamp(build, compiler, target), + Mode::Libtest => libtest_stamp(build, compiler, target), + Mode::Librustc => librustc_stamp(build, compiler, target), + _ => panic!(), + }; + + if build.clear_if_dirty(&tools_dir, &stamp) { + break; + } + + // If we are a rustc tool, and std changed, we also need to clear ourselves out -- our + // dependencies depend on std. Therefore, we iterate up until our own mode. + if mode == cur_mode { + break; + } + } } } @@ -100,7 +116,11 @@ impl Step for ToolBuild { let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path); build.run_expecting(&mut cargo, expectation); - build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host)) + let cargo_out = build.cargo_out(compiler, Mode::Tool, target) + .join(exe(tool, &compiler.host)); + let bin = build.tools_dir(compiler).join(exe(tool, &compiler.host)); + copy(&cargo_out, &bin); + bin } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index a521dd09453..2506048858f 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -14,8 +14,9 @@ //! not a lot of interesting happenings here unfortunately. use std::env; -use std::fs; -use std::io::{self, Write}; +use std::str; +use std::fs::{self, File}; +use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::process::Command; use std::time::{SystemTime, Instant}; @@ -50,6 +51,22 @@ pub fn copy(src: &Path, dst: &Path) { t!(filetime::set_file_times(dst, atime, mtime)); } +pub fn read_stamp_file(stamp: &Path) -> Vec { + let mut paths = Vec::new(); + let mut contents = Vec::new(); + t!(t!(File::open(stamp)).read_to_end(&mut contents)); + // This is the method we use for extracting paths from the stamp file passed to us. See + // run_cargo for more information (in compile.rs). + for part in contents.split(|b| *b == 0) { + if part.is_empty() { + continue + } + let path = PathBuf::from(t!(str::from_utf8(part))); + paths.push(path); + } + paths +} + /// Copies the `src` directory recursively to `dst`. Both are assumed to exist /// when this function is called. pub fn cp_r(src: &Path, dst: &Path) { From 547743ec6adec83c1f8386d9eb2b692dabac4868 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 19 Oct 2017 08:49:07 +0900 Subject: [PATCH 323/365] Fix typos in src/librustc/README.md --- src/librustc/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/README.md b/src/librustc/README.md index 3ac2949b83e..ddf71a06d60 100644 --- a/src/librustc/README.md +++ b/src/librustc/README.md @@ -98,7 +98,7 @@ entire program, and each did a particular check of transformation. We are gradually replacing this pass-based code with an alternative setup based on on-demand **queries**. In the query-model, we work backwards, executing a *query* that expresses our ultimate goal (e.g., -"compiler this crate"). This query in turn may make other queries +"compile this crate"). This query in turn may make other queries (e.g., "get me a list of all modules in the crate"). Those queries make other queries that ultimately bottom out in the base operations, like parsing the input, running the type-checker, and so forth. This @@ -162,7 +162,7 @@ The compiler uses a number of...idiosyncratic abbreviations and things. This glossary attempts to list them and give you a few pointers for understanding them better. -- AST -- the **abstract syntax tree** produced the `syntax` crate; reflects user syntax +- AST -- the **abstract syntax tree** produced by the `syntax` crate; reflects user syntax very closely. - codegen unit -- when we produce LLVM IR, we group the Rust code into a number of codegen units. Each of these units is processed by LLVM independently from one another, From 622d20a85ab234a24ab74ea4afcb4014909754af Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 19 Oct 2017 13:29:12 +0900 Subject: [PATCH 324/365] Fix typos in librustc/ty/README.md --- src/librustc/ty/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/README.md b/src/librustc/ty/README.md index 4f63912a1e0..3fd956ecfb8 100644 --- a/src/librustc/ty/README.md +++ b/src/librustc/ty/README.md @@ -42,7 +42,7 @@ wasteful. Often, we wish to write code that explicitly asserts that it is not taking place during inference. In that case, there is no "local" arena, and all the types that you can access are allocated in the -global arena. To express this, the idea is to us the same lifetime +global arena. To express this, the idea is to use the same lifetime for the `'gcx` and `'tcx` parameters of `TyCtxt`. Just to be a touch confusing, we tend to use the name `'tcx` in such contexts. Here is an example: @@ -100,10 +100,10 @@ fn test_type<'tcx>(ty: Ty<'tcx>) { The `sty` field (the origin of this name is unclear to me; perhaps structural type?) is of type `TypeVariants<'tcx>`, which is an enum -definined all of the different kinds of types in the compiler. +defining all of the different kinds of types in the compiler. > NB: inspecting the `sty` field on types during type inference can be -> risky, as there are may be inference variables and other things to +> risky, as there may be inference variables and other things to > consider, or sometimes types are not yet known that will become > known later.). @@ -132,7 +132,7 @@ a safe approximation, so that is what you get back. > you are going to be testing for type equality, you probably need to > start looking into the inference code to do it right. -You can also find various common types in the tcx itself by accessing +You can also find various common types in the `tcx` itself by accessing `tcx.types.bool`, `tcx.types.char`, etc (see `CommonTypes` for more). ### Beyond types: Other kinds of arena-allocated data structures @@ -143,7 +143,7 @@ module. Here are a few examples: - `Substs`, allocated with `mk_substs` -- this will intern a slice of types, often used to specify the values to be substituted for generics (e.g., `HashMap` - would be represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`. + would be represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). - `TraitRef`, typically passed by value -- a **trait reference** consists of a reference to a trait along with its various type parameters (including `Self`), like `i32: Display` (here, the def-id From 3efa00365fc13f3145b143ee41b90fb5405b334f Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Tue, 17 Oct 2017 14:41:56 +0900 Subject: [PATCH 325/365] Update ThinLTO (internalization) for LLVM 5 Ref: https://github.com/llvm-mirror/llvm/commit/ccb80b9c0f60f33780e5e29bf66a87bb56968b99 --- src/rustllvm/PassWrapper.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index c7d966fcdfd..b397ad1e98f 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -902,7 +902,7 @@ addPreservedGUID(const ModuleSummaryIndex &Index, GlobalValueSummary *GVSummary = Summary.get(); if (isa(GVSummary)) { - FunctionSummary *FS = cast(GVSummary); + auto *FS = cast(GVSummary); for (auto &Call: FS->calls()) { addPreservedGUID(Index, Preserved, Call.first.getGUID()); } @@ -910,6 +910,11 @@ addPreservedGUID(const ModuleSummaryIndex &Index, addPreservedGUID(Index, Preserved, GUID); } } + if (isa(GVSummary)) { + auto *AS = cast(GVSummary); + auto GUID = AS->getAliasee().getOriginalName(); + addPreservedGUID(Index, Preserved, GUID); + } } #else auto SummaryList = Index.findGlobalValueSummaryList(GUID); @@ -997,6 +1002,15 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // combined index // // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` +#if LLVM_VERSION_GE(5, 0) + computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols); + ComputeCrossModuleImport( + Ret->Index, + Ret->ModuleToDefinedGVSummaries, + Ret->ImportLists, + Ret->ExportLists + ); +#else auto DeadSymbols = computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols); ComputeCrossModuleImport( Ret->Index, @@ -1005,6 +1019,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, Ret->ExportLists, &DeadSymbols ); +#endif // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it // impacts the caching. From 906523efea60f4d58d6ce58bc61589d4ff3d7b4e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 19 Oct 2017 11:01:31 +0200 Subject: [PATCH 326/365] Move collector to rustc_trans_utils --- src/Cargo.lock | 1 + src/librustc_trans/back/symbol_names.rs | 2 +- src/librustc_trans/base.rs | 30 +- src/librustc_trans/common.rs | 17 - src/librustc_trans/lib.rs | 5 +- src/librustc_trans/partitioning.rs | 2 +- src/librustc_trans/trans_item.rs | 417 +--------------- src/librustc_trans_utils/Cargo.toml | 1 + .../collector.rs | 3 +- src/librustc_trans_utils/common.rs | 78 +++ src/librustc_trans_utils/lib.rs | 5 + .../monomorphize.rs | 0 src/librustc_trans_utils/trans_item.rs | 464 ++++++++++++++++++ 13 files changed, 565 insertions(+), 460 deletions(-) rename src/{librustc_trans => librustc_trans_utils}/collector.rs (99%) create mode 100644 src/librustc_trans_utils/common.rs rename src/{librustc_trans => librustc_trans_utils}/monomorphize.rs (100%) create mode 100644 src/librustc_trans_utils/trans_item.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 328ce353e2a..0989c430df0 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1787,6 +1787,7 @@ dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", + "rustc_data_structures 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 66a27f1c4a9..0ebfe4daad1 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -98,7 +98,7 @@ //! DefPaths which are much more robust in the face of changes to the code base. use monomorphize::Instance; -use trans_item::{TransItemExt, InstantiationMode}; +use trans_item::{BaseTransItemExt, InstantiationMode}; use rustc::middle::weak_lang_items; use rustc::middle::trans::TransItem; diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 6b53b5b6411..5a3adde8d1d 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -70,7 +70,7 @@ use monomorphize::{self, Instance}; use partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt}; use symbol_names_test; use time_graph; -use trans_item::{TransItem, TransItemExt, DefPathBasedNames}; +use trans_item::{TransItem, BaseTransItemExt, TransItemExt, DefPathBasedNames}; use type_::Type; use type_of; use value::Value; @@ -93,6 +93,7 @@ use syntax::ast; use mir::lvalue::Alignment; pub use rustc_trans_utils::{find_exported_symbols, check_for_rustc_errors_attr}; +pub use rustc_trans_utils::trans_item::linkage_by_name; pub struct StatRecorder<'a, 'tcx: 'a> { ccx: &'a CrateContext<'a, 'tcx>, @@ -618,33 +619,6 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance mir::trans_mir(ccx, lldecl, &mir, instance, sig); } -pub fn linkage_by_name(name: &str) -> Option { - use rustc::middle::trans::Linkage::*; - - // Use the names from src/llvm/docs/LangRef.rst here. Most types are only - // applicable to variable declarations and may not really make sense for - // Rust code in the first place but whitelist them anyway and trust that - // the user knows what s/he's doing. Who knows, unanticipated use cases - // may pop up in the future. - // - // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported - // and don't have to be, LLVM treats them as no-ops. - match name { - "appending" => Some(Appending), - "available_externally" => Some(AvailableExternally), - "common" => Some(Common), - "extern_weak" => Some(ExternalWeak), - "external" => Some(External), - "internal" => Some(Internal), - "linkonce" => Some(LinkOnceAny), - "linkonce_odr" => Some(LinkOnceODR), - "private" => Some(Private), - "weak" => Some(WeakAny), - "weak_odr" => Some(WeakODR), - _ => None, - } -} - pub fn set_link_section(ccx: &CrateContext, llval: ValueRef, attrs: &[ast::Attribute]) { diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 52607904f73..e3856cabcf9 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -36,7 +36,6 @@ use libc::{c_uint, c_char}; use std::iter; use syntax::abi::Abi; -use syntax::attr; use syntax::symbol::InternedString; use syntax_pos::{Span, DUMMY_SP}; @@ -552,22 +551,6 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -pub fn requests_inline<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - instance: &ty::Instance<'tcx> -) -> bool { - if is_inline_instance(tcx, instance) { - return true - } - if let ty::InstanceDef::DropGlue(..) = instance.def { - // Drop glue wants to be instantiated at every translation - // unit, but without an #[inline] hint. We should make this - // available to normal end-users. - return true - } - attr::requests_inline(&instance.def.attrs(tcx)[..]) -} - pub fn is_inline_instance<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &ty::Instance<'tcx> diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 2b1c62c7f1c..88ec3a65d35 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -83,6 +83,9 @@ use rustc::ty::maps::Providers; use rustc::ty::{self, TyCtxt}; use rustc::util::nodemap::{FxHashSet, FxHashMap}; +use rustc_trans_utils::collector; +use rustc_trans_utils::monomorphize; + mod diagnostics; pub mod back { @@ -124,7 +127,6 @@ mod cabi_x86; mod cabi_x86_64; mod cabi_x86_win64; mod callee; -mod collector; mod common; mod consts; mod context; @@ -137,7 +139,6 @@ mod machine; mod metadata; mod meth; mod mir; -mod monomorphize; mod partitioning; mod symbol_names_test; mod time_graph; diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 386806e4c9c..6980ba8a525 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -114,7 +114,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry; use syntax::ast::NodeId; use syntax::symbol::{Symbol, InternedString}; -use trans_item::{TransItem, TransItemExt, InstantiationMode}; +use trans_item::{TransItem, BaseTransItemExt, TransItemExt, InstantiationMode}; pub use rustc::middle::trans::CodegenUnit; diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 060f02ee23e..db1af8cdefb 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -24,50 +24,21 @@ use declare; use llvm; use monomorphize::Instance; use rustc::hir; -use rustc::hir::def_id::DefId; use rustc::middle::trans::{Linkage, Visibility}; -use rustc::session::config::OptLevel; -use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::subst::{Subst, Substs}; +use rustc::ty::{self, TyCtxt, TypeFoldable}; use syntax::ast; -use syntax::attr::{self, InlineAttr}; +use syntax::attr; use syntax_pos::Span; use syntax_pos::symbol::Symbol; use type_of; -use std::fmt::{self, Write}; -use std::iter; +use std::fmt; pub use rustc::middle::trans::TransItem; -/// Describes how a translation item will be instantiated in object files. -#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] -pub enum InstantiationMode { - /// There will be exactly one instance of the given TransItem. It will have - /// external linkage so that it can be linked to from other codegen units. - GloballyShared { - /// In some compilation scenarios we may decide to take functions that - /// are typically `LocalCopy` and instead move them to `GloballyShared` - /// to avoid translating them a bunch of times. In this situation, - /// however, our local copy may conflict with other crates also - /// inlining the same function. - /// - /// This flag indicates that this situation is occuring, and informs - /// symbol name calculation that some extra mangling is needed to - /// avoid conflicts. Note that this may eventually go away entirely if - /// ThinLTO enables us to *always* have a globally shared instance of a - /// function within one crate's compilation. - may_conflict: bool, - }, - - /// Each codegen unit containing a reference to the given TransItem will - /// have its own private copy of the function (with internal linkage). - LocalCopy, -} - -pub trait TransItemExt<'a, 'tcx>: fmt::Debug { - fn as_trans_item(&self) -> &TransItem<'tcx>; +pub use rustc_trans_utils::trans_item::*; +pub use rustc_trans_utils::trans_item::TransItemExt as BaseTransItemExt; +pub trait TransItemExt<'a, 'tcx>: fmt::Debug + BaseTransItemExt<'a, 'tcx> { fn define(&self, ccx: &CrateContext<'a, 'tcx>) { debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}", self.to_string(ccx.tcx()), @@ -165,53 +136,6 @@ pub trait TransItemExt<'a, 'tcx>: fmt::Debug { }.map(|node_id| tcx.hir.span(node_id)) } - fn instantiation_mode(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> InstantiationMode { - let inline_in_all_cgus = - tcx.sess.opts.debugging_opts.inline_in_all_cgus.unwrap_or_else(|| { - tcx.sess.opts.optimize != OptLevel::No - }); - - match *self.as_trans_item() { - TransItem::Fn(ref instance) => { - // If this function isn't inlined or otherwise has explicit - // linkage, then we'll be creating a globally shared version. - if self.explicit_linkage(tcx).is_some() || - !common::requests_inline(tcx, instance) - { - return InstantiationMode::GloballyShared { may_conflict: false } - } - - // At this point we don't have explicit linkage and we're an - // inlined function. If we're inlining into all CGUs then we'll - // be creating a local copy per CGU - if inline_in_all_cgus { - return InstantiationMode::LocalCopy - } - - // Finally, if this is `#[inline(always)]` we're sure to respect - // that with an inline copy per CGU, but otherwise we'll be - // creating one copy of this `#[inline]` function which may - // conflict with upstream crates as it could be an exported - // symbol. - let attrs = instance.def.attrs(tcx); - match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) { - InlineAttr::Always => InstantiationMode::LocalCopy, - _ => { - InstantiationMode::GloballyShared { may_conflict: true } - } - } - } - TransItem::Static(..) => { - InstantiationMode::GloballyShared { may_conflict: false } - } - TransItem::GlobalAsm(..) => { - InstantiationMode::GloballyShared { may_conflict: false } - } - } - } - fn is_generic_fn(&self) -> bool { match *self.as_trans_item() { TransItem::Fn(ref instance) => { @@ -222,97 +146,6 @@ pub trait TransItemExt<'a, 'tcx>: fmt::Debug { } } - fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { - let def_id = match *self.as_trans_item() { - TransItem::Fn(ref instance) => instance.def_id(), - TransItem::Static(node_id) => tcx.hir.local_def_id(node_id), - TransItem::GlobalAsm(..) => return None, - }; - - let attributes = tcx.get_attrs(def_id); - if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") { - if let Some(linkage) = base::linkage_by_name(&name.as_str()) { - Some(linkage) - } else { - let span = tcx.hir.span_if_local(def_id); - if let Some(span) = span { - tcx.sess.span_fatal(span, "invalid linkage specified") - } else { - tcx.sess.fatal(&format!("invalid linkage specified: {}", name)) - } - } - } else { - None - } - } - - /// Returns whether this instance is instantiable - whether it has no unsatisfied - /// predicates. - /// - /// In order to translate an item, all of its predicates must hold, because - /// otherwise the item does not make sense. Type-checking ensures that - /// the predicates of every item that is *used by* a valid item *do* - /// hold, so we can rely on that. - /// - /// However, we translate collector roots (reachable items) and functions - /// in vtables when they are seen, even if they are not used, and so they - /// might not be instantiable. For example, a programmer can define this - /// public function: - /// - /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { - /// <&mut () as Clone>::clone(&s); - /// } - /// - /// That function can't be translated, because the method `<&mut () as Clone>::clone` - /// does not exist. Luckily for us, that function can't ever be used, - /// because that would require for `&'a mut (): Clone` to hold, so we - /// can just not emit any code, or even a linker reference for it. - /// - /// Similarly, if a vtable method has such a signature, and therefore can't - /// be used, we can just not emit it and have a placeholder (a null pointer, - /// which will never be accessed) in its place. - fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { - debug!("is_instantiable({:?})", self); - let (def_id, substs) = match *self.as_trans_item() { - TransItem::Fn(ref instance) => (instance.def_id(), instance.substs), - TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()), - // global asm never has predicates - TransItem::GlobalAsm(..) => return true - }; - - let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs); - traits::normalize_and_test_predicates(tcx, predicates) - } - - fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { - let hir_map = &tcx.hir; - - return match *self.as_trans_item() { - TransItem::Fn(instance) => { - to_string_internal(tcx, "fn ", instance) - }, - TransItem::Static(node_id) => { - let def_id = hir_map.local_def_id(node_id); - let instance = Instance::new(def_id, tcx.intern_substs(&[])); - to_string_internal(tcx, "static ", instance) - }, - TransItem::GlobalAsm(..) => { - "global_asm".to_string() - } - }; - - fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - prefix: &str, - instance: Instance<'tcx>) - -> String { - let mut result = String::with_capacity(32); - result.push_str(prefix); - let printer = DefPathBasedNames::new(tcx, false, false); - printer.push_instance_as_string(instance, &mut result); - result - } - } - fn to_raw_string(&self) -> String { match *self.as_trans_item() { TransItem::Fn(instance) => { @@ -330,11 +163,7 @@ pub trait TransItemExt<'a, 'tcx>: fmt::Debug { } } -impl<'a, 'tcx> TransItemExt<'a, 'tcx> for TransItem<'tcx> { - fn as_trans_item(&self) -> &TransItem<'tcx> { - self - } -} +impl<'a, 'tcx> TransItemExt<'a, 'tcx> for TransItem<'tcx> {} fn predefine_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, node_id: ast::NodeId, @@ -402,235 +231,3 @@ fn predefine_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.instances().borrow_mut().insert(instance, lldecl); } -//=----------------------------------------------------------------------------- -// TransItem String Keys -//=----------------------------------------------------------------------------- - -// The code below allows for producing a unique string key for a trans item. -// These keys are used by the handwritten auto-tests, so they need to be -// predictable and human-readable. -// -// Note: A lot of this could looks very similar to what's already in the -// ppaux module. It would be good to refactor things so we only have one -// parameterizable implementation for printing types. - -/// Same as `unique_type_name()` but with the result pushed onto the given -/// `output` parameter. -pub struct DefPathBasedNames<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - omit_disambiguators: bool, - omit_local_crate_name: bool, -} - -impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - omit_disambiguators: bool, - omit_local_crate_name: bool) - -> Self { - DefPathBasedNames { - tcx, - omit_disambiguators, - omit_local_crate_name, - } - } - - pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) { - match t.sty { - ty::TyBool => output.push_str("bool"), - ty::TyChar => output.push_str("char"), - ty::TyStr => output.push_str("str"), - ty::TyNever => output.push_str("!"), - ty::TyInt(ast::IntTy::Is) => output.push_str("isize"), - ty::TyInt(ast::IntTy::I8) => output.push_str("i8"), - ty::TyInt(ast::IntTy::I16) => output.push_str("i16"), - ty::TyInt(ast::IntTy::I32) => output.push_str("i32"), - ty::TyInt(ast::IntTy::I64) => output.push_str("i64"), - ty::TyInt(ast::IntTy::I128) => output.push_str("i128"), - ty::TyUint(ast::UintTy::Us) => output.push_str("usize"), - ty::TyUint(ast::UintTy::U8) => output.push_str("u8"), - ty::TyUint(ast::UintTy::U16) => output.push_str("u16"), - ty::TyUint(ast::UintTy::U32) => output.push_str("u32"), - ty::TyUint(ast::UintTy::U64) => output.push_str("u64"), - ty::TyUint(ast::UintTy::U128) => output.push_str("u128"), - ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"), - ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"), - ty::TyAdt(adt_def, substs) => { - self.push_def_path(adt_def.did, output); - self.push_type_params(substs, iter::empty(), output); - }, - ty::TyTuple(component_types, _) => { - output.push('('); - for &component_type in component_types { - self.push_type_name(component_type, output); - output.push_str(", "); - } - if !component_types.is_empty() { - output.pop(); - output.pop(); - } - output.push(')'); - }, - ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { - output.push('*'); - match mutbl { - hir::MutImmutable => output.push_str("const "), - hir::MutMutable => output.push_str("mut "), - } - - self.push_type_name(inner_type, output); - }, - ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => { - output.push('&'); - if mutbl == hir::MutMutable { - output.push_str("mut "); - } - - self.push_type_name(inner_type, output); - }, - ty::TyArray(inner_type, len) => { - output.push('['); - self.push_type_name(inner_type, output); - write!(output, "; {}", - len.val.to_const_int().unwrap().to_u64().unwrap()).unwrap(); - output.push(']'); - }, - ty::TySlice(inner_type) => { - output.push('['); - self.push_type_name(inner_type, output); - output.push(']'); - }, - ty::TyDynamic(ref trait_data, ..) => { - if let Some(principal) = trait_data.principal() { - self.push_def_path(principal.def_id(), output); - self.push_type_params(principal.skip_binder().substs, - trait_data.projection_bounds(), - output); - } - }, - ty::TyFnDef(..) | - ty::TyFnPtr(_) => { - let sig = t.fn_sig(self.tcx); - if sig.unsafety() == hir::Unsafety::Unsafe { - output.push_str("unsafe "); - } - - let abi = sig.abi(); - if abi != ::abi::Abi::Rust { - output.push_str("extern \""); - output.push_str(abi.name()); - output.push_str("\" "); - } - - output.push_str("fn("); - - let sig = self.tcx.erase_late_bound_regions_and_normalize(&sig); - - if !sig.inputs().is_empty() { - for ¶meter_type in sig.inputs() { - self.push_type_name(parameter_type, output); - output.push_str(", "); - } - output.pop(); - output.pop(); - } - - if sig.variadic { - if !sig.inputs().is_empty() { - output.push_str(", ..."); - } else { - output.push_str("..."); - } - } - - output.push(')'); - - if !sig.output().is_nil() { - output.push_str(" -> "); - self.push_type_name(sig.output(), output); - } - }, - ty::TyGenerator(def_id, ref closure_substs, _) | - ty::TyClosure(def_id, ref closure_substs) => { - self.push_def_path(def_id, output); - let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id)); - let substs = closure_substs.substs.truncate_to(self.tcx, generics); - self.push_type_params(substs, iter::empty(), output); - } - ty::TyError | - ty::TyInfer(_) | - ty::TyProjection(..) | - ty::TyParam(_) | - ty::TyAnon(..) => { - bug!("DefPathBasedNames: Trying to create type name for \ - unexpected type: {:?}", t); - } - } - } - - pub fn push_def_path(&self, - def_id: DefId, - output: &mut String) { - let def_path = self.tcx.def_path(def_id); - - // some_crate:: - if !(self.omit_local_crate_name && def_id.is_local()) { - output.push_str(&self.tcx.crate_name(def_path.krate).as_str()); - output.push_str("::"); - } - - // foo::bar::ItemName:: - for part in self.tcx.def_path(def_id).data { - if self.omit_disambiguators { - write!(output, "{}::", part.data.as_interned_str()).unwrap(); - } else { - write!(output, "{}[{}]::", - part.data.as_interned_str(), - part.disambiguator).unwrap(); - } - } - - // remove final "::" - output.pop(); - output.pop(); - } - - fn push_type_params(&self, - substs: &Substs<'tcx>, - projections: I, - output: &mut String) - where I: Iterator> - { - let mut projections = projections.peekable(); - if substs.types().next().is_none() && projections.peek().is_none() { - return; - } - - output.push('<'); - - for type_parameter in substs.types() { - self.push_type_name(type_parameter, output); - output.push_str(", "); - } - - for projection in projections { - let projection = projection.skip_binder(); - let name = &self.tcx.associated_item(projection.item_def_id).name.as_str(); - output.push_str(name); - output.push_str("="); - self.push_type_name(projection.ty, output); - output.push_str(", "); - } - - output.pop(); - output.pop(); - - output.push('>'); - } - - pub fn push_instance_as_string(&self, - instance: Instance<'tcx>, - output: &mut String) { - self.push_def_path(instance.def_id(), output); - self.push_type_params(instance.substs, iter::empty(), output); - } -} diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml index bedbea00688..7d9d7cea933 100644 --- a/src/librustc_trans_utils/Cargo.toml +++ b/src/librustc_trans_utils/Cargo.toml @@ -19,3 +19,4 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } +rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans_utils/collector.rs similarity index 99% rename from src/librustc_trans/collector.rs rename to src/librustc_trans_utils/collector.rs index 33a2e96ee66..c87d86262ef 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans_utils/collector.rs @@ -195,6 +195,7 @@ use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::middle::const_val::ConstVal; use rustc::middle::lang_items::{ExchangeMallocFnLangItem}; +use rustc::middle::trans::TransItem; use rustc::traits; use rustc::ty::subst::Substs; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt}; @@ -206,7 +207,7 @@ use common::{def_ty, instance_ty, type_is_sized}; use monomorphize::{self, Instance}; use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap}; -use trans_item::{TransItem, TransItemExt, DefPathBasedNames, InstantiationMode}; +use trans_item::{TransItemExt, DefPathBasedNames, InstantiationMode}; use rustc_data_structures::bitvec::BitVector; diff --git a/src/librustc_trans_utils/common.rs b/src/librustc_trans_utils/common.rs new file mode 100644 index 00000000000..634e37220e2 --- /dev/null +++ b/src/librustc_trans_utils/common.rs @@ -0,0 +1,78 @@ +// Copyright 2012-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. + +#![allow(non_camel_case_types, non_snake_case)] + +//! Code that is useful in various trans modules. + +use rustc::hir::def_id::DefId; +use rustc::hir::map::DefPathData; +use rustc::traits; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::Substs; + +use syntax::attr; +use syntax_pos::DUMMY_SP; + +pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool { + ty.is_sized(tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP) +} + +pub fn requests_inline<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + instance: &ty::Instance<'tcx> +) -> bool { + if is_inline_instance(tcx, instance) { + return true + } + if let ty::InstanceDef::DropGlue(..) = instance.def { + // Drop glue wants to be instantiated at every translation + // unit, but without an #[inline] hint. We should make this + // available to normal end-users. + return true + } + attr::requests_inline(&instance.def.attrs(tcx)[..]) +} + +pub fn is_inline_instance<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + instance: &ty::Instance<'tcx> +) -> bool { + let def_id = match instance.def { + ty::InstanceDef::Item(def_id) => def_id, + ty::InstanceDef::DropGlue(_, Some(_)) => return false, + _ => return true + }; + match tcx.def_key(def_id).disambiguated_data.data { + DefPathData::StructCtor | + DefPathData::EnumVariant(..) | + DefPathData::ClosureExpr => true, + _ => false + } +} + +/// Given a DefId and some Substs, produces the monomorphic item type. +pub fn def_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + substs: &'tcx Substs<'tcx>) + -> Ty<'tcx> +{ + let ty = tcx.type_of(def_id); + tcx.trans_apply_param_substs(substs, &ty) +} + +/// Return the substituted type of an instance. +pub fn instance_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + instance: &ty::Instance<'tcx>) + -> Ty<'tcx> +{ + let ty = instance.def.def_ty(tcx); + tcx.trans_apply_param_substs(instance.substs, &ty) +} diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 6873befd2bf..bc8f8d5a6da 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -38,6 +38,7 @@ extern crate log; #[macro_use] extern crate rustc; extern crate rustc_back; +extern crate rustc_data_structures; extern crate syntax; extern crate syntax_pos; @@ -49,7 +50,11 @@ use rustc::util::nodemap::NodeSet; use syntax::attr; +mod common; pub mod link; +pub mod collector; +pub mod trans_item; +pub mod monomorphize; pub mod trans_crate; /// check for the #[rustc_error] annotation, which forces an diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans_utils/monomorphize.rs similarity index 100% rename from src/librustc_trans/monomorphize.rs rename to src/librustc_trans_utils/monomorphize.rs diff --git a/src/librustc_trans_utils/trans_item.rs b/src/librustc_trans_utils/trans_item.rs new file mode 100644 index 00000000000..0ada39d7d27 --- /dev/null +++ b/src/librustc_trans_utils/trans_item.rs @@ -0,0 +1,464 @@ +// 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. + +//! Walks the crate looking for items/impl-items/trait-items that have +//! either a `rustc_symbol_name` or `rustc_item_path` attribute and +//! generates an error giving, respectively, the symbol name or +//! item-path. This is used for unit testing the code that generates +//! paths etc in all kinds of annoying scenarios. + +use common; +use monomorphize::Instance; +use rustc::hir; +use rustc::hir::def_id::DefId; +use rustc::middle::trans::Linkage; +use rustc::session::config::OptLevel; +use rustc::traits; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::{Subst, Substs}; +use syntax::ast; +use syntax::attr::{self, InlineAttr}; +use std::fmt::{self, Write}; +use std::iter; + +pub use rustc::middle::trans::TransItem; + +pub fn linkage_by_name(name: &str) -> Option { + use rustc::middle::trans::Linkage::*; + + // Use the names from src/llvm/docs/LangRef.rst here. Most types are only + // applicable to variable declarations and may not really make sense for + // Rust code in the first place but whitelist them anyway and trust that + // the user knows what s/he's doing. Who knows, unanticipated use cases + // may pop up in the future. + // + // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported + // and don't have to be, LLVM treats them as no-ops. + match name { + "appending" => Some(Appending), + "available_externally" => Some(AvailableExternally), + "common" => Some(Common), + "extern_weak" => Some(ExternalWeak), + "external" => Some(External), + "internal" => Some(Internal), + "linkonce" => Some(LinkOnceAny), + "linkonce_odr" => Some(LinkOnceODR), + "private" => Some(Private), + "weak" => Some(WeakAny), + "weak_odr" => Some(WeakODR), + _ => None, + } +} + +/// Describes how a translation item will be instantiated in object files. +#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] +pub enum InstantiationMode { + /// There will be exactly one instance of the given TransItem. It will have + /// external linkage so that it can be linked to from other codegen units. + GloballyShared { + /// In some compilation scenarios we may decide to take functions that + /// are typically `LocalCopy` and instead move them to `GloballyShared` + /// to avoid translating them a bunch of times. In this situation, + /// however, our local copy may conflict with other crates also + /// inlining the same function. + /// + /// This flag indicates that this situation is occuring, and informs + /// symbol name calculation that some extra mangling is needed to + /// avoid conflicts. Note that this may eventually go away entirely if + /// ThinLTO enables us to *always* have a globally shared instance of a + /// function within one crate's compilation. + may_conflict: bool, + }, + + /// Each codegen unit containing a reference to the given TransItem will + /// have its own private copy of the function (with internal linkage). + LocalCopy, +} + +pub trait TransItemExt<'a, 'tcx>: fmt::Debug { + fn as_trans_item(&self) -> &TransItem<'tcx>; + + fn instantiation_mode(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> InstantiationMode { + let inline_in_all_cgus = + tcx.sess.opts.debugging_opts.inline_in_all_cgus.unwrap_or_else(|| { + tcx.sess.opts.optimize != OptLevel::No + }); + + match *self.as_trans_item() { + TransItem::Fn(ref instance) => { + // If this function isn't inlined or otherwise has explicit + // linkage, then we'll be creating a globally shared version. + if self.explicit_linkage(tcx).is_some() || + !common::requests_inline(tcx, instance) + { + return InstantiationMode::GloballyShared { may_conflict: false } + } + + // At this point we don't have explicit linkage and we're an + // inlined function. If we're inlining into all CGUs then we'll + // be creating a local copy per CGU + if inline_in_all_cgus { + return InstantiationMode::LocalCopy + } + + // Finally, if this is `#[inline(always)]` we're sure to respect + // that with an inline copy per CGU, but otherwise we'll be + // creating one copy of this `#[inline]` function which may + // conflict with upstream crates as it could be an exported + // symbol. + let attrs = instance.def.attrs(tcx); + match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) { + InlineAttr::Always => InstantiationMode::LocalCopy, + _ => { + InstantiationMode::GloballyShared { may_conflict: true } + } + } + } + TransItem::Static(..) => { + InstantiationMode::GloballyShared { may_conflict: false } + } + TransItem::GlobalAsm(..) => { + InstantiationMode::GloballyShared { may_conflict: false } + } + } + } + + fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { + let def_id = match *self.as_trans_item() { + TransItem::Fn(ref instance) => instance.def_id(), + TransItem::Static(node_id) => tcx.hir.local_def_id(node_id), + TransItem::GlobalAsm(..) => return None, + }; + + let attributes = tcx.get_attrs(def_id); + if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") { + if let Some(linkage) = linkage_by_name(&name.as_str()) { + Some(linkage) + } else { + let span = tcx.hir.span_if_local(def_id); + if let Some(span) = span { + tcx.sess.span_fatal(span, "invalid linkage specified") + } else { + tcx.sess.fatal(&format!("invalid linkage specified: {}", name)) + } + } + } else { + None + } + } + + /// Returns whether this instance is instantiable - whether it has no unsatisfied + /// predicates. + /// + /// In order to translate an item, all of its predicates must hold, because + /// otherwise the item does not make sense. Type-checking ensures that + /// the predicates of every item that is *used by* a valid item *do* + /// hold, so we can rely on that. + /// + /// However, we translate collector roots (reachable items) and functions + /// in vtables when they are seen, even if they are not used, and so they + /// might not be instantiable. For example, a programmer can define this + /// public function: + /// + /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + /// <&mut () as Clone>::clone(&s); + /// } + /// + /// That function can't be translated, because the method `<&mut () as Clone>::clone` + /// does not exist. Luckily for us, that function can't ever be used, + /// because that would require for `&'a mut (): Clone` to hold, so we + /// can just not emit any code, or even a linker reference for it. + /// + /// Similarly, if a vtable method has such a signature, and therefore can't + /// be used, we can just not emit it and have a placeholder (a null pointer, + /// which will never be accessed) in its place. + fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { + debug!("is_instantiable({:?})", self); + let (def_id, substs) = match *self.as_trans_item() { + TransItem::Fn(ref instance) => (instance.def_id(), instance.substs), + TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()), + // global asm never has predicates + TransItem::GlobalAsm(..) => return true + }; + + let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs); + traits::normalize_and_test_predicates(tcx, predicates) + } + + fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String { + let hir_map = &tcx.hir; + + return match *self.as_trans_item() { + TransItem::Fn(instance) => { + to_string_internal(tcx, "fn ", instance) + }, + TransItem::Static(node_id) => { + let def_id = hir_map.local_def_id(node_id); + let instance = Instance::new(def_id, tcx.intern_substs(&[])); + to_string_internal(tcx, "static ", instance) + }, + TransItem::GlobalAsm(..) => { + "global_asm".to_string() + } + }; + + fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + prefix: &str, + instance: Instance<'tcx>) + -> String { + let mut result = String::with_capacity(32); + result.push_str(prefix); + let printer = DefPathBasedNames::new(tcx, false, false); + printer.push_instance_as_string(instance, &mut result); + result + } + } +} + +impl<'a, 'tcx> TransItemExt<'a, 'tcx> for TransItem<'tcx> { + fn as_trans_item(&self) -> &TransItem<'tcx> { + self + } +} + +//=----------------------------------------------------------------------------- +// TransItem String Keys +//=----------------------------------------------------------------------------- + +// The code below allows for producing a unique string key for a trans item. +// These keys are used by the handwritten auto-tests, so they need to be +// predictable and human-readable. +// +// Note: A lot of this could looks very similar to what's already in the +// ppaux module. It would be good to refactor things so we only have one +// parameterizable implementation for printing types. + +/// Same as `unique_type_name()` but with the result pushed onto the given +/// `output` parameter. +pub struct DefPathBasedNames<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + omit_disambiguators: bool, + omit_local_crate_name: bool, +} + +impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + omit_disambiguators: bool, + omit_local_crate_name: bool) + -> Self { + DefPathBasedNames { + tcx, + omit_disambiguators, + omit_local_crate_name, + } + } + + pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) { + match t.sty { + ty::TyBool => output.push_str("bool"), + ty::TyChar => output.push_str("char"), + ty::TyStr => output.push_str("str"), + ty::TyNever => output.push_str("!"), + ty::TyInt(ast::IntTy::Is) => output.push_str("isize"), + ty::TyInt(ast::IntTy::I8) => output.push_str("i8"), + ty::TyInt(ast::IntTy::I16) => output.push_str("i16"), + ty::TyInt(ast::IntTy::I32) => output.push_str("i32"), + ty::TyInt(ast::IntTy::I64) => output.push_str("i64"), + ty::TyInt(ast::IntTy::I128) => output.push_str("i128"), + ty::TyUint(ast::UintTy::Us) => output.push_str("usize"), + ty::TyUint(ast::UintTy::U8) => output.push_str("u8"), + ty::TyUint(ast::UintTy::U16) => output.push_str("u16"), + ty::TyUint(ast::UintTy::U32) => output.push_str("u32"), + ty::TyUint(ast::UintTy::U64) => output.push_str("u64"), + ty::TyUint(ast::UintTy::U128) => output.push_str("u128"), + ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"), + ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"), + ty::TyAdt(adt_def, substs) => { + self.push_def_path(adt_def.did, output); + self.push_type_params(substs, iter::empty(), output); + }, + ty::TyTuple(component_types, _) => { + output.push('('); + for &component_type in component_types { + self.push_type_name(component_type, output); + output.push_str(", "); + } + if !component_types.is_empty() { + output.pop(); + output.pop(); + } + output.push(')'); + }, + ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { + output.push('*'); + match mutbl { + hir::MutImmutable => output.push_str("const "), + hir::MutMutable => output.push_str("mut "), + } + + self.push_type_name(inner_type, output); + }, + ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => { + output.push('&'); + if mutbl == hir::MutMutable { + output.push_str("mut "); + } + + self.push_type_name(inner_type, output); + }, + ty::TyArray(inner_type, len) => { + output.push('['); + self.push_type_name(inner_type, output); + write!(output, "; {}", + len.val.to_const_int().unwrap().to_u64().unwrap()).unwrap(); + output.push(']'); + }, + ty::TySlice(inner_type) => { + output.push('['); + self.push_type_name(inner_type, output); + output.push(']'); + }, + ty::TyDynamic(ref trait_data, ..) => { + if let Some(principal) = trait_data.principal() { + self.push_def_path(principal.def_id(), output); + self.push_type_params(principal.skip_binder().substs, + trait_data.projection_bounds(), + output); + } + }, + ty::TyFnDef(..) | + ty::TyFnPtr(_) => { + let sig = t.fn_sig(self.tcx); + if sig.unsafety() == hir::Unsafety::Unsafe { + output.push_str("unsafe "); + } + + let abi = sig.abi(); + if abi != ::syntax::abi::Abi::Rust { + output.push_str("extern \""); + output.push_str(abi.name()); + output.push_str("\" "); + } + + output.push_str("fn("); + + let sig = self.tcx.erase_late_bound_regions_and_normalize(&sig); + + if !sig.inputs().is_empty() { + for ¶meter_type in sig.inputs() { + self.push_type_name(parameter_type, output); + output.push_str(", "); + } + output.pop(); + output.pop(); + } + + if sig.variadic { + if !sig.inputs().is_empty() { + output.push_str(", ..."); + } else { + output.push_str("..."); + } + } + + output.push(')'); + + if !sig.output().is_nil() { + output.push_str(" -> "); + self.push_type_name(sig.output(), output); + } + }, + ty::TyGenerator(def_id, ref closure_substs, _) | + ty::TyClosure(def_id, ref closure_substs) => { + self.push_def_path(def_id, output); + let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id)); + let substs = closure_substs.substs.truncate_to(self.tcx, generics); + self.push_type_params(substs, iter::empty(), output); + } + ty::TyError | + ty::TyInfer(_) | + ty::TyProjection(..) | + ty::TyParam(_) | + ty::TyAnon(..) => { + bug!("DefPathBasedNames: Trying to create type name for \ + unexpected type: {:?}", t); + } + } + } + + pub fn push_def_path(&self, + def_id: DefId, + output: &mut String) { + let def_path = self.tcx.def_path(def_id); + + // some_crate:: + if !(self.omit_local_crate_name && def_id.is_local()) { + output.push_str(&self.tcx.crate_name(def_path.krate).as_str()); + output.push_str("::"); + } + + // foo::bar::ItemName:: + for part in self.tcx.def_path(def_id).data { + if self.omit_disambiguators { + write!(output, "{}::", part.data.as_interned_str()).unwrap(); + } else { + write!(output, "{}[{}]::", + part.data.as_interned_str(), + part.disambiguator).unwrap(); + } + } + + // remove final "::" + output.pop(); + output.pop(); + } + + fn push_type_params(&self, + substs: &Substs<'tcx>, + projections: I, + output: &mut String) + where I: Iterator> + { + let mut projections = projections.peekable(); + if substs.types().next().is_none() && projections.peek().is_none() { + return; + } + + output.push('<'); + + for type_parameter in substs.types() { + self.push_type_name(type_parameter, output); + output.push_str(", "); + } + + for projection in projections { + let projection = projection.skip_binder(); + let name = &self.tcx.associated_item(projection.item_def_id).name.as_str(); + output.push_str(name); + output.push_str("="); + self.push_type_name(projection.ty, output); + output.push_str(", "); + } + + output.pop(); + output.pop(); + + output.push('>'); + } + + pub fn push_instance_as_string(&self, + instance: Instance<'tcx>, + output: &mut String) { + self.push_def_path(instance.def_id(), output); + self.push_type_params(instance.substs, iter::empty(), output); + } +} From 27cc11931aee7674e4c295ada7d69e0af45f6989 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Wed, 18 Oct 2017 21:55:12 +0200 Subject: [PATCH 327/365] rustbuild: fix dist in debug mode Signed-off-by: Marc-Antoine Perennou --- src/bootstrap/dist.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 02dfa04d920..38dca108012 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -630,7 +630,7 @@ impl Step for Analysis { let image = tmpdir(build).join(format!("{}-{}-image", name, target)); let src = build.stage_out(compiler, Mode::Libstd) - .join(target).join("release").join("deps"); + .join(target).join(build.cargo_dir()).join("deps"); let image_src = src.join("save-analysis"); let dst = image.join("lib/rustlib").join(target).join("analysis"); From dbcd1bec6150a259fea16ddae6c5881b4b676217 Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Thu, 19 Oct 2017 15:48:41 -0200 Subject: [PATCH 328/365] Update libc to include linux gnux32 fixes --- src/liblibc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liblibc b/src/liblibc index 44e4018e1a3..7e33065ce49 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 44e4018e1a37716286ec98cb5b7dd7d33ecaf940 +Subproject commit 7e33065ce49759958c0d1c04fcadef961032a943 From 02635c2d37b7f0a012c9fae1d67723513f3d19c8 Mon Sep 17 00:00:00 2001 From: matthewjasper Date: Thu, 19 Oct 2017 19:48:57 +0100 Subject: [PATCH 329/365] Cleanly error for non-const expression in associated const --- src/librustc_resolve/lib.rs | 4 +++- src/test/compile-fail/issue-44239.rs | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/issue-44239.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4aab43cbec7..c7ec1d072d0 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2084,7 +2084,9 @@ impl<'a> Resolver<'a> { ValueNS, impl_item.span, |n, s| ResolutionError::ConstNotMemberOfTrait(n, s)); - visit::walk_impl_item(this, impl_item); + this.with_constant_rib(|this| + visit::walk_impl_item(this, impl_item) + ); } ImplItemKind::Method(ref sig, _) => { // If this is a trait impl, ensure the method diff --git a/src/test/compile-fail/issue-44239.rs b/src/test/compile-fail/issue-44239.rs new file mode 100644 index 00000000000..131c6526642 --- /dev/null +++ b/src/test/compile-fail/issue-44239.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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. + +fn main() { + let n = 0; + + struct Foo; + impl Foo { + const N: usize = n; + //~^ ERROR attempt to use a non-constant value + } +} From b1f246c12eb3a216b807c329f1756131c1f1bc1e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Oct 2017 13:26:21 -0700 Subject: [PATCH 330/365] ci: Update musl with new release Apparently there's at least one CVE fixed in the new version of musl, and because we're distributing it seems like a good opportunity to update! Unfortunately it looks like #38618 still hasn't been fixed. --- src/ci/docker/cross/build-arm-musl.sh | 2 +- src/ci/docker/dist-i586-gnu-i686-musl/build-musl.sh | 2 +- src/ci/docker/dist-x86_64-musl/build-musl.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/cross/build-arm-musl.sh b/src/ci/docker/cross/build-arm-musl.sh index 780099e2ec1..567e5d9ac98 100755 --- a/src/ci/docker/cross/build-arm-musl.sh +++ b/src/ci/docker/cross/build-arm-musl.sh @@ -11,7 +11,7 @@ set -ex -MUSL=1.1.16 +MUSL=1.1.17 hide_output() { set +x diff --git a/src/ci/docker/dist-i586-gnu-i686-musl/build-musl.sh b/src/ci/docker/dist-i586-gnu-i686-musl/build-musl.sh index ad285a57a84..883859d1fa6 100644 --- a/src/ci/docker/dist-i586-gnu-i686-musl/build-musl.sh +++ b/src/ci/docker/dist-i586-gnu-i686-musl/build-musl.sh @@ -15,7 +15,7 @@ set -ex export CFLAGS="-fPIC -Wa,-mrelax-relocations=no" export CXXFLAGS="-Wa,-mrelax-relocations=no" -MUSL=musl-1.1.16 +MUSL=musl-1.1.17 curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf - cd $MUSL CC=gcc \ diff --git a/src/ci/docker/dist-x86_64-musl/build-musl.sh b/src/ci/docker/dist-x86_64-musl/build-musl.sh index 776da009397..9be8d001149 100644 --- a/src/ci/docker/dist-x86_64-musl/build-musl.sh +++ b/src/ci/docker/dist-x86_64-musl/build-musl.sh @@ -15,7 +15,7 @@ set -ex export CFLAGS="-fPIC -Wa,-mrelax-relocations=no" export CXXFLAGS="-Wa,-mrelax-relocations=no" -MUSL=musl-1.1.16 +MUSL=musl-1.1.17 curl https://www.musl-libc.org/releases/$MUSL.tar.gz | tar xzf - cd $MUSL ./configure --prefix=/musl-x86_64 --disable-shared From 686c1015cfa341748b6de20114e8caba4626931b Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 19 Oct 2017 17:30:37 -0600 Subject: [PATCH 331/365] Make tools which may not build return Option. This makes it mandatory for other steps to have to handle the potential failure instead of failing in an odd way later down the road. --- src/bootstrap/check.rs | 68 +++++++++++++++++++++++------------------- src/bootstrap/dist.rs | 4 ++- src/bootstrap/tool.rs | 40 ++++++++++++++----------- 3 files changed, 62 insertions(+), 50 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index d9ee63eef8c..11bc9f7d217 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -340,25 +340,28 @@ impl Step for Miri { let host = self.host; let compiler = builder.compiler(1, host); - let miri = builder.ensure(tool::Miri { compiler, target: self.host }); - let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); - cargo.arg("--manifest-path").arg(build.src.join("src/tools/miri/Cargo.toml")); + if let Some(miri) = builder.ensure(tool::Miri { compiler, target: self.host }) { + let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); + cargo.arg("--manifest-path").arg(build.src.join("src/tools/miri/Cargo.toml")); - // Don't build tests dynamically, just a pain to work with - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); - // miri tests need to know about the stage sysroot - cargo.env("MIRI_SYSROOT", builder.sysroot(compiler)); - cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler)); - cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler)); - cargo.env("MIRI_PATH", miri); + // Don't build tests dynamically, just a pain to work with + cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + // miri tests need to know about the stage sysroot + cargo.env("MIRI_SYSROOT", builder.sysroot(compiler)); + cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler)); + cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler)); + cargo.env("MIRI_PATH", miri); - builder.add_rustc_lib_path(compiler, &mut cargo); + builder.add_rustc_lib_path(compiler, &mut cargo); - try_run_expecting( - build, - &mut cargo, - builder.build.config.toolstate.miri.passes(ToolState::Testing), - ); + try_run_expecting( + build, + &mut cargo, + builder.build.config.toolstate.miri.passes(ToolState::Testing), + ); + } else { + eprintln!("failed to test miri: could not build"); + } } } @@ -391,24 +394,27 @@ impl Step for Clippy { let host = self.host; let compiler = builder.compiler(stage, host); - let clippy = builder.ensure(tool::Clippy { compiler, target: self.host }); - let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); - cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml")); + if let Some(clippy) = builder.ensure(tool::Clippy { compiler, target: self.host }) { + let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test"); + cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml")); - // Don't build tests dynamically, just a pain to work with - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); - // clippy tests need to know about the stage sysroot - cargo.env("SYSROOT", builder.sysroot(compiler)); - // clippy tests need to find the driver - cargo.env("CLIPPY_DRIVER_PATH", clippy); + // Don't build tests dynamically, just a pain to work with + cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + // clippy tests need to know about the stage sysroot + cargo.env("SYSROOT", builder.sysroot(compiler)); + // clippy tests need to find the driver + cargo.env("CLIPPY_DRIVER_PATH", clippy); - builder.add_rustc_lib_path(compiler, &mut cargo); + builder.add_rustc_lib_path(compiler, &mut cargo); - try_run_expecting( - build, - &mut cargo, - builder.build.config.toolstate.clippy.passes(ToolState::Testing), - ); + try_run_expecting( + build, + &mut cargo, + builder.build.config.toolstate.clippy.passes(ToolState::Testing), + ); + } else { + eprintln!("failed to test clippy: could not build"); + } } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 02dfa04d920..a6663a85484 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1073,10 +1073,12 @@ impl Step for Rls { t!(fs::create_dir_all(&image)); // Prepare the image directory + // We expect RLS to build, because we've exited this step above if tool + // state for RLS isn't testing. let rls = builder.ensure(tool::Rls { compiler: builder.compiler(stage, build.build), target - }); + }).expect("Rls to build: toolstate is testing"); install(&rls, &image.join("bin"), 0o755); let doc = image.join("share/doc/rls"); install(&src.join("README.md"), &doc, 0o644); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index bdbef3a943b..912ffa51975 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -86,7 +86,7 @@ struct ToolBuild { } impl Step for ToolBuild { - type Output = PathBuf; + type Output = Option; fn should_run(run: ShouldRun) -> ShouldRun { run.never() @@ -96,7 +96,7 @@ impl Step for ToolBuild { /// /// This will build the specified tool with the specified `host` compiler in /// `stage` into the normal cargo output directory. - fn run(self, builder: &Builder) -> PathBuf { + fn run(self, builder: &Builder) -> Option { let build = builder.build; let compiler = self.compiler; let target = self.target; @@ -116,11 +116,15 @@ impl Step for ToolBuild { let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path); build.run_expecting(&mut cargo, expectation); - let cargo_out = build.cargo_out(compiler, Mode::Tool, target) - .join(exe(tool, &compiler.host)); - let bin = build.tools_dir(compiler).join(exe(tool, &compiler.host)); - copy(&cargo_out, &bin); - bin + if expectation == BuildExpectation::Succeeding || expectation == BuildExpectation::None { + let cargo_out = build.cargo_out(compiler, Mode::Tool, target) + .join(exe(tool, &compiler.host)); + let bin = build.tools_dir(compiler).join(exe(tool, &compiler.host)); + copy(&cargo_out, &bin); + Some(bin) + } else { + None + } } } @@ -229,7 +233,7 @@ macro_rules! tool { mode: $mode, path: $path, expectation: BuildExpectation::None, - }) + }).expect("expected to build -- BuildExpectation::None") } } )+ @@ -277,7 +281,7 @@ impl Step for RemoteTestServer { mode: Mode::Libstd, path: "src/tools/remote-test-server", expectation: BuildExpectation::None, - }) + }).expect("expected to build -- BuildExpectation::None") } } @@ -395,7 +399,7 @@ impl Step for Cargo { mode: Mode::Librustc, path: "src/tools/cargo", expectation: BuildExpectation::None, - }) + }).expect("BuildExpectation::None - expected to build") } } @@ -406,7 +410,7 @@ pub struct Clippy { } impl Step for Clippy { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -421,7 +425,7 @@ impl Step for Clippy { }); } - fn run(self, builder: &Builder) -> PathBuf { + fn run(self, builder: &Builder) -> Option { // Clippy depends on procedural macros (serde), which requires a full host // compiler to be available, so we need to depend on that. builder.ensure(compile::Rustc { @@ -446,7 +450,7 @@ pub struct Rls { } impl Step for Rls { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -462,7 +466,7 @@ impl Step for Rls { }); } - fn run(self, builder: &Builder) -> PathBuf { + fn run(self, builder: &Builder) -> Option { builder.ensure(native::Openssl { target: self.target, }); @@ -490,7 +494,7 @@ pub struct Rustfmt { } impl Step for Rustfmt { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -506,7 +510,7 @@ impl Step for Rustfmt { }); } - fn run(self, builder: &Builder) -> PathBuf { + fn run(self, builder: &Builder) -> Option { builder.ensure(ToolBuild { compiler: self.compiler, target: self.target, @@ -526,7 +530,7 @@ pub struct Miri { } impl Step for Miri { - type Output = PathBuf; + type Output = Option; const DEFAULT: bool = true; const ONLY_HOSTS: bool = true; @@ -542,7 +546,7 @@ impl Step for Miri { }); } - fn run(self, builder: &Builder) -> PathBuf { + fn run(self, builder: &Builder) -> Option { builder.ensure(ToolBuild { compiler: self.compiler, target: self.target, From ada809917dc4b6f7a48fb60df06c3753bc8a74f3 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Sun, 15 Oct 2017 14:50:40 -0700 Subject: [PATCH 332/365] Initial work to remove typeck_tables call from check_unused --- src/librustc/ty/context.rs | 6 +++--- src/librustc_typeck/check/method/mod.rs | 9 +++++++-- src/librustc_typeck/check/mod.rs | 9 ++++++++- src/librustc_typeck/check/writeback.rs | 4 +++- src/librustc_typeck/check_unused.rs | 7 ++++--- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 24ba38cf147..77889b7c10e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -388,7 +388,7 @@ pub struct TypeckTables<'tcx> { /// Set of trait imports actually used in the method resolution. /// This is used for warning unused imports. - pub used_trait_imports: DefIdSet, + pub used_trait_imports: Rc>, /// If any errors occurred while type-checking this body, /// this field will be set to `true`. @@ -418,7 +418,7 @@ impl<'tcx> TypeckTables<'tcx> { liberated_fn_sigs: ItemLocalMap(), fru_field_types: ItemLocalMap(), cast_kinds: ItemLocalMap(), - used_trait_imports: DefIdSet(), + used_trait_imports: Rc::new(RefCell::new(DefIdSet())), tainted_by_errors: false, free_region_map: FreeRegionMap::new(), } @@ -782,7 +782,7 @@ impl<'gcx> HashStable> for TypeckTables<'gcx> { cast_kinds.hash_stable(hcx, hasher); generator_sigs.hash_stable(hcx, hasher); generator_interiors.hash_stable(hcx, hasher); - used_trait_imports.hash_stable(hcx, hasher); + used_trait_imports.borrow_mut().hash_stable(hcx, hasher); tainted_by_errors.hash_stable(hcx, hasher); free_region_map.hash_stable(hcx, hasher); }) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index d4eda13c6cd..a0c93df8068 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -163,7 +163,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(import_id) = pick.import_id { let import_def_id = self.tcx.hir.local_def_id(import_id); debug!("used_trait_import: {:?}", import_def_id); - self.tables.borrow_mut().used_trait_imports.insert(import_def_id); + + let tables = self.tables.borrow_mut(); + let mut ut = tables.used_trait_imports.borrow_mut(); + ut.insert(import_def_id); } self.tcx.check_stability(pick.item.def_id, call_expr.id, span); @@ -361,7 +364,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(import_id) = pick.import_id { let import_def_id = self.tcx.hir.local_def_id(import_id); debug!("used_trait_import: {:?}", import_def_id); - self.tables.borrow_mut().used_trait_imports.insert(import_def_id); + let tables = self.tables.borrow_mut(); + let mut ut = tables.used_trait_imports.borrow_mut(); + ut.insert(import_def_id); } let def = pick.item.def(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 0ebccbc835f..f6b4dd8470c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -106,9 +106,10 @@ use session::{CompileIncomplete, Session}; use TypeAndSubsts; use lint; use util::common::{ErrorReported, indenter}; -use util::nodemap::{DefIdMap, FxHashMap, NodeMap}; +use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, NodeMap}; use std::cell::{Cell, RefCell, Ref, RefMut}; +use std::rc::Rc; use std::collections::hash_map::Entry; use std::cmp; use std::fmt::Display; @@ -921,6 +922,12 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables } +pub fn get_used_trait_imports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> Rc> { + Rc::clone(&tcx.typeck_tables_of(def_id).used_trait_imports) +} + fn check_abi<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, abi: Abi) { if !tcx.sess.target.target.is_abi_supported(abi) { struct_span_err!(tcx.sess, span, E0570, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b3648d357e5..b6f2551da20 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -23,6 +23,8 @@ use rustc::util::nodemap::DefIdSet; use syntax::ast; use syntax_pos::Span; use std::mem; +use std::rc::Rc; +use std::cell::RefCell; /////////////////////////////////////////////////////////////////////////// // Entry point @@ -49,7 +51,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_generator_interiors(); let used_trait_imports = mem::replace(&mut self.tables.borrow_mut().used_trait_imports, - DefIdSet()); + Rc::new(RefCell::new(DefIdSet()))); debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); wbcx.tables.used_trait_imports = used_trait_imports; diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 0c35b5e6834..cd2bd8499cf 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -19,6 +19,8 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir; use rustc::util::nodemap::DefIdSet; +use check::get_used_trait_imports; + struct CheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, used_trait_imports: DefIdSet, @@ -66,10 +68,9 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut used_trait_imports = DefIdSet(); for &body_id in tcx.hir.krate().bodies.keys() { let item_def_id = tcx.hir.body_owner_def_id(body_id); - let tables = tcx.typeck_tables_of(item_def_id); - let imports = &tables.used_trait_imports; + let imports = get_used_trait_imports(tcx, item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); - used_trait_imports.extend(imports); + used_trait_imports.extend(imports.borrow().iter()); } let mut visitor = CheckVisitor { tcx, used_trait_imports }; From b815ecc597a2457014dd9195e078ebe81c69a588 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Mon, 16 Oct 2017 23:41:51 -0700 Subject: [PATCH 333/365] Add used_trait_imports query --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/ty/context.rs | 9 +++++---- src/librustc/ty/maps/mod.rs | 2 ++ src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_typeck/check/method/mod.rs | 13 ++++++------- src/librustc_typeck/check/mod.rs | 13 +++++++------ src/librustc_typeck/check/writeback.rs | 3 +-- src/librustc_typeck/check_unused.rs | 7 +++---- 8 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 92bbb745bb2..7de557ad0ed 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -500,6 +500,7 @@ define_dep_nodes!( <'tcx> [] InherentImpls(DefId), [] TypeckBodiesKrate, [] TypeckTables(DefId), + [] UsedTraitImports(DefId), [] HasTypeckTables(DefId), [] ConstEval { param_env: ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)> }, [] SymbolName(DefId), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 77889b7c10e..8232c0ed460 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -387,8 +387,9 @@ pub struct TypeckTables<'tcx> { cast_kinds: ItemLocalMap, /// Set of trait imports actually used in the method resolution. - /// This is used for warning unused imports. - pub used_trait_imports: Rc>, + /// This is used for warning unused imports. During type + /// checking, this field should not be cloned. + pub used_trait_imports: Rc, /// If any errors occurred while type-checking this body, /// this field will be set to `true`. @@ -418,7 +419,7 @@ impl<'tcx> TypeckTables<'tcx> { liberated_fn_sigs: ItemLocalMap(), fru_field_types: ItemLocalMap(), cast_kinds: ItemLocalMap(), - used_trait_imports: Rc::new(RefCell::new(DefIdSet())), + used_trait_imports: Rc::new(DefIdSet()), tainted_by_errors: false, free_region_map: FreeRegionMap::new(), } @@ -782,7 +783,7 @@ impl<'gcx> HashStable> for TypeckTables<'gcx> { cast_kinds.hash_stable(hcx, hasher); generator_sigs.hash_stable(hcx, hasher); generator_interiors.hash_stable(hcx, hasher); - used_trait_imports.borrow_mut().hash_stable(hcx, hasher); + used_trait_imports.hash_stable(hcx, hasher); tainted_by_errors.hash_stable(hcx, hasher); free_region_map.hash_stable(hcx, hasher); }) diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index f54391ebb07..f6a01949130 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -183,6 +183,8 @@ define_maps! { <'tcx> [] fn typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, + [] fn used_trait_imports: UsedTraitImports(DefId) -> Rc, + [] fn has_typeck_tables: HasTypeckTables(DefId) -> bool, [] fn coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (), diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 4e301342ee0..767e9a8436c 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -757,6 +757,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::InherentImpls => { force!(inherent_impls, def_id!()); } DepKind::TypeckBodiesKrate => { force!(typeck_item_bodies, LOCAL_CRATE); } DepKind::TypeckTables => { force!(typeck_tables_of, def_id!()); } + DepKind::UsedTraitImports => { force!(used_trait_imports, def_id!()); } DepKind::HasTypeckTables => { force!(has_typeck_tables, def_id!()); } DepKind::SymbolName => { force!(def_symbol_name, def_id!()); } DepKind::SpecializationGraph => { force!(specialization_graph_of, def_id!()); } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index a0c93df8068..58d72e37d51 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -25,6 +25,8 @@ use syntax_pos::Span; use rustc::hir; +use std::rc::Rc; + pub use self::MethodError::*; pub use self::CandidateSource::*; @@ -163,10 +165,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(import_id) = pick.import_id { let import_def_id = self.tcx.hir.local_def_id(import_id); debug!("used_trait_import: {:?}", import_def_id); - - let tables = self.tables.borrow_mut(); - let mut ut = tables.used_trait_imports.borrow_mut(); - ut.insert(import_def_id); + Rc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) + .unwrap().insert(import_def_id); } self.tcx.check_stability(pick.item.def_id, call_expr.id, span); @@ -364,9 +364,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(import_id) = pick.import_id { let import_def_id = self.tcx.hir.local_def_id(import_id); debug!("used_trait_import: {:?}", import_def_id); - let tables = self.tables.borrow_mut(); - let mut ut = tables.used_trait_imports.borrow_mut(); - ut.insert(import_def_id); + Rc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) + .unwrap().insert(import_def_id); } let def = pick.item.def(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f6b4dd8470c..c4c8f65a994 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -743,6 +743,7 @@ pub fn provide(providers: &mut Providers) { closure_kind, generator_sig, adt_destructor, + used_trait_imports, ..*providers }; } @@ -846,6 +847,12 @@ fn has_typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, primary_body_of(tcx, id).is_some() } +fn used_trait_imports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> Rc { + Rc::clone(&tcx.typeck_tables_of(def_id).used_trait_imports) +} + fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::TypeckTables<'tcx> { @@ -922,12 +929,6 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables } -pub fn get_used_trait_imports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> Rc> { - Rc::clone(&tcx.typeck_tables_of(def_id).used_trait_imports) -} - fn check_abi<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, abi: Abi) { if !tcx.sess.target.target.is_abi_supported(abi) { struct_span_err!(tcx.sess, span, E0570, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b6f2551da20..ce2ac73a27e 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -24,7 +24,6 @@ use syntax::ast; use syntax_pos::Span; use std::mem; use std::rc::Rc; -use std::cell::RefCell; /////////////////////////////////////////////////////////////////////////// // Entry point @@ -51,7 +50,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_generator_interiors(); let used_trait_imports = mem::replace(&mut self.tables.borrow_mut().used_trait_imports, - Rc::new(RefCell::new(DefIdSet()))); + Rc::new(DefIdSet())); debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); wbcx.tables.used_trait_imports = used_trait_imports; diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index cd2bd8499cf..29df70a4679 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -19,8 +19,6 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir; use rustc::util::nodemap::DefIdSet; -use check::get_used_trait_imports; - struct CheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, used_trait_imports: DefIdSet, @@ -68,9 +66,10 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut used_trait_imports = DefIdSet(); for &body_id in tcx.hir.krate().bodies.keys() { let item_def_id = tcx.hir.body_owner_def_id(body_id); - let imports = get_used_trait_imports(tcx, item_def_id); + // let tables = tcx.typeck_tables_of(item_def_id); + let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); - used_trait_imports.extend(imports.borrow().iter()); + used_trait_imports.extend(imports.iter()); } let mut visitor = CheckVisitor { tcx, used_trait_imports }; From 24b4dfcf1b9862d3a8fa15a36f1d39ae0971d9f9 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Tue, 17 Oct 2017 18:18:07 -0700 Subject: [PATCH 334/365] Remove commented out line. --- src/librustc_typeck/check_unused.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 29df70a4679..b867a655b4a 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -66,7 +66,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut used_trait_imports = DefIdSet(); for &body_id in tcx.hir.krate().bodies.keys() { let item_def_id = tcx.hir.body_owner_def_id(body_id); - // let tables = tcx.typeck_tables_of(item_def_id); let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); used_trait_imports.extend(imports.iter()); From 6f30ce0be2240758889224781a9f727e7bc325e1 Mon Sep 17 00:00:00 2001 From: cjkenn Date: Thu, 19 Oct 2017 23:06:22 -0700 Subject: [PATCH 335/365] Misc code review changes --- src/librustc/ty/context.rs | 3 ++- src/librustc_typeck/check/mod.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 8232c0ed460..80a9cda1e18 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -388,7 +388,8 @@ pub struct TypeckTables<'tcx> { /// Set of trait imports actually used in the method resolution. /// This is used for warning unused imports. During type - /// checking, this field should not be cloned. + /// checking, this `Rc` should not be cloned: it must have a ref-count + /// of 1 so that we can insert things into the set mutably. pub used_trait_imports: Rc, /// If any errors occurred while type-checking this body, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c4c8f65a994..7807c4c7352 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -850,7 +850,7 @@ fn has_typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn used_trait_imports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Rc { - Rc::clone(&tcx.typeck_tables_of(def_id).used_trait_imports) + tcx.typeck_tables_of(def_id).used_trait_imports.clone() } fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, From a59282d8ed5bf3168bdeccd9b724f322163461bf Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 19 Oct 2017 13:51:28 +0900 Subject: [PATCH 336/365] Fix typos in README.md --- src/librustc/hir/README.md | 4 ++-- src/librustc/mir/README.md | 6 +++--- src/librustc/ty/maps/README.md | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc/hir/README.md b/src/librustc/hir/README.md index c832a897dee..e283fc40c50 100644 --- a/src/librustc/hir/README.md +++ b/src/librustc/hir/README.md @@ -57,7 +57,7 @@ carry around references into the HIR, but rather to carry around *identifier numbers* (or just "ids"). Right now, you will find four sorts of identifiers in active use: -- `DefId`, which primarily name "definitions" or top-level items. +- `DefId`, which primarily names "definitions" or top-level items. - You can think of a `DefId` as being shorthand for a very explicit and complete path, like `std::collections::HashMap`. However, these paths are able to name things that are not nameable in @@ -114,6 +114,6 @@ A **body** represents some kind of executable code, such as the body of a function/closure or the definition of a constant. Bodies are associated with an **owner**, which is typically some kind of item (e.g., a `fn()` or `const`), but could also be a closure expression -(e.g., `|x, y| x + y`). You can use the HIR map to find find the body +(e.g., `|x, y| x + y`). You can use the HIR map to find the body associated with a given def-id (`maybe_body_owned_by()`) or to find the owner of a body (`body_owner_def_id()`). diff --git a/src/librustc/mir/README.md b/src/librustc/mir/README.md index e8ed8bf104c..fb0c7ce1df2 100644 --- a/src/librustc/mir/README.md +++ b/src/librustc/mir/README.md @@ -6,7 +6,7 @@ register and define new MIR transformations and analyses. Most of the code that operates on MIR can be found in the `librustc_mir` crate or other crates. The code found here in -`librustc` is just the datatype definitions, alonging the functions +`librustc` is just the datatype definitions, along with the functions which operate on MIR to be placed everywhere else. ## MIR Data Types and visitor @@ -27,7 +27,7 @@ As a MIR *consumer*, you are expected to use one of the queries that returns a "final MIR". As of the time of this writing, there is only one: `optimized_mir(def_id)`, but more are expected to come in the future. For foreign def-ids, we simply read the MIR from the other -crate's metadata. But for local query, this query will construct the +crate's metadata. But for local def-ids, the query will construct the MIR and then iteratively optimize it by putting it through various pipeline stages. This section describes those pipeline stages and how you can extend them. @@ -51,7 +51,7 @@ a `&'tcx Steal>`, allocated using **stolen** by the next suite of optimizations -- this is an optimization to avoid cloning the MIR. Attempting to use a stolen result will cause a panic in the compiler. Therefore, it is important -that you not read directly from these intermediate queries except as +that you do not read directly from these intermediate queries except as part of the MIR processing pipeline. Because of this stealing mechanism, some care must also be taken to diff --git a/src/librustc/ty/maps/README.md b/src/librustc/ty/maps/README.md index 8abc68d431a..8207c18e677 100644 --- a/src/librustc/ty/maps/README.md +++ b/src/librustc/ty/maps/README.md @@ -169,7 +169,7 @@ That is, they take an `&mut Providers` and mutate it in place. Usually we use the formulation above just because it looks nice, but you could as well do `providers.type_of = type_of`, which would be equivalent. (Here, `type_of` would be a top-level function, defined as we saw -before.) So, if we wanted to have add a provider for some other query, +before.) So, if we want to add a provider for some other query, let's call it `fubar`, into the crate above, we might modify the `provide()` function like so: @@ -185,7 +185,7 @@ pub fn provide(providers: &mut Providers) { fn fubar<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx>, key: DefId) -> Fubar<'tcx> { .. } ``` -NB. Most of the `rustc_*` crate only provide **local +NB. Most of the `rustc_*` crates only provide **local providers**. Almost all **extern providers** wind up going through the `rustc_metadata` crate, which loads the information from the crate metadata. But in some cases there are crates that provide queries for @@ -201,7 +201,7 @@ Well, defining a query takes place in two steps: 1. first, you have to specify the query name and arguments; and then, 2. you have to supply query providers where needed. -The specify the query name and arguments, you simply add an entry +To specify the query name and arguments, you simply add an entry to the big macro invocation in `mod.rs`. This will probably have changed by the time you read this README, but at present it looks something like: From 2812865664ed028be4da785fd0c01b64008902bf Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 20 Oct 2017 16:01:30 +0200 Subject: [PATCH 337/365] Reactivate clippy in toolstate.toml --- src/Cargo.lock | 159 +++++++++++++++++++++++++++++++++++++++ src/Cargo.toml | 1 + src/tools/clippy | 2 +- src/tools/toolstate.toml | 2 +- 4 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 328ce353e2a..560dfe2ab8a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -224,6 +224,16 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cargo_metadata" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cargotest" version = "0.1.0" @@ -270,6 +280,43 @@ dependencies = [ "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "clippy" +version = "0.0.166" +dependencies = [ + "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy-mini-macro-test 0.1.0", + "clippy_lints 0.0.166", + "compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clippy-mini-macro-test" +version = "0.1.0" + +[[package]] +name = "clippy_lints" +version = "0.0.166" +dependencies = [ + "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cmake" version = "0.1.26" @@ -307,6 +354,15 @@ dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "compiletest_rs" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "completion" version = "0.1.0" @@ -469,6 +525,22 @@ name = "dtoa" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "duct" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "enum_primitive" version = "0.1.1" @@ -495,6 +567,14 @@ dependencies = [ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" version = "0.11.0" @@ -752,6 +832,14 @@ dependencies = [ "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itertools" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.3.4" @@ -816,6 +904,11 @@ name = "lazy_static" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazycell" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.0.0" @@ -999,6 +1092,17 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nix" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num" version = "0.1.40" @@ -1110,6 +1214,16 @@ dependencies = [ "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "os_pipe" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" version = "0.3.3" @@ -1229,6 +1343,15 @@ dependencies = [ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pulldown-cmark" +version = "0.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pulldown-cmark" version = "0.1.0" @@ -1243,6 +1366,11 @@ name = "quick-error" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "quine-mc_cluskey" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.2.3" @@ -1893,6 +2021,14 @@ dependencies = [ "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.8.0" @@ -1954,6 +2090,16 @@ dependencies = [ name = "serialize" version = "0.0.0" +[[package]] +name = "shared_child" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "shell-escape" version = "0.1.3" @@ -2484,10 +2630,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" +"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" "checksum cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c674f0870e3dbd4105184ea035acb1c32c8ae69939c9e228d2b11bbfe29efad" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2" "checksum cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "357c07e7a1fc95732793c1edb5901e1a1f305cfcf63a90eb12dbd22bdb6b789d" +"checksum compiletest_rs 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2741d378feb7a434dba54228c89a70b4e427fee521de67cdda3750b8a0265f5a" "checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" "checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7" "checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387" @@ -2504,10 +2652,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" "checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c" +"checksum either 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e311a7479512fbdf858fb54d91ec59f3b9f85bc0113659f46bba12b199d273ce" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab199bf38537c6f38792669e081e0bb278b9b7405bba2642e4e5d15bf732c0e" "checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" @@ -2528,6 +2679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum html5ever 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a49d5001dd1bddf042ea41ed4e0a671d50b1bf187e66b349d7ec613bdce4ad90" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5" +"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "094f87ed101b6832def8632f43db43dc204d27897eb95aca69b26ce2e4011e84" "checksum jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1acd0f9934da94466d2370f36832b9b19271b4abdfdb5e69f0bcd991ebcd515" @@ -2535,6 +2687,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kuchiki 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2ea4f2f7883cd7c6772b06c14abca01a2cc1f75c426cebffcf6b3b925ef9fc" "checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" +"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" "checksum libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d1419b2939a0bc44b77feb34661583c7546b532b192feab36249ab584b86856c" "checksum libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "205fc37e829c5b36de63d14c8dc8b62c5a6a2519b16318ed0977079ca97256a9" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" @@ -2552,6 +2705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" +"checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487" "checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" "checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd" "checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6" @@ -2564,6 +2718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum openssl 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "816914b22eb15671d62c73442a51978f311e911d6a6f6cbdafa6abce1b5038fc" "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" "checksum openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4c63a7d559c1e5afa6d6a9e6fa34bbc5f800ffc9ae08b72c605420b0c4f5e8" +"checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" @@ -2576,8 +2731,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989" "checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478" "checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973" +"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b" "checksum pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a656fdb8b6848f896df5e478a0eb9083681663e37dcb77dd16981ff65329fe8b" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" +"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f120c7510ef7aff254aeb06067fb6fac573ec96a1660e194787cf9dced412bf0" @@ -2598,6 +2755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57" "checksum selectors 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c89b1c6a3c029c82263f7dd2d44d0005ee7374eb09e254ab59dede4353a8c0" +"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7046c9d4c6c522d10b2d098f9bebe2bef227e0e74044d8c1bfcf6b476af799" @@ -2605,6 +2763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" "checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac" +"checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" diff --git a/src/Cargo.toml b/src/Cargo.toml index f4b4189e01f..3e1da987035 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -5,6 +5,7 @@ members = [ "libstd", "libtest", "tools/cargotest", + "tools/clippy", "tools/compiletest", "tools/error_index_generator", "tools/linkchecker", diff --git a/src/tools/clippy b/src/tools/clippy index b62b1b68edc..281bd790de7 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit b62b1b68edcdf23a70cb12f31403c80e97f13634 +Subproject commit 281bd790de7b992831a1ff8a589c0fc38c842c95 diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml index f1684f4c5ac..e62597c5216 100644 --- a/src/tools/toolstate.toml +++ b/src/tools/toolstate.toml @@ -26,7 +26,7 @@ miri = "Broken" # ping @Manishearth @llogiq @mcarton @oli-obk -clippy = "Broken" +clippy = "Compiling" # ping @nrc rls = "Testing" From e57ee3d0bf8d8b11feccab49432d4c5e8fc3a3ca Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Thu, 19 Oct 2017 15:49:59 -0200 Subject: [PATCH 338/365] Fix some tests for linux gnux32 --- src/libcore/tests/hash/sip.rs | 14 ++++++-------- src/libstd/sys/unix/condvar.rs | 5 +++-- src/libstd/sys/unix/fs.rs | 4 ++-- src/libstd/sys/unix/thread.rs | 2 +- src/libstd/sys/unix/time.rs | 4 ++-- src/test/codegen/issue-37945.rs | 1 + src/tools/compiletest/src/util.rs | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/libcore/tests/hash/sip.rs b/src/libcore/tests/hash/sip.rs index 4a9657e0340..c6dd41798f2 100644 --- a/src/libcore/tests/hash/sip.rs +++ b/src/libcore/tests/hash/sip.rs @@ -243,24 +243,22 @@ fn test_siphash_2_4() { t += 1; } } -#[test] #[cfg(target_arch = "arm")] + +#[test] +#[cfg(target_pointer_width = "32")] fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; assert!(hash(&(val as u64)) != hash(&(val as usize))); assert_eq!(hash(&(val as u32)), hash(&(val as usize))); } -#[test] #[cfg(target_arch = "x86_64")] + +#[test] +#[cfg(target_pointer_width = "64")] fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; assert_eq!(hash(&(val as u64)), hash(&(val as usize))); assert!(hash(&(val as u32)) != hash(&(val as usize))); } -#[test] #[cfg(target_arch = "x86")] -fn test_hash_usize() { - let val = 0xdeadbeef_deadbeef_u64; - assert!(hash(&(val as u64)) != hash(&(val as usize))); - assert_eq!(hash(&(val as u32)), hash(&(val as usize))); -} #[test] fn test_hash_idempotent() { diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 89a44b97657..4f878d8ad1f 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -92,14 +92,15 @@ impl Condvar { assert_eq!(r, 0); // Nanosecond calculations can't overflow because both values are below 1e9. - let nsec = dur.subsec_nanos() as libc::c_long + now.tv_nsec as libc::c_long; + let nsec = dur.subsec_nanos() + now.tv_nsec as u32; + let sec = saturating_cast_to_time_t(dur.as_secs()) .checked_add((nsec / 1_000_000_000) as libc::time_t) .and_then(|s| s.checked_add(now.tv_sec)); let nsec = nsec % 1_000_000_000; let timeout = sec.map(|s| { - libc::timespec { tv_sec: s, tv_nsec: nsec } + libc::timespec { tv_sec: s, tv_nsec: nsec as _} }).unwrap_or(TIMESPEC_MAX); let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex), diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index c4616c3b395..a1ca839dc18 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -132,14 +132,14 @@ impl FileAttr { pub fn modified(&self) -> io::Result { Ok(SystemTime::from(libc::timespec { tv_sec: self.stat.st_mtime as libc::time_t, - tv_nsec: self.stat.st_mtime_nsec as libc::c_long, + tv_nsec: self.stat.st_mtime_nsec as _, })) } pub fn accessed(&self) -> io::Result { Ok(SystemTime::from(libc::timespec { tv_sec: self.stat.st_atime as libc::time_t, - tv_nsec: self.stat.st_atime_nsec as libc::c_long, + tv_nsec: self.stat.st_atime_nsec as _, })) } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 6c4a3324296..cc889454ce9 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -149,7 +149,7 @@ impl Thread { pub fn sleep(dur: Duration) { let mut secs = dur.as_secs(); - let mut nsecs = dur.subsec_nanos() as libc::c_long; + let mut nsecs = dur.subsec_nanos() as _; // If we're awoken with a signal then the return value will be -1 and // nanosleep will fill in `ts` with the remaining time. diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index c1bea95ce91..837cd7292e2 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -60,7 +60,7 @@ impl Timespec { Timespec { t: libc::timespec { tv_sec: secs, - tv_nsec: nsec as libc::c_long, + tv_nsec: nsec as _, }, } } @@ -83,7 +83,7 @@ impl Timespec { Timespec { t: libc::timespec { tv_sec: secs, - tv_nsec: nsec as libc::c_long, + tv_nsec: nsec as _, }, } } diff --git a/src/test/codegen/issue-37945.rs b/src/test/codegen/issue-37945.rs index e7c91f30918..df02426badc 100644 --- a/src/test/codegen/issue-37945.rs +++ b/src/test/codegen/issue-37945.rs @@ -13,6 +13,7 @@ // ignore-x86 // ignore-arm // ignore-emscripten +// ignore-gnux32 // ignore 32-bit platforms (LLVM has a bug with them) // See issue #37945. diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 85fa38bbd3b..bd4044b4df3 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -73,7 +73,7 @@ pub fn get_env(triple: &str) -> Option<&str> { } pub fn get_pointer_width(triple: &str) -> &'static str { - if triple.contains("64") || triple.starts_with("s390x") { + if (triple.contains("64") && !triple.ends_with("gnux32")) || triple.starts_with("s390x") { "64bit" } else { "32bit" From 34c0de2067b132c8d68689501604d4fffbe9fba8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 20 Oct 2017 10:11:02 -0700 Subject: [PATCH 339/365] Remove "gender" from code of conduct, keep only "gender identity and expression" Mirrors https://github.com/rust-lang/rust-www/pull/954 . See that pull request for motivation. --- CODE_OF_CONDUCT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 6bec9330186..d42476bc413 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -6,7 +6,7 @@ A version of this document [can be found online](https://www.rust-lang.org/condu **Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org) -* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. +* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. * On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all. * Please be kind and courteous. There's no need to be mean or rude. * Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. From 1af1c2de36d39c5e24846d74f1ae549499bab70d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Oct 2017 20:02:46 -0700 Subject: [PATCH 340/365] rustbuild: Compile rustc with ThinLTO This commit enables ThinLTO for the compiler as well as multiple codegen units. This is intended to get the benefits of parallel codegen while also avoiding any major loss of perf. Finally this commit is also intended as further testing for #45320 and shaking out bugs. --- src/bootstrap/bin/rustc.rs | 3 +++ src/bootstrap/builder.rs | 14 ++++++++++++-- src/bootstrap/config.rs | 7 +++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index aeeda85e924..16a23eb364a 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -175,6 +175,9 @@ fn main() { if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { cmd.arg("-C").arg(format!("codegen-units={}", s)); } + if stage != "0" && env::var("RUSTC_THINLTO").is_ok() { + cmd.arg("-Ccodegen-units=16").arg("-Zthinlto"); + } // Emit save-analysis info. if env::var("RUSTC_SAVE_ANALYSIS") == Ok("api".to_string()) { diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6480b5a619c..5891925f7f7 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -471,8 +471,6 @@ impl<'a> Builder<'a> { .env("RUSTC", self.out.join("bootstrap/debug/rustc")) .env("RUSTC_REAL", self.rustc(compiler)) .env("RUSTC_STAGE", stage.to_string()) - .env("RUSTC_CODEGEN_UNITS", - self.config.rust_codegen_units.to_string()) .env("RUSTC_DEBUG_ASSERTIONS", self.config.rust_debug_assertions.to_string()) .env("RUSTC_SYSROOT", self.sysroot(compiler)) @@ -486,6 +484,10 @@ impl<'a> Builder<'a> { }) .env("TEST_MIRI", self.config.test_miri.to_string()); + if let Some(n) = self.config.rust_codegen_units { + cargo.env("RUSTC_CODEGEN_UNITS", n.to_string()); + } + if let Some(host_linker) = self.build.linker(compiler.host) { cargo.env("RUSTC_HOST_LINKER", host_linker); } @@ -618,6 +620,14 @@ impl<'a> Builder<'a> { // FIXME: cargo bench does not accept `--release` if self.config.rust_optimize && cmd != "bench" { cargo.arg("--release"); + + if mode != Mode::Libstd && + self.config.rust_codegen_units.is_none() && + self.build.is_rust_llvm(compiler.host) + + { + cargo.env("RUSTC_THINLTO", "1"); + } } if self.config.locked_deps { cargo.arg("--locked"); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index d6c83e3acfc..66e5efcea4e 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -81,7 +81,7 @@ pub struct Config { // rust codegen options pub rust_optimize: bool, - pub rust_codegen_units: u32, + pub rust_codegen_units: Option, pub rust_debug_assertions: bool, pub rust_debuginfo: bool, pub rust_debuginfo_lines: bool, @@ -307,7 +307,6 @@ impl Config { config.submodules = true; config.docs = true; config.rust_rpath = true; - config.rust_codegen_units = 1; config.channel = "dev".to_string(); config.codegen_tests = true; config.ignore_git = false; @@ -470,8 +469,8 @@ impl Config { config.musl_root = rust.musl_root.clone().map(PathBuf::from); match rust.codegen_units { - Some(0) => config.rust_codegen_units = num_cpus::get() as u32, - Some(n) => config.rust_codegen_units = n, + Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32), + Some(n) => config.rust_codegen_units = Some(n), None => {} } } From d01427f53e81a24e1c49d1672f37d4809c04a004 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 20 Oct 2017 11:40:04 -0700 Subject: [PATCH 341/365] [test] Add some `#[inline]` to `HashMap` --- src/libstd/collections/hash/map.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 3c0fa0860d3..d96a4f40d3f 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1113,6 +1113,7 @@ impl HashMap /// assert_eq!(map.get(&2), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn get(&self, k: &Q) -> Option<&V> where K: Borrow, Q: Hash + Eq @@ -2554,6 +2555,7 @@ impl super::Recover for HashMap { type Key = K; + #[inline] fn get(&self, key: &Q) -> Option<&K> { self.search(key).into_occupied_bucket().map(|bucket| bucket.into_refs().0) } @@ -2566,6 +2568,7 @@ impl super::Recover for HashMap self.search_mut(key).into_occupied_bucket().map(|bucket| pop_internal(bucket).0) } + #[inline] fn replace(&mut self, key: K) -> Option { self.reserve(1); From f8f9005e57852d4775b952d3b430e458a6a414bb Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 20 Oct 2017 15:29:35 -0400 Subject: [PATCH 342/365] Fix most rendering warnings from switching to CommonMark --- src/liballoc/allocator.rs | 6 +++--- src/liballoc/fmt.rs | 1 - src/libcore/hash/sip.rs | 6 +++--- src/libcore/ptr.rs | 12 ++++++------ src/libstd/ascii.rs | 4 +++- src/libstd/ffi/os_str.rs | 3 +-- src/libstd/net/udp.rs | 2 +- src/libstd/process.rs | 2 +- src/libstd/sys/windows/ext/fs.rs | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs index 5a9cd82b9d1..3a2022ad429 100644 --- a/src/liballoc/allocator.rs +++ b/src/liballoc/allocator.rs @@ -70,7 +70,7 @@ impl Layout { /// /// * `align` must be a power of two, /// - /// * `align` must not exceed 2^31 (i.e. `1 << 31`), + /// * `align` must not exceed 231 (i.e. `1 << 31`), /// /// * `size`, when rounded up to the nearest multiple of `align`, /// must not overflow (i.e. the rounded value must be less than @@ -113,7 +113,7 @@ impl Layout { /// # Safety /// /// This function is unsafe as it does not verify that `align` is - /// a power-of-two that is also less than or equal to 2^31, nor + /// a power-of-two that is also less than or equal to 231, nor /// that `size` aligned to `align` fits within the address space /// (i.e. the `Layout::from_size_align` preconditions). #[inline] @@ -227,7 +227,7 @@ impl Layout { }; // We can assume that `self.align` is a power-of-two that does - // not exceed 2^31. Furthermore, `alloc_size` has already been + // not exceed 231. Furthermore, `alloc_size` has already been // rounded up to a multiple of `self.align`; therefore, the // call to `Layout::from_size_align` below should never panic. Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size)) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 578d90c5ba9..58299d5d836 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -475,7 +475,6 @@ //! them with the same character. For example, the `{` character is escaped with //! `{{` and the `}` character is escaped with `}}`. //! -//! [`format!`]: ../../macro.format.html //! [`usize`]: ../../std/primitive.usize.html //! [`isize`]: ../../std/primitive.isize.html //! [`i8`]: ../../std/primitive.i8.html diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index d82de082da6..4e4d9b3f1e2 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -22,7 +22,7 @@ use mem; /// This is currently the default hashing function used by standard library /// (eg. `collections::HashMap` uses it by default). /// -/// See: https://131002.net/siphash/ +/// See: #[unstable(feature = "sip_hash_13", issue = "34767")] #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] @@ -33,7 +33,7 @@ pub struct SipHasher13 { /// An implementation of SipHash 2-4. /// -/// See: https://131002.net/siphash/ +/// See: #[unstable(feature = "sip_hash_13", issue = "34767")] #[rustc_deprecated(since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead")] @@ -44,7 +44,7 @@ pub struct SipHasher24 { /// An implementation of SipHash 2-4. /// -/// See: https://131002.net/siphash/ +/// See: /// /// SipHash is a general-purpose hashing function: it runs at a good /// speed (competitive with Spooky and City) and permits strong _keyed_ diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 3d6abbb7e49..01990f61fee 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -551,7 +551,7 @@ impl *const T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 263 bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -684,7 +684,7 @@ impl *const T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 263 bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -743,7 +743,7 @@ impl *const T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 263 bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -1182,7 +1182,7 @@ impl *mut T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 263 bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -1382,7 +1382,7 @@ impl *mut T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 263 bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory @@ -1441,7 +1441,7 @@ impl *mut T { /// /// Most platforms fundamentally can't even construct such an allocation. /// For instance, no known 64-bit platform can ever serve a request - /// for 2^63 bytes due to page-table limitations or splitting the address space. + /// for 263 bytes due to page-table limitations or splitting the address space. /// However, some 32-bit and 16-bit platforms may successfully serve a request for /// more than `isize::MAX` bytes with things like Physical Address /// Extension. As such, memory acquired directly from allocators or memory diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 4e3781ecafa..327deb9b419 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -411,10 +411,12 @@ pub trait AsciiExt { fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); } /// Checks if the value is an ASCII punctuation character: + /// /// U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /` /// U+003A ... U+0040 `: ; < = > ? @` - /// U+005B ... U+0060 `[ \\ ] ^ _ \`` + /// U+005B ... U+0060 ``[ \\ ] ^ _ ` `` /// U+007B ... U+007E `{ | } ~` + /// /// For strings, true if all characters in the string are /// ASCII punctuation. /// diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index a97075ff8d8..8c34660f821 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -41,7 +41,7 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// # Creating an `OsString` /// /// **From a Rust string**: `OsString` implements -/// [`From`]`<`[`String`]`>`, so you can use `my_string.`[`from`] to +/// [`From`]`<`[`String`]`>`, so you can use `my_string.from` to /// create an `OsString` from a normal Rust string. /// /// **From slices:** Just like you can start with an empty Rust @@ -63,7 +63,6 @@ use sys_common::{AsInner, IntoInner, FromInner}; /// /// [`OsStr`]: struct.OsStr.html /// [`From`]: ../convert/trait.From.html -/// [`from`]: ../convert/trait.From.html#tymethod.from /// [`String`]: ../string/struct.String.html /// [`&str`]: ../primitive.str.html /// [`u8`]: ../primitive.u8.html diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index a8a242846d7..870d11298fe 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -168,7 +168,7 @@ impl UdpSocket { /// This will return an error when the IP version of the local socket /// does not match that returned from [`ToSocketAddrs`]. /// - /// See https://github.com/rust-lang/rust/issues/34202 for more details. + /// See for more details. /// /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html /// diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 533f6590f83..7c107177c64 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -343,7 +343,7 @@ impl Command { /// The search path to be used may be controlled by setting the /// `PATH` environment variable on the Command, /// but this has some implementation limitations on Windows - /// (see https://github.com/rust-lang/rust/issues/37519). + /// (see ). /// /// # Examples /// diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index a532163f61e..24c41046f26 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -32,7 +32,7 @@ pub trait FileExt { /// function, it is set to the end of the read. /// /// Reading beyond the end of the file will always return with a length of - /// 0. + /// 0\. /// /// Note that similar to `File::read`, it is not an error to return with a /// short read. When returning from such a short read, the file pointer is From ebbcad9ae018e9c6bbd65c573a21783c8fbc0095 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 15 Oct 2017 19:45:14 +0800 Subject: [PATCH 343/365] Fix rustbuild --color conflict when building on Travis outside of Docker. --- src/bootstrap/compile.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index f837371bebe..a8162f0a92f 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -29,7 +29,7 @@ use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use serde_json; -use util::{exe, libdir, is_dylib, copy, read_stamp_file}; +use util::{exe, libdir, is_dylib, copy, read_stamp_file, CiEnv}; use {Build, Compiler, Mode}; use native; use tool; @@ -792,7 +792,7 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) { cargo.arg("--message-format").arg("json") .stdout(Stdio::piped()); - if stderr_isatty() { + if stderr_isatty() && build.ci_env == CiEnv::None { // since we pass message-format=json to cargo, we need to tell the rustc // wrapper to give us colored output if necessary. This is because we // only want Cargo's JSON output, not rustcs. From ff0e9df1520b1d627481a274e9ab0700c9933b6a Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Fri, 20 Oct 2017 18:35:18 -0400 Subject: [PATCH 344/365] update jobserver version to work around macos bug --- src/Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 328ce353e2a..3813aa5d091 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1,7 +1,3 @@ -[root] -name = "workspace_symbol" -version = "0.1.0" - [[package]] name = "advapi32-sys" version = "0.2.0" @@ -199,7 +195,7 @@ dependencies = [ "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -759,7 +755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jobserver" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1429,7 +1425,7 @@ dependencies = [ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", - "jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_back 0.0.0", @@ -1757,7 +1753,7 @@ dependencies = [ "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2440,6 +2436,10 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "workspace_symbol" +version = "0.1.0" + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -2529,7 +2529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" -"checksum jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "094f87ed101b6832def8632f43db43dc204d27897eb95aca69b26ce2e4011e84" +"checksum jobserver 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "931b04e5e57d88cc909528f0d701db36a870b72a052648ded8baf80f9f445e0f" "checksum jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1acd0f9934da94466d2370f36832b9b19271b4abdfdb5e69f0bcd991ebcd515" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kuchiki 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2ea4f2f7883cd7c6772b06c14abca01a2cc1f75c426cebffcf6b3b925ef9fc" From 23bf3300ad913f9315d67e059cbe3a19d098779a Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 17 Oct 2017 21:43:02 -0700 Subject: [PATCH 345/365] Add explanatory text for error E0599 Add a text description of this error instead of just example error code --- src/librustc_typeck/diagnostics.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 8f91d07b53f..594cd0878cb 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -3986,6 +3986,10 @@ details. "##, E0599: r##" +This error occurs when a method is used on a type which doesn't implement it: + +Erroneous code example: + ```compile_fail,E0599 struct Mouth; From fe3ed20d8d72e4b2e4371da423d006021c7b6b97 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 11 Oct 2017 21:21:49 -0400 Subject: [PATCH 346/365] Expand docs/examples for TCP `set_nonblocking` methods. Part of https://github.com/rust-lang/rust/issues/44050. --- src/libstd/net/tcp.rs | 73 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index b904641a336..bd49f390e8b 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -498,18 +498,46 @@ impl TcpStream { /// Moves this TCP stream into or out of nonblocking mode. /// - /// On Unix this corresponds to calling fcntl, and on Windows this - /// corresponds to calling ioctlsocket. + /// This will result in `read`, `write`, `recv` and `send` operations + /// becoming nonblocking, i.e. immediately returning from their calls. + /// If the IO operation is successful, `Ok` is returned and no further + /// action is required. If the IO operation could not be completed and needs + /// to be retried, an error with kind [`io::ErrorKind::WouldBlock`] is + /// returned. + /// + /// On Unix platforms, calling this method corresponds to calling `fcntl` + /// `FIONBIO`. On Windows calling this method corresponds to calling + /// `ioctlsocket` `FIONBIO`. /// /// # Examples /// + /// Reading bytes from a TCP stream in non-blocking mode: + /// /// ```no_run + /// use std::io::{self, Read}; /// use std::net::TcpStream; /// - /// let stream = TcpStream::connect("127.0.0.1:8080") - /// .expect("Couldn't connect to the server..."); + /// let mut stream = TcpStream::connect("127.0.0.1:7878") + /// .expect("Couldn't connect to the server..."); /// stream.set_nonblocking(true).expect("set_nonblocking call failed"); + /// + /// # fn wait_for_fd() { unimplemented!() } + /// let mut buf = vec![]; + /// loop { + /// match stream.read_to_end(&mut buf) { + /// Ok(_) => break, + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// // wait until network socket is ready, typically implemented + /// // via platform-specific APIs such as epoll or IOCP + /// wait_for_fd(); + /// } + /// Err(e) => panic!("encountered IO error: {}", e), + /// }; + /// }; + /// println!("bytes: {:?}", buf); /// ``` + /// + /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) @@ -780,17 +808,48 @@ impl TcpListener { /// Moves this TCP stream into or out of nonblocking mode. /// - /// On Unix this corresponds to calling fcntl, and on Windows this - /// corresponds to calling ioctlsocket. + /// This will result in the `accept` operation becoming nonblocking, + /// i.e. immediately returning from their calls. If the IO operation is + /// successful, `Ok` is returned and no further action is required. If the + /// IO operation could not be completed and needs to be retried, an error + /// with kind [`io::ErrorKind::WouldBlock`] is returned. + /// + /// On Unix platforms, calling this method corresponds to calling `fcntl` + /// `FIONBIO`. On Windows calling this method corresponds to calling + /// `ioctlsocket` `FIONBIO`. /// /// # Examples /// + /// Bind a TCP listener to an address, listen for connections, and read + /// bytes in nonblocking mode: + /// /// ```no_run + /// use std::io; /// use std::net::TcpListener; /// - /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); + /// let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); /// listener.set_nonblocking(true).expect("Cannot set non-blocking"); + /// + /// # fn wait_for_fd() { unimplemented!() } + /// # fn handle_connection(stream: std::net::TcpStream) { unimplemented!() } + /// for stream in listener.incoming() { + /// match stream { + /// Ok(s) => { + /// // do something with the TcpStream + /// handle_connection(s); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// // wait until network socket is ready, typically implemented + /// // via platform-specific APIs such as epoll or IOCP + /// wait_for_fd(); + /// continue; + /// } + /// Err(e) => panic!("encountered IO error: {}", e), + /// } + /// } /// ``` + /// + /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) From 2045e07745914c935e230ec42a1cdaf1539b6815 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sat, 21 Oct 2017 16:47:18 +0100 Subject: [PATCH 347/365] rustbuild: Build stage 1 error index generator at stage 0 At stage 1 rustdoc is built at stage 0 so the error index generator should be as well. This fixes `x.py --stage 1 doc` as rustdoc doesn't even build at stage 1. --- src/bootstrap/tool.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 912ffa51975..688ee6ba295 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -193,12 +193,12 @@ macro_rules! tool { } pub fn tool_default_stage(&self, tool: Tool) -> u32 { - // Compile the error-index in the top stage as it depends on - // rustdoc, so we want to avoid recompiling rustdoc twice if we - // can. Otherwise compile everything else in stage0 as there's - // no need to rebootstrap everything + // Compile the error-index in the same stage as rustdoc to avoid + // recompiling rustdoc twice if we can. Otherwise compile + // everything else in stage0 as there's no need to rebootstrap + // everything. match tool { - Tool::ErrorIndex => self.top_stage, + Tool::ErrorIndex if self.top_stage >= 2 => self.top_stage, _ => 0, } } From f820d2e5672c4a9c29c0ea4dc2fc8f7608eec70b Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sat, 21 Oct 2017 17:16:46 +0100 Subject: [PATCH 348/365] rustbuild: Fix path for the nomicon --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index b9a52a66793..1395be5a6f5 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -66,7 +66,7 @@ macro_rules! book { } book!( - Nomicon, "src/doc/book", "nomicon"; + Nomicon, "src/doc/nomicon", "nomicon"; Reference, "src/doc/reference", "reference"; Rustdoc, "src/doc/rustdoc", "rustdoc"; ); From 8197a0bbaf2c6ab717b40080e0d1201b634500b6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Oct 2017 18:44:33 -0700 Subject: [PATCH 349/365] rustc: Move bytecode compression into codegen This commit moves compression of the bytecode from the `link` module to the `write` module, namely allowing it to be (a) cached by incremental compilation and (b) produced in parallel. The parallelization may show up as some nice wins during normal compilation and the caching in incremental mode should be beneficial for incremental compiles! (no more need to recompress the entire crate's bitcode on all builds) --- src/librustc/dep_graph/graph.rs | 10 +- src/librustc/dep_graph/mod.rs | 1 + .../persist/work_product.rs | 14 +- src/librustc_trans/back/link.rs | 138 +++++---------- src/librustc_trans/back/lto.rs | 18 +- src/librustc_trans/back/write.rs | 157 +++++++++++------- src/librustc_trans/lib.rs | 32 +++- 7 files changed, 194 insertions(+), 176 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 8aff042955c..0fdb6dc068d 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -12,7 +12,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHashingContextProvider}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use session::config::OutputType; use std::cell::{Ref, RefCell}; use std::env; use std::hash::Hash; @@ -647,7 +646,14 @@ impl DepGraph { pub struct WorkProduct { pub cgu_name: String, /// Saved files associated with this CGU - pub saved_files: Vec<(OutputType, String)>, + pub saved_files: Vec<(WorkProductFileKind, String)>, +} + +#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)] +pub enum WorkProductFileKind { + Object, + Bytecode, + BytecodeCompressed, } pub(super) struct CurrentDepGraph { diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 690db8a5522..fe0212423f6 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -21,6 +21,7 @@ mod serialized; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs}; pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor}; +pub use self::graph::WorkProductFileKind; pub use self::prev::PreviousDepGraph; pub use self::query::DepGraphQuery; pub use self::safe::AssertDepGraphSafe; diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 9865e8fb173..f23b8dc85b8 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -11,9 +11,8 @@ //! This module contains files for saving intermediate work-products. use persist::fs::*; -use rustc::dep_graph::{WorkProduct, WorkProductId, DepGraph}; +use rustc::dep_graph::{WorkProduct, WorkProductId, DepGraph, WorkProductFileKind}; use rustc::session::Session; -use rustc::session::config::OutputType; use rustc::util::fs::link_or_copy; use std::path::PathBuf; use std::fs as std_fs; @@ -21,19 +20,24 @@ use std::fs as std_fs; pub fn save_trans_partition(sess: &Session, dep_graph: &DepGraph, cgu_name: &str, - files: &[(OutputType, PathBuf)]) { + files: &[(WorkProductFileKind, PathBuf)]) { debug!("save_trans_partition({:?},{:?})", cgu_name, files); if sess.opts.incremental.is_none() { - return; + return } let work_product_id = WorkProductId::from_cgu_name(cgu_name); let saved_files: Option> = files.iter() .map(|&(kind, ref path)| { - let file_name = format!("cgu-{}.{}", cgu_name, kind.extension()); + let extension = match kind { + WorkProductFileKind::Object => "o", + WorkProductFileKind::Bytecode => "bc", + WorkProductFileKind::BytecodeCompressed => "bc-compressed", + }; + let file_name = format!("cgu-{}.{}", cgu_name, extension); let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); match link_or_copy(path, &path_in_incr_dir) { Ok(_) => Some((kind, file_name)), diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 570a6bbac1e..b203bd640cf 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -9,7 +9,7 @@ // except according to those terms. use super::archive::{ArchiveBuilder, ArchiveConfig}; -use super::bytecode::{self, RLIB_BYTECODE_EXTENSION}; +use super::bytecode::RLIB_BYTECODE_EXTENSION; use super::linker::Linker; use super::command::Command; use super::rpath::RPathConfig; @@ -37,7 +37,7 @@ use std::env; use std::ffi::OsString; use std::fmt; use std::fs::{self, File}; -use std::io::{self, Read, Write, BufWriter}; +use std::io::{self, Write, BufWriter}; use std::path::{Path, PathBuf}; use std::process::{Output, Stdio}; use std::str; @@ -126,14 +126,6 @@ fn command_path(sess: &Session) -> OsString { env::join_paths(new_path).unwrap() } -fn metadata_obj(outputs: &OutputFilenames) -> PathBuf { - outputs.temp_path(OutputType::Object, Some(METADATA_MODULE_NAME)) -} - -fn allocator_obj(outputs: &OutputFilenames) -> PathBuf { - outputs.temp_path(OutputType::Object, Some(ALLOCATOR_MODULE_NAME)) -} - pub fn remove(sess: &Session, path: &Path) { match fs::remove_file(path) { Ok(..) => {} @@ -175,13 +167,23 @@ pub fn link_binary(sess: &Session, // Remove the temporary object file and metadata if we aren't saving temps if !sess.opts.cg.save_temps { if sess.opts.output_types.should_trans() { - for obj in trans.modules.iter() { - remove(sess, &obj.object); + for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) { + remove(sess, obj); } } - remove(sess, &metadata_obj(outputs)); - if trans.allocator_module.is_some() { - remove(sess, &allocator_obj(outputs)); + for obj in trans.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) { + remove(sess, obj); + } + if let Some(ref obj) = trans.metadata_module.object { + remove(sess, obj); + } + if let Some(ref allocator) = trans.allocator_module { + if let Some(ref obj) = allocator.object { + remove(sess, obj); + } + if let Some(ref bc) = allocator.bytecode_compressed { + remove(sess, bc); + } } } @@ -256,8 +258,8 @@ fn link_binary_output(sess: &Session, crate_type: config::CrateType, outputs: &OutputFilenames, crate_name: &str) -> Vec { - for module in trans.modules.iter() { - check_file_is_writeable(&module.object, sess); + for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) { + check_file_is_writeable(obj, sess); } let tmpdir = match TempDir::new("rustc") { @@ -280,20 +282,14 @@ fn link_binary_output(sess: &Session, link_rlib(sess, trans, RlibFlavor::Normal, - outputs, &out_filename, tmpdir.path()).build(); } config::CrateTypeStaticlib => { - link_staticlib(sess, - trans, - outputs, - &out_filename, - tmpdir.path()); + link_staticlib(sess, trans, &out_filename, tmpdir.path()); } _ => { - link_natively(sess, crate_type, &out_filename, - trans, outputs, tmpdir.path()); + link_natively(sess, crate_type, &out_filename, trans, tmpdir.path()); } } out_filenames.push(out_filename); @@ -349,14 +345,13 @@ enum RlibFlavor { fn link_rlib<'a>(sess: &'a Session, trans: &CrateTranslation, flavor: RlibFlavor, - outputs: &OutputFilenames, out_filename: &Path, tmpdir: &Path) -> ArchiveBuilder<'a> { info!("preparing rlib to {:?}", out_filename); let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None)); - for module in trans.modules.iter() { - ab.add_file(&module.object); + for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) { + ab.add_file(obj); } // Note that in this loop we are ignoring the value of `lib.cfg`. That is, @@ -421,56 +416,9 @@ fn link_rlib<'a>(sess: &'a Session, ab.add_file(&metadata); // For LTO purposes, the bytecode of this library is also inserted - // into the archive. If codegen_units > 1, we insert each of the - // bitcode files. - for module in trans.modules.iter() { - // Note that we make sure that the bytecode filename in the - // archive is never exactly 16 bytes long by adding a 16 byte - // extension to it. This is to work around a bug in LLDB that - // would cause it to crash if the name of a file in an archive - // was exactly 16 bytes. - let bc_filename = module.object.with_extension("bc"); - let bc_encoded_filename = tmpdir.join({ - module.object.with_extension(RLIB_BYTECODE_EXTENSION).file_name().unwrap() - }); - - let mut bc_data = Vec::new(); - match fs::File::open(&bc_filename).and_then(|mut f| { - f.read_to_end(&mut bc_data) - }) { - Ok(..) => {} - Err(e) => sess.fatal(&format!("failed to read bytecode: {}", - e)) - } - - let encoded = bytecode::encode(&module.llmod_id, &bc_data); - - let mut bc_file_deflated = match fs::File::create(&bc_encoded_filename) { - Ok(file) => file, - Err(e) => { - sess.fatal(&format!("failed to create compressed \ - bytecode file: {}", e)) - } - }; - - match bc_file_deflated.write_all(&encoded) { - Ok(()) => {} - Err(e) => { - sess.fatal(&format!("failed to write compressed \ - bytecode: {}", e)); - } - }; - - ab.add_file(&bc_encoded_filename); - - // See the bottom of back::write::run_passes for an explanation - // of when we do and don't keep .#module-name#.bc files around. - let user_wants_numbered_bitcode = - sess.opts.output_types.contains_key(&OutputType::Bitcode) && - sess.codegen_units() > 1; - if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode { - remove(sess, &bc_filename); - } + // into the archive. + for bytecode in trans.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) { + ab.add_file(bytecode); } // After adding all files to the archive, we need to update the @@ -482,8 +430,11 @@ fn link_rlib<'a>(sess: &'a Session, } RlibFlavor::StaticlibBase => { - if trans.allocator_module.is_some() { - ab.add_file(&allocator_obj(outputs)); + let obj = trans.allocator_module + .as_ref() + .and_then(|m| m.object.as_ref()); + if let Some(obj) = obj { + ab.add_file(obj); } } } @@ -505,13 +456,11 @@ fn link_rlib<'a>(sess: &'a Session, // metadata file). fn link_staticlib(sess: &Session, trans: &CrateTranslation, - outputs: &OutputFilenames, out_filename: &Path, tempdir: &Path) { let mut ab = link_rlib(sess, trans, RlibFlavor::StaticlibBase, - outputs, out_filename, tempdir); let mut all_native_libs = vec![]; @@ -616,7 +565,6 @@ fn link_natively(sess: &Session, crate_type: config::CrateType, out_filename: &Path, trans: &CrateTranslation, - outputs: &OutputFilenames, tmpdir: &Path) { info!("preparing {:?} to {:?}", crate_type, out_filename); let flavor = sess.linker_flavor(); @@ -656,7 +604,7 @@ fn link_natively(sess: &Session, { let mut linker = trans.linker_info.to_linker(cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, - out_filename, outputs, trans); + out_filename, trans); cmd = linker.finalize(); } if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) { @@ -878,7 +826,6 @@ fn link_args(cmd: &mut Linker, crate_type: config::CrateType, tmpdir: &Path, out_filename: &Path, - outputs: &OutputFilenames, trans: &CrateTranslation) { // The default library location, we need this to find the runtime. @@ -889,8 +836,8 @@ fn link_args(cmd: &mut Linker, let t = &sess.target.target; cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); - for module in trans.modules.iter() { - cmd.add_object(&module.object); + for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) { + cmd.add_object(obj); } cmd.output_filename(out_filename); @@ -913,11 +860,16 @@ fn link_args(cmd: &mut Linker, // object file, so we link that in here. if crate_type == config::CrateTypeDylib || crate_type == config::CrateTypeProcMacro { - cmd.add_object(&metadata_obj(outputs)); + if let Some(obj) = trans.metadata_module.object.as_ref() { + cmd.add_object(obj); + } } - if trans.allocator_module.is_some() { - cmd.add_object(&allocator_obj(outputs)); + let obj = trans.allocator_module + .as_ref() + .and_then(|m| m.object.as_ref()); + if let Some(obj) = obj { + cmd.add_object(obj); } // Try to strip as much out of the generated object by removing unused @@ -1185,9 +1137,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker, for f in archive.src_files() { if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME { - archive.remove_file(&f); - continue - } + archive.remove_file(&f); + continue + } } archive.build(); diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 01d3d656dfe..48c3fd638c3 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -343,8 +343,7 @@ fn thin_lto(diag_handler: &Handler, info!("local module: {} - {}", i, module.llmod_id); let llvm = module.llvm().expect("can't lto pretranslated module"); let name = CString::new(module.llmod_id.clone()).unwrap(); - let buffer = llvm::LLVMRustThinLTOBufferCreate(llvm.llmod); - let buffer = ThinBuffer(buffer); + let buffer = ThinBuffer::new(llvm.llmod); thin_modules.push(llvm::ThinLTOModule { identifier: name.as_ptr(), data: buffer.data().as_ptr(), @@ -499,13 +498,13 @@ unsafe impl Send for ModuleBuffer {} unsafe impl Sync for ModuleBuffer {} impl ModuleBuffer { - fn new(m: ModuleRef) -> ModuleBuffer { + pub fn new(m: ModuleRef) -> ModuleBuffer { ModuleBuffer(unsafe { llvm::LLVMRustModuleBufferCreate(m) }) } - fn data(&self) -> &[u8] { + pub fn data(&self) -> &[u8] { unsafe { let ptr = llvm::LLVMRustModuleBufferPtr(self.0); let len = llvm::LLVMRustModuleBufferLen(self.0); @@ -545,13 +544,20 @@ impl Drop for ThinData { } } -struct ThinBuffer(*mut llvm::ThinLTOBuffer); +pub struct ThinBuffer(*mut llvm::ThinLTOBuffer); unsafe impl Send for ThinBuffer {} unsafe impl Sync for ThinBuffer {} impl ThinBuffer { - fn data(&self) -> &[u8] { + pub fn new(m: ModuleRef) -> ThinBuffer { + unsafe { + let buffer = llvm::LLVMRustThinLTOBufferCreate(m); + ThinBuffer(buffer) + } + } + + pub fn data(&self) -> &[u8] { unsafe { let ptr = llvm::LLVMRustThinLTOBufferPtr(self.0) as *const _; let len = llvm::LLVMRustThinLTOBufferLen(self.0); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index f8dbe68dba9..5550ab9fa55 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -8,14 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use back::lto; +use back::bytecode::{self, RLIB_BYTECODE_EXTENSION}; +use back::lto::{self, ModuleBuffer, ThinBuffer}; use back::link::{self, get_linker, remove}; use back::linker::LinkerInfo; use back::symbol_export::ExportedSymbols; use base; use consts; use rustc_incremental::{save_trans_partition, in_incr_comp_dir}; -use rustc::dep_graph::DepGraph; +use rustc::dep_graph::{DepGraph, WorkProductFileKind}; use rustc::middle::cstore::{LinkMeta, EncodedMetadata}; use rustc::session::config::{self, OutputFilenames, OutputType, OutputTypes, Passes, SomePasses, AllPasses, Sanitizer}; @@ -44,7 +45,7 @@ use rustc_demangle; use std::any::Any; use std::ffi::{CString, CStr}; -use std::fs; +use std::fs::{self, File}; use std::io; use std::io::Write; use std::mem; @@ -228,6 +229,7 @@ pub struct ModuleConfig { // Flags indicating which outputs to produce. emit_no_opt_bc: bool, emit_bc: bool, + emit_bc_compressed: bool, emit_lto_bc: bool, emit_ir: bool, emit_asm: bool, @@ -257,6 +259,7 @@ impl ModuleConfig { emit_no_opt_bc: false, emit_bc: false, + emit_bc_compressed: false, emit_lto_bc: false, emit_ir: false, emit_asm: false, @@ -627,20 +630,34 @@ unsafe fn codegen(cgcx: &CodegenContext, let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); - if write_bc { - let bc_out_c = path2cstr(&bc_out); - if llvm::LLVMRustThinLTOAvailable() { - with_codegen(tm, llmod, config.no_builtins, |cpm| { - llvm::LLVMRustWriteThinBitcodeToFile( - cpm, - llmod, - bc_out_c.as_ptr(), - ) - }); + + if write_bc || config.emit_bc_compressed { + let thin; + let old; + let data = if llvm::LLVMRustThinLTOAvailable() { + thin = ThinBuffer::new(llmod); + thin.data() } else { - llvm::LLVMWriteBitcodeToFile(llmod, bc_out_c.as_ptr()); + old = ModuleBuffer::new(llmod); + old.data() + }; + timeline.record("make-bc"); + + if write_bc { + if let Err(e) = File::create(&bc_out).and_then(|mut f| f.write_all(data)) { + diag_handler.err(&format!("failed to write bytecode: {}", e)); + } + timeline.record("write-bc"); + } + + if config.emit_bc_compressed { + let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); + let data = bytecode::encode(&mtrans.llmod_id, data); + if let Err(e) = File::create(&dst).and_then(|mut f| f.write_all(&data)) { + diag_handler.err(&format!("failed to write bytecode: {}", e)); + } + timeline.record("compress-bc"); } - timeline.record("bc"); } time(config.time_passes, &format!("codegen passes [{}]", module_name.unwrap()), @@ -736,6 +753,7 @@ unsafe fn codegen(cgcx: &CodegenContext, drop(handlers); Ok(mtrans.into_compiled_module(config.emit_obj, config.emit_bc, + config.emit_bc_compressed, &cgcx.output_filenames)) } @@ -822,11 +840,12 @@ pub fn start_async_translation(tcx: TyCtxt, allocator_config.emit_bc = true; } - // Emit bitcode files for the crate if we're emitting an rlib. - // Whenever an rlib is created, the bitcode is inserted into the - // archive in order to allow LTO against it. + // Emit compressed bitcode files for the crate if we're emitting an rlib. + // Whenever an rlib is created, the bitcode is inserted into the archive in + // order to allow LTO against it. if need_crate_bitcode_for_rlib(sess) { - modules_config.emit_bc = true; + modules_config.emit_bc_compressed = true; + allocator_config.emit_bc_compressed = true; } for output_type in output_types_override.keys() { @@ -906,8 +925,7 @@ pub fn start_async_translation(tcx: TyCtxt, fn copy_module_artifacts_into_incr_comp_cache(sess: &Session, dep_graph: &DepGraph, - compiled_modules: &CompiledModules, - crate_output: &OutputFilenames) { + compiled_modules: &CompiledModules) { if sess.opts.incremental.is_none() { return; } @@ -915,20 +933,17 @@ fn copy_module_artifacts_into_incr_comp_cache(sess: &Session, for module in compiled_modules.modules.iter() { let mut files = vec![]; - if module.emit_obj { - let path = crate_output.temp_path(OutputType::Object, Some(&module.name)); - files.push((OutputType::Object, path)); + if let Some(ref path) = module.object { + files.push((WorkProductFileKind::Object, path.clone())); + } + if let Some(ref path) = module.bytecode { + files.push((WorkProductFileKind::Bytecode, path.clone())); + } + if let Some(ref path) = module.bytecode_compressed { + files.push((WorkProductFileKind::BytecodeCompressed, path.clone())); } - if module.emit_bc { - let path = crate_output.temp_path(OutputType::Bitcode, Some(&module.name)); - files.push((OutputType::Bitcode, path)); - } - - save_trans_partition(sess, - dep_graph, - &module.name, - &files); + save_trans_partition(sess, dep_graph, &module.name, &files); } } @@ -1032,8 +1047,6 @@ fn produce_final_output_artifacts(sess: &Session, // well. // Specific rules for keeping .#module-name#.bc: - // - If we're building an rlib (`needs_crate_bitcode`), then keep - // it. // - If the user requested bitcode (`user_wants_bitcode`), and // codegen_units > 1, then keep it. // - If the user requested bitcode but codegen_units == 1, then we @@ -1043,41 +1056,37 @@ fn produce_final_output_artifacts(sess: &Session, // If you change how this works, also update back::link::link_rlib, // where .#module-name#.bc files are (maybe) deleted after making an // rlib. - let needs_crate_bitcode = need_crate_bitcode_for_rlib(sess); let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe); - let keep_numbered_bitcode = needs_crate_bitcode || - (user_wants_bitcode && sess.codegen_units() > 1); + let keep_numbered_bitcode = user_wants_bitcode && sess.codegen_units() > 1; let keep_numbered_objects = needs_crate_object || (user_wants_objects && sess.codegen_units() > 1); for module in compiled_modules.modules.iter() { - let module_name = Some(&module.name[..]); - - if module.emit_obj && !keep_numbered_objects { - let path = crate_output.temp_path(OutputType::Object, module_name); - remove(sess, &path); + if let Some(ref path) = module.object { + if !keep_numbered_objects { + remove(sess, path); + } } - if module.emit_bc && !keep_numbered_bitcode { - let path = crate_output.temp_path(OutputType::Bitcode, module_name); - remove(sess, &path); + if let Some(ref path) = module.bytecode { + if !keep_numbered_bitcode { + remove(sess, path); + } } } - if compiled_modules.metadata_module.emit_bc && !user_wants_bitcode { - let path = crate_output.temp_path(OutputType::Bitcode, - Some(&compiled_modules.metadata_module.name)); - remove(sess, &path); - } - - if let Some(ref allocator_module) = compiled_modules.allocator_module { - if allocator_module.emit_bc && !user_wants_bitcode { - let path = crate_output.temp_path(OutputType::Bitcode, - Some(&allocator_module.name)); + if !user_wants_bitcode { + if let Some(ref path) = compiled_modules.metadata_module.bytecode { remove(sess, &path); } + + if let Some(ref allocator_module) = compiled_modules.allocator_module { + if let Some(ref path) = allocator_module.bytecode { + remove(sess, path); + } + } } } @@ -1149,8 +1158,28 @@ fn execute_work_item(cgcx: &CodegenContext, .as_ref() .unwrap(); let name = &mtrans.name; + let mut object = None; + let mut bytecode = None; + let mut bytecode_compressed = None; for (kind, saved_file) in wp.saved_files { - let obj_out = cgcx.output_filenames.temp_path(kind, Some(name)); + let obj_out = match kind { + WorkProductFileKind::Object => { + let path = cgcx.output_filenames.temp_path(OutputType::Object, Some(name)); + object = Some(path.clone()); + path + } + WorkProductFileKind::Bytecode => { + let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(name)); + bytecode = Some(path.clone()); + path + } + WorkProductFileKind::BytecodeCompressed => { + let path = cgcx.output_filenames.temp_path(OutputType::Bitcode, Some(name)) + .with_extension(RLIB_BYTECODE_EXTENSION); + bytecode_compressed = Some(path.clone()); + path + } + }; let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file); debug!("copying pre-existing module `{}` from {:?} to {}", @@ -1167,16 +1196,18 @@ fn execute_work_item(cgcx: &CodegenContext, } } } - let object = cgcx.output_filenames.temp_path(OutputType::Object, Some(name)); + assert_eq!(object.is_some(), config.emit_obj); + assert_eq!(bytecode.is_some(), config.emit_bc); + assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed); Ok(WorkItemResult::Compiled(CompiledModule { - object, llmod_id: mtrans.llmod_id.clone(), name: module_name, kind: ModuleKind::Regular, pre_existing: true, - emit_bc: config.emit_bc, - emit_obj: config.emit_obj, + object, + bytecode, + bytecode_compressed, })) } else { debug!("llvm-optimizing {:?}", module_name); @@ -2053,8 +2084,7 @@ impl OngoingCrateTranslation { copy_module_artifacts_into_incr_comp_cache(sess, dep_graph, - &compiled_modules, - &self.output_filenames); + &compiled_modules); produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames); @@ -2075,6 +2105,7 @@ impl OngoingCrateTranslation { modules: compiled_modules.modules, allocator_module: compiled_modules.allocator_module, + metadata_module: compiled_modules.metadata_module, }; if self.no_integrated_as { diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 88ec3a65d35..93f2eef76d1 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -64,6 +64,7 @@ extern crate serialize; extern crate cc; // Used to locate MSVC pub use base::trans_crate; +use back::bytecode::RLIB_BYTECODE_EXTENSION; pub use metadata::LlvmMetadataLoader; pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug}; @@ -90,7 +91,7 @@ mod diagnostics; pub mod back { mod archive; - mod bytecode; + pub mod bytecode; mod command; pub(crate) mod linker; pub mod link; @@ -227,21 +228,37 @@ impl ModuleTranslation { pub fn into_compiled_module(self, emit_obj: bool, emit_bc: bool, + emit_bc_compressed: bool, outputs: &OutputFilenames) -> CompiledModule { let pre_existing = match self.source { ModuleSource::Preexisting(_) => true, ModuleSource::Translated(_) => false, }; - let object = outputs.temp_path(OutputType::Object, Some(&self.name)); + let object = if emit_obj { + Some(outputs.temp_path(OutputType::Object, Some(&self.name))) + } else { + None + }; + let bytecode = if emit_bc { + Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))) + } else { + None + }; + let bytecode_compressed = if emit_bc_compressed { + Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)) + .with_extension(RLIB_BYTECODE_EXTENSION)) + } else { + None + }; CompiledModule { llmod_id: self.llmod_id, name: self.name.clone(), kind: self.kind, pre_existing, - emit_obj, - emit_bc, object, + bytecode, + bytecode_compressed, } } } @@ -250,11 +267,11 @@ impl ModuleTranslation { pub struct CompiledModule { pub name: String, pub llmod_id: String, - pub object: PathBuf, pub kind: ModuleKind, pub pre_existing: bool, - pub emit_obj: bool, - pub emit_bc: bool, + pub object: Option, + pub bytecode: Option, + pub bytecode_compressed: Option, } pub enum ModuleSource { @@ -289,6 +306,7 @@ pub struct CrateTranslation { pub crate_name: Symbol, pub modules: Vec, allocator_module: Option, + metadata_module: CompiledModule, pub link: rustc::middle::cstore::LinkMeta, pub metadata: rustc::middle::cstore::EncodedMetadata, windows_subsystem: Option, From 113ebe4f1d9d662de6a9ac0c944eb956cfe71062 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Sat, 21 Oct 2017 22:50:15 +0100 Subject: [PATCH 350/365] Create NormalizeTy query --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/infer/mod.rs | 6 +++--- src/librustc/traits/trans/mod.rs | 6 ++---- src/librustc/ty/context.rs | 3 +++ src/librustc/ty/maps/config.rs | 6 ++++++ src/librustc/ty/maps/mod.rs | 4 ++++ src/librustc_lint/types.rs | 8 ++++---- src/librustc_trans/adt.rs | 2 +- src/librustc_trans/context.rs | 2 +- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_trans/debuginfo/mod.rs | 4 ++-- src/librustc_trans_utils/monomorphize.rs | 2 +- 12 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 6993ef3768a..ebb8868642b 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -635,6 +635,7 @@ define_dep_nodes!( <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, + [] NormalizeTy, ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 39bcd703574..78e6e9ae153 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -480,16 +480,16 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { { assert!(!value.needs_subst()); let value = self.erase_late_bound_regions(value); - self.normalize_associated_type(&value) + self.normalize_associated_type_in(&value) } /// Fully normalizes any associated types in `value`, using an /// empty environment and `Reveal::All` mode (therefore, suitable /// only for monomorphized code during trans, basically). - pub fn normalize_associated_type(self, value: &T) -> T + pub fn normalize_associated_type_in(self, value: &T) -> T where T: TransNormalize<'tcx> { - debug!("normalize_associated_type(t={:?})", value); + debug!("normalize_associated_type_in(t={:?})", value); let param_env = ty::ParamEnv::empty(Reveal::All); let value = self.erase_regions(value); diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index aa3179dd01f..d082fb889b7 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -130,10 +130,8 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> { if !ty.has_projections() { ty } else { - self.tcx.trans_trait_caches.project_cache.memoize(ty, || { - debug!("AssociatedTypeNormalizer: ty={:?}", ty); - self.tcx.normalize_associated_type(&ty) - }) + debug!("AssociatedTypeNormalizer: ty={:?}", ty); + self.tcx.normalize_ty(ty) } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 3d5e8ea583c..b5f04a91203 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2322,4 +2322,7 @@ pub fn provide(providers: &mut ty::maps::Providers) { assert_eq!(cnum, LOCAL_CRATE); tcx.sess.features.borrow().clone_closures }; + providers.normalize_ty = |tcx, ty| { + tcx.normalize_associated_type_in(&ty) + }; } diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 8f8cda0e0f1..0d6fc561a83 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -532,3 +532,9 @@ impl<'tcx> QueryDescription for queries::has_copy_closures<'tcx> { format!("seeing if the crate has enabled `Copy` closures") } } + +impl<'tcx> QueryDescription for queries::normalize_ty<'tcx> { + fn describe(_tcx: TyCtxt, _: Ty) -> String { + format!("normalising types") + } +} \ No newline at end of file diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 839042bf229..f68e15f2695 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -349,6 +349,7 @@ define_maps! { <'tcx> // Normally you would just use `tcx.erase_regions(&value)`, // however, which uses this query as a kind of cache. [] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>, + [] fn normalize_ty: normalize_ty_node(Ty<'tcx>) -> Ty<'tcx>, } ////////////////////////////////////////////////////////////////////// @@ -490,3 +491,6 @@ fn output_filenames_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { fn vtable_methods_node<'tcx>(trait_ref: ty::PolyTraitRef<'tcx>) -> DepConstructor<'tcx> { DepConstructor::VtableMethods{ trait_ref } } +fn normalize_ty_node<'tcx>(_: Ty<'tcx>) -> DepConstructor<'tcx> { + DepConstructor::NormalizeTy +} diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index d3a5d52b295..0baa65508b5 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -431,7 +431,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // fields are actually safe. let mut all_phantom = true; for field in &def.struct_variant().fields { - let field_ty = cx.normalize_associated_type(&field.ty(cx, substs)); + let field_ty = cx.normalize_associated_type_in(&field.ty(cx, substs)); let r = self.check_type_for_ffi(cache, field_ty); match r { FfiSafe => { @@ -463,7 +463,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let mut all_phantom = true; for field in &def.struct_variant().fields { - let field_ty = cx.normalize_associated_type(&field.ty(cx, substs)); + let field_ty = cx.normalize_associated_type_in(&field.ty(cx, substs)); let r = self.check_type_for_ffi(cache, field_ty); match r { FfiSafe => { @@ -516,7 +516,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Check the contained variants. for variant in &def.variants { for field in &variant.fields { - let arg = cx.normalize_associated_type(&field.ty(cx, substs)); + let arg = cx.normalize_associated_type_in(&field.ty(cx, substs)); let r = self.check_type_for_ffi(cache, arg); match r { FfiSafe => {} @@ -629,7 +629,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) { // it is only OK to use this function because extern fns cannot have // any generic types right now: - let ty = self.cx.tcx.normalize_associated_type(&ty); + let ty = self.cx.tcx.normalize_associated_type_in(&ty); match self.check_type_for_ffi(&mut FxHashSet(), ty) { FfiResult::FfiSafe => {} diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 23a45a7962a..6fd406037cd 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -80,7 +80,7 @@ pub fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, ty::TyGenerator(def_id, substs, _) => { if variant_index > 0 { bug!("{} is a generator, which only has one variant", t);} substs.field_tys(def_id, cx.tcx()).map(|t| { - cx.tcx().normalize_associated_type(&t) + cx.tcx().normalize_associated_type_in(&t) }).collect() }, _ => bug!("{} is not a type that can have fields.", t) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 1722d008a54..a1bf64681c0 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -642,7 +642,7 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> { } fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.tcx().normalize_associated_type(&ty) + self.tcx().normalize_associated_type_in(&ty) } } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 201d7867764..a6827abd41b 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -582,7 +582,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } ty::TyGenerator(def_id, substs, _) => { let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx()).map(|t| { - cx.tcx().normalize_associated_type(&t) + cx.tcx().normalize_associated_type_in(&t) }).collect(); prepare_tuple_metadata(cx, t, diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 7e2ac95cd84..0fe5b8f4ca2 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -376,7 +376,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, name_to_append_suffix_to.push_str(","); } - let actual_type = cx.tcx().normalize_associated_type(&actual_type); + let actual_type = cx.tcx().normalize_associated_type_in(&actual_type); // Add actual type name to <...> clause of function name let actual_type_name = compute_debuginfo_type_name(cx, actual_type, @@ -389,7 +389,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { let names = get_type_parameter_names(cx, generics); substs.types().zip(names).map(|(ty, name)| { - let actual_type = cx.tcx().normalize_associated_type(&ty); + let actual_type = cx.tcx().normalize_associated_type_in(&ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); let name = CString::new(name.as_str().as_bytes()).unwrap(); unsafe { diff --git a/src/librustc_trans_utils/monomorphize.rs b/src/librustc_trans_utils/monomorphize.rs index 471be439a8f..079b7ee3eab 100644 --- a/src/librustc_trans_utils/monomorphize.rs +++ b/src/librustc_trans_utils/monomorphize.rs @@ -131,6 +131,6 @@ pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, f: &'tcx ty::FieldDef) -> Ty<'tcx> { - tcx.normalize_associated_type(&f.ty(tcx, param_substs)) + tcx.normalize_associated_type_in(&f.ty(tcx, param_substs)) } From 96a006c186cffef990a5f637084b6d83cc3ae739 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Tue, 3 Oct 2017 22:55:15 +0100 Subject: [PATCH 351/365] added newlines at the end of the file and changed 'normalising' to 'normalizing' --- src/librustc/ty/maps/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 0d6fc561a83..e813f2b104b 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -535,6 +535,6 @@ impl<'tcx> QueryDescription for queries::has_copy_closures<'tcx> { impl<'tcx> QueryDescription for queries::normalize_ty<'tcx> { fn describe(_tcx: TyCtxt, _: Ty) -> String { - format!("normalising types") + format!("normalizing types") } -} \ No newline at end of file +} From 69f5f0d193bbffd880e6f23edad55ebdfd1474f1 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Wed, 11 Oct 2017 18:03:59 +0100 Subject: [PATCH 352/365] added trans_ prefix and pluralised types. Solved failing test on the incremental test-suite. --- src/librustc/infer/mod.rs | 6 +++--- src/librustc/ty/context.rs | 2 +- src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_lint/types.rs | 8 ++++---- src/librustc_trans/adt.rs | 2 +- src/librustc_trans/context.rs | 2 +- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_trans/debuginfo/mod.rs | 4 ++-- src/librustc_trans_utils/monomorphize.rs | 2 +- 9 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 78e6e9ae153..7bc9760b059 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -480,16 +480,16 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { { assert!(!value.needs_subst()); let value = self.erase_late_bound_regions(value); - self.normalize_associated_type_in(&value) + self.trans_normalize_associated_types_in(&value) } /// Fully normalizes any associated types in `value`, using an /// empty environment and `Reveal::All` mode (therefore, suitable /// only for monomorphized code during trans, basically). - pub fn normalize_associated_type_in(self, value: &T) -> T + pub fn trans_normalize_associated_types_in(self, value: &T) -> T where T: TransNormalize<'tcx> { - debug!("normalize_associated_type_in(t={:?})", value); + debug!("trans_normalize_associated_types_in(t={:?})", value); let param_env = ty::ParamEnv::empty(Reveal::All); let value = self.erase_regions(value); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index b5f04a91203..2a3b445ba31 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2323,6 +2323,6 @@ pub fn provide(providers: &mut ty::maps::Providers) { tcx.sess.features.borrow().clone_closures }; providers.normalize_ty = |tcx, ty| { - tcx.normalize_associated_type_in(&ty) + tcx.trans_normalize_associated_types_in(&ty) }; } diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 5f93c3de336..cce96817717 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -697,6 +697,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::FulfillObligation | DepKind::VtableMethods | DepKind::EraseRegionsTy | + DepKind::NormalizeTy | // These are just odd DepKind::Null | diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 0baa65508b5..5beb23c8b82 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -431,7 +431,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // fields are actually safe. let mut all_phantom = true; for field in &def.struct_variant().fields { - let field_ty = cx.normalize_associated_type_in(&field.ty(cx, substs)); + let field_ty = cx.trans_normalize_associated_types_in(&field.ty(cx, substs)); let r = self.check_type_for_ffi(cache, field_ty); match r { FfiSafe => { @@ -463,7 +463,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let mut all_phantom = true; for field in &def.struct_variant().fields { - let field_ty = cx.normalize_associated_type_in(&field.ty(cx, substs)); + let field_ty = cx.trans_normalize_associated_types_in(&field.ty(cx, substs)); let r = self.check_type_for_ffi(cache, field_ty); match r { FfiSafe => { @@ -516,7 +516,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Check the contained variants. for variant in &def.variants { for field in &variant.fields { - let arg = cx.normalize_associated_type_in(&field.ty(cx, substs)); + let arg = cx.trans_normalize_associated_types_in(&field.ty(cx, substs)); let r = self.check_type_for_ffi(cache, arg); match r { FfiSafe => {} @@ -629,7 +629,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) { // it is only OK to use this function because extern fns cannot have // any generic types right now: - let ty = self.cx.tcx.normalize_associated_type_in(&ty); + let ty = self.cx.tcx.trans_normalize_associated_types_in(&ty); match self.check_type_for_ffi(&mut FxHashSet(), ty) { FfiResult::FfiSafe => {} diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 6fd406037cd..91adfe139fa 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -80,7 +80,7 @@ pub fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, ty::TyGenerator(def_id, substs, _) => { if variant_index > 0 { bug!("{} is a generator, which only has one variant", t);} substs.field_tys(def_id, cx.tcx()).map(|t| { - cx.tcx().normalize_associated_type_in(&t) + cx.tcx().trans_normalize_associated_types_in(&t) }).collect() }, _ => bug!("{} is not a type that can have fields.", t) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index a1bf64681c0..d326cfe02fc 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -642,7 +642,7 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> { } fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.tcx().normalize_associated_type_in(&ty) + self.tcx().trans_normalize_associated_types_in(&ty) } } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index a6827abd41b..4f23152fed1 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -582,7 +582,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } ty::TyGenerator(def_id, substs, _) => { let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx()).map(|t| { - cx.tcx().normalize_associated_type_in(&t) + cx.tcx().trans_normalize_associated_types_in(&t) }).collect(); prepare_tuple_metadata(cx, t, diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 0fe5b8f4ca2..631d6b8143e 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -376,7 +376,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, name_to_append_suffix_to.push_str(","); } - let actual_type = cx.tcx().normalize_associated_type_in(&actual_type); + let actual_type = cx.tcx().trans_normalize_associated_types_in(&actual_type); // Add actual type name to <...> clause of function name let actual_type_name = compute_debuginfo_type_name(cx, actual_type, @@ -389,7 +389,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { let names = get_type_parameter_names(cx, generics); substs.types().zip(names).map(|(ty, name)| { - let actual_type = cx.tcx().normalize_associated_type_in(&ty); + let actual_type = cx.tcx().trans_normalize_associated_types_in(&ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); let name = CString::new(name.as_str().as_bytes()).unwrap(); unsafe { diff --git a/src/librustc_trans_utils/monomorphize.rs b/src/librustc_trans_utils/monomorphize.rs index 079b7ee3eab..31d51dce6ea 100644 --- a/src/librustc_trans_utils/monomorphize.rs +++ b/src/librustc_trans_utils/monomorphize.rs @@ -131,6 +131,6 @@ pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, f: &'tcx ty::FieldDef) -> Ty<'tcx> { - tcx.normalize_associated_type_in(&f.ty(tcx, param_substs)) + tcx.trans_normalize_associated_types_in(&f.ty(tcx, param_substs)) } From f2ebe96c6347b9929756454d26dc9efff93c3925 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Wed, 11 Oct 2017 20:31:03 +0100 Subject: [PATCH 353/365] tidier --- src/librustc_lint/types.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 5beb23c8b82..d4d1a94d7ce 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -431,7 +431,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // fields are actually safe. let mut all_phantom = true; for field in &def.struct_variant().fields { - let field_ty = cx.trans_normalize_associated_types_in(&field.ty(cx, substs)); + let field_ty = cx.trans_normalize_associated_types_in( + &field.ty(cx, substs) + ); let r = self.check_type_for_ffi(cache, field_ty); match r { FfiSafe => { @@ -463,7 +465,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let mut all_phantom = true; for field in &def.struct_variant().fields { - let field_ty = cx.trans_normalize_associated_types_in(&field.ty(cx, substs)); + let field_ty = cx.trans_normalize_associated_types_in( + &field.ty(cx, substs) + ); let r = self.check_type_for_ffi(cache, field_ty); match r { FfiSafe => { @@ -516,7 +520,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Check the contained variants. for variant in &def.variants { for field in &variant.fields { - let arg = cx.trans_normalize_associated_types_in(&field.ty(cx, substs)); + let arg = cx.trans_normalize_associated_types_in( + &field.ty(cx, substs) + ); let r = self.check_type_for_ffi(cache, arg); match r { FfiSafe => {} From d870a96f286a27997136954739ab536a9f1b8392 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Mon, 16 Oct 2017 19:39:32 +0100 Subject: [PATCH 354/365] trans_ -> fully_ prefix --- src/librustc/infer/mod.rs | 6 +++--- src/librustc/ty/context.rs | 2 +- src/librustc_lint/types.rs | 8 ++++---- src/librustc_trans/adt.rs | 2 +- src/librustc_trans/context.rs | 2 +- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_trans/debuginfo/mod.rs | 4 ++-- src/librustc_trans_utils/monomorphize.rs | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 7bc9760b059..79eeebfb250 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -480,16 +480,16 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { { assert!(!value.needs_subst()); let value = self.erase_late_bound_regions(value); - self.trans_normalize_associated_types_in(&value) + self.fully_normalize_associated_types_in(&value) } /// Fully normalizes any associated types in `value`, using an /// empty environment and `Reveal::All` mode (therefore, suitable /// only for monomorphized code during trans, basically). - pub fn trans_normalize_associated_types_in(self, value: &T) -> T + pub fn fully_normalize_associated_types_in(self, value: &T) -> T where T: TransNormalize<'tcx> { - debug!("trans_normalize_associated_types_in(t={:?})", value); + debug!("fully_normalize_associated_types_in(t={:?})", value); let param_env = ty::ParamEnv::empty(Reveal::All); let value = self.erase_regions(value); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2a3b445ba31..4616f5a42d6 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2323,6 +2323,6 @@ pub fn provide(providers: &mut ty::maps::Providers) { tcx.sess.features.borrow().clone_closures }; providers.normalize_ty = |tcx, ty| { - tcx.trans_normalize_associated_types_in(&ty) + tcx.fully_normalize_associated_types_in(&ty) }; } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index d4d1a94d7ce..38461b0b364 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -431,7 +431,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // fields are actually safe. let mut all_phantom = true; for field in &def.struct_variant().fields { - let field_ty = cx.trans_normalize_associated_types_in( + let field_ty = cx.fully_normalize_associated_types_in( &field.ty(cx, substs) ); let r = self.check_type_for_ffi(cache, field_ty); @@ -465,7 +465,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let mut all_phantom = true; for field in &def.struct_variant().fields { - let field_ty = cx.trans_normalize_associated_types_in( + let field_ty = cx.fully_normalize_associated_types_in( &field.ty(cx, substs) ); let r = self.check_type_for_ffi(cache, field_ty); @@ -520,7 +520,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Check the contained variants. for variant in &def.variants { for field in &variant.fields { - let arg = cx.trans_normalize_associated_types_in( + let arg = cx.fully_normalize_associated_types_in( &field.ty(cx, substs) ); let r = self.check_type_for_ffi(cache, arg); @@ -635,7 +635,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) { // it is only OK to use this function because extern fns cannot have // any generic types right now: - let ty = self.cx.tcx.trans_normalize_associated_types_in(&ty); + let ty = self.cx.tcx.fully_normalize_associated_types_in(&ty); match self.check_type_for_ffi(&mut FxHashSet(), ty) { FfiResult::FfiSafe => {} diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 91adfe139fa..b06f8e4e671 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -80,7 +80,7 @@ pub fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, ty::TyGenerator(def_id, substs, _) => { if variant_index > 0 { bug!("{} is a generator, which only has one variant", t);} substs.field_tys(def_id, cx.tcx()).map(|t| { - cx.tcx().trans_normalize_associated_types_in(&t) + cx.tcx().fully_normalize_associated_types_in(&t) }).collect() }, _ => bug!("{} is not a type that can have fields.", t) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index d326cfe02fc..6fd24c1786c 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -642,7 +642,7 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> { } fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.tcx().trans_normalize_associated_types_in(&ty) + self.tcx().fully_normalize_associated_types_in(&ty) } } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 4f23152fed1..3bde78e2c6a 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -582,7 +582,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } ty::TyGenerator(def_id, substs, _) => { let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx()).map(|t| { - cx.tcx().trans_normalize_associated_types_in(&t) + cx.tcx().fully_normalize_associated_types_in(&t) }).collect(); prepare_tuple_metadata(cx, t, diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 631d6b8143e..1a284292016 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -376,7 +376,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, name_to_append_suffix_to.push_str(","); } - let actual_type = cx.tcx().trans_normalize_associated_types_in(&actual_type); + let actual_type = cx.tcx().fully_normalize_associated_types_in(&actual_type); // Add actual type name to <...> clause of function name let actual_type_name = compute_debuginfo_type_name(cx, actual_type, @@ -389,7 +389,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { let names = get_type_parameter_names(cx, generics); substs.types().zip(names).map(|(ty, name)| { - let actual_type = cx.tcx().trans_normalize_associated_types_in(&ty); + let actual_type = cx.tcx().fully_normalize_associated_types_in(&ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); let name = CString::new(name.as_str().as_bytes()).unwrap(); unsafe { diff --git a/src/librustc_trans_utils/monomorphize.rs b/src/librustc_trans_utils/monomorphize.rs index 31d51dce6ea..ab61dacf010 100644 --- a/src/librustc_trans_utils/monomorphize.rs +++ b/src/librustc_trans_utils/monomorphize.rs @@ -131,6 +131,6 @@ pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, f: &'tcx ty::FieldDef) -> Ty<'tcx> { - tcx.trans_normalize_associated_types_in(&f.ty(tcx, param_substs)) + tcx.fully_normalize_associated_types_in(&f.ty(tcx, param_substs)) } From 73c95431ee98fde159a7e8e068cdd406bd8810d0 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Mon, 16 Oct 2017 21:09:07 +0100 Subject: [PATCH 355/365] removed unused import --- src/librustc/traits/trans/mod.rs | 18 +----------------- src/librustc/ty/context.rs | 4 ---- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index d082fb889b7..cba139133cf 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -13,16 +13,14 @@ // seems likely that they should eventually be merged into more // general routines. -use dep_graph::{DepGraph, DepKind, DepTrackingMap, DepTrackingMapConfig}; +use dep_graph::{DepKind, DepTrackingMapConfig}; use infer::TransNormalize; -use std::cell::RefCell; use std::marker::PhantomData; use syntax_pos::DUMMY_SP; use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable}; use ty::{self, Ty, TyCtxt}; use ty::subst::{Subst, Substs}; use ty::fold::{TypeFoldable, TypeFolder}; -use util::common::MemoizationMap; /// Attempts to resolve an obligation to a vtable.. The result is /// a shallow vtable resolution -- meaning that we do not @@ -136,20 +134,6 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> { } } -/// Specializes caches used in trans -- in particular, they assume all -/// types are fully monomorphized and that free regions can be erased. -pub struct TransTraitCaches<'tcx> { - project_cache: RefCell>>, -} - -impl<'tcx> TransTraitCaches<'tcx> { - pub fn new(graph: DepGraph) -> Self { - TransTraitCaches { - project_cache: RefCell::new(DepTrackingMap::new(graph)), - } - } -} - // Implement DepTrackingMapConfig for `trait_cache` pub struct TraitSelectionCache<'tcx> { data: PhantomData<&'tcx ()> diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4616f5a42d6..03033b6a06d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -851,9 +851,6 @@ pub struct GlobalCtxt<'tcx> { pub sess: &'tcx Session, - - pub trans_trait_caches: traits::trans::TransTraitCaches<'tcx>, - pub dep_graph: DepGraph, /// Common types, pre-interned for your convenience. @@ -1137,7 +1134,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { tls::enter_global(GlobalCtxt { sess: s, cstore, - trans_trait_caches: traits::trans::TransTraitCaches::new(dep_graph.clone()), global_arenas: arenas, global_interners: interners, dep_graph: dep_graph.clone(), From 20ae2d98c04621f70f166b84d64d617adeecb5d2 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Wed, 18 Oct 2017 17:28:31 +0100 Subject: [PATCH 356/365] moved depnode --- src/librustc/dep_graph/dep_node.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index ebb8868642b..91c84e539cf 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -632,10 +632,9 @@ define_dep_nodes!( <'tcx> [] CodegenUnit(InternedString), [] CompileCodegenUnit(InternedString), [] OutputFilenames, - + [] NormalizeTy, // We use this for most things when incr. comp. is turned off. [] Null, - [] NormalizeTy, ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { From a3667d3209ecc560e9c8fee4a69946eb82fb5d3b Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Sat, 21 Oct 2017 20:11:27 +0100 Subject: [PATCH 357/365] anon NormalizeTy DepNode --- src/librustc/dep_graph/dep_node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 91c84e539cf..7bf8c616817 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -632,7 +632,7 @@ define_dep_nodes!( <'tcx> [] CodegenUnit(InternedString), [] CompileCodegenUnit(InternedString), [] OutputFilenames, - [] NormalizeTy, + [anon] NormalizeTy, // We use this for most things when incr. comp. is turned off. [] Null, ); From 5c51bf5297c3abb11c815d6b8a6d8681790a6ec8 Mon Sep 17 00:00:00 2001 From: Marco Concetto Rudilosso Date: Sat, 21 Oct 2017 22:25:00 +0100 Subject: [PATCH 358/365] renamed query --- src/librustc/traits/trans/mod.rs | 2 +- src/librustc/ty/context.rs | 2 +- src/librustc/ty/maps/config.rs | 2 +- src/librustc/ty/maps/mod.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index cba139133cf..761e7259204 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -129,7 +129,7 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> { ty } else { debug!("AssociatedTypeNormalizer: ty={:?}", ty); - self.tcx.normalize_ty(ty) + self.tcx.fully_normalize_monormophic_ty(ty) } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 03033b6a06d..5e9396068c8 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2318,7 +2318,7 @@ pub fn provide(providers: &mut ty::maps::Providers) { assert_eq!(cnum, LOCAL_CRATE); tcx.sess.features.borrow().clone_closures }; - providers.normalize_ty = |tcx, ty| { + providers.fully_normalize_monormophic_ty = |tcx, ty| { tcx.fully_normalize_associated_types_in(&ty) }; } diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index e813f2b104b..deaafd1efed 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -533,7 +533,7 @@ impl<'tcx> QueryDescription for queries::has_copy_closures<'tcx> { } } -impl<'tcx> QueryDescription for queries::normalize_ty<'tcx> { +impl<'tcx> QueryDescription for queries::fully_normalize_monormophic_ty<'tcx> { fn describe(_tcx: TyCtxt, _: Ty) -> String { format!("normalizing types") } diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index f68e15f2695..e588cdc52d8 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -349,7 +349,7 @@ define_maps! { <'tcx> // Normally you would just use `tcx.erase_regions(&value)`, // however, which uses this query as a kind of cache. [] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>, - [] fn normalize_ty: normalize_ty_node(Ty<'tcx>) -> Ty<'tcx>, + [] fn fully_normalize_monormophic_ty: normalize_ty_node(Ty<'tcx>) -> Ty<'tcx>, } ////////////////////////////////////////////////////////////////////// From aae94c736882ec87e62ad19cec936ac514badbba Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 21 Oct 2017 09:20:25 -0400 Subject: [PATCH 359/365] Improve docs around `Once::call_once_force` and `OnceState`. --- src/libstd/sync/once.rs | 98 ++++++++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 015106fc2e5..30dbf02087d 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -103,8 +103,8 @@ unsafe impl Sync for Once {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Once {} -/// State yielded to the [`call_once_force`] method which can be used to query -/// whether the [`Once`] was previously poisoned or not. +/// State yielded to [`call_once_force`]’s closure parameter. The state can be +/// used to query the poison status of the [`Once`]. /// /// [`call_once_force`]: struct.Once.html#method.call_once_force /// [`Once`]: struct.Once.html @@ -230,17 +230,50 @@ impl Once { /// Performs the same function as [`call_once`] except ignores poisoning. /// + /// Unlike [`call_once`], if this `Once` has been poisoned (i.e. a previous + /// call to `call_once` or `call_once_force` caused a panic), calling + /// `call_once_force` will still invoke the closure `f` and will _not_ + /// result in an immediate panic. If `f` panics, the `Once` will remain + /// in a poison state. If `f` does _not_ panic, the `Once` will no + /// longer be in a poison state and all future calls to `call_once` or + /// `call_one_force` will no-op. + /// + /// The closure `f` is yielded a [`OnceState`] structure which can be used + /// to query the poison status of the `Once`. + /// /// [`call_once`]: struct.Once.html#method.call_once - /// - /// If this `Once` has been poisoned (some initialization panicked) then - /// this function will continue to attempt to call initialization functions - /// until one of them doesn't panic. - /// - /// The closure `f` is yielded a [`OnceState`] structure which can be used to query the - /// state of this `Once` (whether initialization has previously panicked or - /// not). - /// /// [`OnceState`]: struct.OnceState.html + /// + /// # Examples + /// + /// ``` + /// #![feature(once_poison)] + /// + /// use std::sync::{Once, ONCE_INIT}; + /// use std::thread; + /// + /// static INIT: Once = ONCE_INIT; + /// + /// // poison the once + /// let handle = thread::spawn(|| { + /// INIT.call_once(|| panic!()); + /// }); + /// assert!(handle.join().is_err()); + /// + /// // poisoning propagates + /// let handle = thread::spawn(|| { + /// INIT.call_once(|| {}); + /// }); + /// assert!(handle.join().is_err()); + /// + /// // call_once_force will still run and reset the poisoned state + /// INIT.call_once_force(|state| { + /// assert!(state.poisoned()); + /// }); + /// + /// // once any success happens, we stop propagating the poison + /// INIT.call_once(|| {}); + /// ``` #[unstable(feature = "once_poison", issue = "33577")] pub fn call_once_force(&'static self, f: F) where F: FnOnce(&OnceState) { // same as above, just with a different parameter to `call_inner`. @@ -386,12 +419,47 @@ impl Drop for Finish { } impl OnceState { - /// Returns whether the associated [`Once`] has been poisoned. - /// - /// Once an initialization routine for a [`Once`] has panicked it will forever - /// indicate to future forced initialization routines that it is poisoned. + /// Returns whether the associated [`Once`] was poisoned prior to the + /// invocation of the closure passed to [`call_once_force`]. /// + /// [`call_once_force`]: struct.Once.html#method.call_once_force /// [`Once`]: struct.Once.html + /// + /// # Examples + /// + /// A poisoned `Once`: + /// + /// ``` + /// #![feature(once_poison)] + /// + /// use std::sync::{Once, ONCE_INIT}; + /// use std::thread; + /// + /// static INIT: Once = ONCE_INIT; + /// + /// // poison the once + /// let handle = thread::spawn(|| { + /// INIT.call_once(|| panic!()); + /// }); + /// assert!(handle.join().is_err()); + /// + /// INIT.call_once_force(|state| { + /// assert!(state.poisoned()); + /// }); + /// ``` + /// + /// An unpoisoned `Once`: + /// + /// ``` + /// #![feature(once_poison)] + /// + /// use std::sync::{Once, ONCE_INIT}; + /// + /// static INIT: Once = ONCE_INIT; + /// + /// INIT.call_once_force(|state| { + /// assert!(!state.poisoned()); + /// }); #[unstable(feature = "once_poison", issue = "33577")] pub fn poisoned(&self) -> bool { self.poisoned From 19aa23b6d332e693786fa51dbca87828bb884314 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Sun, 22 Oct 2017 10:07:47 -0200 Subject: [PATCH 360/365] Remove deprecated `collections` crate. This reverts commit 6484258f1749499d3e51685df867b3d460a7f0be. --- src/Cargo.lock | 9 --- src/bootstrap/dist.rs | 1 - .../src/library-features/collections.md | 5 -- src/libcollections/Cargo.toml | 12 ---- src/libcollections/lib.rs | 68 ------------------- src/libstd/Cargo.toml | 1 - 6 files changed, 96 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/collections.md delete mode 100644 src/libcollections/Cargo.toml delete mode 100644 src/libcollections/lib.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index d7e3fa1eaf7..a8bcea6d781 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -321,14 +321,6 @@ dependencies = [ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "collections" -version = "0.0.0" -dependencies = [ - "alloc 0.0.0", - "core 0.0.0", -] - [[package]] name = "compiler_builtins" version = "0.0.0" @@ -2137,7 +2129,6 @@ dependencies = [ "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", "libc 0.0.0", diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e41f01ac834..e79f6e086ae 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -738,7 +738,6 @@ impl Step for Src { "src/liballoc_jemalloc", "src/liballoc_system", "src/libbacktrace", - "src/libcollections", "src/libcompiler_builtins", "src/libcore", "src/liblibc", diff --git a/src/doc/unstable-book/src/library-features/collections.md b/src/doc/unstable-book/src/library-features/collections.md deleted file mode 100644 index 5c937833c9e..00000000000 --- a/src/doc/unstable-book/src/library-features/collections.md +++ /dev/null @@ -1,5 +0,0 @@ -# `collections` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml deleted file mode 100644 index 800e36161d2..00000000000 --- a/src/libcollections/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "collections" -version = "0.0.0" - -[lib] -name = "collections" -path = "lib.rs" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs deleted file mode 100644 index 55316db3d5a..00000000000 --- a/src/libcollections/lib.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2017 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. - -#![allow(unused_attributes)] -#![unstable(feature = "collections", - reason = "this library is unlikely to be stabilized in its current \ - form or name", - issue = "27783")] -#![rustc_deprecated(since = "1.20.0", - reason = "collections moved to `alloc`")] -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/", - issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", - test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] -#![no_std] -#![deny(warnings)] - -#![feature(alloc)] -#![feature(collections_range)] -#![feature(macro_reexport)] -#![feature(staged_api)] - -//! Collection types -//! -//! See [`std::collections`](../std/collections/index.html) for a detailed -//! discussion of collections in Rust. - -#[macro_reexport(vec, format)] -extern crate alloc; - -pub use alloc::Bound; - -pub use alloc::binary_heap; -pub use alloc::borrow; -pub use alloc::fmt; -pub use alloc::linked_list; -pub use alloc::range; -pub use alloc::slice; -pub use alloc::str; -pub use alloc::string; -pub use alloc::vec; -pub use alloc::vec_deque; - -pub use alloc::btree_map; -pub use alloc::btree_set; - -#[doc(no_inline)] -pub use alloc::binary_heap::BinaryHeap; -#[doc(no_inline)] -pub use alloc::btree_map::BTreeMap; -#[doc(no_inline)] -pub use alloc::btree_set::BTreeSet; -#[doc(no_inline)] -pub use alloc::linked_list::LinkedList; -#[doc(no_inline)] -pub use alloc::vec_deque::VecDeque; -#[doc(no_inline)] -pub use alloc::string::String; -#[doc(no_inline)] -pub use alloc::vec::Vec; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 866c0038a7f..5dd5f8953a0 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -15,7 +15,6 @@ alloc_jemalloc = { path = "../liballoc_jemalloc", optional = true } alloc_system = { path = "../liballoc_system" } panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } -collections = { path = "../libcollections" } core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } rand = { path = "../librand" } From 170f63e1c6b56140bbd55f9c42bab844e8d09a20 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Sun, 22 Oct 2017 14:54:07 -0200 Subject: [PATCH 361/365] Don't build docs for removed libcollections. --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 271db98638b..16e8ee182bd 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -490,7 +490,7 @@ impl Step for Std { // for which docs must be built. if !build.config.compiler_docs { cargo.arg("--no-deps"); - for krate in &["alloc", "collections", "core", "std", "std_unicode"] { + for krate in &["alloc", "core", "std", "std_unicode"] { cargo.arg("-p").arg(krate); // Create all crate output directories first to make sure rustdoc uses // relative links. From 42ad2d7c31f54a479b39ee6931b515da21098e7d Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sun, 22 Oct 2017 13:14:17 -0400 Subject: [PATCH 362/365] fix stringify docs --- src/libcore/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d64c984ea7d..12667036444 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -682,7 +682,7 @@ mod builtin { #[cfg(dox)] macro_rules! file { () => ({ /* compiler built-in */ }) } - /// A macro which stringifies its argument. + /// A macro which stringifies its arguments. /// /// For more information, see the documentation for [`std::stringify!`]. /// @@ -690,7 +690,7 @@ mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] #[cfg(dox)] - macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) } + macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) } /// Includes a utf8-encoded file as a string. /// From 365eafbc7f78dc8bac70d7f07950c44b0b62abd7 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sun, 22 Oct 2017 13:17:23 -0400 Subject: [PATCH 363/365] fix stringify docs in std --- src/libstd/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 8089671f309..6318e2e4087 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -490,7 +490,7 @@ pub mod builtin { #[macro_export] macro_rules! file { () => ({ /* compiler built-in */ }) } - /// A macro which stringifies its argument. + /// A macro which stringifies its arguments. /// /// This macro will yield an expression of type `&'static str` which is the /// stringification of all the tokens passed to the macro. No restrictions @@ -507,7 +507,7 @@ pub mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] - macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) } + macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) } /// Includes a utf8-encoded file as a string. /// From 214b0f229395d4460cbcccf17d07cf687ff83b0a Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 19 Oct 2017 14:43:47 -0700 Subject: [PATCH 364/365] `crate` shorthand visibility modifier With regrets, this breaks rustfmt and rls. This is in the matter of #45388. --- .../crate-visibility-modifier.md | 20 +++++++++++++++++++ src/librustc/hir/lowering.rs | 2 +- src/libsyntax/ast.rs | 11 +++++++++- src/libsyntax/feature_gate.rs | 11 ++++++++++ src/libsyntax/parse/parser.rs | 8 ++++++-- src/libsyntax/print/pprust.rs | 5 ++++- .../feature-gate-crate_visibility_modifier.rs | 18 +++++++++++++++++ .../restricted/auxiliary/pub_restricted.rs | 7 ++++++- .../privacy/restricted/private-in-public.rs | 3 +++ .../compile-fail/privacy/restricted/test.rs | 2 ++ src/test/parse-fail/issue-20711-2.rs | 2 +- src/test/parse-fail/issue-20711.rs | 2 +- .../parse-fail/removed-syntax-static-fn.rs | 2 +- src/test/run-pass/macro-pub-matcher.rs | 14 ++++++++++++- src/tools/toolstate.toml | 4 ++-- 15 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/crate-visibility-modifier.md create mode 100644 src/test/compile-fail/feature-gate-crate_visibility_modifier.rs diff --git a/src/doc/unstable-book/src/language-features/crate-visibility-modifier.md b/src/doc/unstable-book/src/language-features/crate-visibility-modifier.md new file mode 100644 index 00000000000..11b3ee8edf0 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/crate-visibility-modifier.md @@ -0,0 +1,20 @@ +# `crate_visibility_modifier` + +The tracking issue for this feature is: [#45388] + +[#45388]: https://github.com/rust-lang/rust/issues/45388 + +----- + +The `crate_visibility_modifier` feature allows the `crate` keyword to be used +as a visibility modifier synonymous to `pub(crate)`, indicating that a type +(function, _&c._) is to be visible to the entire enclosing crate, but not to +other crates. + +```rust +#![feature(crate_visibility_modifier)] + +crate struct Foo { + bar: usize, +} +``` diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 848da9637a2..012cc1e4ac1 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2666,7 +2666,7 @@ impl<'a> LoweringContext<'a> { -> hir::Visibility { match *v { Visibility::Public => hir::Public, - Visibility::Crate(_) => hir::Visibility::Crate, + Visibility::Crate(..) => hir::Visibility::Crate, Visibility::Restricted { ref path, id } => { hir::Visibility::Restricted { path: P(self.lower_path(id, path, ParamMode::Explicit, true)), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f445def9e03..1e9ac66d237 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1787,10 +1787,19 @@ impl PolyTraitRef { } } +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum CrateSugar { + /// Source is `pub(crate)` + PubCrate, + + /// Source is (just) `crate` + JustCrate, +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Visibility { Public, - Crate(Span), + Crate(Span, CrateSugar), Restricted { path: P, id: NodeId }, Inherited, } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9060a613bc1..da1a0107f2f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -401,6 +401,9 @@ declare_features! ( // Trait object syntax with `dyn` prefix (active, dyn_trait, "1.22.0", Some(44662)), + + // `crate` as visibility modifier, synonymous to `pub(crate)` + (active, crate_visibility_modifier, "1.23.0", Some(45388)), ); declare_features! ( @@ -1582,6 +1585,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_impl_item(self, ii); } + fn visit_vis(&mut self, vis: &'a ast::Visibility) { + if let ast::Visibility::Crate(span, ast::CrateSugar::JustCrate) = *vis { + gate_feature_post!(&self, crate_visibility_modifier, span, + "`crate` visibility modifier is experimental"); + } + visit::walk_vis(self, vis); + } + fn visit_generics(&mut self, g: &'a ast::Generics) { for t in &g.ty_params { if !t.attrs.is_empty() { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8fd2bad4e44..c9e9a8edcb8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -36,7 +36,7 @@ use ast::SelfKind; use ast::{TraitItem, TraitRef, TraitObjectSyntax}; use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; -use ast::{Visibility, WhereClause}; +use ast::{Visibility, WhereClause, CrateSugar}; use ast::{BinOpKind, UnOp}; use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; @@ -5325,6 +5325,10 @@ impl<'a> Parser<'a> { pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { maybe_whole!(self, NtVis, |x| x); + if self.eat_keyword(keywords::Crate) { + return Ok(Visibility::Crate(self.prev_span, CrateSugar::JustCrate)); + } + if !self.eat_keyword(keywords::Pub) { return Ok(Visibility::Inherited) } @@ -5338,7 +5342,7 @@ impl<'a> Parser<'a> { // `pub(crate)` self.bump(); // `(` self.bump(); // `crate` - let vis = Visibility::Crate(self.prev_span); + let vis = Visibility::Crate(self.prev_span, CrateSugar::PubCrate); self.expect(&token::CloseDelim(token::Paren))?; // `)` return Ok(vis) } else if self.look_ahead(1, |t| t.is_keyword(keywords::In)) { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 02f871c58c7..4082cc03f12 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1440,7 +1440,10 @@ impl<'a> State<'a> { pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> { match *vis { ast::Visibility::Public => self.word_nbsp("pub"), - ast::Visibility::Crate(_) => self.word_nbsp("pub(crate)"), + ast::Visibility::Crate(_, sugar) => match sugar { + ast::CrateSugar::PubCrate => self.word_nbsp("pub(crate)"), + ast::CrateSugar::JustCrate => self.word_nbsp("crate") + } ast::Visibility::Restricted { ref path, .. } => { let path = to_string(|s| s.print_path(path, false, 0, true)); if path == "self" || path == "super" { diff --git a/src/test/compile-fail/feature-gate-crate_visibility_modifier.rs b/src/test/compile-fail/feature-gate-crate_visibility_modifier.rs new file mode 100644 index 00000000000..a2937d6de31 --- /dev/null +++ b/src/test/compile-fail/feature-gate-crate_visibility_modifier.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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. + +crate struct Bender { //~ ERROR `crate` visibility modifier is experimental + earth: bool, + fire: bool, + air: bool, + water: bool, +} + +fn main() {} diff --git a/src/test/compile-fail/privacy/restricted/auxiliary/pub_restricted.rs b/src/test/compile-fail/privacy/restricted/auxiliary/pub_restricted.rs index 82d14ddb502..c4ab96c8456 100644 --- a/src/test/compile-fail/privacy/restricted/auxiliary/pub_restricted.rs +++ b/src/test/compile-fail/privacy/restricted/auxiliary/pub_restricted.rs @@ -8,14 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(crate_visibility_modifier)] + pub(crate) struct Crate; + #[derive(Default)] pub struct Universe { pub x: i32, - pub(crate) y: i32 + pub(crate) y: i32, + crate z: i32, } impl Universe { pub fn f(&self) {} pub(crate) fn g(&self) {} + crate fn h(&self) {} } diff --git a/src/test/compile-fail/privacy/restricted/private-in-public.rs b/src/test/compile-fail/privacy/restricted/private-in-public.rs index 0fdfbaa84bb..4d3f5377797 100644 --- a/src/test/compile-fail/privacy/restricted/private-in-public.rs +++ b/src/test/compile-fail/privacy/restricted/private-in-public.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(crate_visibility_modifier)] + mod foo { struct Priv; mod bar { use foo::Priv; pub(super) fn f(_: Priv) {} pub(crate) fn g(_: Priv) {} //~ ERROR E0446 + crate fn h(_: Priv) {} //~ ERROR E0446 } } diff --git a/src/test/compile-fail/privacy/restricted/test.rs b/src/test/compile-fail/privacy/restricted/test.rs index 2e065ac051b..7f076ebf287 100644 --- a/src/test/compile-fail/privacy/restricted/test.rs +++ b/src/test/compile-fail/privacy/restricted/test.rs @@ -50,8 +50,10 @@ fn main() { let u = Universe::default(); let _ = u.x; let _ = u.y; //~ ERROR private + let _ = u.z; //~ ERROR private u.f(); u.g(); //~ ERROR private + u.h(); //~ ERROR private } mod pathological { diff --git a/src/test/parse-fail/issue-20711-2.rs b/src/test/parse-fail/issue-20711-2.rs index a489864e3f7..3a330d8bee2 100644 --- a/src/test/parse-fail/issue-20711-2.rs +++ b/src/test/parse-fail/issue-20711-2.rs @@ -16,6 +16,6 @@ impl Foo { fn foo() {} #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected one of `const`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe` +} //~ ERROR expected one of `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe` fn main() {} diff --git a/src/test/parse-fail/issue-20711.rs b/src/test/parse-fail/issue-20711.rs index d9789d55a6f..cd79fa8be7c 100644 --- a/src/test/parse-fail/issue-20711.rs +++ b/src/test/parse-fail/issue-20711.rs @@ -14,6 +14,6 @@ struct Foo; impl Foo { #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected one of `const`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe` +} //~ ERROR expected one of `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe` fn main() {} diff --git a/src/test/parse-fail/removed-syntax-static-fn.rs b/src/test/parse-fail/removed-syntax-static-fn.rs index b4c25a75c90..3b783aa79e2 100644 --- a/src/test/parse-fail/removed-syntax-static-fn.rs +++ b/src/test/parse-fail/removed-syntax-static-fn.rs @@ -15,4 +15,4 @@ struct S; impl S { static fn f() {} } -//~^^ ERROR expected one of `const`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}` +//~^^ ERROR expected one of `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe` diff --git a/src/test/run-pass/macro-pub-matcher.rs b/src/test/run-pass/macro-pub-matcher.rs index d79f4b65b69..32145277252 100644 --- a/src/test/run-pass/macro-pub-matcher.rs +++ b/src/test/run-pass/macro-pub-matcher.rs @@ -9,7 +9,7 @@ // except according to those terms. #![allow(dead_code, unused_imports)] -#![feature(macro_vis_matcher)] +#![feature(macro_vis_matcher, crate_visibility_modifier)] /** Ensure that `:vis` matches can be captured in existing positions, and passed @@ -64,6 +64,18 @@ mod with_pub_restricted { vis_passthru! { pub(crate) use A as I; } } +mod with_crate { + vis_passthru! { crate const A: i32 = 0; } + vis_passthru! { crate enum B {} } + vis_passthru! { crate extern "C" fn c() {} } + vis_passthru! { crate mod d {} } + vis_passthru! { crate static E: i32 = 0; } + vis_passthru! { crate struct F; } + vis_passthru! { crate trait G {} } + vis_passthru! { crate type H = i32; } + vis_passthru! { crate use A as I; } +} + mod garden { mod with_pub_restricted_path { vis_passthru! { pub(in garden) const A: i32 = 0; } diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml index e62597c5216..da4d26d78da 100644 --- a/src/tools/toolstate.toml +++ b/src/tools/toolstate.toml @@ -29,7 +29,7 @@ miri = "Broken" clippy = "Compiling" # ping @nrc -rls = "Testing" +rls = "Broken" # ping @nrc -rustfmt = "Testing" +rustfmt = "Broken" From 4b0f004e3ddd4421153fd3a0a85343652aa864ce Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 23 Oct 2017 16:18:00 -0400 Subject: [PATCH 365/365] update inherent_impls tests Now that we are visiting things in a different order during lowering, adding parameters winds up affecting the HirIds assigned to thinks in the method body, whereas it didn't before. We could fix this by reordering the order in which we visit `generics` during lowering, but this feels very fragile. Seems better to just let typeck tables be dirty here. --- src/test/incremental/hashes/inherent_impls.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 5067b571ee6..9351a4b05f1 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -370,9 +370,7 @@ impl Foo { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - // FIXME(michaelwoerister): This is curious but an unused lifetime parameter doesn't seem to - // show up in any of the derived data structures. - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,TypeckTables")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -395,7 +393,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,TypeOfItem", + except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,TypeOfItem,TypeckTables", )] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] @@ -441,7 +439,8 @@ impl Foo { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,TypeOfItem")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,GenericsOfItem,PredicatesOfItem,\ + TypeOfItem,TypeckTables")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] @@ -462,7 +461,7 @@ impl Foo { #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,PredicatesOfItem")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,PredicatesOfItem,TypeckTables")] #[rustc_clean(cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")]