diff --git a/COPYRIGHT b/COPYRIGHT index 9bc018d983d7d..e2d0ed77224e3 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -10,8 +10,8 @@ Copyrights in the Rust project are retained by their contributors. No copyright assignment is required to contribute to the Rust project. Some files include explicit copyright notices and/or license notices. -For full authorship information, see AUTHORS.txt and the version control -history. +For full authorship information, see the version control history or +https://thanks.rust-lang.org Except as otherwise noted (below and/or in individual files), Rust is licensed under the Apache License, Version 2.0 or diff --git a/RELEASES.md b/RELEASES.md index b983851f88198..0368c5414e16f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -190,7 +190,7 @@ Version 1.27.0 (2018-06-21) Language -------- - [Removed 'proc' from the reserved keywords list.][49699] This allows `proc` to - be used as an identifer. + be used as an identifier. - [The dyn syntax is now available.][49968] This syntax is equivalent to the bare `Trait` syntax, and should make it clearer when being used in tandem with `impl Trait`. Since it is equivalent to the following syntax: @@ -4795,7 +4795,7 @@ Language -------- * Patterns with `ref mut` now correctly invoke [`DerefMut`] when - matching against dereferencable values. + matching against dereferenceable values. Libraries --------- diff --git a/src/Cargo.lock b/src/Cargo.lock index 89daa8e09c7d1..2b0833b096629 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2615,18 +2615,9 @@ dependencies = [ "rustc_lsan 0.0.0", "rustc_msan 0.0.0", "rustc_tsan 0.0.0", - "std_unicode 0.0.0", "unwind 0.0.0", ] -[[package]] -name = "std_unicode" -version = "0.0.0" -dependencies = [ - "compiler_builtins 0.0.0", - "core 0.0.0", -] - [[package]] name = "string_cache" version = "0.7.3" diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 71c1c61e3d97e..829487163a945 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -88,7 +88,10 @@ def _download(path, url, probably_big, verbose, exception): option = "-#" else: option = "-s" - run(["curl", option, "--retry", "3", "-Sf", "-o", path, url], + run(["curl", option, + "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds + "--connect-timeout", "30", # timeout if cannot connect within 30 seconds + "--retry", "3", "-Sf", "-o", path, url], verbose=verbose, exception=exception) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 04e8e133b03a1..8c4f2df60fe6f 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -157,7 +157,6 @@ pub fn std_cargo(builder: &Builder, cargo.arg("--features").arg("c mem") .args(&["-p", "alloc"]) .args(&["-p", "compiler_builtins"]) - .args(&["-p", "std_unicode"]) .arg("--manifest-path") .arg(builder.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); } else { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c6b39a52ae135..188e64cd668dd 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -856,7 +856,6 @@ impl Step for Src { "src/librustc_msan", "src/librustc_tsan", "src/libstd", - "src/libstd_unicode", "src/libunwind", "src/rustc/compiler_builtins_shim", "src/rustc/libc_shim", diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 9dbbe6bcfe490..ed9b5b1773fae 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -489,7 +489,7 @@ impl Step for Std { // Keep a whitelist so we do not build internal stdlib crates, these will be // build by the rustc step later if enabled. cargo.arg("--no-deps"); - for krate in &["alloc", "core", "std", "std_unicode"] { + for krate in &["alloc", "core", "std"] { cargo.arg("-p").arg(krate); // Create all crate output directories first to make sure rustdoc uses // relative links. diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 6a013053e580c..60b4d65f44401 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -121,7 +121,10 @@ To learn more about a subcommand, run `./x.py -h`" opts.optmulti("", "exclude", "build paths to exclude", "PATH"); opts.optopt("", "on-fail", "command to run on failure", "CMD"); opts.optflag("", "dry-run", "dry run; don't build anything"); - opts.optopt("", "stage", "stage to build", "N"); + opts.optopt("", "stage", + "stage to build (indicates compiler to use/test, e.g. stage 0 uses the \ + bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)", + "N"); opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling", "N"); opts.optopt("", "src", "path to the root of the rust checkout", "DIR"); opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS"); @@ -258,7 +261,7 @@ Arguments: ./x.py build --stage 1 src/libtest - This will first build everything once (like --stage 0 without further + This will first build everything once (like `--stage 0` without further arguments would), and then use the compiler built in stage 0 to build src/libtest and its dependencies. Once this is done, build/$ARCH/stage1 contains a usable compiler.", @@ -290,10 +293,14 @@ Arguments: ./x.py test src/test/run-pass ./x.py test src/libstd --test-args hash_map - ./x.py test src/libstd --stage 0 + ./x.py test src/libstd --stage 0 --no-doc ./x.py test src/test/ui --bless ./x.py test src/test/ui --compare-mode nll + Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`; + just like `build src/libstd --stage N` it tests the compiler produced by the previous + stage. + If no arguments are passed then the complete artifacts for that stage are compiled and tested. diff --git a/src/doc/book b/src/doc/book index f475da63a18d5..88cdde350fd3a 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit f475da63a18d50217459a601cbef69a4bcac5e71 +Subproject commit 88cdde350fd3a90c93f3bac8b4f168f105d28060 diff --git a/src/doc/man/rustdoc.1 b/src/doc/man/rustdoc.1 index a878380f556b3..d7f78e8f6f4de 100644 --- a/src/doc/man/rustdoc.1 +++ b/src/doc/man/rustdoc.1 @@ -119,7 +119,7 @@ See <\fBhttps://github.com/rust\-lang/rust/issues\fR> for issues. .SH "AUTHOR" -See \fIAUTHORS.txt\fR in the Rust source distribution. +See the version control history or <\fBhttps://thanks.rust\-lang.org\fR> .SH "COPYRIGHT" This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms. diff --git a/src/doc/nomicon b/src/doc/nomicon index 66ef7373409d1..790e96b87f4b5 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 66ef7373409d1979c2839db8886ac2ec9b6a58cd +Subproject commit 790e96b87f4b5817cac310e73a524d25c3d076d8 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index d2a64395a5210..e3719fc78ff4a 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit d2a64395a5210a61d3512a3a5c615f5c47699443 +Subproject commit e3719fc78ff4a21dfd13cfcc9e2ca42cb5de29f4 diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py index 4a38d4be083fd..87c7b21bb8a35 100644 --- a/src/etc/debugger_pretty_printers_common.py +++ b/src/etc/debugger_pretty_printers_common.py @@ -47,6 +47,7 @@ TYPE_KIND_FIXED_SIZE_VEC = 16 TYPE_KIND_REGULAR_UNION = 17 TYPE_KIND_OS_STRING = 18 +TYPE_KIND_STD_VECDEQUE = 19 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$" ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR" @@ -62,6 +63,14 @@ STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF, STD_VEC_FIELD_NAME_LENGTH] +# std::collections::VecDeque<> related constants +STD_VECDEQUE_FIELD_NAME_TAIL = "tail" +STD_VECDEQUE_FIELD_NAME_HEAD = "head" +STD_VECDEQUE_FIELD_NAME_BUF = "buf" +STD_VECDEQUE_FIELD_NAMES = [STD_VECDEQUE_FIELD_NAME_TAIL, + STD_VECDEQUE_FIELD_NAME_HEAD, + STD_VECDEQUE_FIELD_NAME_BUF] + # std::String related constants STD_STRING_FIELD_NAMES = ["vec"] @@ -161,6 +170,11 @@ def __classify_struct(self): self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)): return TYPE_KIND_STD_VEC + # STD COLLECTION VECDEQUE + if (unqualified_type_name.startswith("VecDeque<") and + self.__conforms_to_field_layout(STD_VECDEQUE_FIELD_NAMES)): + return TYPE_KIND_STD_VECDEQUE + # STD STRING if (unqualified_type_name.startswith("String") and self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)): @@ -325,6 +339,25 @@ def extract_length_ptr_and_cap_from_std_vec(vec_val): assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR return (length, data_ptr, capacity) + +def extract_tail_head_ptr_and_cap_from_std_vecdeque(vec_val): + assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VECDEQUE + tail_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_TAIL) + head_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_HEAD) + buf_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_BUF) + + tail = vec_val.get_child_at_index(tail_field_index).as_integer() + head = vec_val.get_child_at_index(head_field_index).as_integer() + buf = vec_val.get_child_at_index(buf_field_index) + + vec_ptr_val = buf.get_child_at_index(0) + capacity = buf.get_child_at_index(1).as_integer() + unique_ptr_val = vec_ptr_val.get_child_at_index(0) + data_ptr = unique_ptr_val.get_child_at_index(0) + assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR + return (tail, head, data_ptr, capacity) + + def extract_length_and_ptr_from_slice(slice_val): assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 0612873e28153..b7de42a938417 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -124,6 +124,9 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_STD_VEC: return RustStdVecPrinter(val) + if type_kind == rustpp.TYPE_KIND_STD_VECDEQUE: + return RustStdVecDequePrinter(val) + if type_kind == rustpp.TYPE_KIND_STD_STRING: return RustStdStringPrinter(val) @@ -274,6 +277,28 @@ def children(self): yield (str(index), (gdb_ptr + index).dereference()) +class RustStdVecDequePrinter(object): + def __init__(self, val): + self.__val = val + + @staticmethod + def display_hint(): + return "array" + + def to_string(self): + (tail, head, data_ptr, cap) = \ + rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val) + return (self.__val.type.get_unqualified_type_name() + + ("(len: %i, cap: %i)" % (head - tail, cap))) + + def children(self): + (tail, head, data_ptr, cap) = \ + rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val) + gdb_ptr = data_ptr.get_wrapped_value() + for index in xrange(tail, head): + yield (str(index), (gdb_ptr + index).dereference()) + + class RustStdStringPrinter(object): def __init__(self, val): self.__val = val diff --git a/src/libcore/char/decode.rs b/src/libcore/char/decode.rs index 0b8dce19dffa1..cc52f048b891b 100644 --- a/src/libcore/char/decode.rs +++ b/src/libcore/char/decode.rs @@ -11,135 +11,8 @@ //! UTF-8 and UTF-16 decoding iterators use fmt; -use iter::FusedIterator; use super::from_u32_unchecked; -/// An iterator over an iterator of bytes of the characters the bytes represent -/// as UTF-8 -#[unstable(feature = "decode_utf8", issue = "33906")] -#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: - https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] -#[derive(Clone, Debug)] -#[allow(deprecated)] -pub struct DecodeUtf8>(::iter::Peekable); - -/// Decodes an `Iterator` of bytes as UTF-8. -#[unstable(feature = "decode_utf8", issue = "33906")] -#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: - https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] -#[allow(deprecated)] -#[inline] -pub fn decode_utf8>(i: I) -> DecodeUtf8 { - DecodeUtf8(i.into_iter().peekable()) -} - -/// `::next` returns this for an invalid input sequence. -#[unstable(feature = "decode_utf8", issue = "33906")] -#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: - https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] -#[derive(PartialEq, Eq, Debug)] -#[allow(deprecated)] -pub struct InvalidSequence(()); - -#[unstable(feature = "decode_utf8", issue = "33906")] -#[allow(deprecated)] -impl> Iterator for DecodeUtf8 { - type Item = Result; - #[inline] - - fn next(&mut self) -> Option> { - self.0.next().map(|first_byte| { - // Emit InvalidSequence according to - // Unicode §5.22 Best Practice for U+FFFD Substitution - // http://www.unicode.org/versions/Unicode9.0.0/ch05.pdf#G40630 - - // Roughly: consume at least one byte, - // then validate one byte at a time and stop before the first unexpected byte - // (which might be the valid start of the next byte sequence). - - let mut code_point; - macro_rules! first_byte { - ($mask: expr) => { - code_point = u32::from(first_byte & $mask) - } - } - macro_rules! continuation_byte { - () => { continuation_byte!(0x80..=0xBF) }; - ($range: pat) => { - match self.0.peek() { - Some(&byte @ $range) => { - code_point = (code_point << 6) | u32::from(byte & 0b0011_1111); - self.0.next(); - } - _ => return Err(InvalidSequence(())) - } - } - } - - match first_byte { - 0x00..=0x7F => { - first_byte!(0b1111_1111); - } - 0xC2..=0xDF => { - first_byte!(0b0001_1111); - continuation_byte!(); - } - 0xE0 => { - first_byte!(0b0000_1111); - continuation_byte!(0xA0..=0xBF); // 0x80..=0x9F here are overlong - continuation_byte!(); - } - 0xE1..=0xEC | 0xEE..=0xEF => { - first_byte!(0b0000_1111); - continuation_byte!(); - continuation_byte!(); - } - 0xED => { - first_byte!(0b0000_1111); - continuation_byte!(0x80..=0x9F); // 0xA0..0xBF here are surrogates - continuation_byte!(); - } - 0xF0 => { - first_byte!(0b0000_0111); - continuation_byte!(0x90..=0xBF); // 0x80..0x8F here are overlong - continuation_byte!(); - continuation_byte!(); - } - 0xF1..=0xF3 => { - first_byte!(0b0000_0111); - continuation_byte!(); - continuation_byte!(); - continuation_byte!(); - } - 0xF4 => { - first_byte!(0b0000_0111); - continuation_byte!(0x80..=0x8F); // 0x90..0xBF here are beyond char::MAX - continuation_byte!(); - continuation_byte!(); - } - _ => return Err(InvalidSequence(())) // Illegal first byte, overlong, or beyond MAX - } - unsafe { - Ok(from_u32_unchecked(code_point)) - } - }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let (lower, upper) = self.0.size_hint(); - - // A code point is at most 4 bytes long. - let min_code_points = lower / 4; - - (min_code_points, upper) - } -} - -#[unstable(feature = "decode_utf8", issue = "33906")] -#[allow(deprecated)] -impl> FusedIterator for DecodeUtf8 {} - /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s. #[stable(feature = "decode_utf16", since = "1.9.0")] #[derive(Clone, Debug)] diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs index 59bcf1383f47a..5be673db3200d 100644 --- a/src/libcore/char/mod.rs +++ b/src/libcore/char/mod.rs @@ -50,11 +50,6 @@ pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error}; pub use unicode::tables::UNICODE_VERSION; #[unstable(feature = "unicode_version", issue = "49726")] pub use unicode::version::UnicodeVersion; -#[unstable(feature = "decode_utf8", issue = "33906")] -#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead: - https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")] -#[allow(deprecated)] -pub use self::decode::{decode_utf8, DecodeUtf8, InvalidSequence}; use fmt::{self, Write}; use iter::FusedIterator; diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index 98c504a3f7bef..6045fac2b4b3d 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -36,6 +36,8 @@ pub struct LocalFutureObj<'a, T> { _marker: PhantomData<&'a ()>, } +impl<'a, T> Unpin for LocalFutureObj<'a, T> {} + impl<'a, T> LocalFutureObj<'a, T> { /// Create a `LocalFutureObj` from a custom trait object representation. #[inline] @@ -104,6 +106,7 @@ impl<'a, T> Drop for LocalFutureObj<'a, T> { /// information #44874) pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); +impl<'a, T> Unpin for FutureObj<'a, T> {} unsafe impl<'a, T> Send for FutureObj<'a, T> {} impl<'a, T> FutureObj<'a, T> { diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 0b8f8f0703df7..3bc2861460e14 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1903,10 +1903,12 @@ $EndFeature, " /// # Examples /// /// ``` + /// #![feature(int_to_from_bytes)] + /// /// let bytes = i32::min_value().to_be().to_bytes(); /// assert_eq!(bytes, [0x80, 0, 0, 0]); /// ``` - #[stable(feature = "int_to_from_bytes", since = "1.29.0")] + #[unstable(feature = "int_to_from_bytes", issue = "49792")] #[inline] pub fn to_bytes(self) -> [u8; mem::size_of::()] { unsafe { mem::transmute(self) } @@ -1923,10 +1925,12 @@ $EndFeature, " /// # Examples /// /// ``` + /// #![feature(int_to_from_bytes)] + /// /// let int = i32::from_be(i32::from_bytes([0x80, 0, 0, 0])); /// assert_eq!(int, i32::min_value()); /// ``` - #[stable(feature = "int_to_from_bytes", since = "1.29.0")] + #[unstable(feature = "int_to_from_bytes", issue = "49792")] #[inline] pub fn from_bytes(bytes: [u8; mem::size_of::()]) -> Self { unsafe { mem::transmute(bytes) } @@ -3508,10 +3512,12 @@ $EndFeature, " /// # Examples /// /// ``` + /// #![feature(int_to_from_bytes)] + /// /// let bytes = 0x1234_5678_u32.to_be().to_bytes(); /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]); /// ``` - #[stable(feature = "int_to_from_bytes", since = "1.29.0")] + #[unstable(feature = "int_to_from_bytes", issue = "49792")] #[inline] pub fn to_bytes(self) -> [u8; mem::size_of::()] { unsafe { mem::transmute(self) } @@ -3528,10 +3534,12 @@ $EndFeature, " /// # Examples /// /// ``` + /// #![feature(int_to_from_bytes)] + /// /// let int = u32::from_be(u32::from_bytes([0x12, 0x34, 0x56, 0x78])); /// assert_eq!(int, 0x1234_5678_u32); /// ``` - #[stable(feature = "int_to_from_bytes", since = "1.29.0")] + #[unstable(feature = "int_to_from_bytes", issue = "49792")] #[inline] pub fn from_bytes(bytes: [u8; mem::size_of::()]) -> Self { unsafe { mem::transmute(bytes) } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 9f9dbd0777a14..2b6c376f8a71c 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -146,7 +146,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use iter::{FromIterator, FusedIterator, TrustedLen}; -use {hint, mem, ops}; +use {hint, mem, ops::{self, Deref}}; use mem::PinMut; // Note that this is not a lang item per se, but it has a hidden dependency on @@ -953,6 +953,17 @@ impl Option { } } +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Option { + /// Converts from `&Option` to `Option<&T::Target>`. + /// + /// Leaves the original Option in-place, creating a new one with a reference + /// to the original one, additionally coercing the contents via `Deref`. + pub fn deref(&self) -> Option<&T::Target> { + self.as_ref().map(|t| t.deref()) + } +} + impl Option> { /// Transposes an `Option` of a `Result` into a `Result` of an `Option`. /// @@ -989,7 +1000,6 @@ fn expect_failed(msg: &str) -> ! { panic!("{}", msg) } - ///////////////////////////////////////////////////////////////////////////// // Trait implementations ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index fe5914c72e1ac..479c10c4ffbae 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -680,46 +680,6 @@ impl *const T { } } - /// Calculates the distance between two pointers. The returned value is in - /// units of T: the distance in bytes is divided by `mem::size_of::()`. - /// - /// If the address different between the two pointers ia not a multiple of - /// `mem::size_of::()` then the result of the division is rounded towards - /// zero. - /// - /// This function returns `None` if `T` is a zero-sized type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(offset_to)] - /// #![allow(deprecated)] - /// - /// fn main() { - /// let a = [0; 5]; - /// let ptr1: *const i32 = &a[1]; - /// let ptr2: *const i32 = &a[3]; - /// assert_eq!(ptr1.offset_to(ptr2), Some(2)); - /// assert_eq!(ptr2.offset_to(ptr1), Some(-2)); - /// assert_eq!(unsafe { ptr1.offset(2) }, ptr2); - /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1); - /// } - /// ``` - #[unstable(feature = "offset_to", issue = "41079")] - #[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \ - opposite argument order. If you're writing unsafe code, consider `offset_from`.")] - #[inline] - pub fn offset_to(self, other: *const T) -> Option where T: Sized { - let size = mem::size_of::(); - if size == 0 { - None - } else { - Some(other.wrapping_offset_from(self)) - } - } - /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// @@ -1464,46 +1424,6 @@ impl *mut T { } } - /// Calculates the distance between two pointers. The returned value is in - /// units of T: the distance in bytes is divided by `mem::size_of::()`. - /// - /// If the address different between the two pointers ia not a multiple of - /// `mem::size_of::()` then the result of the division is rounded towards - /// zero. - /// - /// This function returns `None` if `T` is a zero-sized type. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(offset_to)] - /// #![allow(deprecated)] - /// - /// fn main() { - /// let mut a = [0; 5]; - /// let ptr1: *mut i32 = &mut a[1]; - /// let ptr2: *mut i32 = &mut a[3]; - /// assert_eq!(ptr1.offset_to(ptr2), Some(2)); - /// assert_eq!(ptr2.offset_to(ptr1), Some(-2)); - /// assert_eq!(unsafe { ptr1.offset(2) }, ptr2); - /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1); - /// } - /// ``` - #[unstable(feature = "offset_to", issue = "41079")] - #[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \ - opposite argument order. If you're writing unsafe code, consider `offset_from`.")] - #[inline] - pub fn offset_to(self, other: *const T) -> Option where T: Sized { - let size = mem::size_of::(); - if size == 0 { - None - } else { - Some(other.wrapping_offset_from(self)) - } - } - /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// diff --git a/src/libcore/result.rs b/src/libcore/result.rs index e0cc669d0350a..fb496836c2c10 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -242,7 +242,7 @@ use fmt; use iter::{FromIterator, FusedIterator, TrustedLen}; -use ops; +use ops::{self, Deref}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). /// @@ -909,6 +909,44 @@ impl Result { } } +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `&Result` to `Result<&T::Target, &E>`. + /// + /// Leaves the original Result in-place, creating a new one with a reference + /// to the original one, additionally coercing the `Ok` arm of the Result via + /// `Deref`. + pub fn deref_ok(&self) -> Result<&T::Target, &E> { + self.as_ref().map(|t| t.deref()) + } +} + +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `&Result` to `Result<&T, &E::Target>`. + /// + /// Leaves the original Result in-place, creating a new one with a reference + /// to the original one, additionally coercing the `Err` arm of the Result via + /// `Deref`. + pub fn deref_err(&self) -> Result<&T, &E::Target> + { + self.as_ref().map_err(|e| e.deref()) + } +} + +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `&Result` to `Result<&T::Target, &E::Target>`. + /// + /// Leaves the original Result in-place, creating a new one with a reference + /// to the original one, additionally coercing both the `Ok` and `Err` arms + /// of the Result via `Deref`. + pub fn deref(&self) -> Result<&T::Target, &E::Target> + { + self.as_ref().map(|t| t.deref()).map_err(|e| e.deref()) + } +} + impl Result, E> { /// Transposes a `Result` of an `Option` into an `Option` of a `Result`. /// diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 321b432d3f430..d770536ef4279 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -42,7 +42,7 @@ impl Waker { /// `Arc` type and the safe `Wake` trait. #[inline] pub unsafe fn new(inner: NonNull) -> Self { - Waker { inner: inner } + Waker { inner } } /// Wake up the task associated with this `Waker`. @@ -120,7 +120,7 @@ impl LocalWaker { /// on the current thread. #[inline] pub unsafe fn new(inner: NonNull) -> Self { - LocalWaker { inner: inner } + LocalWaker { inner } } /// Wake up the task associated with this `LocalWaker`. @@ -159,7 +159,9 @@ impl LocalWaker { impl From for Waker { #[inline] fn from(local_waker: LocalWaker) -> Self { - Waker { inner: local_waker.inner } + let inner = local_waker.inner; + mem::forget(local_waker); + Waker { inner } } } diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs index d2a9ed75be658..46c54056e2cc9 100644 --- a/src/libcore/tests/char.rs +++ b/src/libcore/tests/char.rs @@ -363,54 +363,3 @@ fn eu_iterator_specializations() { check('\u{12340}'); check('\u{10FFFF}'); } - -#[test] -#[allow(deprecated)] -fn test_decode_utf8() { - macro_rules! assert_decode_utf8 { - ($input_bytes: expr, $expected_str: expr) => { - let input_bytes: &[u8] = &$input_bytes; - let s = char::decode_utf8(input_bytes.iter().cloned()) - .map(|r_b| r_b.unwrap_or('\u{FFFD}')) - .collect::(); - assert_eq!(s, $expected_str, - "input bytes: {:?}, expected str: {:?}, result: {:?}", - input_bytes, $expected_str, s); - assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str); - } - } - - assert_decode_utf8!([], ""); - assert_decode_utf8!([0x41], "A"); - assert_decode_utf8!([0xC1, 0x81], "��"); - assert_decode_utf8!([0xE2, 0x99, 0xA5], "♥"); - assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A"); - assert_decode_utf8!([0xE2, 0x99], "�"); - assert_decode_utf8!([0xE2, 0x99, 0x41], "�A"); - assert_decode_utf8!([0xC0], "�"); - assert_decode_utf8!([0xC0, 0x41], "�A"); - assert_decode_utf8!([0x80], "�"); - assert_decode_utf8!([0x80, 0x41], "�A"); - assert_decode_utf8!([0xFE], "�"); - assert_decode_utf8!([0xFE, 0x41], "�A"); - assert_decode_utf8!([0xFF], "�"); - assert_decode_utf8!([0xFF, 0x41], "�A"); - assert_decode_utf8!([0xC0, 0x80], "��"); - - // Surrogates - assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}"); - assert_decode_utf8!([0xED, 0xA0, 0x80], "���"); - assert_decode_utf8!([0xED, 0xBF, 0x80], "���"); - assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}"); - - // char::MAX - assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}"); - assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "�A"); - assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "����"); - - // 5 and 6 bytes sequence - // Part of the original design of UTF-8, - // but invalid now that UTF-8 is artificially restricted to match the range of UTF-16. - assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "�����"); - assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "������"); -} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 6fcfaae453500..2323b30a0104a 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -43,6 +43,7 @@ #![feature(align_offset)] #![feature(reverse_bits)] #![feature(iterator_find_map)] +#![feature(inner_deref)] #![feature(slice_internals)] #![feature(option_replace)] diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index 324ebf435651d..1324ba2d9a9c3 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -298,6 +298,23 @@ fn test_try() { assert_eq!(try_option_err(), Err(NoneError)); } +#[test] +fn test_option_deref() { + // Some: &Option::Some(T) -> Option<&T::Deref::Target>::Some(&*T) + let ref_option = &Some(&42); + assert_eq!(ref_option.deref(), Some(&42)); + + let ref_option = &Some(String::from("a result")); + assert_eq!(ref_option.deref(), Some("a result")); + + let ref_option = &Some(vec![1, 2, 3, 4, 5]); + assert_eq!(ref_option.deref(), Some(&[1, 2, 3, 4, 5][..])); + + // None: &Option>::None -> None + let ref_option: &Option<&i32> = &None; + assert_eq!(ref_option.deref(), None); +} + #[test] fn test_replace() { let mut x = Some(2); diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs index 0616252c82c89..0c00992ffd84e 100644 --- a/src/libcore/tests/result.rs +++ b/src/libcore/tests/result.rs @@ -233,3 +233,96 @@ fn test_try() { } assert_eq!(try_result_err(), Err(1)); } + +#[test] +fn test_result_deref() { + // &Result::Ok(T).deref_ok() -> + // Result<&T::Deref::Target, &E>::Ok(&*T) + let ref_ok = &Result::Ok::<&i32, u8>(&42); + let expected_result = Result::Ok::<&i32, &u8>(&42); + assert_eq!(ref_ok.deref_ok(), expected_result); + + let ref_ok = &Result::Ok::(String::from("a result")); + let expected_result = Result::Ok::<&str, &u32>("a result"); + assert_eq!(ref_ok.deref_ok(), expected_result); + + let ref_ok = &Result::Ok::, u32>(vec![1, 2, 3, 4, 5]); + let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]); + assert_eq!(ref_ok.deref_ok(), expected_result); + + // &Result::Ok(T).deref() -> + // Result<&T::Deref::Target, &E::Deref::Target>::Ok(&*T) + let ref_ok = &Result::Ok::<&i32, &u8>(&42); + let expected_result = Result::Ok::<&i32, &u8>(&42); + assert_eq!(ref_ok.deref(), expected_result); + + let ref_ok = &Result::Ok::(String::from("a result")); + let expected_result = Result::Ok::<&str, &u32>("a result"); + assert_eq!(ref_ok.deref(), expected_result); + + let ref_ok = &Result::Ok::, &u32>(vec![1, 2, 3, 4, 5]); + let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]); + assert_eq!(ref_ok.deref(), expected_result); + + // &Result::Err(T).deref_err() -> + // Result<&T, &E::Deref::Target>::Err(&*E) + let ref_err = &Result::Err::(&41); + let expected_result = Result::Err::<&u8, &i32>(&41); + assert_eq!(ref_err.deref_err(), expected_result); + + let ref_err = &Result::Err::(String::from("an error")); + let expected_result = Result::Err::<&u32, &str>("an error"); + assert_eq!(ref_err.deref_err(), expected_result); + + let ref_err = &Result::Err::>(vec![5, 4, 3, 2, 1]); + let expected_result = Result::Err::<&u32, &[i32]>(&[5, 4, 3, 2, 1][..]); + assert_eq!(ref_err.deref_err(), expected_result); + + // &Result::Err(T).deref_err() -> + // Result<&T, &E::Deref::Target>::Err(&*E) + let ref_err = &Result::Err::<&u8, &i32>(&41); + let expected_result = Result::Err::<&u8, &i32>(&41); + assert_eq!(ref_err.deref(), expected_result); + + let ref_err = &Result::Err::<&u32, String>(String::from("an error")); + let expected_result = Result::Err::<&u32, &str>("an error"); + assert_eq!(ref_err.deref(), expected_result); + + let ref_err = &Result::Err::<&u32, Vec>(vec![5, 4, 3, 2, 1]); + let expected_result = Result::Err::<&u32, &[i32]>(&[5, 4, 3, 2, 1][..]); + assert_eq!(ref_err.deref(), expected_result); + + // The following cases test calling deref_* with the wrong variant (i.e. + // `deref_ok()` with a `Result::Err()`, or `deref_err()` with a `Result::Ok()`. + // While unusual, these cases are supported to ensure that an `inner_deref` + // call can still be made even when one of the Result types does not implement + // `Deref` (for example, std::io::Error). + + // &Result::Ok(T).deref_err() -> + // Result<&T, &E::Deref::Target>::Ok(&T) + let ref_ok = &Result::Ok::(42); + let expected_result = Result::Ok::<&i32, &u8>(&42); + assert_eq!(ref_ok.deref_err(), expected_result); + + let ref_ok = &Result::Ok::<&str, &u32>("a result"); + let expected_result = Result::Ok::<&&str, &u32>(&"a result"); + assert_eq!(ref_ok.deref_err(), expected_result); + + let ref_ok = &Result::Ok::<[i32; 5], &u32>([1, 2, 3, 4, 5]); + let expected_result = Result::Ok::<&[i32; 5], &u32>(&[1, 2, 3, 4, 5]); + assert_eq!(ref_ok.deref_err(), expected_result); + + // &Result::Err(E).deref_ok() -> + // Result<&T::Deref::Target, &E>::Err(&E) + let ref_err = &Result::Err::<&u8, i32>(41); + let expected_result = Result::Err::<&u8, &i32>(&41); + assert_eq!(ref_err.deref_ok(), expected_result); + + let ref_err = &Result::Err::<&u32, &str>("an error"); + let expected_result = Result::Err::<&u32, &&str>(&"an error"); + assert_eq!(ref_err.deref_ok(), expected_result); + + let ref_err = &Result::Err::<&u32, [i32; 5]>([5, 4, 3, 2, 1]); + let expected_result = Result::Err::<&u32, &[i32; 5]>(&[5, 4, 3, 2, 1]); + assert_eq!(ref_err.deref_ok(), expected_result); +} diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c1b205620892..96b7d865dc8ba 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -575,7 +575,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session, // Check for future incompatibility lints and issue a stronger warning. let lints = sess.lint_store.borrow(); let lint_id = LintId::of(lint); - if let Some(future_incompatible) = lints.future_incompatible(lint_id) { + let future_incompatible = lints.future_incompatible(lint_id); + if let Some(future_incompatible) = future_incompatible { const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ it will become a hard error"; @@ -593,20 +594,21 @@ pub fn struct_lint_level<'a>(sess: &'a Session, future_incompatible.reference); err.warn(&explanation); err.note(&citation); + } - // If this lint is *not* a future incompatibility warning then we want to be - // sure to not be too noisy in some situations. If this code originates in a - // foreign macro, aka something that this crate did not itself author, then - // it's likely that there's nothing this crate can do about it. We probably - // want to skip the lint entirely. - // - // For some lints though (like unreachable code) there's clear actionable - // items to take care of (delete the macro invocation). As a result we have - // a few lints we whitelist here for allowing a lint even though it's in a - // foreign macro invocation. - } else if !lint.report_in_external_macro { - if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { - err.cancel(); + // If this code originates in a foreign macro, aka something that this crate + // did not itself author, then it's likely that there's nothing this crate + // can do about it. We probably want to skip the lint entirely. + if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { + // Any suggestions made here are likely to be incorrect, so anything we + // emit shouldn't be automatically fixed by rustfix. + err.allow_suggestions(false); + + // If this is a future incompatible lint it'll become a hard error, so + // we have to emit *something*. Also allow lints to whitelist themselves + // on a case-by-case basis for emission in a foreign macro. + if future_incompatible.is_none() && !lint.report_in_external_macro { + err.cancel() } } diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 3b5f927d52f00..95a1c5fae2fcc 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -16,6 +16,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::Session; use rustc::session::config::Sanitizer; use rustc::ty::TyCtxt; +use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; use rustc_data_structures::sync::Lrc; use rustc_data_structures::fx::FxHashMap; @@ -30,12 +31,16 @@ use context::CodegenCx; /// Mark LLVM function to use provided inline heuristic. #[inline] -pub fn inline(val: ValueRef, inline: InlineAttr) { +pub fn inline(cx: &CodegenCx, val: ValueRef, inline: InlineAttr) { use self::InlineAttr::*; match inline { Hint => Attribute::InlineHint.apply_llfn(Function, val), Always => Attribute::AlwaysInline.apply_llfn(Function, val), - Never => Attribute::NoInline.apply_llfn(Function, val), + Never => { + if !cx.tcx().sess.target.target.options.ignore_inline_never { + Attribute::NoInline.apply_llfn(Function, val); + } + }, None => { Attribute::InlineHint.unapply_llfn(Function, val); Attribute::AlwaysInline.unapply_llfn(Function, val); @@ -126,7 +131,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator { pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(id); - inline(llfn, codegen_fn_attrs.inline); + inline(cx, llfn, codegen_fn_attrs.inline); set_frame_pointer_elimination(cx, llfn); set_probestack(cx, llfn); diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index b34d0f1cd9070..ba6d3e782f199 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -565,6 +565,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn range_metadata(&self, load: ValueRef, range: Range) { + if self.sess().target.target.arch == "amdgpu" { + // amdgpu/LLVM does something weird and thinks a i64 value is + // split into a v2i32, halving the bitwidth LLVM expects, + // tripping an assertion. So, for now, just disable this + // optimization. + return; + } + unsafe { let llty = val_ty(load); let v = [ diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 2c01bd42cc77a..b9cb412796964 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -95,7 +95,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, debug!("get_fn: not casting pointer!"); if instance.def.is_inline(tcx) { - attributes::inline(llfn, attributes::InlineAttr::Hint); + attributes::inline(cx, llfn, attributes::InlineAttr::Hint); } attributes::from_fn_attrs(cx, llfn, instance.def.def_id()); diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index a528008e3b4bd..3bbcf98f20f32 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -181,7 +181,7 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance); if instance.def.is_inline(cx.tcx) { - attributes::inline(lldecl, attributes::InlineAttr::Hint); + attributes::inline(cx, lldecl, attributes::InlineAttr::Hint); } attributes::from_fn_attrs(cx, lldecl, instance.def.def_id()); diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index a0f3abda077f9..1b34898b99084 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -26,6 +26,7 @@ use syntax_pos::{MultiSpan, Span}; pub struct DiagnosticBuilder<'a> { pub handler: &'a Handler, diagnostic: Diagnostic, + allow_suggestions: bool, } /// In general, the `DiagnosticBuilder` uses deref to allow access to @@ -186,27 +187,67 @@ impl<'a> DiagnosticBuilder<'a> { msg: &str, suggestions: Vec) -> &mut Self); - forward!(pub fn span_suggestion_with_applicability(&mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability) - -> &mut Self); - forward!(pub fn span_suggestions_with_applicability(&mut self, - sp: Span, - msg: &str, - suggestions: Vec, - applicability: Applicability) - -> &mut Self); - forward!(pub fn span_suggestion_short_with_applicability(&mut self, - sp: Span, - msg: &str, - suggestion: String, - applicability: Applicability) - -> &mut Self); + pub fn span_suggestion_with_applicability(&mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability) + -> &mut Self { + if !self.allow_suggestions { + return self + } + self.diagnostic.span_suggestion_with_applicability( + sp, + msg, + suggestion, + applicability, + ); + self + } + + pub fn span_suggestions_with_applicability(&mut self, + sp: Span, + msg: &str, + suggestions: Vec, + applicability: Applicability) + -> &mut Self { + if !self.allow_suggestions { + return self + } + self.diagnostic.span_suggestions_with_applicability( + sp, + msg, + suggestions, + applicability, + ); + self + } + + pub fn span_suggestion_short_with_applicability(&mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability) + -> &mut Self { + if !self.allow_suggestions { + return self + } + self.diagnostic.span_suggestion_short_with_applicability( + sp, + msg, + suggestion, + applicability, + ); + self + } forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); + pub fn allow_suggestions(&mut self, allow: bool) -> &mut Self { + self.allow_suggestions = allow; + self + } + /// Convenience function for internal use, clients should use one of the /// struct_* methods on Handler. pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuilder<'a> { @@ -228,7 +269,11 @@ impl<'a> DiagnosticBuilder<'a> { /// diagnostic. pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> { - DiagnosticBuilder { handler, diagnostic } + DiagnosticBuilder { + handler, + diagnostic, + allow_suggestions: true, + } } } diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 1619637b827df..316926b1995be 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -81,7 +81,7 @@ fn main() { let is_crossed = target != host; let mut optional_components = - vec!["x86", "arm", "aarch64", "mips", "powerpc", + vec!["x86", "arm", "aarch64", "amdgpu", "mips", "powerpc", "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx"]; let mut version_cmd = Command::new(&llvm_config); diff --git a/src/librustc_target/abi/call/amdgpu.rs b/src/librustc_target/abi/call/amdgpu.rs new file mode 100644 index 0000000000000..62462f04d8f56 --- /dev/null +++ b/src/librustc_target/abi/call/amdgpu.rs @@ -0,0 +1,42 @@ +// Copyright 2018 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 abi::call::{ArgType, FnType, }; +use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; + +fn classify_ret_ty<'a, Ty, C>(_tuncx: C, ret: &mut ArgType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + ret.extend_integer_width_to(32); +} + +fn classify_arg_ty<'a, Ty, C>(_cx: C, arg: &mut ArgType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + arg.extend_integer_width_to(32); +} + +pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + if !fty.ret.is_ignore() { + classify_ret_ty(cx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(cx, arg); + } +} diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index ca5aba5b6420a..8a59fc925900a 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -13,6 +13,7 @@ use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; use spec::HasTargetSpec; mod aarch64; +mod amdgpu; mod arm; mod asmjs; mod hexagon; @@ -480,6 +481,7 @@ impl<'a, Ty> FnType<'a, Ty> { x86_64::compute_abi_info(cx, self); }, "aarch64" => aarch64::compute_abi_info(cx, self), + "amdgpu" => amdgpu::compute_abi_info(cx, self), "arm" => arm::compute_abi_info(cx, self), "mips" => mips::compute_abi_info(cx, self), "mips64" => mips64::compute_abi_info(cx, self), diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index c5d21cdc46adb..26da933989fd2 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -635,6 +635,12 @@ pub struct TargetOptions { /// typically because the platform needs to unwind for things like stack /// unwinders. pub requires_uwtable: bool, + + /// Targets like AMDGPU add alwaysinline hints everywhere, + /// and basically inline everything regardless of our wishes anyway. + /// This causes LLVM validation errors due to the conflicting attributes. + /// Defaults to false. + pub ignore_inline_never: bool, } impl Default for TargetOptions { @@ -713,6 +719,7 @@ impl Default for TargetOptions { embed_bitcode: false, emit_debug_gdb_scripts: true, requires_uwtable: false, + ignore_inline_never: false, } } } @@ -972,6 +979,7 @@ impl Target { key!(embed_bitcode, bool); key!(emit_debug_gdb_scripts, bool); key!(requires_uwtable, bool); + key!(ignore_inline_never, bool); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -1181,6 +1189,7 @@ impl ToJson for Target { target_option_val!(embed_bitcode); target_option_val!(emit_debug_gdb_scripts); target_option_val!(requires_uwtable); + target_option_val!(ignore_inline_never); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f658d57426497..90b7c44d86aa2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -425,9 +425,6 @@ impl Item { pub fn is_enum(&self) -> bool { self.type_() == ItemType::Enum } - pub fn is_fn(&self) -> bool { - self.type_() == ItemType::Function - } pub fn is_associated_type(&self) -> bool { self.type_() == ItemType::AssociatedType } @@ -1197,7 +1194,8 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option })?; match ty.def { Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => { - let item = cx.tcx.inherent_impls(did).iter() + let item = cx.tcx.inherent_impls(did) + .iter() .flat_map(|imp| cx.tcx.associated_items(*imp)) .find(|item| item.ident.name == item_name); if let Some(item) = item { @@ -1208,26 +1206,23 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option }; Ok((ty.def, Some(format!("{}.{}", out, item_name)))) } else { - let is_enum = match ty.def { - Def::Enum(_) => true, - _ => false, - }; - let elem = if is_enum { - cx.tcx.adt_def(did).all_fields().find(|item| item.ident.name == item_name) - } else { - cx.tcx.adt_def(did) - .non_enum_variant() - .fields - .iter() - .find(|item| item.ident.name == item_name) - }; - if let Some(item) = elem { - Ok((ty.def, - Some(format!("{}.{}", - if is_enum { "variant" } else { "structfield" }, - item.ident)))) - } else { - Err(()) + match cx.tcx.type_of(did).sty { + ty::TyAdt(def, _) => { + if let Some(item) = def.all_fields() + .find(|item| item.ident.name == item_name) { + Ok((ty.def, + Some(format!("{}.{}", + if def.is_enum() { + "variant" + } else { + "structfield" + }, + item.ident)))) + } else { + Err(()) + } + } + _ => Err(()), } } } @@ -2188,10 +2183,6 @@ pub struct FnDecl { } impl FnDecl { - pub fn has_self(&self) -> bool { - self.inputs.values.len() > 0 && self.inputs.values[0].name == "self" - } - pub fn self_type(&self) -> Option { self.inputs.values.get(0).and_then(|v| v.to_self()) } @@ -3547,21 +3538,6 @@ pub struct Path { } impl Path { - pub fn singleton(name: String) -> Path { - Path { - global: false, - def: Def::Err, - segments: vec![PathSegment { - name, - args: GenericArgs::AngleBracketed { - lifetimes: Vec::new(), - types: Vec::new(), - bindings: Vec::new(), - } - }] - } - } - pub fn last_name(&self) -> &str { self.segments.last().unwrap().name.as_str() } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 591c660138aee..d6e8f3d938e93 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -11,7 +11,6 @@ //! This module is used to store stuff from Rust's AST in a more convenient //! manner (and with prettier names) before cleaning. pub use self::StructType::*; -pub use self::TypeBound::*; use syntax::ast; use syntax::ast::{Name, NodeId}; @@ -91,11 +90,6 @@ pub enum StructType { Unit, } -pub enum TypeBound { - RegionBound, - TraitBound(hir::TraitRef) -} - pub struct Struct { pub vis: hir::Visibility, pub stab: Option, diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index ddc5d56b474fc..6d96bc8e36038 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -12,19 +12,13 @@ use std::mem; use clean::*; -pub enum FoldItem { - Retain(Item), - Strip(Item), - Erase, -} +pub struct StripItem(pub Item); -impl FoldItem { - pub fn fold(self) -> Option { - match self { - FoldItem::Erase => None, - FoldItem::Retain(i) => Some(i), - FoldItem::Strip(item@ Item { inner: StrippedItem(..), .. } ) => Some(item), - FoldItem::Strip(mut i) => { +impl StripItem { + pub fn strip(self) -> Option { + match self.0 { + Item { inner: StrippedItem(..), .. } => Some(self.0), + mut i => { i.inner = StrippedItem(box i.inner); Some(i) } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 6cf9b143373a8..065778d8d0725 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -60,20 +60,6 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str> String::from_utf8_lossy(&out[..]).into_owned() } -/// Highlights `src`, returning the HTML output. Returns only the inner html to -/// be inserted into an element. C.f., `render_with_highlighting` which includes -/// an enclosing `
` block.
-pub fn render_inner_with_highlighting(src: &str) -> io::Result {
-    let sess = parse::ParseSess::new(FilePathMapping::empty());
-    let fm = sess.codemap().new_filemap(FileName::Custom("stdin".to_string()), src.to_string());
-
-    let mut out = Vec::new();
-    let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None), sess.codemap());
-    classifier.write_source(&mut out)?;
-
-    Ok(String::from_utf8_lossy(&out).into_owned())
-}
-
 /// Processes a program (nested in the internal `lexer`), classifying strings of
 /// text by highlighting category (`Class`). Calls out to a `Writer` to write
 /// each span of text in sequence.
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 613ca01ff82f8..041a233617083 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -25,6 +25,7 @@
 #![feature(vec_remove_item)]
 #![feature(entry_and_modify)]
 #![feature(ptr_offset_from)]
+#![feature(crate_visibility_modifier)]
 
 #![recursion_limit="256"]
 
@@ -72,28 +73,28 @@ use rustc_target::spec::TargetTriple;
 use rustc::session::config::get_cmd_lint_options;
 
 #[macro_use]
-pub mod externalfiles;
+mod externalfiles;
 
-pub mod clean;
-pub mod core;
-pub mod doctree;
-pub mod fold;
+mod clean;
+mod core;
+mod doctree;
+mod fold;
 pub mod html {
-    pub mod highlight;
-    pub mod escape;
-    pub mod item_type;
-    pub mod format;
-    pub mod layout;
+    crate mod highlight;
+    crate mod escape;
+    crate mod item_type;
+    crate mod format;
+    crate mod layout;
     pub mod markdown;
-    pub mod render;
-    pub mod toc;
+    crate mod render;
+    crate mod toc;
 }
-pub mod markdown;
-pub mod passes;
-pub mod visit_ast;
-pub mod visit_lib;
-pub mod test;
-pub mod theme;
+mod markdown;
+mod passes;
+mod visit_ast;
+mod visit_lib;
+mod test;
+mod theme;
 
 use clean::AttributesExt;
 
@@ -140,7 +141,7 @@ fn unstable(name: &'static str, f: F) -> RustcOptGroup
     RustcOptGroup::unstable(name, f)
 }
 
-pub fn opts() -> Vec {
+fn opts() -> Vec {
     vec![
         stable("h", |o| o.optflag("h", "help", "show this help message")),
         stable("V", |o| o.optflag("V", "version", "print rustdoc's version")),
@@ -334,7 +335,7 @@ pub fn opts() -> Vec {
     ]
 }
 
-pub fn usage(argv0: &str) {
+fn usage(argv0: &str) {
     let mut options = getopts::Options::new();
     for option in opts() {
         (option.apply)(&mut options);
@@ -342,7 +343,7 @@ pub fn usage(argv0: &str) {
     println!("{}", options.usage(&format!("{} [options] ", argv0)));
 }
 
-pub fn main_args(args: &[String]) -> isize {
+fn main_args(args: &[String]) -> isize {
     let mut options = getopts::Options::new();
     for option in opts() {
         (option.apply)(&mut options);
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 8de4fed5bf0c0..aa4acaf75bf31 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -15,7 +15,7 @@ use std::mem;
 
 use clean::{self, GetDefId, Item};
 use fold;
-use fold::FoldItem::Strip;
+use fold::StripItem;
 
 mod collapse_docs;
 pub use self::collapse_docs::collapse_docs;
@@ -35,24 +35,44 @@ pub use self::unindent_comments::unindent_comments;
 mod propagate_doc_cfg;
 pub use self::propagate_doc_cfg::propagate_doc_cfg;
 
-type Pass = (&'static str,                                      // name
-             fn(clean::Crate) -> clean::Crate,                  // fn
-             &'static str);                                     // description
+type Pass = (
+    &'static str,                     // name
+    fn(clean::Crate) -> clean::Crate, // fn
+    &'static str,
+); // description
 
 pub const PASSES: &'static [Pass] = &[
-    ("strip-hidden", strip_hidden,
-     "strips all doc(hidden) items from the output"),
-    ("unindent-comments", unindent_comments,
-     "removes excess indentation on comments in order for markdown to like it"),
-    ("collapse-docs", collapse_docs,
-     "concatenates all document attributes into one document attribute"),
-    ("strip-private", strip_private,
-     "strips all private items from a crate which cannot be seen externally, \
-      implies strip-priv-imports"),
-    ("strip-priv-imports", strip_priv_imports,
-     "strips all private import statements (`use`, `extern crate`) from a crate"),
-    ("propagate-doc-cfg", propagate_doc_cfg,
-     "propagates `#[doc(cfg(...))]` to child items"),
+    (
+        "strip-hidden",
+        strip_hidden,
+        "strips all doc(hidden) items from the output",
+    ),
+    (
+        "unindent-comments",
+        unindent_comments,
+        "removes excess indentation on comments in order for markdown to like it",
+    ),
+    (
+        "collapse-docs",
+        collapse_docs,
+        "concatenates all document attributes into one document attribute",
+    ),
+    (
+        "strip-private",
+        strip_private,
+        "strips all private items from a crate which cannot be seen externally, \
+         implies strip-priv-imports",
+    ),
+    (
+        "strip-priv-imports",
+        strip_priv_imports,
+        "strips all private import statements (`use`, `extern crate`) from a crate",
+    ),
+    (
+        "propagate-doc-cfg",
+        propagate_doc_cfg,
+        "propagates `#[doc(cfg(...))]` to child items",
+    ),
 ];
 
 pub const DEFAULT_PASSES: &'static [&'static str] = &[
@@ -79,15 +99,9 @@ pub enum DefaultPassOption {
 
 pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] {
     match default_set {
-        DefaultPassOption::Default => {
-            DEFAULT_PASSES
-        },
-        DefaultPassOption::Private => {
-            DEFAULT_PRIVATE_PASSES
-        },
-        DefaultPassOption::None => {
-            &[]
-        },
+        DefaultPassOption::Default => DEFAULT_PASSES,
+        DefaultPassOption::Private => DEFAULT_PRIVATE_PASSES,
+        DefaultPassOption::None => &[],
     }
 }
 
@@ -110,14 +124,21 @@ impl<'a> fold::DocFolder for Stripper<'a> {
                 return ret;
             }
             // These items can all get re-exported
-            clean::ExistentialItem(..) |
-            clean::TypedefItem(..) | clean::StaticItem(..) |
-            clean::StructItem(..) | clean::EnumItem(..) |
-            clean::TraitItem(..) | clean::FunctionItem(..) |
-            clean::VariantItem(..) | clean::MethodItem(..) |
-            clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) |
-            clean::ConstantItem(..) | clean::UnionItem(..) |
-            clean::AssociatedConstItem(..) | clean::ForeignTypeItem => {
+            clean::ExistentialItem(..)
+            | clean::TypedefItem(..)
+            | clean::StaticItem(..)
+            | clean::StructItem(..)
+            | clean::EnumItem(..)
+            | clean::TraitItem(..)
+            | clean::FunctionItem(..)
+            | clean::VariantItem(..)
+            | clean::MethodItem(..)
+            | clean::ForeignFunctionItem(..)
+            | clean::ForeignStaticItem(..)
+            | clean::ConstantItem(..)
+            | clean::UnionItem(..)
+            | clean::AssociatedConstItem(..)
+            | clean::ForeignTypeItem => {
                 if i.def_id.is_local() {
                     if !self.access_levels.is_exported(i.def_id) {
                         return None;
@@ -127,14 +148,14 @@ impl<'a> fold::DocFolder for Stripper<'a> {
 
             clean::StructFieldItem(..) => {
                 if i.visibility != Some(clean::Public) {
-                    return Strip(i).fold();
+                    return StripItem(i).strip();
                 }
             }
 
             clean::ModuleItem(..) => {
                 if i.def_id.is_local() && i.visibility != Some(clean::Public) {
                     let old = mem::replace(&mut self.update_retained, false);
-                    let ret = Strip(self.fold_item_recur(i).unwrap()).fold();
+                    let ret = StripItem(self.fold_item_recur(i).unwrap()).strip();
                     self.update_retained = old;
                     return ret;
                 }
@@ -167,7 +188,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
             // Struct variant fields have inherited visibility
             clean::VariantItem(clean::Variant {
-                kind: clean::VariantKind::Struct(..)
+                kind: clean::VariantKind::Struct(..),
             }) => true,
             _ => false,
         };
@@ -192,7 +213,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
 
 // This stripper discards all impls which reference stripped items
 struct ImplStripper<'a> {
-    retained: &'a DefIdSet
+    retained: &'a DefIdSet,
 }
 
 impl<'a> fold::DocFolder for ImplStripper<'a> {
@@ -203,9 +224,7 @@ impl<'a> fold::DocFolder for ImplStripper<'a> {
                 return None;
             }
             if let Some(did) = imp.for_.def_id() {
-                if did.is_local() && !imp.for_.is_generic() &&
-                    !self.retained.contains(&did)
-                {
+                if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) {
                     return None;
                 }
             }
@@ -233,9 +252,12 @@ struct ImportStripper;
 impl fold::DocFolder for ImportStripper {
     fn fold_item(&mut self, i: Item) -> Option {
         match i.inner {
-            clean::ExternCrateItem(..) |
-            clean::ImportItem(..) if i.visibility != Some(clean::Public) => None,
-            _ => self.fold_item_recur(i)
+            clean::ExternCrateItem(..) | clean::ImportItem(..)
+                if i.visibility != Some(clean::Public) =>
+            {
+                None
+            }
+            _ => self.fold_item_recur(i),
         }
     }
 }
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index b1545233f8a2b..279c9603703cd 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -15,7 +15,7 @@ use clean::{self, AttributesExt, NestedAttributesExt};
 use clean::Item;
 use fold;
 use fold::DocFolder;
-use fold::FoldItem::Strip;
+use fold::StripItem;
 use passes::ImplStripper;
 
 /// Strip items marked `#[doc(hidden)]`
@@ -49,7 +49,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
                     // strip things like impl methods but when doing so
                     // we must not add any items to the `retained` set.
                     let old = mem::replace(&mut self.update_retained, false);
-                    let ret = Strip(self.fold_item_recur(i).unwrap()).fold();
+                    let ret = StripItem(self.fold_item_recur(i).unwrap()).strip();
                     self.update_retained = old;
                     return ret;
                 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 09d304b71a2c1..287913d2cc9b8 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -105,8 +105,8 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
     }
 
     pub fn visit_variant_data(&mut self, item: &hir::Item,
-                            name: ast::Name, sd: &hir::VariantData,
-                            generics: &hir::Generics) -> Struct {
+                              name: ast::Name, sd: &hir::VariantData,
+                              generics: &hir::Generics) -> Struct {
         debug!("Visiting struct");
         let struct_type = struct_type_from_def(&*sd);
         Struct {
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 5a2dce5930a4b..5348c9a0f3498 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -22,7 +22,6 @@ core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
-std_unicode = { path = "../libstd_unicode" }
 unwind = { path = "../libunwind" }
 
 [dev-dependencies]
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 376410677346c..0c8e95aa42624 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -154,180 +154,6 @@ pub trait AsciiExt {
     /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
     #[stable(feature = "ascii", since = "1.9.0")]
     fn make_ascii_lowercase(&mut self);
-
-    /// Checks if the value is an ASCII alphabetic character:
-    /// U+0041 'A' ... U+005A 'Z' or U+0061 'a' ... U+007A 'z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII alphabetic.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_alphabetic)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_alphabetic)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII uppercase character:
-    /// U+0041 'A' ... U+005A 'Z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII uppercase.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_uppercase)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_uppercase)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII lowercase character:
-    /// U+0061 'a' ... U+007A 'z'.
-    /// For strings, true if all characters in the string are
-    /// ASCII lowercase.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_lowercase)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_lowercase)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII alphanumeric character:
-    /// U+0041 'A' ... U+005A 'Z', U+0061 'a' ... U+007A 'z', or
-    /// U+0030 '0' ... U+0039 '9'.
-    /// For strings, true if all characters in the string are
-    /// ASCII alphanumeric.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_alphanumeric)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_alphanumeric)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII decimal digit:
-    /// U+0030 '0' ... U+0039 '9'.
-    /// For strings, true if all characters in the string are
-    /// ASCII digits.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_digit)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_digit)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_digit(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII hexadecimal digit:
-    /// U+0030 '0' ... U+0039 '9', U+0041 'A' ... U+0046 'F', or
-    /// U+0061 'a' ... U+0066 'f'.
-    /// For strings, true if all characters in the string are
-    /// ASCII hex digits.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_hexdigit)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_hexdigit)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    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+007B ... U+007E `{ | } ~`
-    ///
-    /// For strings, true if all characters in the string are
-    /// ASCII punctuation.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_punctuation)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_punctuation)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII graphic character:
-    /// U+0021 '!' ... U+007E '~'.
-    /// For strings, true if all characters in the string are
-    /// ASCII graphic characters.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_graphic)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_graphic)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII whitespace character:
-    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
-    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
-    /// For strings, true if all characters in the string are
-    /// ASCII whitespace.
-    ///
-    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
-    /// whitespace][infra-aw].  There are several other definitions in
-    /// wide use.  For instance, [the POSIX locale][pct] includes
-    /// U+000B VERTICAL TAB as well as all the above characters,
-    /// but—from the very same specification—[the default rule for
-    /// "field splitting" in the Bourne shell][bfs] considers *only*
-    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
-    ///
-    /// If you are writing a program that will process an existing
-    /// file format, check what that format's definition of whitespace is
-    /// before using this function.
-    ///
-    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
-    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
-    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_whitespace)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_whitespace)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
-
-    /// Checks if the value is an ASCII control character:
-    /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
-    /// Note that most ASCII whitespace characters are control
-    /// characters, but SPACE is not.
-    ///
-    /// # Note
-    ///
-    /// This method will be deprecated in favor of the identically-named
-    /// inherent methods on `u8` and `char`.
-    /// For `[u8]` use `.iter().all(u8::is_ascii_control)`.
-    /// For `str` use `.bytes().all(u8::is_ascii_control)`.
-    #[unstable(feature = "ascii_ctype", issue = "39658")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
-    fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
 macro_rules! delegating_ascii_methods {
@@ -352,47 +178,12 @@ macro_rules! delegating_ascii_methods {
     }
 }
 
-macro_rules! delegating_ascii_ctype_methods {
-    () => {
-        #[inline]
-        fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
-
-        #[inline]
-        fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
-
-        #[inline]
-        fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
-
-        #[inline]
-        fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
-
-        #[inline]
-        fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
-
-        #[inline]
-        fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
-
-        #[inline]
-        fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
-
-        #[inline]
-        fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
-
-        #[inline]
-        fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
-
-        #[inline]
-        fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
 impl AsciiExt for u8 {
     type Owned = u8;
 
     delegating_ascii_methods!();
-    delegating_ascii_ctype_methods!();
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -401,7 +192,6 @@ impl AsciiExt for char {
     type Owned = char;
 
     delegating_ascii_methods!();
-    delegating_ascii_ctype_methods!();
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -410,56 +200,6 @@ impl AsciiExt for [u8] {
     type Owned = Vec;
 
     delegating_ascii_methods!();
-
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_alphabetic())
-    }
-
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_uppercase())
-    }
-
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_lowercase())
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_alphanumeric())
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_digit())
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_hexdigit())
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_punctuation())
-    }
-
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_graphic())
-    }
-
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_whitespace())
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        self.iter().all(|b| b.is_ascii_control())
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -468,54 +208,4 @@ impl AsciiExt for str {
     type Owned = String;
 
     delegating_ascii_methods!();
-
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_alphabetic())
-    }
-
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_uppercase())
-    }
-
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_lowercase())
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_alphanumeric())
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_digit())
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_hexdigit())
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_punctuation())
-    }
-
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_graphic())
-    }
-
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_whitespace())
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        self.bytes().all(|b| b.is_ascii_control())
-    }
 }
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 754e2bbc4122b..b2777f5c48541 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -642,6 +642,12 @@ impl fmt::Debug for CString {
 
 #[stable(feature = "cstring_into", since = "1.7.0")]
 impl From for Vec {
+    /// Converts a [`CString`] into a [`Vec`]``.
+    ///
+    /// The conversion consumes the [`CString`], and removes the terminating NUL byte.
+    ///
+    /// [`Vec`]: ../vec/struct.Vec.html
+    /// [`CString`]: ../ffi/struct.CString.html
     #[inline]
     fn from(s: CString) -> Vec {
         s.into_bytes()
@@ -700,6 +706,10 @@ impl<'a> From<&'a CStr> for Box {
 
 #[stable(feature = "c_string_from_box", since = "1.18.0")]
 impl From> for CString {
+    /// Converts a [`Box`]`` into a [`CString`] without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`CString`]: ../ffi/struct.CString.html
     #[inline]
     fn from(s: Box) -> CString {
         s.into_c_string()
@@ -716,6 +726,10 @@ impl Clone for Box {
 
 #[stable(feature = "box_from_c_string", since = "1.20.0")]
 impl From for Box {
+    /// Converts a [`CString`] into a [`Box`]`` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Box`]: ../boxed/struct.Box.html
     #[inline]
     fn from(s: CString) -> Box {
         s.into_boxed_c_str()
@@ -748,6 +762,10 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From for Arc {
+    /// Converts a [`CString`] into a [`Arc`]`` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Arc`]: ../sync/struct.Arc.html
     #[inline]
     fn from(s: CString) -> Arc {
         let arc: Arc<[u8]> = Arc::from(s.into_inner());
@@ -766,6 +784,10 @@ impl<'a> From<&'a CStr> for Arc {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From for Rc {
+    /// Converts a [`CString`] into a [`Rc`]`` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Rc`]: ../rc/struct.Rc.html
     #[inline]
     fn from(s: CString) -> Rc {
         let rc: Rc<[u8]> = Rc::from(s.into_inner());
@@ -839,6 +861,10 @@ impl fmt::Display for NulError {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From for io::Error {
+    /// Converts a [`NulError`] into a [`io::Error`].
+    ///
+    /// [`NulError`]: ../ffi/struct.NulError.html
+    /// [`io::Error`]: ../io/struct.Error.html
     fn from(_: NulError) -> io::Error {
         io::Error::new(io::ErrorKind::InvalidInput,
                        "data provided contains a nul byte")
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index b1c6e7af693d0..9e501a84e05ec 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -348,6 +348,12 @@ impl OsString {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From for OsString {
+    /// Converts a [`String`] into a [`OsString`].
+    ///
+    /// The conversion copies the data, and includes an allocation on the heap.
+    ///
+    /// [`String`]: ../string/struct.String.html
+    /// [`OsString`]: struct.OsString.html
     fn from(s: String) -> OsString {
         OsString { inner: Buf::from_string(s) }
     }
@@ -630,6 +636,10 @@ impl<'a> From<&'a OsStr> for Box {
 
 #[stable(feature = "os_string_from_box", since = "1.18.0")]
 impl From> for OsString {
+    /// Converts a `Box` into a `OsString` without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     fn from(boxed: Box) -> OsString {
         boxed.into_os_string()
     }
@@ -637,6 +647,10 @@ impl From> for OsString {
 
 #[stable(feature = "box_from_os_string", since = "1.20.0")]
 impl From for Box {
+    /// Converts a [`OsString`] into a [`Box`]`` without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     fn from(s: OsString) -> Box {
         s.into_boxed_os_str()
     }
@@ -652,6 +666,10 @@ impl Clone for Box {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From for Arc {
+    /// Converts a [`OsString`] into a [`Arc`]`` without copying or allocating.
+    ///
+    /// [`Arc`]: ../sync/struct.Arc.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     #[inline]
     fn from(s: OsString) -> Arc {
         let arc = s.inner.into_arc();
@@ -670,6 +688,10 @@ impl<'a> From<&'a OsStr> for Arc {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From for Rc {
+    /// Converts a [`OsString`] into a [`Rc`]`` without copying or allocating.
+    ///
+    /// [`Rc`]: ../rc/struct.Rc.html
+    /// [`OsString`]: ../ffi/struct.OsString.html
     #[inline]
     fn from(s: OsString) -> Rc {
         let rc = s.inner.into_rc();
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 2babf508fdcc3..03c97de6ec1e9 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -154,33 +154,6 @@ impl BufReader {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
 
-    /// Returns `true` if there are no bytes in the internal buffer.
-    ///
-    /// # Examples
-    //
-    /// ```no_run
-    /// # #![feature(bufreader_is_empty)]
-    /// use std::io::BufReader;
-    /// use std::io::BufRead;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let f1 = File::open("log.txt")?;
-    ///     let mut reader = BufReader::new(f1);
-    ///     assert!(reader.is_empty());
-    ///
-    ///     if reader.fill_buf()?.len() > 0 {
-    ///         assert!(!reader.is_empty());
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
-    #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")]
-    pub fn is_empty(&self) -> bool {
-        self.buffer().is_empty()
-    }
-
     /// Returns a reference to the internally buffered data.
     ///
     /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
@@ -1265,25 +1238,6 @@ mod tests {
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
-    #[test]
-    #[allow(deprecated)]
-    fn read_char_buffered() {
-        let buf = [195, 159];
-        let reader = BufReader::with_capacity(1, &buf[..]);
-        assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß');
-    }
-
-    #[test]
-    #[allow(deprecated)]
-    fn test_chars() {
-        let buf = [195, 159, b'a'];
-        let reader = BufReader::with_capacity(1, &buf[..]);
-        let mut it = reader.chars();
-        assert_eq!(it.next().unwrap().unwrap(), 'ß');
-        assert_eq!(it.next().unwrap().unwrap(), 'a');
-        assert!(it.next().is_none());
-    }
-
     #[test]
     #[should_panic]
     fn dont_panic_in_drop_on_panicked_flush() {
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 3622df16b9d0b..14f20151dca86 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -550,26 +550,6 @@ mod tests {
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
-    #[test]
-    #[allow(deprecated)]
-    fn test_read_char() {
-        let b = &b"Vi\xE1\xBB\x87t"[..];
-        let mut c = Cursor::new(b).chars();
-        assert_eq!(c.next().unwrap().unwrap(), 'V');
-        assert_eq!(c.next().unwrap().unwrap(), 'i');
-        assert_eq!(c.next().unwrap().unwrap(), 'ệ');
-        assert_eq!(c.next().unwrap().unwrap(), 't');
-        assert!(c.next().is_none());
-    }
-
-    #[test]
-    #[allow(deprecated)]
-    fn test_read_bad_char() {
-        let b = &b"\x80"[..];
-        let mut c = Cursor::new(b).chars();
-        assert!(c.next().unwrap().is_err());
-    }
-
     #[test]
     fn seek_past_end() {
         let buf = [0xff];
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 8530487484827..5e89ad45f81d2 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -270,10 +270,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use cmp;
-use core::str as core_str;
-use error as std_error;
 use fmt;
-use result;
 use str;
 use memchr;
 use ptr;
@@ -800,53 +797,6 @@ pub trait Read {
         Bytes { inner: self }
     }
 
-    /// Transforms this `Read` instance to an [`Iterator`] over [`char`]s.
-    ///
-    /// This adaptor will attempt to interpret this reader as a UTF-8 encoded
-    /// sequence of characters. The returned iterator will return [`None`] once
-    /// EOF is reached for this reader. Otherwise each element yielded will be a
-    /// [`Result`]`<`[`char`]`, E>` where `E` may contain information about what I/O error
-    /// occurred or where decoding failed.
-    ///
-    /// Currently this adaptor will discard intermediate data read, and should
-    /// be avoided if this is not desired.
-    ///
-    /// # Examples
-    ///
-    /// [`File`]s implement `Read`:
-    ///
-    /// [`File`]: ../fs/struct.File.html
-    /// [`Iterator`]: ../../std/iter/trait.Iterator.html
-    /// [`Result`]: ../../std/result/enum.Result.html
-    /// [`char`]: ../../std/primitive.char.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// ```no_run
-    /// #![feature(io)]
-    /// use std::io;
-    /// use std::io::prelude::*;
-    /// use std::fs::File;
-    ///
-    /// fn main() -> io::Result<()> {
-    ///     let mut f = File::open("foo.txt")?;
-    ///
-    ///     for c in f.chars() {
-    ///         println!("{}", c.unwrap());
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    #[unstable(feature = "io", reason = "the semantics of a partial read/write \
-                                         of where errors happen is currently \
-                                         unclear and may change",
-               issue = "27802")]
-    #[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-        https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-    #[allow(deprecated)]
-    fn chars(self) -> Chars where Self: Sized {
-        Chars { inner: self }
-    }
-
     /// Creates an adaptor which will chain this stream with another.
     ///
     /// The returned `Read` instance will first read all bytes from this object
@@ -2005,104 +1955,6 @@ impl Iterator for Bytes {
     }
 }
 
-/// An iterator over the `char`s of a reader.
-///
-/// This struct is generally created by calling [`chars`][chars] on a reader.
-/// Please see the documentation of `chars()` for more details.
-///
-/// [chars]: trait.Read.html#method.chars
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-#[derive(Debug)]
-#[allow(deprecated)]
-pub struct Chars {
-    inner: R,
-}
-
-/// An enumeration of possible errors that can be generated from the `Chars`
-/// adapter.
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
-    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
-#[derive(Debug)]
-#[allow(deprecated)]
-pub enum CharsError {
-    /// Variant representing that the underlying stream was read successfully
-    /// but it did not contain valid utf8 data.
-    NotUtf8,
-
-    /// Variant representing that an I/O error occurred.
-    Other(Error),
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[allow(deprecated)]
-impl Iterator for Chars {
-    type Item = result::Result;
-
-    fn next(&mut self) -> Option> {
-        let first_byte = match read_one_byte(&mut self.inner)? {
-            Ok(b) => b,
-            Err(e) => return Some(Err(CharsError::Other(e))),
-        };
-        let width = core_str::utf8_char_width(first_byte);
-        if width == 1 { return Some(Ok(first_byte as char)) }
-        if width == 0 { return Some(Err(CharsError::NotUtf8)) }
-        let mut buf = [first_byte, 0, 0, 0];
-        {
-            let mut start = 1;
-            while start < width {
-                match self.inner.read(&mut buf[start..width]) {
-                    Ok(0) => return Some(Err(CharsError::NotUtf8)),
-                    Ok(n) => start += n,
-                    Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
-                    Err(e) => return Some(Err(CharsError::Other(e))),
-                }
-            }
-        }
-        Some(match str::from_utf8(&buf[..width]).ok() {
-            Some(s) => Ok(s.chars().next().unwrap()),
-            None => Err(CharsError::NotUtf8),
-        })
-    }
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[allow(deprecated)]
-impl std_error::Error for CharsError {
-    fn description(&self) -> &str {
-        match *self {
-            CharsError::NotUtf8 => "invalid utf8 encoding",
-            CharsError::Other(ref e) => std_error::Error::description(e),
-        }
-    }
-    fn cause(&self) -> Option<&dyn std_error::Error> {
-        match *self {
-            CharsError::NotUtf8 => None,
-            CharsError::Other(ref e) => e.cause(),
-        }
-    }
-}
-
-#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
-           issue = "27802")]
-#[allow(deprecated)]
-impl fmt::Display for CharsError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            CharsError::NotUtf8 => {
-                "byte stream did not contain valid utf8".fmt(f)
-            }
-            CharsError::Other(ref e) => e.fmt(f),
-        }
-    }
-}
-
 /// An iterator over the contents of an instance of `BufRead` split on a
 /// particular byte.
 ///
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index ae804ad409ee3..bbe80df7e8bdb 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -731,7 +731,8 @@ const NOTIFIED: usize = 2;
 ///   specifying a maximum time to block the thread for.
 ///
 /// * The [`unpark`] method on a [`Thread`] atomically makes the token available
-///   if it wasn't already.
+///   if it wasn't already. Because the token is initially absent, [`unpark`]
+///   followed by [`park`] will result in the second call returning immediately.
 ///
 /// In other words, each [`Thread`] acts a bit like a spinlock that can be
 /// locked and unlocked using `park` and `unpark`.
@@ -766,6 +767,8 @@ const NOTIFIED: usize = 2;
 /// // Let some time pass for the thread to be spawned.
 /// thread::sleep(Duration::from_millis(10));
 ///
+/// // There is no race condition here, if `unpark`
+/// // happens first, `park` will return immediately.
 /// println!("Unpark the thread");
 /// parked_thread.thread().unpark();
 ///
diff --git a/src/libstd_unicode/Cargo.toml b/src/libstd_unicode/Cargo.toml
deleted file mode 100644
index b1c55c2e4b6ce..0000000000000
--- a/src/libstd_unicode/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "std_unicode"
-version = "0.0.0"
-
-[lib]
-name = "std_unicode"
-path = "lib.rs"
-test = false
-bench = false
-
-[dependencies]
-core = { path = "../libcore" }
-compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs
deleted file mode 100644
index c0d47f1fcb42b..0000000000000
--- a/src/libstd_unicode/lib.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-//! # The Unicode Library
-//!
-//! Unicode-intensive functions for `char` and `str` types.
-//!
-//! This crate provides a collection of Unicode-related functionality,
-//! including decompositions, conversions, etc., and provides traits
-//! implementing these functions for the `char` and `str` types.
-//!
-//! The functionality included here is only that which is necessary to
-//! provide for basic string-related manipulations. This crate does not
-//! (yet) aim to provide a full set of Unicode tables.
-
-#![unstable(feature = "unicode", issue = "27783")]
-#![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/",
-       html_playground_url = "https://play.rust-lang.org/",
-       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
-       test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
-#![no_std]
-
-#![feature(unicode_internals)]
-#![feature(staged_api)]
-#![rustc_deprecated(since = "1.27.0", reason = "moved into libcore")]
-
-pub use core::unicode::*;
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 40fb2c69e57cb..37a021a952914 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -396,7 +396,7 @@ declare_features! (
     // Infer outlives requirements; RFC 2093
     (active, infer_outlives_requirements, "1.26.0", Some(44493), None),
 
-    // Infer outlives requirements; RFC 2093
+    // Infer static outlives requirements; RFC 2093
     (active, infer_static_outlives_requirements, "1.26.0", Some(44493), None),
 
     // Multiple patterns with `|` in `if let` and `while let`
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 85fbc4bf378a5..6501b3873e29c 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -1092,7 +1092,7 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
     auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
 
     if (!MOrErr)
-      return std::move(MOrErr);
+      return MOrErr;
 
     // The rest of this closure is a workaround for
     // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
@@ -1110,14 +1110,14 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
     // shouldn't be a perf hit.
     if (Error Err = (*MOrErr)->materializeMetadata()) {
       Expected> Ret(std::move(Err));
-      return std::move(Ret);
+      return Ret;
     }
 
     auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
     if (WasmCustomSections)
       WasmCustomSections->eraseFromParent();
 
-    return std::move(MOrErr);
+    return MOrErr;
   };
   FunctionImporter Importer(Data->Index, Loader);
   Expected Result = Importer.importFunctions(Mod, ImportList);
diff --git a/src/test/codegen/slice-position-bounds-check.rs b/src/test/codegen/slice-position-bounds-check.rs
new file mode 100644
index 0000000000000..bcbf7fd83cf00
--- /dev/null
+++ b/src/test/codegen/slice-position-bounds-check.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.
+
+// no-system-llvm
+// compile-flags: -O
+#![crate_type = "lib"]
+
+fn search(arr: &mut [T], a: &T) -> Result {
+    match arr.iter().position(|x| x == a) {
+        Some(p) => {
+            Ok(p)
+        },
+        None => Err(()),
+    }
+}
+
+// CHECK-LABEL: @position_no_bounds_check
+#[no_mangle]
+pub fn position_no_bounds_check(y: &mut [u32], x: &u32, z: &u32) -> bool {
+    // This contains "call assume" so we cannot just rule out all calls
+    // CHECK-NOT: panic
+    if let Ok(p) = search(y, x) {
+      y[p] == *z
+    } else {
+      false
+    }
+}
diff --git a/src/test/compile-fail/issue-50264-inner-deref-trait/option_deref.rs b/src/test/compile-fail/issue-50264-inner-deref-trait/option_deref.rs
new file mode 100644
index 0000000000000..4c67fb3bef103
--- /dev/null
+++ b/src/test/compile-fail/issue-50264-inner-deref-trait/option_deref.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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(inner_deref)]
+
+fn main() {
+    let _result = &Some(42).deref();
+//~^ ERROR no method named `deref` found for type `std::option::Option<{integer}>`
+}
diff --git a/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref.rs b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref.rs
new file mode 100644
index 0000000000000..73bdf0b920907
--- /dev/null
+++ b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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(inner_deref)]
+
+fn main() {
+    let _result = &Ok(42).deref();
+//~^ ERROR no method named `deref` found
+}
diff --git a/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_err.rs b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_err.rs
new file mode 100644
index 0000000000000..5d1e7472d8f18
--- /dev/null
+++ b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_err.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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(inner_deref)]
+
+fn main() {
+    let _result = &Err(41).deref_err();
+//~^ ERROR no method named `deref_err` found
+}
diff --git a/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_ok.rs b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_ok.rs
new file mode 100644
index 0000000000000..bee8e0c062bae
--- /dev/null
+++ b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_ok.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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(inner_deref)]
+
+fn main() {
+    let _result = &Ok(42).deref_ok();
+//~^ ERROR no method named `deref_ok` found
+}
diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.rs b/src/test/rustdoc-ui/intra-doc-alias-ice.rs
new file mode 100644
index 0000000000000..a459ab5dd2bea
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc-alias-ice.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+#![deny(intra_doc_link_resolution_failure)]
+
+pub type TypeAlias = usize;
+
+/// [broken cross-reference](TypeAlias::hoge) //~ ERROR
+pub fn some_public_item() {}
diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr
new file mode 100644
index 0000000000000..231963976ea75
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr
@@ -0,0 +1,13 @@
+error: `[TypeAlias::hoge]` cannot be resolved, ignoring it...
+  --> $DIR/intra-doc-alias-ice.rs:15:30
+   |
+15 | /// [broken cross-reference](TypeAlias::hoge) //~ ERROR
+   |                              ^^^^^^^^^^^^^^^ cannot be resolved, ignoring
+   |
+note: lint level defined here
+  --> $DIR/intra-doc-alias-ice.rs:11:9
+   |
+11 | #![deny(intra_doc_link_resolution_failure)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
diff --git a/src/test/ui-fulldeps/rust-2018/auxiliary/suggestions-not-always-applicable.rs b/src/test/ui-fulldeps/rust-2018/auxiliary/suggestions-not-always-applicable.rs
new file mode 100644
index 0000000000000..7ae4731fde196
--- /dev/null
+++ b/src/test/ui-fulldeps/rust-2018/auxiliary/suggestions-not-always-applicable.rs
@@ -0,0 +1,22 @@
+// Copyright 2018 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 = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn foo(_attr: TokenStream, _f: TokenStream) -> TokenStream {
+    "pub fn foo() -> ::Foo { ::Foo }".parse().unwrap()
+}
diff --git a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed
new file mode 100644
index 0000000000000..e5b47c70863e5
--- /dev/null
+++ b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed
@@ -0,0 +1,37 @@
+// Copyright 2018 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:suggestions-not-always-applicable.rs
+// compile-flags: --edition 2015
+// run-rustfix
+// rustfix-only-machine-applicable
+// compile-pass
+
+#![feature(rust_2018_preview)]
+#![warn(rust_2018_compatibility)]
+
+extern crate suggestions_not_always_applicable as foo;
+
+pub struct Foo;
+
+mod test {
+    use crate::foo::foo;
+
+    #[foo] //~ WARN: absolute paths must start with
+    //~| WARN: previously accepted
+    //~| WARN: absolute paths
+    //~| WARN: previously accepted
+    fn main() {
+    }
+}
+
+fn main() {
+    test::foo();
+}
diff --git a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs
new file mode 100644
index 0000000000000..e5b47c70863e5
--- /dev/null
+++ b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs
@@ -0,0 +1,37 @@
+// Copyright 2018 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:suggestions-not-always-applicable.rs
+// compile-flags: --edition 2015
+// run-rustfix
+// rustfix-only-machine-applicable
+// compile-pass
+
+#![feature(rust_2018_preview)]
+#![warn(rust_2018_compatibility)]
+
+extern crate suggestions_not_always_applicable as foo;
+
+pub struct Foo;
+
+mod test {
+    use crate::foo::foo;
+
+    #[foo] //~ WARN: absolute paths must start with
+    //~| WARN: previously accepted
+    //~| WARN: absolute paths
+    //~| WARN: previously accepted
+    fn main() {
+    }
+}
+
+fn main() {
+    test::foo();
+}
diff --git a/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.stderr b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.stderr
new file mode 100644
index 0000000000000..76dc139b58f07
--- /dev/null
+++ b/src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.stderr
@@ -0,0 +1,24 @@
+warning: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/suggestions-not-always-applicable.rs:27:5
+   |
+LL |     #[foo] //~ WARN: absolute paths must start with
+   |     ^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/suggestions-not-always-applicable.rs:18:9
+   |
+LL | #![warn(rust_2018_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: #[warn(absolute_paths_not_starting_with_crate)] implied by #[warn(rust_2018_compatibility)]
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
+warning: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/suggestions-not-always-applicable.rs:27:5
+   |
+LL |     #[foo] //~ WARN: absolute paths must start with
+   |     ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
diff --git a/src/test/ui/nll/issue-52133.rs b/src/test/ui/nll/issue-52113.rs
similarity index 100%
rename from src/test/ui/nll/issue-52133.rs
rename to src/test/ui/nll/issue-52113.rs
diff --git a/src/test/ui/nll/issue-52133.stderr b/src/test/ui/nll/issue-52113.stderr
similarity index 94%
rename from src/test/ui/nll/issue-52133.stderr
rename to src/test/ui/nll/issue-52113.stderr
index c1841004cf620..4a7c10c3f1af8 100644
--- a/src/test/ui/nll/issue-52133.stderr
+++ b/src/test/ui/nll/issue-52113.stderr
@@ -1,5 +1,5 @@
 error[E0623]: lifetime mismatch
-  --> $DIR/issue-52133.rs:43:9
+  --> $DIR/issue-52113.rs:43:9
    |
 LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
    |                                  --------------------         ------- these two types are declared with different lifetimes...
diff --git a/src/tools/clippy b/src/tools/clippy
index afd91248eda02..b0dabce47803c 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit afd91248eda02cf2968e4e02c77b6c10ecd3fd4f
+Subproject commit b0dabce47803c18b935ec5390de69e04ad5304c2
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index d77261f495972..5f68d00eab1d4 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -231,6 +231,7 @@ pub struct TestProps {
     pub normalize_stderr: Vec<(String, String)>,
     pub failure_status: i32,
     pub run_rustfix: bool,
+    pub rustfix_only_machine_applicable: bool,
 }
 
 impl TestProps {
@@ -263,6 +264,7 @@ impl TestProps {
             normalize_stderr: vec![],
             failure_status: -1,
             run_rustfix: false,
+            rustfix_only_machine_applicable: false,
         }
     }
 
@@ -397,6 +399,11 @@ impl TestProps {
             if !self.run_rustfix {
                 self.run_rustfix = config.parse_run_rustfix(ln);
             }
+
+            if !self.rustfix_only_machine_applicable {
+                self.rustfix_only_machine_applicable =
+                    config.parse_rustfix_only_machine_applicable(ln);
+            }
         });
 
         if self.failure_status == -1 {
@@ -663,6 +670,10 @@ impl Config {
         self.parse_name_directive(line, "run-rustfix")
     }
 
+    fn parse_rustfix_only_machine_applicable(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "rustfix-only-machine-applicable")
+    }
+
     fn parse_edition(&self, line: &str) -> Option {
         self.parse_name_value_directive(line, "edition")
     }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index ce7828144cd0c..c8f3956415d53 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2624,7 +2624,11 @@ impl<'test> TestCx<'test> {
             let suggestions = get_suggestions_from_json(
                 &proc_res.stderr,
                 &HashSet::new(),
-                Filter::Everything,
+                if self.props.rustfix_only_machine_applicable {
+                    Filter::MachineApplicableOnly
+                } else {
+                    Filter::Everything
+                },
             ).unwrap();
             let fixed_code = apply_suggestions(&unfixed_code, &suggestions).expect(&format!(
                 "failed to apply suggestions for {:?} with rustfix",
@@ -2686,7 +2690,7 @@ impl<'test> TestCx<'test> {
             if !res.status.success() {
                 self.fatal_proc_rec("failed to compile fixed code", &res);
             }
-            if !res.stderr.is_empty() {
+            if !res.stderr.is_empty() && !self.props.rustfix_only_machine_applicable {
                 self.fatal_proc_rec("fixed code is still producing diagnostics", &res);
             }
         }