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..13042ab07e217 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -94,9 +94,9 @@ Misc Compatibility Notes ------------------- -- [Rust will no longer consider trait objects with duplicated constraints to - have implementations.][51276] For example the below code will now fail - to compile. +- [Rust will consider trait objects with duplicated constraints to be the same + type as without the duplicated constraint.][51276] For example the below code will + now fail to compile. ```rust trait Trait {} @@ -160,6 +160,17 @@ Compatibility Notes [`{Any + Send + Sync}::downcast_ref`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref-2 [`{Any + Send + Sync}::is`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.is-2 +Version 1.27.2 (2018-07-20) +=========================== + +Compatibility Notes +------------------- + +- The borrow checker was fixed to avoid potential unsoundness when using + match ergonomics: [#52213][52213]. + +[52213]: https://github.com/rust-lang/rust/issues/52213 + Version 1.27.1 (2018-07-10) =========================== @@ -190,7 +201,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 +4806,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 be32872dad80a..b2e41589893cc 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2612,18 +2612,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/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/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/liballoc/vec.rs b/src/liballoc/vec.rs index 5efe1e23309a7..cc913dfbb4b01 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -690,14 +690,20 @@ impl Vec { /// [`drain`]: #method.drain #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { + let current_len = self.len; unsafe { + let mut ptr = self.as_mut_ptr().offset(self.len as isize); + // Set the final length at the end, keeping in mind that + // dropping an element might panic. Works around a missed + // optimization, as seen in the following issue: + // https://github.com/rust-lang/rust/issues/51802 + let mut local_len = SetLenOnDrop::new(&mut self.len); + // drop any extra elements - while len < self.len { - // decrement len before the drop_in_place(), so a panic on Drop - // doesn't re-drop the just-failed value. - self.len -= 1; - let len = self.len; - ptr::drop_in_place(self.get_unchecked_mut(len)); + for _ in len..current_len { + local_len.decrement_len(1); + ptr = ptr.offset(-1); + ptr::drop_in_place(ptr); } } } @@ -1512,6 +1518,11 @@ impl<'a> SetLenOnDrop<'a> { fn increment_len(&mut self, increment: usize) { self.local_len += increment; } + + #[inline] + fn decrement_len(&mut self, decrement: usize) { + self.local_len -= decrement; + } } impl<'a> Drop for SetLenOnDrop<'a> { diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 64348e05de7db..8e30b0d5d5a17 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -174,7 +174,10 @@ mod platform { } } - #[cfg(any(target_os = "android", target_os = "redox", target_os = "solaris"))] + #[cfg(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris"))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { // On android we currently target API level 9 which unfortunately @@ -197,7 +200,10 @@ mod platform { libc::memalign(layout.align(), layout.size()) as *mut u8 } - #[cfg(not(any(target_os = "android", target_os = "redox", target_os = "solaris")))] + #[cfg(not(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris")))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); 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/ops/unsize.rs b/src/libcore/ops/unsize.rs index cd896859b16bc..da72f3748425d 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -13,7 +13,7 @@ use marker::Unsize; /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. /// -/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] +/// See the [DST coercion RFC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] /// for more details. /// /// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize` 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/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/librustc/lint/context.rs b/src/librustc/lint/context.rs index 14cfaa8153377..15630157722fa 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -42,7 +42,7 @@ use util::nodemap::FxHashMap; use std::default::Default as StdDefault; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span}; +use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString}; use errors::DiagnosticBuilder; use hir; use hir::def_id::LOCAL_CRATE; @@ -133,6 +133,12 @@ pub enum CheckLintNameResult<'a> { /// The lint is either renamed or removed. This is the warning /// message, and an optional new name (`None` if removed). Warning(String, Option), + /// The lint is from a tool. If the Option is None, then either + /// the lint does not exist in the tool or the code was not + /// compiled with the tool and therefore the lint was never + /// added to the `LintStore`. Otherwise the `LintId` will be + /// returned as if it where a rustc lint. + Tool(Option<&'a [LintId]>), } impl LintStore { @@ -288,7 +294,7 @@ impl LintStore { sess: &Session, lint_name: &str, level: Level) { - let db = match self.check_lint_name(lint_name) { + let db = match self.check_lint_name(lint_name, None) { CheckLintNameResult::Ok(_) => None, CheckLintNameResult::Warning(ref msg, _) => { Some(sess.struct_warn(msg)) @@ -296,6 +302,7 @@ impl LintStore { CheckLintNameResult::NoLint => { Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) } + CheckLintNameResult::Tool(_) => unreachable!(), }; if let Some(mut db) = db { @@ -319,26 +326,41 @@ impl LintStore { /// it emits non-fatal warnings and there are *two* lint passes that /// inspect attributes, this is only run from the late pass to avoid /// printing duplicate warnings. - pub fn check_lint_name(&self, lint_name: &str) -> CheckLintNameResult { - match self.by_name.get(lint_name) { - Some(&Renamed(ref new_name, _)) => { - CheckLintNameResult::Warning( - format!("lint `{}` has been renamed to `{}`", lint_name, new_name), - Some(new_name.to_owned()) - ) - }, - Some(&Removed(ref reason)) => { - CheckLintNameResult::Warning( - format!("lint `{}` has been removed: `{}`", lint_name, reason), - None - ) - }, - None => { - match self.lint_groups.get(lint_name) { - None => CheckLintNameResult::NoLint, - Some(ids) => CheckLintNameResult::Ok(&ids.0), - } + pub fn check_lint_name( + &self, + lint_name: &str, + tool_name: Option, + ) -> CheckLintNameResult { + let complete_name = if let Some(tool_name) = tool_name { + format!("{}::{}", tool_name, lint_name) + } else { + lint_name.to_string() + }; + if let Some(_) = tool_name { + match self.by_name.get(&complete_name) { + None => match self.lint_groups.get(&*complete_name) { + None => return CheckLintNameResult::Tool(None), + Some(ids) => return CheckLintNameResult::Tool(Some(&ids.0)), + }, + Some(&Id(ref id)) => return CheckLintNameResult::Tool(Some(slice::from_ref(id))), + // If the lint was registered as removed or renamed by the lint tool, we don't need + // to treat tool_lints and rustc lints different and can use the code below. + _ => {} } + } + match self.by_name.get(&complete_name) { + Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning( + format!("lint `{}` has been renamed to `{}`", lint_name, new_name), + Some(new_name.to_owned()), + ), + Some(&Removed(ref reason)) => CheckLintNameResult::Warning( + format!("lint `{}` has been removed: `{}`", lint_name, reason), + None, + ), + None => match self.lint_groups.get(&*complete_name) { + None => CheckLintNameResult::NoLint, + Some(ids) => CheckLintNameResult::Ok(&ids.0), + }, Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)), } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index b7b6aba970bff..483e2ea8a96cd 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -227,8 +227,10 @@ impl<'a> LintLevelsBuilder<'a> { continue } }; - if let Some(lint_tool) = word.is_scoped() { - if !self.sess.features_untracked().tool_lints { + let tool_name = if let Some(lint_tool) = word.is_scoped() { + let gate_feature = !self.sess.features_untracked().tool_lints; + let known_tool = attr::is_known_lint_tool(lint_tool); + if gate_feature { feature_gate::emit_feature_err(&sess.parse_sess, "tool_lints", word.span, @@ -236,8 +238,7 @@ impl<'a> LintLevelsBuilder<'a> { &format!("scoped lint `{}` is experimental", word.ident)); } - - if !attr::is_known_lint_tool(lint_tool) { + if !known_tool { span_err!( sess, lint_tool.span, @@ -247,10 +248,16 @@ impl<'a> LintLevelsBuilder<'a> { ); } - continue - } + if gate_feature || !known_tool { + continue + } + + Some(lint_tool.as_str()) + } else { + None + }; let name = word.name(); - match store.check_lint_name(&name.as_str()) { + match store.check_lint_name(&name.as_str(), tool_name) { CheckLintNameResult::Ok(ids) => { let src = LintSource::Node(name, li.span); for id in ids { @@ -258,6 +265,20 @@ impl<'a> LintLevelsBuilder<'a> { } } + CheckLintNameResult::Tool(result) => { + if let Some(ids) = result { + let complete_name = &format!("{}::{}", tool_name.unwrap(), name); + let src = LintSource::Node(Symbol::intern(complete_name), li.span); + for id in ids { + specs.insert(*id, (level, src)); + } + } + // If Tool(None) is returned, then either the lint does not exist in the + // tool or the code was not compiled with the tool and therefore the lint + // was never added to the `LintStore`. To detect this is the responsibility + // of the lint tool. + } + _ if !self.warn_about_weird_lints => {} CheckLintNameResult::Warning(msg, renamed) => { @@ -298,7 +319,7 @@ impl<'a> LintLevelsBuilder<'a> { if name.as_str().chars().any(|c| c.is_uppercase()) { let name_lower = name.as_str().to_lowercase().to_string(); if let CheckLintNameResult::NoLint = - store.check_lint_name(&name_lower) { + store.check_lint_name(&name_lower, tool_name) { db.emit(); } else { db.span_suggestion_with_applicability( diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c1b205620892..d267c1812773b 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -139,6 +139,26 @@ macro_rules! declare_lint { ); } +#[macro_export] +macro_rules! declare_tool_lint { + ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => ( + declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false} + ); + ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, + report_in_external_macro: $rep: expr) => ( + declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep} + ); + ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => ( + $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint { + name: &concat!(stringify!($tool), "::", stringify!($NAME)), + default_level: $crate::lint::$Level, + desc: $desc, + edition_lint_opts: None, + report_in_external_macro: $external, + }; + ); +} + /// Declare a static `LintArray` and return it as an expression. #[macro_export] macro_rules! lint_array { @@ -575,7 +595,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 +614,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/middle/dead.rs b/src/librustc/middle/dead.rs index e4fc1b09fcebc..0f889549b58e3 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -554,12 +554,16 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { hir::ItemKind::Impl(..) => self.tcx.sess.codemap().def_span(item.span), _ => item.span, }; + let participle = match item.node { + hir::ItemKind::Struct(..) => "constructed", // Issue #52325 + _ => "used" + }; self.warn_dead_code( item.id, span, item.name, item.node.descriptive_variant(), - "used", + participle, ); } else { // Only continue if we didn't warn diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs index 4a72ab57fcc08..b5f52d54ae471 100644 --- a/src/librustc_data_structures/small_vec.rs +++ b/src/librustc_data_structures/small_vec.rs @@ -169,10 +169,18 @@ impl FromIterator for SmallVec { impl Extend for SmallVec { fn extend>(&mut self, iter: I) { - let iter = iter.into_iter(); - self.reserve(iter.size_hint().0); - for el in iter { - self.push(el); + if self.is_array() { + let iter = iter.into_iter(); + self.reserve(iter.size_hint().0); + + for el in iter { + self.push(el); + } + } else { + match self.0 { + AccumulateVec::Heap(ref mut vec) => vec.extend(iter), + _ => unreachable!() + } } } } @@ -213,3 +221,119 @@ impl Decodable for SmallVec }) } } + +#[cfg(test)] +mod tests { + extern crate test; + use self::test::Bencher; + + use super::*; + + #[bench] + fn fill_small_vec_1_10_with_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(10); + + sv.extend(0..10); + }) + } + + #[bench] + fn fill_small_vec_1_10_wo_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 1]> = SmallVec::new(); + + sv.extend(0..10); + }) + } + + #[bench] + fn fill_small_vec_8_10_with_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(10); + + sv.extend(0..10); + }) + } + + #[bench] + fn fill_small_vec_8_10_wo_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 8]> = SmallVec::new(); + + sv.extend(0..10); + }) + } + + #[bench] + fn fill_small_vec_32_10_with_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(10); + + sv.extend(0..10); + }) + } + + #[bench] + fn fill_small_vec_32_10_wo_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 32]> = SmallVec::new(); + + sv.extend(0..10); + }) + } + + #[bench] + fn fill_small_vec_1_50_with_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(50); + + sv.extend(0..50); + }) + } + + #[bench] + fn fill_small_vec_1_50_wo_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 1]> = SmallVec::new(); + + sv.extend(0..50); + }) + } + + #[bench] + fn fill_small_vec_8_50_with_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(50); + + sv.extend(0..50); + }) + } + + #[bench] + fn fill_small_vec_8_50_wo_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 8]> = SmallVec::new(); + + sv.extend(0..50); + }) + } + + #[bench] + fn fill_small_vec_32_50_with_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(50); + + sv.extend(0..50); + }) + } + + #[bench] + fn fill_small_vec_32_50_wo_cap(b: &mut Bencher) { + b.iter(|| { + let mut sv: SmallVec<[usize; 32]> = SmallVec::new(); + + sv.extend(0..50); + }) + } +} 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_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4ba96f643b0cc..27221296ff31f 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -331,6 +331,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } if mbcx.errors_buffer.len() > 0 { + mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span()); + if tcx.migrate_borrowck() { match tcx.borrowck(def_id).signalled_any_error { SignalledError::NoErrorsSeen => { diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 103f431d4bac9..4d988fef450b8 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -341,7 +341,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { // another match arm binds_to.sort(); binds_to.dedup(); - for local in binds_to { + let mut multipart_suggestion = Vec::with_capacity(binds_to.len()); + for (j, local) in binds_to.into_iter().enumerate() { let bind_to = &self.mir.local_decls[local]; let binding_span = bind_to.source_info.span; @@ -350,13 +351,15 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { Mutability::Not => "ref", Mutability::Mut => "ref mut", }; + if j == 0 { + err.span_label(binding_span, format!("data moved here")); + } else { + err.span_label(binding_span, format!("... and here")); + } match bind_to.name { Some(name) => { - err.span_suggestion( - binding_span, - "to prevent move, use ref or ref mut", - format!("{} {:?}", ref_kind, name), - ); + multipart_suggestion.push((binding_span, + format!("{} {}", ref_kind, name))); } None => { err.span_label( @@ -366,6 +369,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } } } + err.multipart_suggestion("to prevent move, use ref or ref mut", + multipart_suggestion); } // Nothing to suggest. GroupedMoveError::OtherIllegalMove { .. } => (), diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 9a84daf53dbd4..cd2de3247cfba 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { let local_decl = &self.mir.local_decls[*local]; let suggestion = match local_decl.is_user_variable.as_ref().unwrap() { ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => { - Some(suggest_ampmut_self(local_decl)) + Some(suggest_ampmut_self(self.tcx, local_decl)) } ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { @@ -418,8 +418,22 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } } -fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(local_decl: &mir::LocalDecl<'tcx>) -> (Span, String) { - (local_decl.source_info.span, "&mut self".to_string()) +fn suggest_ampmut_self<'cx, 'gcx, 'tcx>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + local_decl: &mir::LocalDecl<'tcx>, +) -> (Span, String) { + let sp = local_decl.source_info.span; + (sp, match tcx.sess.codemap().span_to_snippet(sp) { + Ok(snippet) => { + let lt_pos = snippet.find('\''); + if let Some(lt_pos) = lt_pos { + format!("&{}mut self", &snippet[lt_pos..snippet.len() - 4]) + } else { + "&mut self".to_string() + } + } + _ => "&mut self".to_string() + }) } // When we want to suggest a user change a local variable to be a `&mut`, there @@ -447,9 +461,15 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>( let locations = mir.find_assignments(local); if locations.len() > 0 { let assignment_rhs_span = mir.source_info(locations[0]).span; - let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span); - if let Ok(src) = snippet { - if src.starts_with('&') { + if let Ok(src) = tcx.sess.codemap().span_to_snippet(assignment_rhs_span) { + if let (true, Some(ws_pos)) = ( + src.starts_with("&'"), + src.find(|c: char| -> bool { c.is_whitespace() }), + ) { + let lt_name = &src[1..ws_pos]; + let ty = &src[ws_pos..]; + return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty)); + } else if src.starts_with('&') { let borrowed_expr = src[1..].to_string(); return (assignment_rhs_span, format!("&mut {}", borrowed_expr)); } @@ -466,13 +486,25 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>( None => local_decl.source_info.span, }; + if let Ok(src) = tcx.sess.codemap().span_to_snippet(highlight_span) { + if let (true, Some(ws_pos)) = ( + src.starts_with("&'"), + src.find(|c: char| -> bool { c.is_whitespace() }), + ) { + let lt_name = &src[1..ws_pos]; + let ty = &src[ws_pos..]; + return (highlight_span, format!("&{} mut{}", lt_name, ty)); + } + } + let ty_mut = local_decl.ty.builtin_deref(true).unwrap(); assert_eq!(ty_mut.mutbl, hir::MutImmutable); - if local_decl.ty.is_region_ptr() { - (highlight_span, format!("&mut {}", ty_mut.ty)) - } else { - (highlight_span, format!("*mut {}", ty_mut.ty)) - } + (highlight_span, + if local_decl.ty.is_region_ptr() { + format!("&mut {}", ty_mut.ty) + } else { + format!("*mut {}", ty_mut.ty) + }) } fn is_closure_or_generator(ty: ty::Ty) -> bool { diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index a509ec08a142e..6a447d81dc3cb 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -1213,11 +1213,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() { let mut vals_for_guard = Vec::with_capacity(num_patterns); for _ in 0..num_patterns { - let val_for_guard_idx = self.local_decls.push(local.clone()); + let val_for_guard_idx = self.local_decls.push(LocalDecl { + // This variable isn't mutated but has a name, so has to be + // immutable to avoid the unused mut lint. + mutability: Mutability::Not, + ..local.clone() + }); vals_for_guard.push(val_for_guard_idx); } let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> { - mutability, + // See previous comment. + mutability: Mutability::Not, ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty), name: Some(name), source_info, diff --git a/src/librustc_target/spec/aarch64_unknown_hermit.rs b/src/librustc_target/spec/aarch64_unknown_hermit.rs new file mode 100644 index 0000000000000..6b81c62e48b87 --- /dev/null +++ b/src/librustc_target/spec/aarch64_unknown_hermit.rs @@ -0,0 +1,32 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::hermit_base::opts(); + base.max_atomic_width = Some(128); + base.abi_blacklist = super::arm_base::abi_blacklist(); + base.linker = Some("aarch64-hermit-gcc".to_string()); + + Ok(Target { + llvm_target: "aarch64-unknown-hermit".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "hermit".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_target/spec/hermit_base.rs b/src/librustc_target/spec/hermit_base.rs new file mode 100644 index 0000000000000..2a24f771e9289 --- /dev/null +++ b/src/librustc_target/spec/hermit_base.rs @@ -0,0 +1,37 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions}; +use std::default::Default; + +pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + "-Wl,-Bstatic".to_string(), + "-Wl,--no-dynamic-linker".to_string(), + "-Wl,--gc-sections".to_string(), + "-Wl,--as-needed".to_string(), + ]); + + TargetOptions { + exe_allocation_crate: None, + executables: true, + has_elf_tls: true, + linker_is_gnu: true, + no_default_libraries: false, + panic_strategy: PanicStrategy::Abort, + position_independent_executables: false, + pre_link_args: args, + relocation_model: "static".to_string(), + target_family: Some("unix".to_string()), + tls_model: "local-exec".to_string(), + .. Default::default() + } +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index c5d21cdc46adb..6c2d16d6a17eb 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -62,6 +62,7 @@ mod cloudabi_base; mod dragonfly_base; mod freebsd_base; mod haiku_base; +mod hermit_base; mod linux_base; mod linux_musl_base; mod openbsd_base; @@ -373,6 +374,9 @@ supported_targets! { ("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf), ("i686-unknown-cloudabi", i686_unknown_cloudabi), ("x86_64-unknown-cloudabi", x86_64_unknown_cloudabi), + + ("aarch64-unknown-hermit", aarch64_unknown_hermit), + ("x86_64-unknown-hermit", x86_64_unknown_hermit), } /// Everything `rustc` knows about how to compile for a specific target. diff --git a/src/librustc_target/spec/x86_64_unknown_hermit.rs b/src/librustc_target/spec/x86_64_unknown_hermit.rs new file mode 100644 index 0000000000000..9f9f2e6ec43e9 --- /dev/null +++ b/src/librustc_target/spec/x86_64_unknown_hermit.rs @@ -0,0 +1,33 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::hermit_base::opts(); + base.cpu = "x86-64".to_string(); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.linker = Some("x86_64-hermit-gcc".to_string()); + base.max_atomic_width = Some(64); + + Ok(Target { + llvm_target: "x86_64-unknown-hermit".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "hermit".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7454f79ed6bbb..45566230fdaae 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1194,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 { @@ -1205,26 +1206,29 @@ 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) = if def.is_enum() { + def.all_fields().find(|item| item.ident.name == item_name) + } else { + def.non_enum_variant() + .fields + .iter() + .find(|item| item.ident.name == item_name) + } { + Ok((ty.def, + Some(format!("{}.{}", + if def.is_enum() { + "variant" + } else { + "structfield" + }, + item.ident)))) + } else { + Err(()) + } + } + _ => Err(()), } } } diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 10b6c9850ae77..9631ea059cc43 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -12,7 +12,9 @@ use std::fs; use std::path::Path; use std::str; use errors; -use html::markdown::Markdown; +use syntax::feature_gate::UnstableFeatures; +use html::markdown::{IdMap, ErrorCodes, Markdown}; +use std::cell::RefCell; #[derive(Clone)] pub struct ExternalHtml { @@ -29,8 +31,10 @@ pub struct ExternalHtml { impl ExternalHtml { pub fn load(in_header: &[String], before_content: &[String], after_content: &[String], - md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler) + md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler, + id_map: &mut IdMap) -> Option { + let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); load_external_files(in_header, diag) .and_then(|ih| load_external_files(before_content, diag) @@ -38,7 +42,8 @@ impl ExternalHtml { ) .and_then(|(ih, bc)| load_external_files(md_before_content, diag) - .map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[])))) + .map(|m_bc| (ih, + format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), codes)))) ) .and_then(|(ih, bc)| load_external_files(after_content, diag) @@ -46,7 +51,8 @@ impl ExternalHtml { ) .and_then(|(ih, bc, ac)| load_external_files(md_after_content, diag) - .map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[])))) + .map(|m_ac| (ih, bc, + format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map), codes)))) ) .map(|(ih, bc, ac)| ExternalHtml { diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 065778d8d0725..73d7a9ab8599d 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -13,12 +13,7 @@ //! This module uses libsyntax's lexer to provide token-based highlighting for //! the HTML documentation generated by rustdoc. //! -//! If you just want to syntax highlighting for a Rust program, then you can use -//! the `render_inner_with_highlighting` or `render_with_highlighting` -//! functions. For more advanced use cases (if you want to supply your own css -//! classes or control how the HTML is generated, or even generate something -//! other then HTML), then you should implement the `Writer` trait and use a -//! `Classifier`. +//! Use the `render_with_highlighting` to highlight some rust code. use html::escape::Escape; @@ -33,7 +28,7 @@ use syntax::parse; use syntax_pos::{Span, FileName}; /// Highlights `src`, returning the HTML output. -pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>, +pub fn render_with_highlighting(src: &str, class: Option<&str>, extension: Option<&str>, tooltip: Option<(&str, &str)>) -> String { debug!("highlighting: ================\n{}\n==============", src); @@ -46,7 +41,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str> class='tooltiptext'>{}", class, tooltip).unwrap(); } - write_header(class, id, &mut out).unwrap(); + write_header(class, &mut out).unwrap(); let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None), sess.codemap()); if let Err(_) = classifier.write_source(&mut out) { @@ -63,7 +58,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str> /// 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. -pub struct Classifier<'a> { +struct Classifier<'a> { lexer: lexer::StringReader<'a>, codemap: &'a CodeMap, @@ -75,7 +70,7 @@ pub struct Classifier<'a> { /// How a span of text is classified. Mostly corresponds to token kinds. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Class { +enum Class { None, Comment, DocComment, @@ -103,7 +98,7 @@ pub enum Class { /// The classifier will call into the `Writer` implementation as it finds spans /// of text to highlight. Exactly how that text should be highlighted is up to /// the implementation. -pub trait Writer { +trait Writer { /// Called when we start processing a span of text that should be highlighted. /// The `Class` argument specifies how it should be highlighted. fn enter_span(&mut self, _: Class) -> io::Result<()>; @@ -111,11 +106,9 @@ pub trait Writer { /// Called at the end of a span of highlighted text. fn exit_span(&mut self) -> io::Result<()>; - /// Called for a span of text, usually, but not always, a single token. If - /// the string of text (`T`) does correspond to a token, then the token will - /// also be passed. If the text should be highlighted differently from the - /// surrounding text, then the `Class` argument will be a value other than - /// `None`. + /// Called for a span of text. If the text should be highlighted differently from the + /// surrounding text, then the `Class` argument will be a value other than `None`. + /// /// The following sequences of callbacks are equivalent: /// ```plain /// enter_span(Foo), string("text", None), exit_span() @@ -125,8 +118,7 @@ pub trait Writer { /// more flexible. fn string(&mut self, text: T, - klass: Class, - tok: Option<&TokenAndSpan>) + klass: Class) -> io::Result<()>; } @@ -135,8 +127,7 @@ pub trait Writer { impl Writer for U { fn string(&mut self, text: T, - klass: Class, - _tas: Option<&TokenAndSpan>) + klass: Class) -> io::Result<()> { match klass { Class::None => write!(self, "{}", text), @@ -154,7 +145,7 @@ impl Writer for U { } impl<'a> Classifier<'a> { - pub fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> { + fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> { Classifier { lexer, codemap, @@ -186,7 +177,7 @@ impl<'a> Classifier<'a> { /// is used. All source code emission is done as slices from the source map, /// not from the tokens themselves, in order to stay true to the original /// source. - pub fn write_source(&mut self, + fn write_source(&mut self, out: &mut W) -> io::Result<()> { loop { @@ -208,7 +199,7 @@ impl<'a> Classifier<'a> { -> io::Result<()> { let klass = match tas.tok { token::Shebang(s) => { - out.string(Escape(&s.as_str()), Class::None, Some(&tas))?; + out.string(Escape(&s.as_str()), Class::None)?; return Ok(()); }, @@ -272,8 +263,8 @@ impl<'a> Classifier<'a> { self.in_attribute = true; out.enter_span(Class::Attribute)?; } - out.string("#", Class::None, None)?; - out.string("!", Class::None, None)?; + out.string("#", Class::None)?; + out.string("!", Class::None)?; return Ok(()); } @@ -282,13 +273,13 @@ impl<'a> Classifier<'a> { self.in_attribute = true; out.enter_span(Class::Attribute)?; } - out.string("#", Class::None, None)?; + out.string("#", Class::None)?; return Ok(()); } token::CloseDelim(token::Bracket) => { if self.in_attribute { self.in_attribute = false; - out.string("]", Class::None, None)?; + out.string("]", Class::None)?; out.exit_span()?; return Ok(()); } else { @@ -344,7 +335,7 @@ impl<'a> Classifier<'a> { // Anything that didn't return above is the simple case where we the // class just spans a single token, so we can use the `string` method. - out.string(Escape(&self.snip(tas.sp)), klass, Some(&tas)) + out.string(Escape(&self.snip(tas.sp)), klass) } // Helper function to get a snippet from the codemap. @@ -355,7 +346,7 @@ impl<'a> Classifier<'a> { impl Class { /// Returns the css class expected by rustdoc for each `Class`. - pub fn rustdoc_class(self) -> &'static str { + fn rustdoc_class(self) -> &'static str { match self { Class::None => "", Class::Comment => "comment", @@ -379,15 +370,8 @@ impl Class { } } -fn write_header(class: Option<&str>, - id: Option<&str>, - out: &mut dyn Write) - -> io::Result<()> { - write!(out, "
\n", class.unwrap_or(""))
+fn write_header(class: Option<&str>, out: &mut dyn Write) -> io::Result<()> {
+    write!(out, "
\n", class.unwrap_or(""))
 }
 
 fn write_footer(out: &mut dyn Write) -> io::Result<()> {
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 8d85adfb3d0ff..b22e239e20a0e 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -18,16 +18,17 @@
 //! ```
 //! #![feature(rustc_private)]
 //!
-//! use rustdoc::html::markdown::Markdown;
+//! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes};
+//! use std::cell::RefCell;
 //!
 //! let s = "My *markdown* _text_";
-//! let html = format!("{}", Markdown(s, &[]));
+//! let mut id_map = IdMap::new();
+//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map), ErrorCodes::Yes));
 //! // ... something using html
 //! ```
 
 #![allow(non_camel_case_types)]
 
-use rustc::session;
 use std::cell::RefCell;
 use std::collections::{HashMap, VecDeque};
 use std::default::Default;
@@ -35,10 +36,7 @@ use std::fmt::{self, Write};
 use std::borrow::Cow;
 use std::ops::Range;
 use std::str;
-use syntax::feature_gate::UnstableFeatures;
-use syntax::codemap::Span;
 
-use html::render::derive_id;
 use html::toc::TocBuilder;
 use html::highlight;
 use test;
@@ -50,15 +48,38 @@ use pulldown_cmark::{Options, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES};
 /// formatted, this struct will emit the HTML corresponding to the rendered
 /// version of the contained markdown string.
 /// The second parameter is a list of link replacements
-pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)]);
+pub struct Markdown<'a>(
+    pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders the markdown with a
 /// table of contents.
-pub struct MarkdownWithToc<'a>(pub &'a str);
+pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
-pub struct MarkdownHtml<'a>(pub &'a str);
+pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
 /// A unit struct like `Markdown`, that renders only the first paragraph.
 pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
 
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum ErrorCodes {
+    Yes,
+    No,
+}
+
+impl ErrorCodes {
+    pub fn from(b: bool) -> Self {
+        match b {
+            true => ErrorCodes::Yes,
+            false => ErrorCodes::No,
+        }
+    }
+
+    pub fn as_bool(self) -> bool {
+        match self {
+            ErrorCodes::Yes => true,
+            ErrorCodes::No => false,
+        }
+    }
+}
+
 /// Controls whether a line will be hidden or shown in HTML output.
 ///
 /// All lines are used in documentation tests.
@@ -129,12 +150,14 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> =
 /// Adds syntax highlighting and playground Run buttons to rust code blocks.
 struct CodeBlocks<'a, I: Iterator>> {
     inner: I,
+    check_error_codes: ErrorCodes,
 }
 
 impl<'a, I: Iterator>> CodeBlocks<'a, I> {
-    fn new(iter: I) -> Self {
+    fn new(iter: I, error_codes: ErrorCodes) -> Self {
         CodeBlocks {
             inner: iter,
+            check_error_codes: error_codes,
         }
     }
 }
@@ -147,7 +170,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> {
         let compile_fail;
         let ignore;
         if let Some(Event::Start(Tag::CodeBlock(lang))) = event {
-            let parse_result = LangString::parse(&lang);
+            let parse_result = LangString::parse(&lang, self.check_error_codes);
             if !parse_result.rust {
                 return Some(Event::Start(Tag::CodeBlock(lang)));
             }
@@ -224,7 +247,6 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> {
                                       if ignore { " ignore" }
                                       else if compile_fail { " compile_fail" }
                                       else { "" })),
-                        None,
                         playground_button.as_ref().map(String::as_str),
                         tooltip));
             Some(Event::Html(s.into()))
@@ -266,23 +288,25 @@ impl<'a, 'b, I: Iterator>> Iterator for LinkReplacer<'a, 'b, I>
 }
 
 /// Make headings links with anchor ids and build up TOC.
-struct HeadingLinks<'a, 'b, I: Iterator>> {
+struct HeadingLinks<'a, 'b, 'ids, I: Iterator>> {
     inner: I,
     toc: Option<&'b mut TocBuilder>,
     buf: VecDeque>,
+    id_map: &'ids mut IdMap,
 }
 
-impl<'a, 'b, I: Iterator>> HeadingLinks<'a, 'b, I> {
-    fn new(iter: I, toc: Option<&'b mut TocBuilder>) -> Self {
+impl<'a, 'b, 'ids, I: Iterator>> HeadingLinks<'a, 'b, 'ids, I> {
+    fn new(iter: I, toc: Option<&'b mut TocBuilder>, ids: &'ids mut IdMap) -> Self {
         HeadingLinks {
             inner: iter,
             toc,
             buf: VecDeque::new(),
+            id_map: ids,
         }
     }
 }
 
-impl<'a, 'b, I: Iterator>> Iterator for HeadingLinks<'a, 'b, I> {
+impl<'a, 'b, 'ids, I: Iterator>> Iterator for HeadingLinks<'a, 'b, 'ids, I> {
     type Item = Event<'a>;
 
     fn next(&mut self) -> Option {
@@ -301,7 +325,7 @@ impl<'a, 'b, I: Iterator>> Iterator for HeadingLinks<'a, 'b, I>
                 }
                 self.buf.push_back(event);
             }
-            let id = derive_id(id);
+            let id = self.id_map.derive(id);
 
             if let Some(ref mut builder) = self.toc {
                 let mut html_header = String::new();
@@ -467,10 +491,17 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> {
     }
 }
 
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span,
-                          sess: Option<&session::Session>) {
-    tests.set_position(position);
+pub struct TestableCodeError(());
 
+impl fmt::Display for TestableCodeError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "invalid start of a new code block")
+    }
+}
+
+pub fn find_testable_code(
+    doc: &str, tests: &mut test::Collector, error_codes: ErrorCodes,
+) -> Result<(), TestableCodeError> {
     let mut parser = Parser::new(doc);
     let mut prev_offset = 0;
     let mut nb_lines = 0;
@@ -481,7 +512,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                 let block_info = if s.is_empty() {
                     LangString::all_false()
                 } else {
-                    LangString::parse(&*s)
+                    LangString::parse(&*s, error_codes)
                 };
                 if !block_info.rust {
                     continue
@@ -510,18 +541,10 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                     let text = lines.collect::>>().join("\n");
                     nb_lines += doc[prev_offset..offset].lines().count();
                     let line = tests.get_line() + (nb_lines - 1);
-                    let filename = tests.get_filename();
-                    tests.add_test(text.to_owned(),
-                                   block_info.should_panic, block_info.no_run,
-                                   block_info.ignore, block_info.test_harness,
-                                   block_info.compile_fail, block_info.error_codes,
-                                   line, filename, block_info.allow_fail);
+                    tests.add_test(text, block_info, line);
                     prev_offset = offset;
                 } else {
-                    if let Some(ref sess) = sess {
-                        sess.span_warn(position, "invalid start of a new code block");
-                    }
-                    break;
+                    return Err(TestableCodeError(()));
                 }
             }
             Event::Start(Tag::Header(level)) => {
@@ -539,19 +562,20 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
             _ => {}
         }
     }
