From acdafa0fb13a8d1e1e76ce4bf4725104a0b749cb Mon Sep 17 00:00:00 2001 From: Markus Wein Date: Wed, 11 Jul 2018 13:21:10 +0200 Subject: [PATCH 01/56] Document From conversions for OsString and OsStr --- src/libstd/ffi/os_str.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index b1c6e7af693d0..9b91bd0d41efa 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -348,6 +348,11 @@ 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 +635,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 +646,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 +665,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 +687,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(); From b81ee0b370ebc1a9e15a5c6a68b2201ddbdaa36f Mon Sep 17 00:00:00 2001 From: Markus Wein Date: Wed, 11 Jul 2018 13:32:03 +0200 Subject: [PATCH 02/56] Document From conversions for CString and CStr --- src/libstd/ffi/c_str.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index b816f4b7850ef..14ace79581924 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -642,6 +642,11 @@ 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 +705,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 +725,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 +761,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 +783,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 +860,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") From 6c50ee5abc1f41aaf587f74cc317819ff8eca7d8 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 21 Jul 2018 17:55:34 -0700 Subject: [PATCH 03/56] dead-code lint: say "constructed" for structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a sequel to November 2017's #46103 / 1a9dc2e9. It had been reported (more than once—at least #19140, #44083, and #44565) that the "never used" language was confusing for enum variants that were "used" as match patterns, so the wording was changed to say never "constructed" specifically for enum variants. More recently, the same issue was raised for structs (#52325). It seems consistent to say "constructed" here, too, for the same reasons. We considered using more specific word "called" for unused functions and methods (while we declined to do this in #46103, the rationale given in the commit message doesn't actually make sense), but it turns out that Cargo's test suite expects the "never used" message, and maybe we don't care enough even to make a Cargo PR over such a petty and subjective wording change. This resolves #52325. --- src/librustc/middle/dead.rs | 6 +++++- src/test/compile-fail/lint-dead-code-1.rs | 4 ++-- src/test/compile-fail/lint-dead-code-3.rs | 2 +- src/test/ui/span/macro-span-replacement.rs | 2 +- src/test/ui/span/macro-span-replacement.stderr | 4 ++-- src/test/ui/span/unused-warning-point-at-signature.rs | 2 +- src/test/ui/span/unused-warning-point-at-signature.stderr | 4 ++-- 7 files changed, 14 insertions(+), 10 deletions(-) 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/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/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/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` From ed5edcb3186e87715143bbd53ab1dfa69771cbf9 Mon Sep 17 00:00:00 2001 From: Markus Wein Date: Mon, 23 Jul 2018 15:38:15 +0200 Subject: [PATCH 04/56] Seperate summaries from rest of the comment --- src/libstd/ffi/c_str.rs | 1 + src/libstd/ffi/os_str.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 14ace79581924..01558457f6c4c 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -643,6 +643,7 @@ 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 diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 9b91bd0d41efa..9e501a84e05ec 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -349,6 +349,7 @@ 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 From 7fb0a5204a3c35f69708b5691a93e1aa58dd025c Mon Sep 17 00:00:00 2001 From: Thomas Gideon Date: Thu, 26 Jul 2018 12:30:04 -0400 Subject: [PATCH 05/56] Update clippy to latest master --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 922bf1d2acf7b779fddd1bc05415d4d9052f9ec2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 27 Jul 2018 14:01:42 +0300 Subject: [PATCH 06/56] Clarify thread::park semantics --- src/libstd/thread/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 90f054186d161..6f3945301e439 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(); /// From 5f87f78b148c1825b92514580f47866c5ae67fbb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 27 Jul 2018 14:44:20 +0300 Subject: [PATCH 07/56] Fix ws --- src/libstd/thread/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 6f3945301e439..e9bd0332d987b 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -731,7 +731,7 @@ 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. Because the token is initially absent, [`unpark`] +/// 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 From 173c33019e0daf982d64bc6658f4aca5b0dac419 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 28 Jul 2018 21:18:34 +0100 Subject: [PATCH 08/56] Don't make "fake" match variables mutable --- src/librustc_mir/build/matches/mod.rs | 10 ++++++++-- src/test/ui/nll/extra-unused-mut.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) 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/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)); } From b6d3143488bd91017df4d60a7229745086aa5f5f Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 29 Jul 2018 15:43:54 +0900 Subject: [PATCH 09/56] pretty print for std::collections::vecdeque --- src/etc/debugger_pretty_printers_common.py | 33 ++++++++++++++++++++++ src/etc/gdb_rust_pretty_printing.py | 23 +++++++++++++++ 2 files changed, 56 insertions(+) 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..410301ee6f16d 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,26 @@ 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 From ea25cf1cc6da92c85e7c17753e6b1defd8effee9 Mon Sep 17 00:00:00 2001 From: Josef Reinhard Brandl Date: Sun, 29 Jul 2018 10:31:20 +0200 Subject: [PATCH 10/56] Fix From --- src/libcore/task/wake.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 } } } From 9ccd7eef1eeda8d207f62dae0c32d35cad7fa826 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 29 Jul 2018 12:20:06 +0100 Subject: [PATCH 11/56] Fix -Wpessimizing-move warnings in rustllvm/PassWrapper --- src/rustllvm/PassWrapper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 85fbc4bf378a5..6501b3873e29c 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -1092,7 +1092,7 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true); if (!MOrErr) - return std::move(MOrErr); + return MOrErr; // The rest of this closure is a workaround for // https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports @@ -1110,14 +1110,14 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { // shouldn't be a perf hit. if (Error Err = (*MOrErr)->materializeMetadata()) { Expected> Ret(std::move(Err)); - return std::move(Ret); + return Ret; } auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections"); if (WasmCustomSections) WasmCustomSections->eraseFromParent(); - return std::move(MOrErr); + return MOrErr; }; FunctionImporter Importer(Data->Index, Loader); Expected Result = Importer.importFunctions(Mod, ImportList); From 9845ee08867e3527b9e57c86b08d38d5a0db255a Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 29 Jul 2018 23:45:32 +0900 Subject: [PATCH 12/56] fix coding style --- src/etc/gdb_rust_pretty_printing.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 410301ee6f16d..b7de42a938417 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -286,12 +286,14 @@ 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) + (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) + (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()) From 2b25ee0764660f33e103babee1a2d5040eee4491 Mon Sep 17 00:00:00 2001 From: toidiu Date: Sun, 29 Jul 2018 21:12:58 -0400 Subject: [PATCH 13/56] update comment --- src/libsyntax/feature_gate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 087fec097191b..a32f3724cd455 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` From 2994b27e4033c2a0b77ab90f5a896ce09a122992 Mon Sep 17 00:00:00 2001 From: kennytm Date: Mon, 30 Jul 2018 12:06:22 +0800 Subject: [PATCH 14/56] Add timeout to use of `curl` in bootstrap.py. --- src/bootstrap/bootstrap.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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) From c57deb923e56e04634b7e4b3fdc0f84ea0d41ed4 Mon Sep 17 00:00:00 2001 From: Donato Sciarra Date: Sun, 29 Jul 2018 19:50:30 +0200 Subject: [PATCH 15/56] Remove references to AUTHORS.txt file Refer instead to thanks page. --- COPYRIGHT | 4 ++-- src/doc/man/rustdoc.1 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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/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. From 4b466ee4f94d7c17b0634495dc959e6f5dd4cc5a Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 30 Jul 2018 11:20:11 +0200 Subject: [PATCH 16/56] Introduce the declare_tool_lint macro --- src/librustc/lint/mod.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c1b205620892..6940826ba8653 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 { From f8d1dc88a7994d25e481d0272b555b22f9026afb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 30 Jul 2018 12:52:01 +0200 Subject: [PATCH 17/56] improve --stage documentation --- src/bootstrap/flags.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 6a013053e580c..23a02c86683b1 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"); From aa7d7d0c2b7c85ae860b9eba61d59005b0d049b0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 30 Jul 2018 12:57:20 +0200 Subject: [PATCH 18/56] improve test stage documentation --- src/bootstrap/flags.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 23a02c86683b1..60b4d65f44401 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -261,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.", @@ -293,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. From e50f4eeaadcea0c1dcc28e15dfe91dd38393a6da Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Mon, 30 Jul 2018 15:50:51 +0200 Subject: [PATCH 19/56] Add targets for HermitCore (https://hermitcore.org) to the Rust compiler and port libstd to it. As a start, the port uses the simplest possible configuration (no jemalloc, abort on panic) and makes use of existing Unix-specific code wherever possible. It adds targets for x86_64 (current main HermitCore platform) and aarch64 (HermitCore platform under development). Together with the patches to "liblibc" and "llvm", this enables HermitCore applications to be written in Rust. --- src/liballoc_system/lib.rs | 4 +- .../spec/aarch64_unknown_hermit.rs | 32 ++ src/librustc_target/spec/hermit_base.rs | 37 ++ src/librustc_target/spec/mod.rs | 4 + .../spec/x86_64_unknown_hermit.rs | 33 ++ src/libstd/os/hermit/fs.rs | 389 ++++++++++++++++++ src/libstd/os/hermit/mod.rs | 16 + src/libstd/os/hermit/raw.rs | 27 ++ src/libstd/os/mod.rs | 1 + src/libstd/sys/unix/args.rs | 3 +- src/libstd/sys/unix/condvar.rs | 10 +- src/libstd/sys/unix/env.rs | 11 + src/libstd/sys/unix/fast_thread_local.rs | 2 +- src/libstd/sys/unix/fs.rs | 10 +- src/libstd/sys/unix/mod.rs | 1 + src/libstd/sys/unix/os.rs | 3 +- src/libstd/sys/unix/thread.rs | 3 +- src/libstd/sys/unix/time.rs | 4 +- src/tools/build-manifest/src/main.rs | 1 + src/tools/compiletest/src/util.rs | 1 + 20 files changed, 576 insertions(+), 16 deletions(-) create mode 100644 src/librustc_target/spec/aarch64_unknown_hermit.rs create mode 100644 src/librustc_target/spec/hermit_base.rs create mode 100644 src/librustc_target/spec/x86_64_unknown_hermit.rs create mode 100644 src/libstd/os/hermit/fs.rs create mode 100644 src/libstd/os/hermit/mod.rs create mode 100644 src/libstd/os/hermit/raw.rs diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 64348e05de7db..39768301b9d2c 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -174,7 +174,7 @@ 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 +197,7 @@ 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/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/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..b3ac9e5c140f4 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,7 @@ 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 +115,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/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/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"), From 57c77426ae6b4f9380a85a2aed80dc0900e7b93c Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 30 Jul 2018 11:29:23 +0200 Subject: [PATCH 20/56] Check if the lint_name is from a tool and if the tool_lint exists --- src/librustc/lint/context.rs | 64 ++++++++++++++++++++++++------------ src/librustc/lint/levels.rs | 36 +++++++++++++++----- 2 files changed, 71 insertions(+), 29 deletions(-) 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..6a29b8c3e3e6c 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,19 @@ 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)); + } + } + //FIXME: if Tool(None) is returned than the lint either does not exist in + //the lint tool or the code doesn't get compiled with the lint tool and + //therefore the lint cannot exist. + } + _ if !self.warn_about_weird_lints => {} CheckLintNameResult::Warning(msg, renamed) => { @@ -298,7 +318,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( From d4ff949953141877743ee95123a492c4e48c3809 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 30 Jul 2018 11:30:07 +0200 Subject: [PATCH 21/56] Add a test for the declare_tool_lint macro --- .../ui-fulldeps/auxiliary/lint_tool_test.rs | 48 +++++++++++++++++++ src/test/ui-fulldeps/lint_tool_test.rs | 24 ++++++++++ src/test/ui-fulldeps/lint_tool_test.stderr | 8 ++++ 3 files changed, 80 insertions(+) create mode 100644 src/test/ui-fulldeps/auxiliary/lint_tool_test.rs create mode 100644 src/test/ui-fulldeps/lint_tool_test.rs create mode 100644 src/test/ui-fulldeps/lint_tool_test.stderr 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 + From 7b9388b7b5fcdbb2f7e7178dc0a533e3284184c5 Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Mon, 30 Jul 2018 16:07:00 +0200 Subject: [PATCH 22/56] Explain that the tool is responsible for unknown tool_lints --- src/librustc/lint/levels.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 6a29b8c3e3e6c..483e2ea8a96cd 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -273,9 +273,10 @@ impl<'a> LintLevelsBuilder<'a> { specs.insert(*id, (level, src)); } } - //FIXME: if Tool(None) is returned than the lint either does not exist in - //the lint tool or the code doesn't get compiled with the lint tool and - //therefore the lint cannot exist. + // 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 => {} From ca762ba9547649f57e2d8a3e56b83d0a6298fbb2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 Jul 2018 14:53:15 -0700 Subject: [PATCH 23/56] rustc: Disallow machine applicability in foreign macros Recent changes to lints disallowed lints from being emitted against code located in foreign macros, except for future-incompatible lints. For a future incompatible lint, however, the automatic suggestions may not be applicable! This commit updates this code path to force all applicability suggestions made to foreign macros to never be `MachineApplicable`. This should avoid rustfix actually attempting fixing these suggestions, causing non-compiling code to be produced. Closes rust-lang/cargo#5799 --- src/librustc/lint/mod.rs | 30 +++---- src/librustc_errors/diagnostic_builder.rs | 83 ++++++++++++++----- .../suggestions-not-always-applicable.rs | 22 +++++ .../suggestions-not-always-applicable.fixed | 37 +++++++++ .../suggestions-not-always-applicable.rs | 37 +++++++++ .../suggestions-not-always-applicable.stderr | 24 ++++++ src/tools/compiletest/src/header.rs | 11 +++ src/tools/compiletest/src/runtest.rs | 8 +- 8 files changed, 217 insertions(+), 35 deletions(-) create mode 100644 src/test/ui-fulldeps/rust-2018/auxiliary/suggestions-not-always-applicable.rs create mode 100644 src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.fixed create mode 100644 src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.rs create mode 100644 src/test/ui-fulldeps/rust-2018/suggestions-not-always-applicable.stderr diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c1b205620892..96b7d865dc8ba 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -575,7 +575,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session, // Check for future incompatibility lints and issue a stronger warning. let lints = sess.lint_store.borrow(); let lint_id = LintId::of(lint); - if let Some(future_incompatible) = lints.future_incompatible(lint_id) { + let future_incompatible = lints.future_incompatible(lint_id); + if let Some(future_incompatible) = future_incompatible { const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ it will become a hard error"; @@ -593,20 +594,21 @@ pub fn struct_lint_level<'a>(sess: &'a Session, future_incompatible.reference); err.warn(&explanation); err.note(&citation); + } - // If this lint is *not* a future incompatibility warning then we want to be - // sure to not be too noisy in some situations. If this code originates in a - // foreign macro, aka something that this crate did not itself author, then - // it's likely that there's nothing this crate can do about it. We probably - // want to skip the lint entirely. - // - // For some lints though (like unreachable code) there's clear actionable - // items to take care of (delete the macro invocation). As a result we have - // a few lints we whitelist here for allowing a lint even though it's in a - // foreign macro invocation. - } else if !lint.report_in_external_macro { - if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { - err.cancel(); + // If this code originates in a foreign macro, aka something that this crate + // did not itself author, then it's likely that there's nothing this crate + // can do about it. We probably want to skip the lint entirely. + if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { + // Any suggestions made here are likely to be incorrect, so anything we + // emit shouldn't be automatically fixed by rustfix. + err.allow_suggestions(false); + + // If this is a future incompatible lint it'll become a hard error, so + // we have to emit *something*. Also allow lints to whitelist themselves + // on a case-by-case basis for emission in a foreign macro. + if future_incompatible.is_none() && !lint.report_in_external_macro { + err.cancel() } } diff --git a/src/librustc_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/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/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); } } From d9331749f152b60ea376016fa387ed9eea5e8e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 30 Jul 2018 17:41:19 +0200 Subject: [PATCH 24/56] releases.md: fix 2 typos --- RELEASES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index b983851f88198..0368c5414e16f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -190,7 +190,7 @@ Version 1.27.0 (2018-06-21) Language -------- - [Removed 'proc' from the reserved keywords list.][49699] This allows `proc` to - be used as an identifer. + be used as an identifier. - [The dyn syntax is now available.][49968] This syntax is equivalent to the bare `Trait` syntax, and should make it clearer when being used in tandem with `impl Trait`. Since it is equivalent to the following syntax: @@ -4795,7 +4795,7 @@ Language -------- * Patterns with `ref mut` now correctly invoke [`DerefMut`] when - matching against dereferencable values. + matching against dereferenceable values. Libraries --------- From b6b025bdafe150103b443b36e2ed4c4e164814e8 Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Mon, 30 Jul 2018 17:05:30 +0100 Subject: [PATCH 25/56] Fix wrong issue number in the test name --- src/test/ui/nll/{issue-52133.rs => issue-52113.rs} | 0 src/test/ui/nll/{issue-52133.stderr => issue-52113.stderr} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/test/ui/nll/{issue-52133.rs => issue-52113.rs} (100%) rename src/test/ui/nll/{issue-52133.stderr => issue-52113.stderr} (94%) 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... From d8b3c830fbcdd14d085209a8dcc3399151f3286a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 26 Jul 2018 14:54:41 +0200 Subject: [PATCH 26/56] Remove the unstable std_unicode crate, deprecated since 1.27 Its former contents are now in libcore. --- src/Cargo.lock | 9 --------- src/bootstrap/compile.rs | 1 - src/bootstrap/dist.rs | 1 - src/bootstrap/doc.rs | 2 +- src/libstd/Cargo.toml | 1 - src/libstd_unicode/Cargo.toml | 14 -------------- src/libstd_unicode/lib.rs | 36 ----------------------------------- 7 files changed, 1 insertion(+), 63 deletions(-) delete mode 100644 src/libstd_unicode/Cargo.toml delete mode 100644 src/libstd_unicode/lib.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 89daa8e09c7d1..2b0833b096629 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2615,18 +2615,9 @@ dependencies = [ "rustc_lsan 0.0.0", "rustc_msan 0.0.0", "rustc_tsan 0.0.0", - "std_unicode 0.0.0", "unwind 0.0.0", ] -[[package]] -name = "std_unicode" -version = "0.0.0" -dependencies = [ - "compiler_builtins 0.0.0", - "core 0.0.0", -] - [[package]] name = "string_cache" version = "0.7.3" diff --git a/src/bootstrap/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/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_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::*; From 4ca77f702f813332defe15a0aa73707628bf592e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 26 Jul 2018 15:03:49 +0200 Subject: [PATCH 27/56] Remove unstable and deprecated APIs --- src/libcore/char/decode.rs | 127 --------------- src/libcore/char/mod.rs | 5 - src/libcore/ptr.rs | 80 ---------- src/libcore/tests/char.rs | 51 ------ src/libstd/ascii.rs | 310 ------------------------------------- src/libstd/io/buffered.rs | 46 ------ src/libstd/io/cursor.rs | 20 --- src/libstd/io/mod.rs | 148 ------------------ 8 files changed, 787 deletions(-) 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/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/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/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/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. /// From cbbcecbee065d4031618615365b0d234fe5b112b Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 30 Jul 2018 09:13:30 -0700 Subject: [PATCH 28/56] Implement Unpin for FutureObj and LocalFutureObj --- src/libcore/future/future_obj.rs | 3 +++ 1 file changed, 3 insertions(+) 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> { From 9169934e27c955787e94186364dcc6fcb7455e4d Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 30 Jul 2018 14:54:33 +0200 Subject: [PATCH 29/56] Use Vec::extend in SmallVec::extend when applicable --- src/librustc_data_structures/small_vec.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs index 83eb54fade177..bfa580eb18660 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!() + } } } } From d5f1f70a8e8d3f54230fe07eb0a79002161b2788 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 30 Jul 2018 00:07:39 +0200 Subject: [PATCH 30/56] Fix Alias intra doc ICE --- src/librustdoc/clean/mod.rs | 40 +++++++++---------- src/librustdoc/visit_ast.rs | 4 +- src/test/rustdoc-ui/intra-doc-alias-ice.rs | 16 ++++++++ .../rustdoc-ui/intra-doc-alias-ice.stderr | 13 ++++++ 4 files changed, 50 insertions(+), 23 deletions(-) create mode 100644 src/test/rustdoc-ui/intra-doc-alias-ice.rs create mode 100644 src/test/rustdoc-ui/intra-doc-alias-ice.stderr diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c050e30fea050..e019b26dd1dd9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1197,7 +1197,8 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option })?; match ty.def { Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => { - let item = cx.tcx.inherent_impls(did).iter() + let item = cx.tcx.inherent_impls(did) + .iter() .flat_map(|imp| cx.tcx.associated_items(*imp)) .find(|item| item.ident.name == item_name); if let Some(item) = item { @@ -1208,26 +1209,23 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option }; Ok((ty.def, Some(format!("{}.{}", out, item_name)))) } else { - let is_enum = match ty.def { - Def::Enum(_) => true, - _ => false, - }; - let elem = if is_enum { - cx.tcx.adt_def(did).all_fields().find(|item| item.ident.name == item_name) - } else { - cx.tcx.adt_def(did) - .non_enum_variant() - .fields - .iter() - .find(|item| item.ident.name == item_name) - }; - if let Some(item) = elem { - Ok((ty.def, - Some(format!("{}.{}", - if is_enum { "variant" } else { "structfield" }, - item.ident)))) - } else { - Err(()) + match cx.tcx.type_of(did).sty { + ty::TyAdt(def, _) => { + if let Some(item) = def.all_fields() + .find(|item| item.ident.name == item_name) { + Ok((ty.def, + Some(format!("{}.{}", + if def.is_enum() { + "variant" + } else { + "structfield" + }, + item.ident)))) + } else { + Err(()) + } + } + _ => Err(()), } } } 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/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 `/]` + From 1ea2765918d1212a07e1359537470c477d82a681 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 30 Jul 2018 13:08:56 -0700 Subject: [PATCH 31/56] run-pass/const-endianness: negate before to_le() `const LE_I128` needs parentheses to negate the value *before* calling `to_le()`, otherwise it doesn't match the operations performed in the black-boxed part of the test. This only makes a tangible difference on big-endian targets. --- src/test/run-pass/const-endianess.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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()); } From c883edfbc6b669bea4264f5a79e2bee0e5766c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Jul 2018 15:41:39 -0700 Subject: [PATCH 32/56] Include lifetime in mutability suggestion in NLL messages --- .../borrow_check/mutability_errors.rs | 54 +++++++++++++++---- .../ui/did_you_mean/issue-39544.nll.stderr | 6 +-- ...orrow-overloaded-auto-deref-mut.nll.stderr | 4 +- ...wck-borrow-overloaded-deref-mut.nll.stderr | 4 +- src/test/ui/span/mut-arg-hint.nll.stderr | 2 +- ...unds-inconsistent-copy-reborrow.nll.stderr | 4 +- 6 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 571a1188d49ca..310ddb5e78ad2 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/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/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/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/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 From 4ad4ad02ebf6920aee2a15a6b18aadd877b3535f Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Tue, 31 Jul 2018 09:49:10 +0200 Subject: [PATCH 33/56] Fix coding style. --- src/liballoc_system/lib.rs | 10 ++++++++-- src/libstd/sys/unix/condvar.rs | 5 ++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 39768301b9d2c..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 = "hermit", 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 = "hermit", 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/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index b3ac9e5c140f4..2007da7b1f6be 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -85,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", target_os = "hermit")))] + #[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; From ca5264826430cb5dab7a3c61394e8e795bbbd851 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Tue, 31 Jul 2018 14:11:04 +0200 Subject: [PATCH 34/56] Benchmarks for SmallVec --- src/librustc_data_structures/small_vec.rs | 116 ++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs index bfa580eb18660..2398a6f99259c 100644 --- a/src/librustc_data_structures/small_vec.rs +++ b/src/librustc_data_structures/small_vec.rs @@ -225,3 +225,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); + }) + } +} From e8c29959cde82359283ba4b2e705f7c691538414 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 31 Jul 2018 14:30:46 +0200 Subject: [PATCH 35/56] Sort NLL error diagnostics by span in an attempt to make them match source order (and thus, hopefully, more closely match user expectation). --- src/librustc_mir/borrow_check/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4ba96f643b0cc..3b767bfdd40ec 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -331,6 +331,10 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } if mbcx.errors_buffer.len() > 0 { + mbcx.errors_buffer.sort_by(|diag1, diag2| { + diag1.span.primary_span().cmp(&diag2.span.primary_span()) + }); + if tcx.migrate_borrowck() { match tcx.borrowck(def_id).signalled_any_error { SignalledError::NoErrorsSeen => { From 6787e25c29c8282bcc9c61e887baec83e41a9834 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 31 Jul 2018 14:35:43 +0200 Subject: [PATCH 36/56] Blindly update the `#[rustc_region]` tests which got touched by the NLL diagnostic change. --- .../escape-argument-callee.stderr | 18 ++-- ...pagate-approximated-fail-no-postdom.stderr | 22 ++--- ...er-to-static-comparing-against-free.stderr | 22 ++--- ...oximated-shorter-to-static-no-bound.stderr | 26 +++--- ...mated-shorter-to-static-wrong-bound.stderr | 26 +++--- ...ail-to-approximate-longer-no-bounds.stderr | 22 ++--- ...-to-approximate-longer-wrong-bounds.stderr | 22 ++--- .../propagate-from-trait-match.stderr | 30 +++---- .../return-wrong-bound-region.stderr | 18 ++-- .../projection-no-regions-closure.stderr | 32 +++---- .../projection-one-region-closure.stderr | 84 +++++++++---------- ...tion-one-region-trait-bound-closure.stderr | 36 ++++---- ...tion-two-region-trait-bound-closure.stderr | 60 ++++++------- ...ram-closure-approximate-lower-bound.stderr | 16 ++-- ...m-closure-outlives-from-return-type.stderr | 16 ++-- ...-closure-outlives-from-where-clause.stderr | 58 ++++++------- 16 files changed, 254 insertions(+), 254 deletions(-) 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/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 | From 26776858cfaf2a46643ea0655fc0a2f4bf362df9 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 31 Jul 2018 14:36:50 +0200 Subject: [PATCH 37/56] Update tests that use `-Z borrowck=compare` or `#[feature(nll)]` to accmmodate diagnostic change. --- src/test/ui/borrowck/issue-41962.stderr | 34 +++++++++---------- .../ui/borrowck/two-phase-multi-mut.stderr | 16 ++++----- 2 files changed, 25 insertions(+), 25 deletions(-) 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/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 From faf841a9f61f60240e6c5353c58abcbf38b21237 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 31 Jul 2018 14:51:36 +0200 Subject: [PATCH 38/56] Update the `.nll.stderr` files under new sorted-by-span scheme. --- src/test/ui/hygiene/fields-move.nll.stderr | 18 +++++++------- src/test/ui/issue-27592.nll.stderr | 16 ++++++------- .../span/dropck_arr_cycle_checked.nll.stderr | 16 ++++++------- .../span/dropck_vec_cycle_checked.nll.stderr | 16 ++++++------- src/test/ui/span/range-2.nll.stderr | 16 ++++++------- .../regions-escape-loop-via-vec.nll.stderr | 22 ++++++++--------- ...d-is-not-static-ensures-scoping.nll.stderr | 24 +++++++++---------- .../vec_refs_data_with_early_death.nll.stderr | 16 ++++++------- 8 files changed, 72 insertions(+), 72 deletions(-) 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-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/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/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/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 From 830ac8c87fb76c44c8ed42d4111d0b05b7f6caad Mon Sep 17 00:00:00 2001 From: pravic Date: Tue, 31 Jul 2018 16:28:50 +0300 Subject: [PATCH 39/56] Fix a typo in unsize.rs RfC -> RFC --- src/libcore/ops/unsize.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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` From a5a3f765eb36aee69bfdaba1f82760973b63c780 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 31 Jul 2018 17:22:12 +0200 Subject: [PATCH 40/56] NLL: On "cannot move out of type" error, print original source before rewrite. * Arguably this change is sometimes injecting noise into the output (namely in the cases where the suggested rewrite is inline with the suggestion and we end up highlighting the original source code). I would not be opposed to something more aggressive/dynamic, like revising the suggestion code to automatically print the original source when necessary (e.g. when the error does not have a span that includes the span of the suggestion). * Also, as another note on this change: The doc comment for `Diagnostic::span_suggestion` says: /// The message /// /// * should not end in any punctuation (a `:` is added automatically) /// * should not be a question /// * should not contain any parts like "the following", "as shown" but the `:` is *not* added when the emitted line appears out-of-line relative to the suggestion. I find that to be an unfortunate UI experience. ---- As a drive-by fix, also changed code to combine multiple suggestions for a pattern into a single multipart suggestion (which vastly improves user experience IMO). ---- Includes the updates to expected NLL diagnostics. --- src/librustc_mir/borrow_check/move_errors.rs | 17 +++++++---- .../borrowck-move-error-with-note.nll.stderr | 10 ++++--- .../borrowck-move-out-of-vec-tail.nll.stderr | 13 ++++++--- .../borrowck-vec-pattern-nesting.nll.stderr | 27 +++++++++-------- src/test/ui/borrowck/issue-51415.nll.stderr | 1 + .../overlapping_spans.nll.stderr | 5 +++- src/test/ui/issue-12567.nll.stderr | 28 +++++++++++++----- src/test/ui/nll/move-errors.stderr | 29 +++++++++++++------ 8 files changed, 86 insertions(+), 44 deletions(-) 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/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-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/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/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/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 From 0af5a6be0531a1ad038bd150239847cb4acc5026 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 21 Jul 2018 16:12:16 -0600 Subject: [PATCH 41/56] Pull out nightly checking to edges Parsing the code block's LangString (```foo) previously checked itself to see if we were on nightly; that isn't the right place to do so. Move that check slightly outwards to better abstract LangString. (This is also an optimization as we avoid the costly environment variable load of RUSTC_BOOTSTRAP). --- src/librustdoc/html/markdown.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 8d85adfb3d0ff..d01745f4a46fa 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -129,12 +129,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: bool, } impl<'a, I: Iterator>> CodeBlocks<'a, I> { fn new(iter: I) -> Self { CodeBlocks { inner: iter, + check_error_codes: UnstableFeatures::from_environment().is_nightly_build(), } } } @@ -147,7 +149,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))); } @@ -471,6 +473,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp sess: Option<&session::Session>) { tests.set_position(position); + let is_nightly = UnstableFeatures::from_environment().is_nightly_build(); let mut parser = Parser::new(doc); let mut prev_offset = 0; let mut nb_lines = 0; @@ -481,7 +484,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, is_nightly) }; if !block_info.rust { continue @@ -569,14 +572,10 @@ impl LangString { } } - fn parse(string: &str) -> LangString { + fn parse(string: &str, allow_error_code_check: bool) -> LangString { 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| @@ -842,7 +841,7 @@ mod tests { 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, true), LangString { should_panic, no_run, ignore, From ad40e4517f1969e60eac9fcac2affa75bb2e715e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 21 Jul 2018 16:30:02 -0600 Subject: [PATCH 42/56] Provide warnings for invalid code blocks in markdown files Previously we would only warn on Rust code but we can also do so when testing markdown (the diag::Handler is available). --- src/librustdoc/html/markdown.rs | 8 +++----- src/librustdoc/markdown.rs | 2 +- src/librustdoc/test.rs | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index d01745f4a46fa..0774ce34718fb 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -27,7 +27,6 @@ #![allow(non_camel_case_types)] -use rustc::session; use std::cell::RefCell; use std::collections::{HashMap, VecDeque}; use std::default::Default; @@ -37,6 +36,7 @@ use std::ops::Range; use std::str; use syntax::feature_gate::UnstableFeatures; use syntax::codemap::Span; +use errors; use html::render::derive_id; use html::toc::TocBuilder; @@ -470,7 +470,7 @@ 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>) { + handler: &errors::Handler) { tests.set_position(position); let is_nightly = UnstableFeatures::from_environment().is_nightly_build(); @@ -521,9 +521,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp line, filename, block_info.allow_fail); prev_offset = offset; } else { - if let Some(ref sess) = sess { - sess.span_warn(position, "invalid start of a new code block"); - } + handler.span_warn(position, "invalid start of a new code block"); break; } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 36a8fc94dba2f..82489e9fbdbf4 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -156,7 +156,7 @@ 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); + find_testable_code(&input_str, &mut collector, DUMMY_SP, diag); 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..a6667e1772858 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -692,7 +692,7 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { markdown::find_testable_code(&doc, self.collector, attrs.span.unwrap_or(DUMMY_SP), - Some(self.sess)); + self.sess.diagnostic()); } nested(self); From de5cebdba58770ab555476bc4cdf23d89bd0c3ea Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 21 Jul 2018 16:54:30 -0600 Subject: [PATCH 43/56] Provide test configuration through struct This is far more sound than passing many different arguments of the same type. --- src/librustdoc/html/markdown.rs | 25 ++++++++++--------------- src/librustdoc/test.rs | 24 +++++++++++------------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 0774ce34718fb..c73e6d4b3554f 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -513,12 +513,7 @@ 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 { handler.span_warn(position, "invalid start of a new code block"); @@ -543,16 +538,16 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp } #[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 { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index a6667e1772858..2885ce615d246 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, LangString}; #[derive(Clone, Default)] pub struct TestOptions { @@ -533,10 +533,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 +549,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 +570,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 +602,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 { From 03e34f8f816c2594238585bdca39716f4050cb69 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 21 Jul 2018 17:15:25 -0600 Subject: [PATCH 44/56] Remove dependency on error handling from find_testable_code --- src/librustdoc/html/markdown.rs | 21 +++++++++++++-------- src/librustdoc/markdown.rs | 6 +++++- src/librustdoc/test.rs | 10 ++++++---- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c73e6d4b3554f..54fd041fb004b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -34,10 +34,8 @@ 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 errors; +use syntax::feature_gate::UnstableFeatures; use html::render::derive_id; use html::toc::TocBuilder; use html::highlight; @@ -469,10 +467,17 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { } } -pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span, - handler: &errors::Handler) { - 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 +) -> Result<(), TestableCodeError> { let is_nightly = UnstableFeatures::from_environment().is_nightly_build(); let mut parser = Parser::new(doc); let mut prev_offset = 0; @@ -516,8 +521,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp tests.add_test(text, block_info, line); prev_offset = offset; } else { - handler.span_warn(position, "invalid start of a new code block"); - break; + return Err(TestableCodeError(())); } } Event::Start(Tag::Header(level)) => { @@ -535,6 +539,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp _ => {} } } + Ok(()) } #[derive(Eq, PartialEq, Clone, Debug)] diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 82489e9fbdbf4..4d1eae1470f04 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -156,7 +156,11 @@ 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, diag); + collector.set_position(DUMMY_SP); + let res = find_testable_code(&input_str, &mut collector); + 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 2885ce615d246..9723b45280089 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -687,10 +687,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), - self.sess.diagnostic()); + self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP)); + let res = markdown::find_testable_code(&doc, self.collector); + if let Err(err) = res { + self.sess.diagnostic().span_warn(attrs.span.unwrap_or(DUMMY_SP), + &err.to_string()); + } } nested(self); From 01d95558e62f40f958618292afd4abae2fb3c236 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 22 Jul 2018 11:10:19 -0600 Subject: [PATCH 45/56] Further extract error code switch Removes dependency on UnstableFeatures from markdown rendering --- src/librustdoc/externalfiles.rs | 8 ++- src/librustdoc/html/markdown.rs | 81 ++++++++++++++++--------- src/librustdoc/html/render.rs | 40 ++++++------ src/librustdoc/markdown.rs | 11 ++-- src/librustdoc/test.rs | 10 +-- src/tools/error_index_generator/main.rs | 4 +- 6 files changed, 96 insertions(+), 58 deletions(-) diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 10b6c9850ae77..67502ab8e1531 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -12,7 +12,8 @@ use std::fs; use std::path::Path; use std::str; use errors; -use html::markdown::Markdown; +use syntax::feature_gate::UnstableFeatures; +use html::markdown::{ErrorCodes, Markdown}; #[derive(Clone)] pub struct ExternalHtml { @@ -31,6 +32,7 @@ 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) -> 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 +40,7 @@ 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, &[], codes)))) ) .and_then(|(ih, bc)| load_external_files(after_content, diag) @@ -46,7 +48,7 @@ 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, &[], codes)))) ) .map(|(ih, bc, ac)| ExternalHtml { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 54fd041fb004b..f65211f97be58 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -18,10 +18,10 @@ //! ``` //! #![feature(rustc_private)] //! -//! use rustdoc::html::markdown::Markdown; +//! use rustdoc::html::markdown::{Markdown, ErrorCodes}; //! //! let s = "My *markdown* _text_"; -//! let html = format!("{}", Markdown(s, &[])); +//! let html = format!("{}", Markdown(s, &[], ErrorCodes::Yes)); //! // ... something using html //! ``` @@ -35,7 +35,6 @@ use std::borrow::Cow; use std::ops::Range; use std::str; -use syntax::feature_gate::UnstableFeatures; use html::render::derive_id; use html::toc::TocBuilder; use html::highlight; @@ -48,15 +47,37 @@ 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 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 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 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. @@ -127,14 +148,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: bool, + 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: UnstableFeatures::from_environment().is_nightly_build(), + check_error_codes: error_codes, } } } @@ -476,9 +497,8 @@ impl fmt::Display for TestableCodeError { } pub fn find_testable_code( - doc: &str, tests: &mut test::Collector + doc: &str, tests: &mut test::Collector, error_codes: ErrorCodes, ) -> Result<(), TestableCodeError> { - let is_nightly = UnstableFeatures::from_environment().is_nightly_build(); let mut parser = Parser::new(doc); let mut prev_offset = 0; let mut nb_lines = 0; @@ -489,7 +509,7 @@ pub fn find_testable_code( let block_info = if s.is_empty() { LangString::all_false() } else { - LangString::parse(&*s, is_nightly) + LangString::parse(&*s, error_codes) }; if !block_info.rust { continue @@ -570,7 +590,8 @@ impl LangString { } } - fn parse(string: &str, allow_error_code_check: bool) -> 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(); @@ -620,7 +641,7 @@ 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, codes) = *self; // This is actually common enough to special-case if md.is_empty() { return Ok(()) } @@ -645,7 +666,7 @@ impl<'a> fmt::Display for Markdown<'a> { CodeBlocks::new( LinkReplacer::new( HeadingLinks::new(p, None), - links)))); + links), codes))); fmt.write_str(&s) } @@ -653,7 +674,7 @@ 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, codes) = *self; let mut opts = Options::empty(); opts.insert(OPTION_ENABLE_TABLES); @@ -665,8 +686,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)); + let p = CodeBlocks::new(p, codes); + let p = Footnotes::new(p); + html::push_html(&mut s, p); + } write!(fmt, "", toc.into_toc())?; @@ -676,7 +701,7 @@ 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, codes) = *self; // This is actually common enough to special-case if md.is_empty() { return Ok(()) } @@ -694,8 +719,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); + let p = CodeBlocks::new(p, codes); + let p = Footnotes::new(p); + html::push_html(&mut s, p); fmt.write_str(&s) } @@ -830,7 +857,7 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option>)> { #[cfg(test)] mod tests { - use super::{LangString, Markdown, MarkdownHtml}; + use super::{ErrorCodes, LangString, Markdown, MarkdownHtml}; use super::plain_summary_line; use html::render::reset_ids; @@ -839,7 +866,7 @@ mod tests { 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, true), LangString { + assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString { should_panic, no_run, ignore, @@ -878,14 +905,14 @@ mod tests { #[test] fn issue_17736() { let markdown = "# title"; - Markdown(markdown, &[]).to_string(); + Markdown(markdown, &[], ErrorCodes::Yes).to_string(); reset_ids(true); } #[test] fn test_header() { fn t(input: &str, expect: &str) { - let output = Markdown(input, &[]).to_string(); + let output = Markdown(input, &[], ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); reset_ids(true); } @@ -907,7 +934,7 @@ mod tests { #[test] fn test_header_ids_multiple_blocks() { fn t(input: &str, expect: &str) { - let output = Markdown(input, &[]).to_string(); + let output = Markdown(input, &[], ErrorCodes::Yes).to_string(); assert_eq!(output, expect, "original: {}", input); } @@ -948,7 +975,7 @@ mod tests { #[test] fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { - let output = MarkdownHtml(input).to_string(); + let output = MarkdownHtml(input, 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..b9b058cb54826 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -56,6 +56,7 @@ 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 +73,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}; use html::{highlight, layout}; use minifier; @@ -99,6 +100,7 @@ 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, pub shared: Arc, } @@ -581,6 +583,7 @@ pub fn run(mut krate: clean::Crate, current: Vec::new(), dst, render_redirect_pages: false, + codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), shared: Arc::new(scx), }; @@ -2221,13 +2224,14 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re fn render_markdown(w: &mut fmt::Formatter, md_text: &str, links: Vec<(String, String)>, - prefix: &str,) + prefix: &str, + codes: ErrorCodes) -> fmt::Result { - write!(w, "
{}{}
", prefix, Markdown(md_text, &links)) + write!(w, "
{}{}
", prefix, Markdown(md_text, &links, codes)) } fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink, - prefix: &str) -> fmt::Result { + prefix: &str, codes: ErrorCodes) -> fmt::Result { if let Some(s) = item.doc_value() { let markdown = if s.contains('\n') { format!("{} [Read more]({})", @@ -2235,7 +2239,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, &markdown, item.links(), prefix, codes)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2261,7 +2265,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, &*s, item.links(), prefix, cx.codes)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2508,6 +2512,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 +2526,11 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) }; @@ -2559,7 +2561,9 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", unstable_extra, - MarkdownHtml(&stab.unstable_reason)); + MarkdownHtml( + &stab.unstable_reason, + error_codes)); stability.push(format!("
{}
", text)); } @@ -2582,11 +2586,11 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) } @@ -3811,7 +3815,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi write!(w, "")?; if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { write!(w, "
{}
", - Markdown(&*dox, &i.impl_item.links()))?; + Markdown(&*dox, &i.impl_item.links(), cx.codes))?; } } @@ -3897,7 +3901,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } else if show_def_docs { // In case the item isn't documented, // provide short documentation from the trait. - document_short(w, it, link, &prefix)?; + document_short(w, it, link, &prefix, cx.codes)?; } } } else { @@ -3909,7 +3913,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi } else { document_stability(w, cx, item)?; if show_def_docs { - document_short(w, item, link, &prefix)?; + document_short(w, item, link, &prefix, cx.codes)?; } } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 4d1eae1470f04..97a3b2c1ea02c 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -19,6 +19,7 @@ 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}; @@ -26,7 +27,7 @@ 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, Markdown, MarkdownWithToc, find_testable_code}; use test::{TestOptions, Collector}; /// Separate any lines at the start of the file that begin with `# ` or `%`. @@ -88,10 +89,11 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches, reset_ids(false); + let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); let text = if include_toc { - MarkdownWithToc(text).to_string() + MarkdownWithToc(text, error_codes).to_string() } else { - Markdown(text, &[]).to_string() + Markdown(text, &[], error_codes).to_string() }; let err = write!( @@ -157,7 +159,8 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, Some(PathBuf::from(input)), linker, edition); collector.set_position(DUMMY_SP); - let res = find_testable_code(&input_str, &mut collector); + 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()); } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 9723b45280089..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::{self, LangString}; +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); @@ -662,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> { @@ -688,7 +690,7 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { // anything else, this will combine them for us if let Some(doc) = attrs.collapsed_doc_value() { self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP)); - let res = markdown::find_testable_code(&doc, self.collector); + 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()); diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index e72f90554d3c5..79c5be125b35f 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -24,7 +24,7 @@ use std::path::PathBuf; use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}; -use rustdoc::html::markdown::{Markdown, PLAYGROUND}; +use rustdoc::html::markdown::{Markdown, ErrorCodes, PLAYGROUND}; use rustc_serialize::json; enum OutputFormat { @@ -100,7 +100,7 @@ impl Formatter for HTMLFormatter { // Description rendered as markdown. match info.description { - Some(ref desc) => write!(output, "{}", Markdown(desc, &[]))?, + Some(ref desc) => write!(output, "{}", Markdown(desc, &[], ErrorCodes::Yes))?, None => write!(output, "

No description.

\n")?, } From 2216db9de78f2da623bea80594f1d9a7b54ddb54 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 22 Jul 2018 07:39:52 -0600 Subject: [PATCH 46/56] Format code for easier editing --- src/librustdoc/html/markdown.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index f65211f97be58..8f8973875649b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -661,12 +661,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), codes))); + let p = HeadingLinks::new(p, None); + 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) } From 38e311e4486b475c498ed1afdb6a036cdd702ebf Mon Sep 17 00:00:00 2001 From: Laurentiu Nicola Date: Tue, 31 Jul 2018 18:36:04 +0300 Subject: [PATCH 47/56] Use SetLenOnDrop in Vec::truncate() This avoids a redundant length check in some cases when calling `Vec::truncate` or `Vec::clear`. Fixes #51802 --- src/liballoc/vec.rs | 23 +++++++++++++++++------ src/test/codegen/vec-clear.rs | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 src/test/codegen/vec-clear.rs 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/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() +} From d94bdf8c66932b0cecc0024508316131c797dc2a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 31 Jul 2018 21:43:29 +0200 Subject: [PATCH 48/56] Put back original field discovery --- src/librustdoc/clean/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e019b26dd1dd9..2d4f365c7d78e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1211,8 +1211,14 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option } else { match cx.tcx.type_of(did).sty { ty::TyAdt(def, _) => { - if let Some(item) = def.all_fields() - .find(|item| item.ident.name == item_name) { + 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() { From 40a60464d4172db38f72a6f4f1141aa117f7d672 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 31 Jul 2018 22:37:41 +0300 Subject: [PATCH 49/56] Only run the sparc-abi test on sparc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is not required for LLVM to have SPARC target support, so it is necessary to only run this test when LLVM does support SPARC. Sadly, it isn’t possible to specify exactly this constraint. Instead, we specify that this test should run on SPARC host only (it surely is sane assumption to make that compiler running on a SPARC can generate SPARC, right?) Since you cannot specify multiple `only-*` to have it run on both 32-bit and 64-bit SPARC we pick 64-bit SPARC, because it is exactly what is being tested by this test. Fixes #52881 --- src/test/codegen/sparc-struct-abi.rs | 1 + 1 file changed, 1 insertion(+) 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] From 779792ff384cd244f480ded0b60e5bf31124133b Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 31 Jul 2018 23:00:01 +0200 Subject: [PATCH 50/56] address review feedback (`sort_by_key` is so much cleaner here than `sort_by`!). --- src/librustc_mir/borrow_check/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 3b767bfdd40ec..27221296ff31f 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -331,9 +331,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } if mbcx.errors_buffer.len() > 0 { - mbcx.errors_buffer.sort_by(|diag1, diag2| { - diag1.span.primary_span().cmp(&diag2.span.primary_span()) - }); + mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span()); if tcx.migrate_borrowck() { match tcx.borrowck(def_id).signalled_any_error { From 6b138f5167d64fb1e13aba7a7479567548e7b34c Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 31 Jul 2018 23:13:41 +0200 Subject: [PATCH 51/56] Backport 1.27.2 release notes --- RELEASES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index b983851f88198..a0a3ae3121783 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -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) =========================== From 7bea518d3a792d9c8df508b0af83ceb857ce75b7 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 22 Jul 2018 07:25:00 -0600 Subject: [PATCH 52/56] Remove global derive_id and reset_ids functions Previously these functions relied on TLS but we can instead thread the relevant state through explicitly. --- src/librustdoc/externalfiles.rs | 12 +- src/librustdoc/html/markdown.rs | 154 ++++++++++++++++-------- src/librustdoc/html/render.rs | 147 +++++++++------------- src/librustdoc/lib.rs | 6 +- src/librustdoc/markdown.rs | 11 +- src/tools/error_index_generator/main.rs | 13 +- 6 files changed, 190 insertions(+), 153 deletions(-) diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 67502ab8e1531..9631ea059cc43 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -13,7 +13,8 @@ use std::path::Path; use std::str; use errors; use syntax::feature_gate::UnstableFeatures; -use html::markdown::{ErrorCodes, Markdown}; +use html::markdown::{IdMap, ErrorCodes, Markdown}; +use std::cell::RefCell; #[derive(Clone)] pub struct ExternalHtml { @@ -30,7 +31,8 @@ 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) @@ -40,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, &[], codes)))) + .map(|m_bc| (ih, + format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), codes)))) ) .and_then(|(ih, bc)| load_external_files(after_content, diag) @@ -48,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, &[], codes)))) + .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/markdown.rs b/src/librustdoc/html/markdown.rs index 8f8973875649b..706671f21eff5 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -18,10 +18,12 @@ //! ``` //! #![feature(rustc_private)] //! -//! use rustdoc::html::markdown::{Markdown, ErrorCodes}; +//! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes}; +//! use std::cell::RefCell; //! //! let s = "My *markdown* _text_"; -//! let html = format!("{}", Markdown(s, &[], ErrorCodes::Yes)); +//! let mut id_map = IdMap::new(); +//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map), ErrorCodes::Yes)); //! // ... something using html //! ``` @@ -35,7 +37,6 @@ use std::borrow::Cow; use std::ops::Range; use std::str; -use html::render::derive_id; use html::toc::TocBuilder; use html::highlight; use test; @@ -47,12 +48,13 @@ 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 ErrorCodes); +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 ErrorCodes); +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 ErrorCodes); +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)]); @@ -287,23 +289,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 { @@ -322,7 +326,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(); @@ -641,7 +645,8 @@ impl LangString { impl<'a> fmt::Display for Markdown<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let Markdown(md, links, codes) = *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(()) } @@ -661,7 +666,7 @@ impl<'a> fmt::Display for Markdown<'a> { let mut s = String::with_capacity(md.len() * 3 / 2); - let p = HeadingLinks::new(p, None); + 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); @@ -673,7 +678,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, codes) = *self; + let MarkdownWithToc(md, ref ids, codes) = *self; + let mut ids = ids.borrow_mut(); let mut opts = Options::empty(); opts.insert(OPTION_ENABLE_TABLES); @@ -686,7 +692,7 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> { let mut toc = TocBuilder::new(); { - let p = 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); @@ -700,7 +706,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, codes) = *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(()) } @@ -718,7 +725,7 @@ impl<'a> fmt::Display for MarkdownHtml<'a> { let mut s = String::with_capacity(md.len() * 3 / 2); - let p = 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); @@ -835,7 +842,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 { @@ -854,11 +864,67 @@ 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::{ErrorCodes, 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() { @@ -901,19 +967,12 @@ mod tests { t("text,no_run", false, true, false, false, false, false, false, v()); } - #[test] - fn issue_17736() { - let markdown = "# title"; - Markdown(markdown, &[], ErrorCodes::Yes).to_string(); - reset_ids(true); - } - #[test] fn test_header() { fn t(input: &str, expect: &str) { - let output = Markdown(input, &[], ErrorCodes::Yes).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", "

\ @@ -932,28 +991,24 @@ mod tests { #[test] fn test_header_ids_multiple_blocks() { - fn t(input: &str, expect: &str) { - let output = Markdown(input, &[], ErrorCodes::Yes).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", "

"); - 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] @@ -974,7 +1029,8 @@ mod tests { #[test] fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { - let output = MarkdownHtml(input, ErrorCodes::Yes).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 b9b058cb54826..c1375fd37fd69 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -50,6 +50,7 @@ use std::mem; use std::path::{PathBuf, Path, Component}; use std::str; use std::sync::Arc; +use std::rc::Rc; use externalfiles::ExternalHtml; @@ -73,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, ErrorCodes}; +use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap}; use html::{highlight, layout}; use minifier; @@ -89,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, @@ -101,10 +102,12 @@ pub struct Context { /// 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, @@ -452,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", @@ -472,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` @@ -515,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(), @@ -584,6 +558,7 @@ pub fn run(mut krate: clean::Crate, 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), }; @@ -1711,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 { @@ -1865,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, @@ -2222,16 +2205,18 @@ 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, - codes: ErrorCodes) + prefix: &str) -> fmt::Result { - write!(w, "
{}{}
", prefix, Markdown(md_text, &links, codes)) + 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, - prefix: &str, codes: ErrorCodes) -> fmt::Result { +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') { format!("{} [Read more]({})", @@ -2239,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, codes)?; + render_markdown(w, cx, &markdown, item.links(), prefix)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2265,7 +2250,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, cx.codes)?; + render_markdown(w, cx, &*s, item.links(), prefix)?; } else if !prefix.is_empty() { write!(w, "
{}
", prefix)?; } @@ -2431,7 +2416,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 { @@ -2526,7 +2511,8 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec 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, + RefCell::new(&mut ids), error_codes)); stability.push(format!("
{}
", text)); @@ -2583,14 +2571,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) } @@ -2831,8 +2820,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(), cx.codes))?; + Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), cx.codes))?; } } @@ -3836,8 +3826,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, "

\ - Example