+    Ok(())
 }
 
 #[derive(Eq, PartialEq, Clone, Debug)]
-struct LangString {
+pub struct LangString {
     original: String,
-    should_panic: bool,
-    no_run: bool,
-    ignore: bool,
-    rust: bool,
-    test_harness: bool,
-    compile_fail: bool,
-    error_codes: Vec,
-    allow_fail: bool,
+    pub should_panic: bool,
+    pub no_run: bool,
+    pub ignore: bool,
+    pub rust: bool,
+    pub test_harness: bool,
+    pub compile_fail: bool,
+    pub error_codes: Vec,
+    pub allow_fail: bool,
 }
 
 impl LangString {
@@ -569,14 +593,11 @@ impl LangString {
         }
     }
 
-    fn parse(string: &str) -> LangString {
+    fn parse(string: &str, allow_error_code_check: ErrorCodes) -> LangString {
+        let allow_error_code_check = allow_error_code_check.as_bool();
         let mut seen_rust_tags = false;
         let mut seen_other_tags = false;
         let mut data = LangString::all_false();
-        let mut allow_error_code_check = false;
-        if UnstableFeatures::from_environment().is_nightly_build() {
-            allow_error_code_check = true;
-        }
 
         data.original = string.to_owned();
         let tokens = string.split(|c: char|
@@ -623,7 +644,8 @@ impl LangString {
 
 impl<'a> fmt::Display for Markdown<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let Markdown(md, links) = *self;
+        let Markdown(md, links, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
@@ -643,12 +665,11 @@ impl<'a> fmt::Display for Markdown<'a> {
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
-        html::push_html(&mut s,
-                        Footnotes::new(
-                            CodeBlocks::new(
-                                LinkReplacer::new(
-                                    HeadingLinks::new(p, None),
-                                    links))));
+        let p = HeadingLinks::new(p, None, &mut ids);
+        let p = LinkReplacer::new(p, links);
+        let p = CodeBlocks::new(p, codes);
+        let p = Footnotes::new(p);
+        html::push_html(&mut s, p);
 
         fmt.write_str(&s)
     }
@@ -656,7 +677,8 @@ impl<'a> fmt::Display for Markdown<'a> {
 
 impl<'a> fmt::Display for MarkdownWithToc<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let MarkdownWithToc(md) = *self;
+        let MarkdownWithToc(md, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         let mut opts = Options::empty();
         opts.insert(OPTION_ENABLE_TABLES);
@@ -668,8 +690,12 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> {
 
         let mut toc = TocBuilder::new();
 
-        html::push_html(&mut s,
-                        Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, Some(&mut toc)))));
+        {
+            let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
+            let p = CodeBlocks::new(p, codes);
+            let p = Footnotes::new(p);
+            html::push_html(&mut s, p);
+        }
 
         write!(fmt, "", toc.into_toc())?;
 
@@ -679,7 +705,8 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> {
 
 impl<'a> fmt::Display for MarkdownHtml<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let MarkdownHtml(md) = *self;
+        let MarkdownHtml(md, ref ids, codes) = *self;
+        let mut ids = ids.borrow_mut();
 
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
@@ -697,8 +724,10 @@ impl<'a> fmt::Display for MarkdownHtml<'a> {
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
-        html::push_html(&mut s,
-                        Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, None))));
+        let p = HeadingLinks::new(p, None, &mut ids);
+        let p = CodeBlocks::new(p, codes);
+        let p = Footnotes::new(p);
+        html::push_html(&mut s, p);
 
         fmt.write_str(&s)
     }
@@ -812,7 +841,10 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option>)> {
         let p = Parser::new_with_broken_link_callback(md, opts,
             Some(&push));
 
-        let iter = Footnotes::new(HeadingLinks::new(p, None));
+        // There's no need to thread an IdMap through to here because
+        // the IDs generated aren't going to be emitted anywhere.
+        let mut ids = IdMap::new();
+        let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
 
         for ev in iter {
             if let Event::Start(Tag::Link(dest, _)) = ev {
@@ -831,18 +863,74 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option>)> {
     links
 }
 
+#[derive(Default)]
+pub struct IdMap {
+    map: HashMap,
+}
+
+impl IdMap {
+    pub fn new() -> Self {
+        IdMap::default()
+    }
+
+    pub fn populate>(&mut self, ids: I) {
+        for id in ids {
+            let _ = self.derive(id);
+        }
+    }
+
+    pub fn reset(&mut self) {
+        self.map = HashMap::new();
+    }
+
+    pub fn derive(&mut self, candidate: String) -> String {
+        let id = match self.map.get_mut(&candidate) {
+            None => candidate,
+            Some(a) => {
+                let id = format!("{}-{}", candidate, *a);
+                *a += 1;
+                id
+            }
+        };
+
+        self.map.insert(id.clone(), 1);
+        id
+    }
+}
+
+#[cfg(test)]
+#[test]
+fn test_unique_id() {
+    let input = ["foo", "examples", "examples", "method.into_iter","examples",
+                 "method.into_iter", "foo", "main", "search", "methods",
+                 "examples", "method.into_iter", "assoc_type.Item", "assoc_type.Item"];
+    let expected = ["foo", "examples", "examples-1", "method.into_iter", "examples-2",
+                    "method.into_iter-1", "foo-1", "main", "search", "methods",
+                    "examples-3", "method.into_iter-2", "assoc_type.Item", "assoc_type.Item-1"];
+
+    let map = RefCell::new(IdMap::new());
+    let test = || {
+        let mut map = map.borrow_mut();
+        let actual: Vec = input.iter().map(|s| map.derive(s.to_string())).collect();
+        assert_eq!(&actual[..], expected);
+    };
+    test();
+    map.borrow_mut().reset();
+    test();
+}
+
 #[cfg(test)]
 mod tests {
-    use super::{LangString, Markdown, MarkdownHtml};
+    use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap};
     use super::plain_summary_line;
-    use html::render::reset_ids;
+    use std::cell::RefCell;
 
     #[test]
     fn test_lang_string_parse() {
         fn t(s: &str,
             should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
             compile_fail: bool, allow_fail: bool, error_codes: Vec) {
-            assert_eq!(LangString::parse(s), LangString {
+            assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString {
                 should_panic,
                 no_run,
                 ignore,
@@ -878,19 +966,12 @@ mod tests {
         t("text,no_run",           false,        true,   false,  false, false, false, false, v());
     }
 
-    #[test]
-    fn issue_17736() {
-        let markdown = "# title";
-        Markdown(markdown, &[]).to_string();
-        reset_ids(true);
-    }
-
     #[test]
     fn test_header() {
         fn t(input: &str, expect: &str) {
-            let output = Markdown(input, &[]).to_string();
+            let mut map = IdMap::new();
+            let output = Markdown(input, &[], RefCell::new(&mut map), ErrorCodes::Yes).to_string();
             assert_eq!(output, expect, "original: {}", input);
-            reset_ids(true);
         }
 
         t("# Foo bar", "

\ @@ -909,28 +990,24 @@ mod tests { #[test] fn test_header_ids_multiple_blocks() { - fn t(input: &str, expect: &str) { - let output = Markdown(input, &[]).to_string(); + let mut map = IdMap::new(); + fn t(map: &mut IdMap, input: &str, expect: &str) { + let output = Markdown(input, &[], RefCell::new(map), ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); } - let test = || { - t("# Example", "

\ - Example

"); - t("# Panics", "

\ - Panics

"); - t("# Example", "

\ - Example

"); - t("# Main", "

\ - Main

"); - t("# Example", "

\ - Example

"); - t("# Panics", "

\ - Panics

"); - }; - test(); - reset_ids(true); - test(); + t(&mut map, "# Example", "

\ + Example

"); + t(&mut map, "# Panics", "

\ + Panics

"); + t(&mut map, "# Example", "

\ + Example

"); + t(&mut map, "# Main", "

\ + Main

"); + t(&mut map, "# Example", "

\ + Example

"); + t(&mut map, "# Panics", "

\ + Panics

"); } #[test] @@ -951,7 +1028,8 @@ mod tests { #[test] fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { - let output = MarkdownHtml(input).to_string(); + let mut idmap = IdMap::new(); + let output = MarkdownHtml(input, RefCell::new(&mut idmap), ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 24a9bf416e444..c2978a62489a0 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -50,12 +50,14 @@ use std::mem; use std::path::{PathBuf, Path, Component}; use std::str; use std::sync::Arc; +use std::rc::Rc; use externalfiles::ExternalHtml; use serialize::json::{ToJson, Json, as_json}; use syntax::ast; use syntax::codemap::FileName; +use syntax::feature_gate::UnstableFeatures; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; @@ -72,7 +74,7 @@ use html::format::{GenericBounds, WhereClause, href, AbiSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; use html::item_type::ItemType; -use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine}; +use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap}; use html::{highlight, layout}; use minifier; @@ -88,7 +90,7 @@ pub type NameDoc = (String, Option); /// easily cloned because it is cloned per work-job (about once per item in the /// rustdoc tree). #[derive(Clone)] -pub struct Context { +struct Context { /// Current hierarchy of components leading down to what's currently being /// rendered pub current: Vec, @@ -99,10 +101,13 @@ pub struct Context { /// real location of an item. This is used to allow external links to /// publicly reused items to redirect to the right location. pub render_redirect_pages: bool, + pub codes: ErrorCodes, + /// The map used to ensure all generated 'id=' attributes are unique. + id_map: Rc>, pub shared: Arc, } -pub struct SharedContext { +struct SharedContext { /// The path to the crate root source minus the file name. /// Used for simplifying paths to the highlighted source code files. pub src_root: PathBuf, @@ -450,9 +455,8 @@ impl ToJson for IndexItemFunctionType { thread_local!(static CACHE_KEY: RefCell> = Default::default()); thread_local!(pub static CURRENT_LOCATION_KEY: RefCell> = RefCell::new(Vec::new())); -thread_local!(pub static USED_ID_MAP: RefCell> = RefCell::new(init_ids())); -fn init_ids() -> FxHashMap { +pub fn initial_ids() -> Vec { [ "main", "search", @@ -470,36 +474,7 @@ fn init_ids() -> FxHashMap { "methods", "deref-methods", "implementations", - ].into_iter().map(|id| (String::from(*id), 1)).collect() -} - -/// This method resets the local table of used ID attributes. This is typically -/// used at the beginning of rendering an entire HTML page to reset from the -/// previous state (if any). -pub fn reset_ids(embedded: bool) { - USED_ID_MAP.with(|s| { - *s.borrow_mut() = if embedded { - init_ids() - } else { - FxHashMap() - }; - }); -} - -pub fn derive_id(candidate: String) -> String { - USED_ID_MAP.with(|map| { - let id = match map.borrow_mut().get_mut(&candidate) { - None => candidate, - Some(a) => { - let id = format!("{}-{}", candidate, *a); - *a += 1; - id - } - }; - - map.borrow_mut().insert(id.clone(), 1); - id - }) + ].into_iter().map(|id| (String::from(*id))).collect() } /// Generates the documentation for `crate` into the directory `dst` @@ -513,7 +488,8 @@ pub fn run(mut krate: clean::Crate, renderinfo: RenderInfo, sort_modules_alphabetically: bool, themes: Vec, - enable_minification: bool) -> Result<(), Error> { + enable_minification: bool, + id_map: IdMap) -> Result<(), Error> { let src_root = match krate.src { FileName::Real(ref p) => match p.parent() { Some(p) => p.to_path_buf(), @@ -581,6 +557,8 @@ pub fn run(mut krate: clean::Crate, current: Vec::new(), dst, render_redirect_pages: false, + codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), + id_map: Rc::new(RefCell::new(id_map)), shared: Arc::new(scx), }; @@ -1708,6 +1686,11 @@ impl<'a> fmt::Display for Settings<'a> { } impl Context { + fn derive_id(&self, id: String) -> String { + let mut map = self.id_map.borrow_mut(); + map.derive(id) + } + /// String representation of how to get back to the root path of the 'doc/' /// folder in terms of a relative URL. fn root_path(&self) -> String { @@ -1862,7 +1845,10 @@ impl Context { resource_suffix: &self.shared.resource_suffix, }; - reset_ids(true); + { + self.id_map.borrow_mut().reset(); + self.id_map.borrow_mut().populate(initial_ids()); + } if !self.render_redirect_pages { layout::render(writer, &self.shared.layout, &page, @@ -2219,14 +2205,17 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re /// Render md_text as markdown. fn render_markdown(w: &mut fmt::Formatter, + cx: &Context, md_text: &str, links: Vec<(String, String)>, - prefix: &str,) + prefix: &str) -> fmt::Result { - write!(w, "
{}{}
", prefix, Markdown(md_text, &links)) + let mut ids = cx.id_map.borrow_mut(); + write!(w, "
{}{}
", + prefix, Markdown(md_text, &links, RefCell::new(&mut ids), cx.codes)) } -fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink, +fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink, prefix: &str) -> fmt::Result { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { @@ -2235,7 +2224,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin } else { plain_summary_line(Some(s)).to_string() }; - render_markdown(w, &markdown, item.links(), prefix)?; + render_markdown(w, cx, &markdown, item.links(), prefix)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2250,7 +2239,6 @@ fn render_assoc_const_value(item: &clean::Item) -> String { None, None, None, - None, ) } _ => String::new(), @@ -2261,7 +2249,7 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item, cx: &Context, prefix: &str) -> fmt::Result { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); - render_markdown(w, &*s, item.links(), prefix)?; + render_markdown(w, cx, &*s, item.links(), prefix)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2427,7 +2415,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, let (short, name) = item_ty_to_strs(&myty.unwrap()); write!(w, "

\ {name}

\n", - id = derive_id(short.to_owned()), name = name)?; + id = cx.derive_id(short.to_owned()), name = name)?; } match myitem.inner { @@ -2508,6 +2496,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec { let mut stability = vec![]; + let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); if let Some(stab) = item.stability.as_ref() { let deprecated_reason = if show_reason && !stab.deprecated_reason.is_empty() { @@ -2521,14 +2510,12 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) }; @@ -2555,11 +2542,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec", unstable_extra)); } else { + let mut ids = cx.id_map.borrow_mut(); let text = format!("🔬 \ This is a nightly-only experimental API. {}\ {}", unstable_extra, - MarkdownHtml(&stab.unstable_reason)); + MarkdownHtml( + &stab.unstable_reason, + RefCell::new(&mut ids), + error_codes)); stability.push(format!("
{}
", text)); } @@ -2579,14 +2570,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) } @@ -2827,8 +2819,8 @@ fn item_trait( -> fmt::Result { let name = m.name.as_ref().unwrap(); let item_type = m.type_(); - let id = derive_id(format!("{}.{}", item_type, name)); - let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); + let id = cx.derive_id(format!("{}.{}", item_type, name)); + let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "{extra}

\

")?; if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { + let mut ids = cx.id_map.borrow_mut(); write!(w, "
{}
", - Markdown(&*dox, &i.impl_item.links()))?; + Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), cx.codes))?; } } @@ -3832,8 +3825,8 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi clean::TyMethodItem(clean::TyMethod{ ref decl, .. }) => { // Only render when the method is not static or we allow static methods if render_method_item { - let id = derive_id(format!("{}.{}", item_type, name)); - let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); + let id = cx.derive_id(format!("{}.{}", item_type, name)); + let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type)?; write!(w, "{}", spotlight_decl(decl)?)?; write!(w, "

")?; write!(fmt, "{}", - highlight::render_with_highlighting(s, None, None, None, None))?; + highlight::render_with_highlighting(s, None, None, None))?; Ok(()) } } @@ -4568,7 +4561,6 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, w.write_str(&highlight::render_with_highlighting(&t.source, Some("macro"), None, - None, None)) })?; document(w, cx, it) @@ -4715,25 +4707,6 @@ pub fn cache() -> Arc { CACHE_KEY.with(|c| c.borrow().clone()) } -#[cfg(test)] -#[test] -fn test_unique_id() { - let input = ["foo", "examples", "examples", "method.into_iter","examples", - "method.into_iter", "foo", "main", "search", "methods", - "examples", "method.into_iter", "assoc_type.Item", "assoc_type.Item"]; - let expected = ["foo", "examples", "examples-1", "method.into_iter", "examples-2", - "method.into_iter-1", "foo-1", "main-1", "search-1", "methods-1", - "examples-3", "method.into_iter-2", "assoc_type.Item", "assoc_type.Item-1"]; - - let test = || { - let actual: Vec = input.iter().map(|s| derive_id(s.to_string())).collect(); - assert_eq!(&actual[..], expected); - }; - test(); - reset_ids(true); - test(); -} - #[cfg(test)] #[test] fn test_name_key() { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 041a233617083..0a4955f4fbd10 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -500,12 +500,14 @@ fn main_args(args: &[String]) -> isize { } } + let mut id_map = html::markdown::IdMap::new(); + id_map.populate(html::render::initial_ids()); let external_html = match ExternalHtml::load( &matches.opt_strs("html-in-header"), &matches.opt_strs("html-before-content"), &matches.opt_strs("html-after-content"), &matches.opt_strs("markdown-before-content"), - &matches.opt_strs("markdown-after-content"), &diag) { + &matches.opt_strs("markdown-after-content"), &diag, &mut id_map) { Some(eh) => eh, None => return 3, }; @@ -562,7 +564,7 @@ fn main_args(args: &[String]) -> isize { renderinfo, sort_modules_alphabetically, themes, - enable_minification) + enable_minification, id_map) .expect("failed to generate documentation"); 0 } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 36a8fc94dba2f..05661dc685663 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -12,6 +12,7 @@ use std::default::Default; use std::fs::File; use std::io::prelude::*; use std::path::{PathBuf, Path}; +use std::cell::RefCell; use errors; use getopts; @@ -19,14 +20,14 @@ use testing; use rustc::session::search_paths::SearchPaths; use rustc::session::config::{Externs, CodegenOptions}; use syntax::codemap::DUMMY_SP; +use syntax::feature_gate::UnstableFeatures; use syntax::edition::Edition; use externalfiles::{ExternalHtml, LoadStringError, load_string}; -use html::render::reset_ids; use html::escape::Escape; use html::markdown; -use html::markdown::{Markdown, MarkdownWithToc, find_testable_code}; +use html::markdown::{ErrorCodes, IdMap, Markdown, MarkdownWithToc, find_testable_code}; use test::{TestOptions, Collector}; /// Separate any lines at the start of the file that begin with `# ` or `%`. @@ -86,12 +87,12 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, } let title = metadata[0]; - reset_ids(false); - + let mut ids = IdMap::new(); + let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); let text = if include_toc { - MarkdownWithToc(text).to_string() + MarkdownWithToc(text, RefCell::new(&mut ids), error_codes).to_string() } else { - Markdown(text, &[]).to_string() + Markdown(text, &[], RefCell::new(&mut ids), error_codes).to_string() }; let err = write!( @@ -156,7 +157,12 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, true, opts, maybe_sysroot, None, Some(PathBuf::from(input)), linker, edition); - find_testable_code(&input_str, &mut collector, DUMMY_SP, None); + collector.set_position(DUMMY_SP); + let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); + let res = find_testable_code(&input_str, &mut collector, codes); + if let Err(err) = res { + diag.span_warn(DUMMY_SP, &err.to_string()); + } test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&test_args, collector.tests, testing::Options::new().display_output(display_warnings)); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 2966b9e9819b4..650a2408aa6ed 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -42,7 +42,7 @@ use errors; use errors::emitter::ColorConfig; use clean::Attributes; -use html::markdown; +use html::markdown::{self, ErrorCodes, LangString}; #[derive(Clone, Default)] pub struct TestOptions { @@ -145,7 +145,8 @@ pub fn run(input_path: &Path, let mut hir_collector = HirCollector { sess: &sess, collector: &mut collector, - map: &map + map: &map, + codes: ErrorCodes::from(sess.opts.unstable_features.is_nightly_build()), }; hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { intravisit::walk_crate(this, krate); @@ -533,10 +534,8 @@ impl Collector { format!("{} - {} (line {})", filename, self.names.join("::"), line) } - pub fn add_test(&mut self, test: String, - should_panic: bool, no_run: bool, should_ignore: bool, - as_test_harness: bool, compile_fail: bool, error_codes: Vec, - line: usize, filename: FileName, allow_fail: bool) { + pub fn add_test(&mut self, test: String, config: LangString, line: usize) { + let filename = self.get_filename(); let name = self.generate_name(line, &filename); let cfgs = self.cfgs.clone(); let libs = self.libs.clone(); @@ -551,10 +550,10 @@ impl Collector { self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { name: testing::DynTestName(name.clone()), - ignore: should_ignore, + ignore: config.ignore, // compiler failures are test failures should_panic: testing::ShouldPanic::No, - allow_fail, + allow_fail: config.allow_fail, }, testfn: testing::DynTestFn(box move || { let panic = io::set_panic(None); @@ -572,11 +571,11 @@ impl Collector { libs, cg, externs, - should_panic, - no_run, - as_test_harness, - compile_fail, - error_codes, + config.should_panic, + config.no_run, + config.test_harness, + config.compile_fail, + config.error_codes, &opts, maybe_sysroot, linker, @@ -604,7 +603,7 @@ impl Collector { self.position = position; } - pub fn get_filename(&self) -> FileName { + fn get_filename(&self) -> FileName { if let Some(ref codemap) = self.codemap { let filename = codemap.span_to_filename(self.position); if let FileName::Real(ref filename) = filename { @@ -664,7 +663,8 @@ impl Collector { struct HirCollector<'a, 'hir: 'a> { sess: &'a session::Session, collector: &'a mut Collector, - map: &'a hir::map::Map<'hir> + map: &'a hir::map::Map<'hir>, + codes: ErrorCodes, } impl<'a, 'hir> HirCollector<'a, 'hir> { @@ -689,10 +689,12 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { // the collapse-docs pass won't combine sugared/raw doc attributes, or included files with // anything else, this will combine them for us if let Some(doc) = attrs.collapsed_doc_value() { - markdown::find_testable_code(&doc, - self.collector, - attrs.span.unwrap_or(DUMMY_SP), - Some(self.sess)); + self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP)); + let res = markdown::find_testable_code(&doc, self.collector, self.codes); + if let Err(err) = res { + self.sess.diagnostic().span_warn(attrs.span.unwrap_or(DUMMY_SP), + &err.to_string()); + } } nested(self); 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/os/hermit/fs.rs b/src/libstd/os/hermit/fs.rs new file mode 100644 index 0000000000000..d2e751668a67b --- /dev/null +++ b/src/libstd/os/hermit/fs.rs @@ -0,0 +1,389 @@ +// 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. + +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use libc; + +use fs::Metadata; +use sys_common::AsInner; + +#[allow(deprecated)] +use os::hermit::raw; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Gain a reference to the underlying `stat` structure which contains + /// the raw information returned by the OS. + /// + /// The contents of the returned [`stat`] are **not** consistent across + /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the + /// cross-Unix abstractions contained within the raw stat. + /// + /// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let stat = meta.as_raw_stat(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext", since = "1.1.0")] + #[rustc_deprecated(since = "1.8.0", + reason = "deprecated in favor of the accessor \ + methods of this trait")] + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat; + + /// Returns the device ID on which this file resides. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_dev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + /// Returns the inode number. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ino()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + /// Returns the file type and mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mode()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + /// Returns the number of hard links to file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_nlink()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + /// Returns the user ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_uid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + /// Returns the group ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_gid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + /// Returns the device ID that this file represents. Only relevant for special file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_rdev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes. + /// + /// The size of a symbolic link is the length of the pathname it contains, + /// without a terminating null byte. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_size()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + /// Returns the last access time. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + /// Returns the last access time, nano seconds part. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + /// Returns the last modification time. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + /// Returns the last modification time, nano seconds part. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + /// Returns the last status change time. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + /// Returns the last status change time, nano seconds part. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + /// Returns the "preferred" blocksize for efficient filesystem I/O. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blksize()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + /// Returns the number of blocks allocated to the file, 512-byte units. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blocks()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat { + unsafe { + &*(self.as_inner().as_inner() as *const libc::stat64 + as *const raw::stat) + } + } + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atime_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtime_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctime_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/src/libstd/os/hermit/mod.rs b/src/libstd/os/hermit/mod.rs new file mode 100644 index 0000000000000..fcb22cdad641f --- /dev/null +++ b/src/libstd/os/hermit/mod.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. + +//! HermitCore-specific definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod raw; +pub mod fs; diff --git a/src/libstd/os/hermit/raw.rs b/src/libstd/os/hermit/raw.rs new file mode 100644 index 0000000000000..282afe0b6e1c0 --- /dev/null +++ b/src/libstd/os/hermit/raw.rs @@ -0,0 +1,27 @@ +// 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. + +//! HermitCore-specific raw type definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] +#![rustc_deprecated(since = "1.8.0", + reason = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions")] +#![allow(deprecated)] +#![allow(missing_debug_implementations)] + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub use libc::pthread_t; + +#[doc(inline)] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub use libc::{dev_t, mode_t, off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t}; diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index ac7809451d152..c384ec9168ac4 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -47,6 +47,7 @@ cfg_if! { #[cfg(target_os = "solaris")] pub mod solaris; #[cfg(target_os = "emscripten")] pub mod emscripten; #[cfg(target_os = "fuchsia")] pub mod fuchsia; + #[cfg(target_os = "hermit")] pub mod hermit; #[cfg(any(target_os = "redox", unix))] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index dc1dba6f2f9b7..7e32ec1347e9e 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -66,7 +66,8 @@ impl DoubleEndedIterator for Args { target_os = "emscripten", target_os = "haiku", target_os = "l4re", - target_os = "fuchsia"))] + target_os = "fuchsia", + target_os = "hermit"))] mod imp { use os::unix::prelude::*; use ptr; diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 4f878d8ad1fa8..2007da7b1f6be 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -41,13 +41,15 @@ impl Condvar { #[cfg(any(target_os = "macos", target_os = "ios", target_os = "l4re", - target_os = "android"))] + target_os = "android", + target_os = "hermit"))] pub unsafe fn init(&mut self) {} #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "l4re", - target_os = "android")))] + target_os = "android", + target_os = "hermit")))] pub unsafe fn init(&mut self) { use mem; let mut attr: libc::pthread_condattr_t = mem::uninitialized(); @@ -83,7 +85,10 @@ impl Condvar { // where we configure condition variable to use monotonic clock (instead of // default system clock). This approach avoids all problems that result // from changes made to the system time. - #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))] + #[cfg(not(any(target_os = "macos", + target_os = "ios", + target_os = "android", + target_os = "hermit")))] pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { use mem; @@ -113,7 +118,7 @@ impl Condvar { // This implementation is modeled after libcxx's condition_variable // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46 // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367 - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))] + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))] pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool { use ptr; use time::Instant; diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs index 00cf7eca75dc3..ad116c57f557e 100644 --- a/src/libstd/sys/unix/env.rs +++ b/src/libstd/sys/unix/env.rs @@ -172,3 +172,14 @@ pub mod os { pub const EXE_SUFFIX: &'static str = ""; pub const EXE_EXTENSION: &'static str = ""; } + +#[cfg(target_os = "hermit")] +pub mod os { + pub const FAMILY: &'static str = "unix"; + pub const OS: &'static str = "hermit"; + pub const DLL_PREFIX: &'static str = "lib"; + pub const DLL_SUFFIX: &'static str = ".so"; + pub const DLL_EXTENSION: &'static str = "so"; + pub const EXE_SUFFIX: &'static str = ""; + pub const EXE_EXTENSION: &'static str = ""; +} diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index d59d800a57947..c13a0fea1e05c 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -20,7 +20,7 @@ // fallback implementation to use as well. // // Due to rust-lang/rust#18804, make sure this is not generic! -#[cfg(any(target_os = "linux", target_os = "fuchsia"))] +#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { use libc; use mem; diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 662a76d6725a6..7a89d9857bbcf 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -325,12 +325,12 @@ impl DirEntry { lstat(&self.path()) } - #[cfg(any(target_os = "solaris", target_os = "haiku"))] + #[cfg(any(target_os = "solaris", target_os = "haiku", target_os = "hermit"))] pub fn file_type(&self) -> io::Result { lstat(&self.path()).map(|m| m.file_type()) } - #[cfg(not(any(target_os = "solaris", target_os = "haiku")))] + #[cfg(not(any(target_os = "solaris", target_os = "haiku", target_os = "hermit")))] pub fn file_type(&self) -> io::Result { match self.entry.d_type { libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }), @@ -352,7 +352,8 @@ impl DirEntry { target_os = "solaris", target_os = "haiku", target_os = "l4re", - target_os = "fuchsia"))] + target_os = "fuchsia", + target_os = "hermit"))] pub fn ino(&self) -> u64 { self.entry.d_ino as u64 } @@ -383,7 +384,8 @@ impl DirEntry { target_os = "linux", target_os = "emscripten", target_os = "l4re", - target_os = "haiku"))] + target_os = "haiku", + target_os = "hermit"))] fn name_bytes(&self) -> &[u8] { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes() diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index c1298e5040dbe..c738003caf1d9 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -28,6 +28,7 @@ use libc; #[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform; #[cfg(all(not(dox), target_os = "fuchsia"))] pub use os::fuchsia as platform; #[cfg(all(not(dox), target_os = "l4re"))] pub use os::linux as platform; +#[cfg(all(not(dox), target_os = "hermit"))] pub use os::hermit as platform; pub use self::rand::hashmap_random_keys; pub use libc::strlen; diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index addf555eb1065..1d92e8fc97c7a 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -47,6 +47,7 @@ extern { target_os = "netbsd", target_os = "openbsd", target_os = "android", + target_os = "hermit", target_env = "newlib"), link_name = "__errno")] #[cfg_attr(target_os = "solaris", link_name = "___errno")] @@ -376,7 +377,7 @@ pub fn current_exe() -> io::Result { } } -#[cfg(any(target_os = "fuchsia", target_os = "l4re"))] +#[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))] pub fn current_exe() -> io::Result { use io::ErrorKind; Err(io::Error::new(ErrorKind::Other, "Not yet implemented!")) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index e26306c045d31..f3a45d2465739 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -138,7 +138,8 @@ impl Thread { target_os = "solaris", target_os = "haiku", target_os = "l4re", - target_os = "emscripten"))] + target_os = "emscripten", + target_os = "hermit"))] pub fn set_name(_name: &CStr) { // Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name. } diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 89786eb2a6c48..0b1fb726357e1 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -345,9 +345,9 @@ mod inner { } } - #[cfg(not(target_os = "dragonfly"))] + #[cfg(not(any(target_os = "dragonfly", target_os = "hermit")))] pub type clock_t = libc::c_int; - #[cfg(target_os = "dragonfly")] + #[cfg(any(target_os = "dragonfly", target_os = "hermit"))] pub type clock_t = libc::c_ulong; fn now(clock: clock_t) -> Timespec { 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 3f5550bf95fd2..a13e4ffa8f829 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -1075,7 +1075,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 @@ -1093,14 +1093,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/sparc-struct-abi.rs b/src/test/codegen/sparc-struct-abi.rs index d3b7a5cd59882..56c4364d598e7 100644 --- a/src/test/codegen/sparc-struct-abi.rs +++ b/src/test/codegen/sparc-struct-abi.rs @@ -11,6 +11,7 @@ // Checks that we correctly codegen extern "C" functions returning structs. // See issue #52638. +// only-sparc64 // compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib #![feature(no_core, lang_items)] #![no_core] diff --git a/src/test/codegen/vec-clear.rs b/src/test/codegen/vec-clear.rs new file mode 100644 index 0000000000000..a73dd077cea11 --- /dev/null +++ b/src/test/codegen/vec-clear.rs @@ -0,0 +1,21 @@ +// 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. + +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @vec_clear +#[no_mangle] +pub fn vec_clear(x: &mut Vec) { + // CHECK-NOT: load + // CHECK-NOT: icmp + x.clear() +} diff --git a/src/test/compile-fail/lint-dead-code-1.rs b/src/test/compile-fail/lint-dead-code-1.rs index d6ca5e6b1d969..2fe72365bab1c 100644 --- a/src/test/compile-fail/lint-dead-code-1.rs +++ b/src/test/compile-fail/lint-dead-code-1.rs @@ -19,7 +19,7 @@ pub use foo2::Bar2; mod foo { - pub struct Bar; //~ ERROR: struct is never used + pub struct Bar; //~ ERROR: struct is never constructed } mod foo2 { @@ -42,7 +42,7 @@ const CONST_USED_IN_ENUM_DISCRIMINANT: isize = 11; pub type typ = *const UsedStruct4; pub struct PubStruct; -struct PrivStruct; //~ ERROR: struct is never used +struct PrivStruct; //~ ERROR: struct is never constructed struct UsedStruct1 { #[allow(dead_code)] x: isize diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs index f680e39544933..112d363095253 100644 --- a/src/test/compile-fail/lint-dead-code-3.rs +++ b/src/test/compile-fail/lint-dead-code-3.rs @@ -20,7 +20,7 @@ extern { pub fn extern_foo(); } -struct Foo; //~ ERROR: struct is never used +struct Foo; //~ ERROR: struct is never constructed impl Foo { fn foo(&self) { //~ ERROR: method is never used bar() diff --git a/src/test/run-pass/const-endianess.rs b/src/test/run-pass/const-endianess.rs index fa34b49210a6a..95c738d3ec49a 100644 --- a/src/test/run-pass/const-endianess.rs +++ b/src/test/run-pass/const-endianess.rs @@ -25,7 +25,7 @@ fn main() { #[cfg(not(target_arch = "asmjs"))] { const BE_U128: u128 = 999999u128.to_be(); - const LE_I128: i128 = -999999i128.to_le(); + const LE_I128: i128 = (-999999i128).to_le(); assert_eq!(BE_U128, b(999999u128).to_be()); assert_eq!(LE_I128, b(-999999i128).to_le()); } diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index cf417f8d412ee..dbc65569afa87 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -12,7 +12,7 @@ error[E0425]: cannot find value `no` in this scope 3 | no | ^^ not found in this scope -thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:332:13 +thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:333:13 note: Run with `RUST_BACKTRACE=1` for a backtrace. ---- $DIR/failed-doctest-output.rs - SomeStruct (line 20) stdout ---- @@ -21,7 +21,7 @@ thread '$DIR/failed-doctest-output.rs - SomeStruct (line 20)' panicked at 'test thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1 note: Run with `RUST_BACKTRACE=1` for a backtrace. -', librustdoc/test.rs:367:17 +', librustdoc/test.rs:368:17 failures: 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/auxiliary/lint_tool_test.rs b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs new file mode 100644 index 0000000000000..01fa2f3459ea7 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs @@ -0,0 +1,48 @@ +// 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(plugin_registrar)] +#![feature(box_syntax, rustc_private)] +#![feature(macro_vis_matcher)] +#![feature(macro_at_most_once_rep)] + +extern crate syntax; + +// Load rustc as a plugin to get macros +#[macro_use] +extern crate rustc; +extern crate rustc_plugin; + +use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, + LintArray}; +use rustc_plugin::Registry; +use syntax::ast; +declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff"); + +struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(TEST_LINT) + } +} + +impl EarlyLintPass for Pass { + fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { + if it.ident.name == "lintme" { + cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); + } + } +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_early_lint_pass(box Pass); +} diff --git a/src/test/ui-fulldeps/lint_tool_test.rs b/src/test/ui-fulldeps/lint_tool_test.rs new file mode 100644 index 0000000000000..ccdcd2df31b4f --- /dev/null +++ b/src/test/ui-fulldeps/lint_tool_test.rs @@ -0,0 +1,24 @@ +// 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. + +// run-pass +// aux-build:lint_tool_test.rs +// ignore-stage1 +#![feature(plugin)] +#![feature(tool_lints)] +#![plugin(lint_tool_test)] +#![allow(dead_code)] + +fn lintme() { } //~ WARNING item is named 'lintme' + +#[allow(clippy::test_lint)] +pub fn main() { + fn lintme() { } +} diff --git a/src/test/ui-fulldeps/lint_tool_test.stderr b/src/test/ui-fulldeps/lint_tool_test.stderr new file mode 100644 index 0000000000000..22d0f458e7d7b --- /dev/null +++ b/src/test/ui-fulldeps/lint_tool_test.stderr @@ -0,0 +1,8 @@ +warning: item is named 'lintme' + --> $DIR/lint_tool_test.rs:19:1 + | +LL | fn lintme() { } //~ WARNING item is named 'lintme' + | ^^^^^^^^^^^^^^^ + | + = note: #[warn(clippy::test_lint)] on by default + 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/borrowck/borrowck-move-error-with-note.nll.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr index a34c97974da11..1b913471924b7 100644 --- a/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr +++ b/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr @@ -19,14 +19,16 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait | LL | match (S {f: "foo".to_string(), g: "bar".to_string()}) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here +... +LL | f: _s, + | -- data moved here +LL | g: _t + | -- ... and here help: to prevent move, use ref or ref mut | LL | f: ref _s, - | ^^^^^^ -help: to prevent move, use ref or ref mut - | LL | g: ref _t - | ^^^^^^ + | error[E0507]: cannot move out of borrowed content --> $DIR/borrowck-move-error-with-note.rs:57:11 diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr index d01b24507d9fe..95a7894d53254 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr @@ -3,14 +3,19 @@ error[E0508]: cannot move out of type `[Foo]`, a non-copy slice | LL | match tail { | ^^^^ cannot move out of here +LL | &[Foo { string: a }, + | - data moved here +... +LL | Foo { string: b }] => { + | - ... and here help: to prevent move, use ref or ref mut | LL | &[Foo { string: ref a }, - | ^^^^^ -help: to prevent move, use ref or ref mut - | +LL | //~^ ERROR cannot move out of type `[Foo]` +LL | //~| cannot move out +LL | //~| to prevent move LL | Foo { string: ref b }] => { - | ^^^^^ + | error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr index 50ef3ba40e7b2..2779132590e2c 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr @@ -28,7 +28,10 @@ error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy sli LL | match vec { | ^^^ cannot move out of here LL | &mut [_a, //~ ERROR cannot move out - | -- help: to prevent move, use ref or ref mut: `ref _a` + | -- + | | + | data moved here + | help: to prevent move, use ref or ref mut: `ref _a` error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice --> $DIR/borrowck-vec-pattern-nesting.rs:57:13 @@ -46,7 +49,10 @@ LL | match vec { | ^^^ cannot move out of here ... LL | _b] => {} - | -- help: to prevent move, use ref or ref mut: `ref _b` + | -- + | | + | data moved here + | help: to prevent move, use ref or ref mut: `ref _b` error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice --> $DIR/borrowck-vec-pattern-nesting.rs:70:13 @@ -62,18 +68,15 @@ error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy sli | LL | match vec { | ^^^ cannot move out of here +LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out + | -- -- -- ... and here + | | | + | | ... and here + | data moved here help: to prevent move, use ref or ref mut | -LL | &mut [ref _a, _b, _c] => {} //~ ERROR cannot move out - | ^^^^^^ -help: to prevent move, use ref or ref mut - | -LL | &mut [_a, ref _b, _c] => {} //~ ERROR cannot move out - | ^^^^^^ -help: to prevent move, use ref or ref mut - | -LL | &mut [_a, _b, ref _c] => {} //~ ERROR cannot move out - | ^^^^^^ +LL | &mut [ref _a, ref _b, ref _c] => {} //~ ERROR cannot move out + | ^^^^^^ ^^^^^^ ^^^^^^ error[E0508]: cannot move out of type `[std::boxed::Box]`, a non-copy slice --> $DIR/borrowck-vec-pattern-nesting.rs:82:13 diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index 4048243acfa2b..b6e005a6673eb 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -17,41 +17,41 @@ LL | if let Some(thing) = maybe { = note: move occurs because the value has type `std::vec::Vec`, which does not implement the `Copy` trait error[E0382]: use of moved value: `maybe` (Mir) - --> $DIR/issue-41962.rs:17:30 + --> $DIR/issue-41962.rs:17:16 | LL | if let Some(thing) = maybe { - | ----- ^^^^^ value used here after move - | | - | value moved here + | ^^^^^-----^ + | | | + | | value moved here + | value used here after move | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait -error[E0382]: borrow of moved value: `maybe` (Mir) - --> $DIR/issue-41962.rs:17:30 +error[E0382]: use of moved value (Mir) + --> $DIR/issue-41962.rs:17:21 | LL | if let Some(thing) = maybe { - | ----- ^^^^^ value borrowed here after move - | | - | value moved here + | ^^^^^ value moved here in previous iteration of loop | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait error[E0382]: use of moved value: `maybe` (Mir) - --> $DIR/issue-41962.rs:17:16 + --> $DIR/issue-41962.rs:17:30 | LL | if let Some(thing) = maybe { - | ^^^^^-----^ - | | | - | | value moved here - | value used here after move + | ----- ^^^^^ value used here after move + | | + | value moved here | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait -error[E0382]: use of moved value (Mir) - --> $DIR/issue-41962.rs:17:21 +error[E0382]: borrow of moved value: `maybe` (Mir) + --> $DIR/issue-41962.rs:17:30 | LL | if let Some(thing) = maybe { - | ^^^^^ value moved here in previous iteration of loop + | ----- ^^^^^ value borrowed here after move + | | + | value moved here | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait diff --git a/src/test/ui/borrowck/issue-51415.nll.stderr b/src/test/ui/borrowck/issue-51415.nll.stderr index d872c7efe2bc1..20713c3392e8e 100644 --- a/src/test/ui/borrowck/issue-51415.nll.stderr +++ b/src/test/ui/borrowck/issue-51415.nll.stderr @@ -4,6 +4,7 @@ error[E0507]: cannot move out of borrowed content LL | let opt = a.iter().enumerate().find(|(_, &s)| { | ^^^^^-^ | | | + | | data moved here | | help: to prevent move, use ref or ref mut: `ref s` | cannot move out of borrowed content diff --git a/src/test/ui/borrowck/two-phase-multi-mut.stderr b/src/test/ui/borrowck/two-phase-multi-mut.stderr index 0c02acf654855..a7e1dd9536453 100644 --- a/src/test/ui/borrowck/two-phase-multi-mut.stderr +++ b/src/test/ui/borrowck/two-phase-multi-mut.stderr @@ -1,21 +1,21 @@ error[E0499]: cannot borrow `foo` as mutable more than once at a time - --> $DIR/two-phase-multi-mut.rs:23:16 + --> $DIR/two-phase-multi-mut.rs:23:5 | LL | foo.method(&mut foo); - | -----------^^^^^^^^- + | ^^^^^^^^^^^--------^ | | | - | | second mutable borrow occurs here - | first mutable borrow occurs here + | | first mutable borrow occurs here + | second mutable borrow occurs here | borrow later used here error[E0499]: cannot borrow `foo` as mutable more than once at a time - --> $DIR/two-phase-multi-mut.rs:23:5 + --> $DIR/two-phase-multi-mut.rs:23:16 | LL | foo.method(&mut foo); - | ^^^^^^^^^^^--------^ + | -----------^^^^^^^^- | | | - | | first mutable borrow occurs here - | second mutable borrow occurs here + | | second mutable borrow occurs here + | first mutable borrow occurs here | borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/codemap_tests/overlapping_spans.nll.stderr b/src/test/ui/codemap_tests/overlapping_spans.nll.stderr index 34616a8de45ed..a1fbcf1430db9 100644 --- a/src/test/ui/codemap_tests/overlapping_spans.nll.stderr +++ b/src/test/ui/codemap_tests/overlapping_spans.nll.stderr @@ -4,7 +4,10 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait LL | match (S {f:"foo".to_string()}) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here LL | S {f:_s} => {} //~ ERROR cannot move out - | -- help: to prevent move, use ref or ref mut: `ref _s` + | -- + | | + | data moved here + | help: to prevent move, use ref or ref mut: `ref _s` error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39544.nll.stderr b/src/test/ui/did_you_mean/issue-39544.nll.stderr index 00e4cc6b0c35d..8c848b33241ca 100644 --- a/src/test/ui/did_you_mean/issue-39544.nll.stderr +++ b/src/test/ui/did_you_mean/issue-39544.nll.stderr @@ -10,7 +10,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:26:17 | LL | fn foo<'z>(&'z self) { - | -------- help: consider changing this to be a mutable reference: `&mut self` + | -------- help: consider changing this to be a mutable reference: `&'z mut self` LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -35,7 +35,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:35:17 | LL | fn foo2<'a>(&'a self, other: &Z) { - | -------- help: consider changing this to be a mutable reference: `&mut self` + | -------- help: consider changing this to be a mutable reference: `&'a mut self` LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -52,7 +52,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:40:17 | LL | fn foo3<'a>(self: &'a Self, other: &Z) { - | -------- help: consider changing this to be a mutable reference: `&mut Z` + | -------- help: consider changing this to be a mutable reference: `&'a mut Self` LL | let _ = &mut self.x; //~ ERROR cannot borrow | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/hygiene/fields-move.nll.stderr b/src/test/ui/hygiene/fields-move.nll.stderr index 51f8067b8ce5b..56b77714991ca 100644 --- a/src/test/ui/hygiene/fields-move.nll.stderr +++ b/src/test/ui/hygiene/fields-move.nll.stderr @@ -1,27 +1,27 @@ error[E0382]: use of moved value: `foo.x` - --> $DIR/fields-move.rs:38:42 + --> $DIR/fields-move.rs:28:9 | LL | $foo.x | ------ value moved here ... +LL | $foo.x //~ ERROR use of moved value: `foo.x` + | ^^^^^^ value used here after move +... LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x` - | ^^^^^ value used here after move + | ----- value moved here +LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x` + | ----------------- in this macro invocation | = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait error[E0382]: use of moved value: `foo.x` - --> $DIR/fields-move.rs:28:9 + --> $DIR/fields-move.rs:38:42 | LL | $foo.x | ------ value moved here ... -LL | $foo.x //~ ERROR use of moved value: `foo.x` - | ^^^^^^ value used here after move -... LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x` - | ----- value moved here -LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x` - | ----------------- in this macro invocation + | ^^^^^ value used here after move | = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait diff --git a/src/test/ui/issue-12567.nll.stderr b/src/test/ui/issue-12567.nll.stderr index a040f7c3c8d1b..29bda252b9115 100644 --- a/src/test/ui/issue-12567.nll.stderr +++ b/src/test/ui/issue-12567.nll.stderr @@ -3,28 +3,40 @@ error[E0508]: cannot move out of type `[T]`, a non-copy slice | LL | match (l1, l2) { | ^^^^^^^^ cannot move out of here +LL | (&[], &[]) => println!("both empty"), +LL | (&[], &[hd, ..]) | (&[hd, ..], &[]) + | -- data moved here +... +LL | (&[hd1, ..], &[hd2, ..]) + | --- ... and here help: to prevent move, use ref or ref mut | LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[]) - | ^^^^^^ -help: to prevent move, use ref or ref mut - | +LL | => println!("one empty"), +LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice +LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice LL | (&[hd1, ..], &[ref hd2, ..]) - | ^^^^^^^ + | error[E0508]: cannot move out of type `[T]`, a non-copy slice --> $DIR/issue-12567.rs:14:11 | LL | match (l1, l2) { | ^^^^^^^^ cannot move out of here +LL | (&[], &[]) => println!("both empty"), +LL | (&[], &[hd, ..]) | (&[hd, ..], &[]) + | -- data moved here +... +LL | (&[hd1, ..], &[hd2, ..]) + | --- ... and here help: to prevent move, use ref or ref mut | LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[]) - | ^^^^^^ -help: to prevent move, use ref or ref mut - | +LL | => println!("one empty"), +LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice +LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice LL | (&[ref hd1, ..], &[hd2, ..]) - | ^^^^^^^ + | error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-27592.nll.stderr b/src/test/ui/issue-27592.nll.stderr index 0b55117cad2ce..36a15e79ac825 100644 --- a/src/test/ui/issue-27592.nll.stderr +++ b/src/test/ui/issue-27592.nll.stderr @@ -1,11 +1,3 @@ -error[E0597]: borrowed value does not live long enough - --> $DIR/issue-27592.rs:26:33 - | -LL | write(|| format_args!("{}", String::from("Hello world"))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here - | | - | temporary value does not live long enough - error[E0597]: borrowed value does not live long enough --> $DIR/issue-27592.rs:26:27 | @@ -14,6 +6,14 @@ LL | write(|| format_args!("{}", String::from("Hello world"))); | | | temporary value does not live long enough +error[E0597]: borrowed value does not live long enough + --> $DIR/issue-27592.rs:26:33 + | +LL | write(|| format_args!("{}", String::from("Hello world"))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here + | | + | temporary value does not live long enough + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index ccf116e640d42..862d1f0b179c0 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -4,15 +4,6 @@ warning: not reporting region error due to nll LL | let mut closure = expect_sig(|p, y| *p = y); | ^ -error: unsatisfied lifetime constraints - --> $DIR/escape-argument-callee.rs:36:45 - | -LL | let mut closure = expect_sig(|p, y| *p = y); - | - - ^^^^^^ requires that `'1` must outlive `'2` - | | | - | | has type `&'1 i32` - | has type `&mut &'2 i32` - note: No external requirements --> $DIR/escape-argument-callee.rs:36:38 | @@ -24,6 +15,15 @@ LL | let mut closure = expect_sig(|p, y| *p = y); for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32)) ] +error: unsatisfied lifetime constraints + --> $DIR/escape-argument-callee.rs:36:45 + | +LL | let mut closure = expect_sig(|p, y| *p = y); + | - - ^^^^^^ requires that `'1` must outlive `'2` + | | | + | | has type `&'1 i32` + | has type `&mut &'2 i32` + note: No external requirements --> $DIR/escape-argument-callee.rs:30:1 | diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index b450882490195..72b7104b99dd3 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -4,17 +4,6 @@ warning: not reporting region error due to nll LL | let p = x.get(); | ^^^^^^^ -error: unsatisfied lifetime constraints - --> $DIR/propagate-approximated-fail-no-postdom.rs:57:13 - | -LL | |_outlives1, _outlives2, _outlives3, x, y| { - | ---------- ---------- has type `std::cell::Cell<&'2 &u32>` - | | - | has type `std::cell::Cell<&&'1 u32>` -... -LL | demand_y(x, y, p) //~ ERROR - | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` - note: No external requirements --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9 | @@ -31,6 +20,17 @@ LL | | }, for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)) ] +error: unsatisfied lifetime constraints + --> $DIR/propagate-approximated-fail-no-postdom.rs:57:13 + | +LL | |_outlives1, _outlives2, _outlives3, x, y| { + | ---------- ---------- has type `std::cell::Cell<&'2 &u32>` + | | + | has type `std::cell::Cell<&&'1 u32>` +... +LL | demand_y(x, y, p) //~ ERROR + | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + note: No external requirements --> $DIR/propagate-approximated-fail-no-postdom.rs:48:1 | diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index a3588ff07e6a5..43c39dee2448a 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -4,17 +4,6 @@ warning: not reporting region error due to nll LL | foo(cell, |cell_a, cell_x| { | ^^^ -error: borrowed data escapes outside of closure - --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9 - | -LL | foo(cell, |cell_a, cell_x| { - | ------ ------ `cell_x` is a reference that is only valid in the closure body - | | - | `cell_a` is declared here, outside of the closure body -LL | //~^ WARNING not reporting region error due to nll -LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure - | ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here - note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15 | @@ -31,6 +20,17 @@ LL | | }) for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>)) ] +error: borrowed data escapes outside of closure + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9 + | +LL | foo(cell, |cell_a, cell_x| { + | ------ ------ `cell_x` is a reference that is only valid in the closure body + | | + | `cell_a` is declared here, outside of the closure body +LL | //~^ WARNING not reporting region error due to nll +LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure + | ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here + note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1 | diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index d5495b69c7ced..c3bbf1035dbc5 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -23,19 +23,6 @@ LL | | }); = note: number of external vids: 4 = note: where '_#1r: '_#0r -error: borrowed data escapes outside of function - --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5 - | -LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | ------ `cell_a` is a reference that is only valid in the function body -LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { -LL | | //~^ ERROR -LL | | -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll -LL | | }); - | |______^ `cell_a` escapes the function body here - note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1 | @@ -50,5 +37,18 @@ LL | | } | = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs [] +error: borrowed data escapes outside of function + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | ------ `cell_a` is a reference that is only valid in the function body +LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { +LL | | //~^ ERROR +LL | | +LL | | // Only works if 'x: 'y: +LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll +LL | | }); + | |______^ `cell_a` escapes the function body here + error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 50e2dd23da8a8..9f259e2dee590 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -23,19 +23,6 @@ LL | | }); = note: number of external vids: 5 = note: where '_#1r: '_#0r -error: borrowed data escapes outside of function - --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5 - | -LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | ------ `cell_a` is a reference that is only valid in the function body -LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { -LL | | //~^ ERROR -LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) -LL | | //~^ WARNING not reporting region error due to nll -LL | | }); - | |______^ `cell_a` escapes the function body here - note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1 | @@ -50,5 +37,18 @@ LL | | } | = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs [] +error: borrowed data escapes outside of function + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | ------ `cell_a` is a reference that is only valid in the function body +LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { +LL | | //~^ ERROR +LL | | // Only works if 'x: 'y: +LL | | demand_y(x, y, x.get()) +LL | | //~^ WARNING not reporting region error due to nll +LL | | }); + | |______^ `cell_a` escapes the function body here + error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 40ebda4419b2a..cd5e6f29f5f48 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -4,17 +4,6 @@ warning: not reporting region error due to nll LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ -error: unsatisfied lifetime constraints - --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9 - | -LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - | --------- - has type `&std::cell::Cell<&'1 u32>` - | | - | has type `&std::cell::Cell<&'2 &u32>` -LL | // Only works if 'x: 'y: -LL | demand_y(x, y, x.get()) - | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` - note: No external requirements --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47 | @@ -32,6 +21,17 @@ LL | | }); for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>)) ] +error: unsatisfied lifetime constraints + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | --------- - has type `&std::cell::Cell<&'1 u32>` + | | + | has type `&std::cell::Cell<&'2 &u32>` +LL | // Only works if 'x: 'y: +LL | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + note: No external requirements --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:44:1 | diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 37ea610397696..2176575e0aa12 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -4,17 +4,6 @@ warning: not reporting region error due to nll LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ -error: unsatisfied lifetime constraints - --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9 - | -LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | ---------- ---------- has type `&std::cell::Cell<&'2 &u32>` - | | - | has type `&std::cell::Cell<&'1 &u32>` -LL | // Only works if 'x: 'y: -LL | demand_y(x, y, x.get()) - | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` - note: No external requirements --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47 | @@ -32,6 +21,17 @@ LL | | }); for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>)) ] +error: unsatisfied lifetime constraints + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ---------- ---------- has type `&std::cell::Cell<&'2 &u32>` + | | + | has type `&std::cell::Cell<&'1 &u32>` +LL | // Only works if 'x: 'y: +LL | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + note: No external requirements --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:48:1 | diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 42d5b15bd5a29..8f8a99df5f052 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -26,21 +26,6 @@ LL | | }); = note: number of external vids: 3 = note: where T: '_#1r -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/propagate-from-trait-match.rs:42:36 - | -LL | establish_relationships(value, |value| { - | ____________________________________^ -LL | | //~^ ERROR the parameter type `T` may not live long enough -LL | | -LL | | // This function call requires that -... | -LL | | //~^ WARNING not reporting region error due to nll -LL | | }); - | |_____^ - | - = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... - note: No external requirements --> $DIR/propagate-from-trait-match.rs:38:1 | @@ -58,6 +43,21 @@ LL | | } T ] +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/propagate-from-trait-match.rs:42:36 + | +LL | establish_relationships(value, |value| { + | ____________________________________^ +LL | | //~^ ERROR the parameter type `T` may not live long enough +LL | | +LL | | // This function call requires that +... | +LL | | //~^ WARNING not reporting region error due to nll +LL | | }); + | |_____^ + | + = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... + error: aborting due to previous error For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index d6d1645ceeacc..d2e088815e118 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -4,15 +4,6 @@ warning: not reporting region error due to nll LL | expect_sig(|a, b| b); // ought to return `a` | ^ -error: unsatisfied lifetime constraints - --> $DIR/return-wrong-bound-region.rs:21:23 - | -LL | expect_sig(|a, b| b); // ought to return `a` - | - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2` - | | | - | | has type `&'1 i32` - | has type `&'2 i32` - note: No external requirements --> $DIR/return-wrong-bound-region.rs:21:16 | @@ -24,6 +15,15 @@ LL | expect_sig(|a, b| b); // ought to return `a` for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32 ] +error: unsatisfied lifetime constraints + --> $DIR/return-wrong-bound-region.rs:21:23 + | +LL | expect_sig(|a, b| b); // ought to return `a` + | - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2` + | | | + | | has type `&'1 i32` + | has type `&'2 i32` + note: No external requirements --> $DIR/return-wrong-bound-region.rs:20:1 | diff --git a/src/test/ui/nll/extra-unused-mut.rs b/src/test/ui/nll/extra-unused-mut.rs index ce07e2b0e2184..472ac2cf1e84c 100644 --- a/src/test/ui/nll/extra-unused-mut.rs +++ b/src/test/ui/nll/extra-unused-mut.rs @@ -55,10 +55,19 @@ fn parse_dot_or_call_expr_with(mut attrs: Vec) { ); } +// Found when trying to bootstrap rustc +fn if_guard(x: Result) { + match x { + Ok(mut r) | Err(mut r) if true => r = 1, + _ => (), + } +} + fn main() { ref_argument(0); mutable_upvar(); generator_mutable_upvar(); ref_closure_argument(); parse_dot_or_call_expr_with(Vec::new()); + if_guard(Ok(0)); } 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/test/ui/nll/move-errors.stderr b/src/test/ui/nll/move-errors.stderr index 3f2c651ae3a6a..53d60d3f6d649 100644 --- a/src/test/ui/nll/move-errors.stderr +++ b/src/test/ui/nll/move-errors.stderr @@ -59,6 +59,7 @@ error[E0509]: cannot move out of type `D`, which implements the `Drop` trait LL | let C(D(s)) = c; | - ^ cannot move out of here | | + | data moved here | help: to prevent move, use ref or ref mut: `ref s` error[E0507]: cannot move out of borrowed content @@ -88,7 +89,10 @@ LL | match x { | ^ cannot move out of here ... LL | B::U(D(s)) => (), - | - help: to prevent move, use ref or ref mut: `ref s` + | - + | | + | data moved here + | help: to prevent move, use ref or ref mut: `ref s` error[E0509]: cannot move out of type `D`, which implements the `Drop` trait --> $DIR/move-errors.rs:105:11 @@ -97,7 +101,10 @@ LL | match x { | ^ cannot move out of here ... LL | (D(s), &t) => (), - | - help: to prevent move, use ref or ref mut: `ref s` + | - + | | + | data moved here + | help: to prevent move, use ref or ref mut: `ref s` error[E0507]: cannot move out of borrowed content --> $DIR/move-errors.rs:105:11 @@ -106,21 +113,25 @@ LL | match x { | ^ cannot move out of borrowed content ... LL | (D(s), &t) => (), - | - help: to prevent move, use ref or ref mut: `ref t` + | - + | | + | data moved here + | help: to prevent move, use ref or ref mut: `ref t` error[E0509]: cannot move out of type `F`, which implements the `Drop` trait --> $DIR/move-errors.rs:115:11 | LL | match x { | ^ cannot move out of here +LL | //~^ ERROR +LL | F(s, mut t) => (), + | - ----- ... and here + | | + | data moved here help: to prevent move, use ref or ref mut | -LL | F(ref s, mut t) => (), - | ^^^^^ -help: to prevent move, use ref or ref mut - | -LL | F(s, ref mut t) => (), - | ^^^^^^^^^ +LL | F(ref s, ref mut t) => (), + | ^^^^^ ^^^^^^^^^ error[E0507]: cannot move out of borrowed content --> $DIR/move-errors.rs:123:11 diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index dd12e8220c456..6d2170729ffb9 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -25,14 +25,6 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: number of external vids: 4 = note: where ::Item: '_#2r -error[E0309]: the associated type `::Item` may not live long enough - --> $DIR/projection-no-regions-closure.rs:35:23 - | -LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `::Item: ReEarlyBound(0, 'a)`... - note: No external requirements --> $DIR/projection-no-regions-closure.rs:31:1 | @@ -50,6 +42,14 @@ LL | | } T ] +error[E0309]: the associated type `::Item` may not live long enough + --> $DIR/projection-no-regions-closure.rs:35:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: ReEarlyBound(0, 'a)`... + note: External requirements --> $DIR/projection-no-regions-closure.rs:45:23 | @@ -97,14 +97,6 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: number of external vids: 5 = note: where ::Item: '_#3r -error[E0309]: the associated type `::Item` may not live long enough - --> $DIR/projection-no-regions-closure.rs:53:23 - | -LL | with_signature(x, |mut y| Box::new(y.next())) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `::Item: ReEarlyBound(0, 'a)`... - note: No external requirements --> $DIR/projection-no-regions-closure.rs:49:1 | @@ -123,6 +115,14 @@ LL | | } T ] +error[E0309]: the associated type `::Item` may not live long enough + --> $DIR/projection-no-regions-closure.rs:53:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: ReEarlyBound(0, 'a)`... + note: External requirements --> $DIR/projection-no-regions-closure.rs:64:23 | diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index 456c52d3a51b8..ed8491349a257 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -32,20 +32,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where T: '_#2r = note: where '_#1r: '_#2r -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:55:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... - -error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-closure.rs:55:5 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - note: No external requirements --> $DIR/projection-one-region-closure.rs:51:1 | @@ -63,6 +49,20 @@ LL | | } T ] +error: unsatisfied lifetime constraints + --> $DIR/projection-one-region-closure.rs:55:5 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:55:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... + note: External requirements --> $DIR/projection-one-region-closure.rs:67:29 | @@ -80,20 +80,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where T: '_#3r = note: where '_#2r: '_#3r -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:67:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... - -error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-closure.rs:67:5 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - note: No external requirements --> $DIR/projection-one-region-closure.rs:62:1 | @@ -112,6 +98,20 @@ LL | | } T ] +error: unsatisfied lifetime constraints + --> $DIR/projection-one-region-closure.rs:67:5 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:67:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... + note: External requirements --> $DIR/projection-one-region-closure.rs:89:29 | @@ -129,20 +129,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where T: '_#3r = note: where '_#2r: '_#3r -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:89:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... - -error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-closure.rs:89:5 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - note: No external requirements --> $DIR/projection-one-region-closure.rs:74:1 | @@ -161,6 +147,20 @@ LL | | } T ] +error: unsatisfied lifetime constraints + --> $DIR/projection-one-region-closure.rs:89:5 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:89:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... + note: External requirements --> $DIR/projection-one-region-closure.rs:102:29 | diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 35c0405ff89e2..8318ce10745d3 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -31,12 +31,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 5 = note: where '_#1r: '_#2r -error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-trait-bound-closure.rs:47:5 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - note: No external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:43:1 | @@ -54,6 +48,12 @@ LL | | } T ] +error: unsatisfied lifetime constraints + --> $DIR/projection-one-region-trait-bound-closure.rs:47:5 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + note: External requirements --> $DIR/projection-one-region-trait-bound-closure.rs:58:29 | @@ -70,12 +70,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 5 = note: where '_#2r: '_#3r -error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-trait-bound-closure.rs:58:5 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - note: No external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:53:1 | @@ -94,6 +88,12 @@ LL | | } T ] +error: unsatisfied lifetime constraints + --> $DIR/projection-one-region-trait-bound-closure.rs:58:5 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + note: External requirements --> $DIR/projection-one-region-trait-bound-closure.rs:79:29 | @@ -110,12 +110,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 5 = note: where '_#2r: '_#3r -error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-trait-bound-closure.rs:79:5 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - note: No external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:64:1 | @@ -134,6 +128,12 @@ LL | | } T ] +error: unsatisfied lifetime constraints + --> $DIR/projection-one-region-trait-bound-closure.rs:79:5 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + note: External requirements --> $DIR/projection-one-region-trait-bound-closure.rs:90:29 | diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index a713971d17cb3..1452573d57a25 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -38,14 +38,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 6 = note: where >::AssocType: '_#3r -error[E0309]: the associated type `>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`... - note: No external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:44:1 | @@ -64,6 +56,14 @@ LL | | } T ] +error[E0309]: the associated type `>::AssocType` may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`... + note: External requirements --> $DIR/projection-two-region-trait-bound-closure.rs:59:29 | @@ -81,14 +81,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 6 = note: where >::AssocType: '_#4r -error[E0309]: the associated type `>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:59:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `>::AssocType: ReEarlyBound(0, 'a)`... - note: No external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:54:1 | @@ -108,6 +100,14 @@ LL | | } T ] +error[E0309]: the associated type `>::AssocType` may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:59:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `>::AssocType: ReEarlyBound(0, 'a)`... + note: External requirements --> $DIR/projection-two-region-trait-bound-closure.rs:80:29 | @@ -125,14 +125,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 6 = note: where >::AssocType: '_#4r -error[E0309]: the associated type `>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:80:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `>::AssocType: ReEarlyBound(0, 'a)`... - note: No external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:65:1 | @@ -152,6 +144,14 @@ LL | | } T ] +error[E0309]: the associated type `>::AssocType` may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:80:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `>::AssocType: ReEarlyBound(0, 'a)`... + note: External requirements --> $DIR/projection-two-region-trait-bound-closure.rs:91:29 | @@ -239,12 +239,6 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 5 = note: where >::AssocType: '_#2r -error: unsatisfied lifetime constraints - --> $DIR/projection-two-region-trait-bound-closure.rs:108:5 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - note: No external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:104:1 | @@ -262,6 +256,12 @@ LL | | } T ] +error: unsatisfied lifetime constraints + --> $DIR/projection-two-region-trait-bound-closure.rs:108:5 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + note: External requirements --> $DIR/projection-two-region-trait-bound-closure.rs:119:29 | diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 39382df8d8a91..87f55b4e14d96 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -60,14 +60,6 @@ LL | twice(cell, value, |a, b| invoke(a, b)); = note: number of external vids: 4 = note: where T: '_#1r -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24 - | -LL | twice(cell, value, |a, b| invoke(a, b)); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`... - note: No external requirements --> $DIR/ty-param-closure-approximate-lower-bound.rs:41:1 | @@ -83,6 +75,14 @@ LL | | } T ] +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24 + | +LL | twice(cell, value, |a, b| invoke(a, b)); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`... + error: aborting due to previous error For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 8babbe3fd97d2..aec0d98c79aa4 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -25,14 +25,6 @@ LL | with_signature(x, |y| y) = note: number of external vids: 4 = note: where T: '_#2r -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23 - | -LL | with_signature(x, |y| y) - | ^^^^^ - | - = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... - note: No external requirements --> $DIR/ty-param-closure-outlives-from-return-type.rs:25:1 | @@ -50,6 +42,14 @@ LL | | } T ] +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23 + | +LL | with_signature(x, |y| y) + | ^^^^^ + | + = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... + error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5 | diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index b9426eba0f66d..67a158860d64c 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -31,21 +31,6 @@ LL | | }) = note: number of external vids: 4 = note: where T: '_#1r -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26 - | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | //~^ ERROR the parameter type `T` may not live long enough -LL | | // -LL | | // See `correct_region`, which explains the point of this -... | -LL | | //~^ WARNING not reporting region error due to nll -LL | | }) - | |_____^ - | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`... - note: No external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:36:1 | @@ -62,6 +47,21 @@ LL | | } T ] +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26 + | +LL | with_signature(a, b, |x, y| { + | __________________________^ +LL | | //~^ ERROR the parameter type `T` may not live long enough +LL | | // +LL | | // See `correct_region`, which explains the point of this +... | +LL | | //~^ WARNING not reporting region error due to nll +LL | | }) + | |_____^ + | + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`... + note: External requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:54:26 | @@ -122,20 +122,6 @@ LL | | }) = note: number of external vids: 5 = note: where T: '_#2r -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26 - | -LL | with_signature(a, b, |x, y| { - | __________________________^ -LL | | //~^ ERROR the parameter type `T` may not live long enough -LL | | // See `correct_region` -LL | | require(&x, &y) -LL | | //~^ WARNING not reporting region error due to nll -LL | | }) - | |_____^ - | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`... - note: No external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1 | @@ -153,6 +139,20 @@ LL | | } T ] +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26 + | +LL | with_signature(a, b, |x, y| { + | __________________________^ +LL | | //~^ ERROR the parameter type `T` may not live long enough +LL | | // See `correct_region` +LL | | require(&x, &y) +LL | | //~^ WARNING not reporting region error due to nll +LL | | }) + | |_____^ + | + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`... + note: External requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:89:26 | diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr index 366bfc8fa20a5..4a693a3b05d4e 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr @@ -26,7 +26,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5 | LL | fn assign_field2<'a>(x: &'a Own) { - | -------------- help: consider changing this to be a mutable reference: `&mut Own` + | -------------- help: consider changing this to be a mutable reference: `&'a mut Own` LL | x.y = 3; //~ ERROR cannot borrow | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -58,7 +58,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6 | LL | fn assign_method2<'a>(x: &'a Own) { - | -------------- help: consider changing this to be a mutable reference: `&mut Own` + | -------------- help: consider changing this to be a mutable reference: `&'a mut Own` LL | *x.y_mut() = 3; //~ ERROR cannot borrow | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr index 69bf246ff3fef..44a5062cb4d43 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr @@ -10,7 +10,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11 | LL | fn deref_extend_mut1<'a>(x: &'a Own) -> &'a mut isize { - | -------------- help: consider changing this to be a mutable reference: `&mut Own` + | -------------- help: consider changing this to be a mutable reference: `&'a mut Own` LL | &mut **x //~ ERROR cannot borrow | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -26,7 +26,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6 | LL | fn assign2<'a>(x: &'a Own) { - | -------------- help: consider changing this to be a mutable reference: `&mut Own` + | -------------- help: consider changing this to be a mutable reference: `&'a mut Own` LL | **x = 3; //~ ERROR cannot borrow | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr b/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr index 6c0373ce1570a..76a25fa661ece 100644 --- a/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr +++ b/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr @@ -1,25 +1,25 @@ -error[E0597]: `b3` does not live long enough - --> $DIR/dropck_arr_cycle_checked.rs:105:24 +error[E0597]: `b2` does not live long enough + --> $DIR/dropck_arr_cycle_checked.rs:103:24 | -LL | b1.a[1].v.set(Some(&b3)); +LL | b1.a[0].v.set(Some(&b2)); | ^^^ borrowed value does not live long enough ... LL | } | - | | - | `b3` dropped here while still borrowed + | `b2` dropped here while still borrowed | borrow later used here, when `b1` is dropped -error[E0597]: `b2` does not live long enough - --> $DIR/dropck_arr_cycle_checked.rs:103:24 +error[E0597]: `b3` does not live long enough + --> $DIR/dropck_arr_cycle_checked.rs:105:24 | -LL | b1.a[0].v.set(Some(&b2)); +LL | b1.a[1].v.set(Some(&b3)); | ^^^ borrowed value does not live long enough ... LL | } | - | | - | `b2` dropped here while still borrowed + | `b3` dropped here while still borrowed | borrow later used here, when `b1` is dropped error[E0597]: `b1` does not live long enough diff --git a/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr index c0950e7929678..e6f43e0a71b56 100644 --- a/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr +++ b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr @@ -1,25 +1,25 @@ -error[E0597]: `c3` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:115:24 +error[E0597]: `c2` does not live long enough + --> $DIR/dropck_vec_cycle_checked.rs:113:24 | -LL | c1.v[1].v.set(Some(&c3)); +LL | c1.v[0].v.set(Some(&c2)); | ^^^ borrowed value does not live long enough ... LL | } | - | | - | `c3` dropped here while still borrowed + | `c2` dropped here while still borrowed | borrow later used here, when `c1` is dropped -error[E0597]: `c2` does not live long enough - --> $DIR/dropck_vec_cycle_checked.rs:113:24 +error[E0597]: `c3` does not live long enough + --> $DIR/dropck_vec_cycle_checked.rs:115:24 | -LL | c1.v[0].v.set(Some(&c2)); +LL | c1.v[1].v.set(Some(&c3)); | ^^^ borrowed value does not live long enough ... LL | } | - | | - | `c2` dropped here while still borrowed + | `c3` dropped here while still borrowed | borrow later used here, when `c1` is dropped error[E0597]: `c1` does not live long enough diff --git a/src/test/ui/span/macro-span-replacement.rs b/src/test/ui/span/macro-span-replacement.rs index 4fe35042300e7..7374f15746851 100644 --- a/src/test/ui/span/macro-span-replacement.rs +++ b/src/test/ui/span/macro-span-replacement.rs @@ -14,7 +14,7 @@ macro_rules! m { ($a:tt $b:tt) => { - $b $a; //~ WARN struct is never used + $b $a; //~ WARN struct is never constructed } } diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index bb59fa206df1d..b12ca86d3c929 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -1,7 +1,7 @@ -warning: struct is never used: `S` +warning: struct is never constructed: `S` --> $DIR/macro-span-replacement.rs:17:14 | -LL | $b $a; //~ WARN struct is never used +LL | $b $a; //~ WARN struct is never constructed | ^ ... LL | m!(S struct); diff --git a/src/test/ui/span/mut-arg-hint.nll.stderr b/src/test/ui/span/mut-arg-hint.nll.stderr index f264ea1f91676..f42cf6500e2ea 100644 --- a/src/test/ui/span/mut-arg-hint.nll.stderr +++ b/src/test/ui/span/mut-arg-hint.nll.stderr @@ -10,7 +10,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:18:5 | LL | pub fn foo<'a>(mut a: &'a String) { - | ---------- help: consider changing this to be a mutable reference: `&mut std::string::String` + | ---------- help: consider changing this to be a mutable reference: `&'a mut String` LL | a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/src/test/ui/span/range-2.nll.stderr b/src/test/ui/span/range-2.nll.stderr index 049618fe4744b..2a82e1b8ada8c 100644 --- a/src/test/ui/span/range-2.nll.stderr +++ b/src/test/ui/span/range-2.nll.stderr @@ -1,21 +1,21 @@ -error[E0597]: `b` does not live long enough - --> $DIR/range-2.rs:17:13 +error[E0597]: `a` does not live long enough + --> $DIR/range-2.rs:17:9 | LL | &a..&b - | ^^ borrowed value does not live long enough + | ^^ borrowed value does not live long enough LL | }; - | - `b` dropped here while still borrowed + | - `a` dropped here while still borrowed ... LL | r.use_ref(); | - borrow later used here -error[E0597]: `a` does not live long enough - --> $DIR/range-2.rs:17:9 +error[E0597]: `b` does not live long enough + --> $DIR/range-2.rs:17:13 | LL | &a..&b - | ^^ borrowed value does not live long enough + | ^^ borrowed value does not live long enough LL | }; - | - `a` dropped here while still borrowed + | - `b` dropped here while still borrowed ... LL | r.use_ref(); | - borrow later used here diff --git a/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr index 33fca7fa703b0..4d81211673e6e 100644 --- a/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr +++ b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr @@ -20,6 +20,17 @@ LL | let mut z = x; //~ ERROR cannot use `x` because it was mutably borr LL | _y.push(&mut z); | -- borrow later used here +error[E0597]: `z` does not live long enough + --> $DIR/regions-escape-loop-via-vec.rs:17:17 + | +LL | _y.push(&mut z); + | -- ^^^^^^ borrowed value does not live long enough + | | + | borrow later used here +... +LL | } + | - `z` dropped here while still borrowed + error[E0503]: cannot use `x` because it was mutably borrowed --> $DIR/regions-escape-loop-via-vec.rs:19:9 | @@ -32,17 +43,6 @@ LL | //~^ ERROR `z` does not live long enough LL | x += 1; //~ ERROR cannot assign | ^^^^^^ use of borrowed `x` -error[E0597]: `z` does not live long enough - --> $DIR/regions-escape-loop-via-vec.rs:17:17 - | -LL | _y.push(&mut z); - | -- ^^^^^^ borrowed value does not live long enough - | | - | borrow later used here -... -LL | } - | - `z` dropped here while still borrowed - error: aborting due to 4 previous errors Some errors occurred: E0503, E0597. diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr index 7f7217b8004a6..1753f710b8842 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr @@ -1,3 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-ensures-scoping.rs:26:17 + | +LL | let y = &x; + | ^^ borrowed value does not live long enough +... +LL | }; + | - `x` dropped here while still borrowed +LL | +LL | bad.join(); + | --- borrow later used here + error[E0597]: `y` does not live long enough --> $DIR/send-is-not-static-ensures-scoping.rs:29:16 | @@ -13,18 +25,6 @@ LL | LL | bad.join(); | --- borrow later used here -error[E0597]: `x` does not live long enough - --> $DIR/send-is-not-static-ensures-scoping.rs:26:17 - | -LL | let y = &x; - | ^^ borrowed value does not live long enough -... -LL | }; - | - `x` dropped here while still borrowed -LL | -LL | bad.join(); - | --- borrow later used here - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/span/unused-warning-point-at-signature.rs b/src/test/ui/span/unused-warning-point-at-signature.rs index 6a7071d49aed6..c074f03db469c 100644 --- a/src/test/ui/span/unused-warning-point-at-signature.rs +++ b/src/test/ui/span/unused-warning-point-at-signature.rs @@ -19,7 +19,7 @@ enum Enum { //~ WARN enum is never used D, } -struct Struct { //~ WARN struct is never used +struct Struct { //~ WARN struct is never constructed a: usize, b: usize, c: usize, diff --git a/src/test/ui/span/unused-warning-point-at-signature.stderr b/src/test/ui/span/unused-warning-point-at-signature.stderr index de234344d8409..8344853d6def5 100644 --- a/src/test/ui/span/unused-warning-point-at-signature.stderr +++ b/src/test/ui/span/unused-warning-point-at-signature.stderr @@ -11,10 +11,10 @@ LL | #![warn(unused)] | ^^^^^^ = note: #[warn(dead_code)] implied by #[warn(unused)] -warning: struct is never used: `Struct` +warning: struct is never constructed: `Struct` --> $DIR/unused-warning-point-at-signature.rs:22:1 | -LL | struct Struct { //~ WARN struct is never used +LL | struct Struct { //~ WARN struct is never constructed | ^^^^^^^^^^^^^ warning: function is never used: `func` diff --git a/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr index 73256b4fb17c9..60905367063a4 100644 --- a/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr +++ b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr @@ -1,27 +1,27 @@ -error[E0597]: `y` does not live long enough - --> $DIR/vec_refs_data_with_early_death.rs:29:12 +error[E0597]: `x` does not live long enough + --> $DIR/vec_refs_data_with_early_death.rs:27:12 | -LL | v.push(&y); +LL | v.push(&x); | ^^ borrowed value does not live long enough ... LL | } | - | | - | `y` dropped here while still borrowed + | `x` dropped here while still borrowed | borrow later used here, when `v` is dropped | = note: values in a scope are dropped in the opposite order they are defined -error[E0597]: `x` does not live long enough - --> $DIR/vec_refs_data_with_early_death.rs:27:12 +error[E0597]: `y` does not live long enough + --> $DIR/vec_refs_data_with_early_death.rs:29:12 | -LL | v.push(&x); +LL | v.push(&y); | ^^ borrowed value does not live long enough ... LL | } | - | | - | `x` dropped here while still borrowed + | `y` dropped here while still borrowed | borrow later used here, when `v` is dropped | = note: values in a scope are dropped in the opposite order they are defined diff --git a/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr b/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr index 215faf6c73c36..56897baeb4eff 100644 --- a/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr +++ b/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:16:5 | LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { - | --------------- help: consider changing this to be a mutable reference: `&mut &mut i32` + | --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32` LL | *t //~ ERROR | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -10,7 +10,7 @@ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:20:6 | LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { - | --------------- help: consider changing this to be a mutable reference: `&mut &mut i32` + | --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32` LL | {*t} //~ ERROR | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 83b2895e1d65d..bbce87a7c9adf 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -109,6 +109,7 @@ static TARGETS: &'static [&'static str] = &[ "x86_64-sun-solaris", "x86_64-unknown-cloudabi", "x86_64-unknown-freebsd", + "x86_64-unknown-hermit", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-musl", 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); } } diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 91e7399f1f492..2a716970ca7b9 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -25,6 +25,7 @@ const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("freebsd", "freebsd"), ("fuchsia", "fuchsia"), ("haiku", "haiku"), + ("hermit", "hermit"), ("ios", "ios"), ("l4re", "l4re"), ("linux", "linux"), diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index e72f90554d3c5..40917cc5db0d5 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -21,10 +21,11 @@ use std::fs::{read_dir, File}; use std::io::{Read, Write}; use std::path::Path; use std::path::PathBuf; +use std::cell::RefCell; use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}; -use rustdoc::html::markdown::{Markdown, PLAYGROUND}; +use rustdoc::html::markdown::{Markdown, IdMap, ErrorCodes, PLAYGROUND}; use rustc_serialize::json; enum OutputFormat { @@ -36,7 +37,7 @@ enum OutputFormat { impl OutputFormat { fn from(format: &str) -> OutputFormat { match &*format.to_lowercase() { - "html" => OutputFormat::HTML(HTMLFormatter), + "html" => OutputFormat::HTML(HTMLFormatter(RefCell::new(IdMap::new()))), "markdown" => OutputFormat::Markdown(MarkdownFormatter), s => OutputFormat::Unknown(s.to_owned()), } @@ -51,7 +52,7 @@ trait Formatter { fn footer(&self, output: &mut dyn Write) -> Result<(), Box>; } -struct HTMLFormatter; +struct HTMLFormatter(RefCell); struct MarkdownFormatter; impl Formatter for HTMLFormatter { @@ -100,7 +101,11 @@ impl Formatter for HTMLFormatter { // Description rendered as markdown. match info.description { - Some(ref desc) => write!(output, "{}", Markdown(desc, &[]))?, + Some(ref desc) => { + let mut id_map = self.0.borrow_mut(); + write!(output, "{}", + Markdown(desc, &[], RefCell::new(&mut id_map), ErrorCodes::Yes))? + }, None => write!(output, "

No description.

\n")?, }