From 73ed6cf7fb7696ced5b6487de1e14bced35be601 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Mon, 23 Oct 2017 22:49:06 +0200 Subject: [PATCH 01/29] Implement From for TryRecvError and RecvTimeoutError --- src/libstd/sync/mpsc/mod.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 45a26e594b065..b3c4d8c40a10d 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1677,6 +1677,15 @@ impl error::Error for TryRecvError { } } +#[stable(feature = "mpsc_recv_error_from", since = "1.23.0")] +impl From for TryRecvError { + fn from(err: RecvError) -> TryRecvError { + match err { + RecvError => TryRecvError::Disconnected, + } + } +} + #[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")] impl fmt::Display for RecvTimeoutError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1709,6 +1718,15 @@ impl error::Error for RecvTimeoutError { } } +#[stable(feature = "mpsc_recv_error_from", since = "1.23.0")] +impl From for RecvTimeoutError { + fn from(err: RecvError) -> RecvTimeoutError { + match err { + RecvError => RecvTimeoutError::Disconnected, + } + } +} + #[cfg(all(test, not(target_os = "emscripten")))] mod tests { use env; From 448215d226f2946c08d01ff230570a6e3b64b1de Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Tue, 31 Oct 2017 00:18:53 +0100 Subject: [PATCH 02/29] Implement From> for TrySendError --- src/libstd/sync/mpsc/mod.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index b3c4d8c40a10d..8d7f60f9d2c03 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1625,6 +1625,15 @@ impl error::Error for TrySendError { } } +#[stable(feature = "mpsc_error_conversions", since = "1.23.0")] +impl From> for TrySendError { + fn from(err: SendError) -> TrySendError { + match err { + SendError(t) => TrySendError::Disconnected(t), + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for RecvError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1677,7 +1686,7 @@ impl error::Error for TryRecvError { } } -#[stable(feature = "mpsc_recv_error_from", since = "1.23.0")] +#[stable(feature = "mpsc_error_conversions", since = "1.23.0")] impl From for TryRecvError { fn from(err: RecvError) -> TryRecvError { match err { @@ -1718,7 +1727,7 @@ impl error::Error for RecvTimeoutError { } } -#[stable(feature = "mpsc_recv_error_from", since = "1.23.0")] +#[stable(feature = "mpsc_error_conversions", since = "1.23.0")] impl From for RecvTimeoutError { fn from(err: RecvError) -> RecvTimeoutError { match err { From 6ceb5f4bec83b525c5df409559272f0e10863f6a Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Wed, 22 Nov 2017 00:00:01 +0100 Subject: [PATCH 03/29] Stabilize spin_loop_hint --- .../{hint-core-should-pause.md => spin-loop-hint.md} | 8 ++++---- src/libcore/sync/atomic.rs | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) rename src/doc/unstable-book/src/library-features/{hint-core-should-pause.md => spin-loop-hint.md} (80%) diff --git a/src/doc/unstable-book/src/library-features/hint-core-should-pause.md b/src/doc/unstable-book/src/library-features/spin-loop-hint.md similarity index 80% rename from src/doc/unstable-book/src/library-features/hint-core-should-pause.md rename to src/doc/unstable-book/src/library-features/spin-loop-hint.md index 05e057be4932d..cd33f0c5e0293 100644 --- a/src/doc/unstable-book/src/library-features/hint-core-should-pause.md +++ b/src/doc/unstable-book/src/library-features/spin-loop-hint.md @@ -1,4 +1,4 @@ -# `hint_core_should_pause` +# `spin_loop_hint` The tracking issue for this feature is: [#41196] @@ -23,7 +23,7 @@ fn spin_loop(value: &AtomicBool) { These programs can be improved in performance like so: ```rust,no_run -#![feature(hint_core_should_pause)] +#![feature(spin_loop_hint)] use std::sync::atomic; use std::sync::atomic::{AtomicBool,Ordering}; @@ -32,10 +32,10 @@ fn spin_loop(value: &AtomicBool) { if value.load(Ordering::Acquire) { break; } - atomic::hint_core_should_pause(); + atomic::spin_loop_hint(); } } ``` -Further improvements could combine `hint_core_should_pause` with +Further improvements could combine `spin_loop_hint` with exponential backoff or `std::thread::yield_now`. diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index b7cf6d778a2f9..5486cb2926650 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -103,9 +103,8 @@ use fmt; /// /// On some platforms this function may not do anything at all. #[inline] -#[unstable(feature = "hint_core_should_pause", issue = "41196")] -pub fn hint_core_should_pause() -{ +#[stable(feature = "spin_loop_hint", since = "1.23.0")] +pub fn spin_loop_hint() { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] unsafe { asm!("pause" ::: "memory" : "volatile"); From a115fcd1a0c272e1a176e3e341b323b134f23097 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Wed, 22 Nov 2017 11:24:57 +0100 Subject: [PATCH 04/29] Remove spin-loop-hint from the unstable book --- .../src/library-features/spin-loop-hint.md | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/spin-loop-hint.md diff --git a/src/doc/unstable-book/src/library-features/spin-loop-hint.md b/src/doc/unstable-book/src/library-features/spin-loop-hint.md deleted file mode 100644 index cd33f0c5e0293..0000000000000 --- a/src/doc/unstable-book/src/library-features/spin-loop-hint.md +++ /dev/null @@ -1,41 +0,0 @@ -# `spin_loop_hint` - -The tracking issue for this feature is: [#41196] - -[#41196]: https://github.com/rust-lang/rust/issues/41196 - ------------------------- - -Many programs have spin loops like the following: - -```rust,no_run -use std::sync::atomic::{AtomicBool,Ordering}; - -fn spin_loop(value: &AtomicBool) { - loop { - if value.load(Ordering::Acquire) { - break; - } - } -} -``` - -These programs can be improved in performance like so: - -```rust,no_run -#![feature(spin_loop_hint)] -use std::sync::atomic; -use std::sync::atomic::{AtomicBool,Ordering}; - -fn spin_loop(value: &AtomicBool) { - loop { - if value.load(Ordering::Acquire) { - break; - } - atomic::spin_loop_hint(); - } -} -``` - -Further improvements could combine `spin_loop_hint` with -exponential backoff or `std::thread::yield_now`. From 5962d7e0079c4c2156a783e156a76c5d0824df22 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 24 Nov 2017 18:52:42 +0100 Subject: [PATCH 05/29] Expand docs of <$Int>::from_str_radix, based on that of char::to_digit --- src/libcore/num/mod.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 1230066e2b33b..19e91a65964ae 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -132,7 +132,14 @@ macro_rules! int_impl { /// Converts a string slice in a given base to an integer. /// + /// The string is expected to be an optional `+` or `-` sign + /// followed by digits. /// Leading and trailing whitespace represent an error. + /// Digits are a subset of these characters, depending on `radix`: + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` /// /// # Panics /// @@ -1301,7 +1308,18 @@ macro_rules! uint_impl { /// Converts a string slice in a given base to an integer. /// + /// The string is expected to be an optional `+` sign + /// followed by digits. /// Leading and trailing whitespace represent an error. + /// Digits are a subset of these characters, depending on `radix`: + /// + /// * `0-9` + /// * `a-z` + /// * `A-Z` + /// + /// # Panics + /// + /// This function panics if `radix` is not in the range from 2 to 36. /// /// # Examples /// From fa6ae4c82872d4cd325072400a04e386f4004dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Nov 2017 14:47:40 -0800 Subject: [PATCH 06/29] Suggest using slice when encountering `let x = ""[..];` --- src/librustc/hir/mod.rs | 17 +++++++ src/librustc/traits/error_reporting.rs | 29 ++++++++++++ .../ui/suggestions/str-array-assignment.rs | 17 +++++++ .../suggestions/str-array-assignment.stderr | 44 +++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 src/test/ui/suggestions/str-array-assignment.rs create mode 100644 src/test/ui/suggestions/str-array-assignment.stderr diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 39ec33eef1fec..986f1b9e4196f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -244,6 +244,23 @@ impl Path { pub fn is_global(&self) -> bool { !self.segments.is_empty() && self.segments[0].name == keywords::CrateRoot.name() } + + /// Wether this path is any of `::std::ops::{Range, RangeTo, RangeFrom}`. + pub fn is_range(&self) -> bool { + let mut base = ["{{root}}", "std", "ops"].iter().map(|p| p.to_string()).collect::>(); + let range_paths = ["Range", "RangeTo", "RangeFrom"]; + let segments = self.segments.iter() + .map(|segment| format!("{}", segment.name)) + .collect::>(); + for path in &range_paths { + base.push(path.to_string()); + if base == segments { + return true; + } + base.pop(); + } + false + } } impl fmt::Debug for Path { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 46ec2be4a1f9b..a8a8b20012b7a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -581,6 +581,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { trait_ref.self_ty())); } + self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); + // Try to report a help message if !trait_ref.has_infer_types() && self.predicate_can_apply(obligation.param_env, trait_ref) { @@ -821,6 +823,33 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.emit(); } + /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a + /// suggestion to borrow the initializer in order to use have a slice instead. + fn suggest_borrow_on_unsized_slice(&self, + code: &ObligationCauseCode<'tcx>, + err: &mut DiagnosticBuilder<'tcx>) { + if let &ObligationCauseCode::VariableType(node_id) = code { + let parent_node = self.tcx.hir.get_parent_node(node_id); + if let Some(hir::map::NodeLocal(ref local)) = self.tcx.hir.find(parent_node) { + if let Some(ref expr) = local.init { + if let hir::ExprIndex(_, ref index) = expr.node { + if let hir::ExprStruct(hir::QPath::Resolved(None, ref path), + ..) = index.node { + if let (Ok(snippet), true) = ( + self.tcx.sess.codemap().span_to_snippet(expr.span), + path.is_range() + ) { + err.span_suggestion(expr.span, + "consider a slice instead", + format!("&{}", snippet)); + } + } + } + } + } + } + } + fn report_arg_count_mismatch( &self, span: Span, diff --git a/src/test/ui/suggestions/str-array-assignment.rs b/src/test/ui/suggestions/str-array-assignment.rs new file mode 100644 index 0000000000000..523e7bea6224b --- /dev/null +++ b/src/test/ui/suggestions/str-array-assignment.rs @@ -0,0 +1,17 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let s = "abc"; + let t = if true { s[..2] } else { s }; + let u: &str = if true { s[..2] } else { s }; + let v = s[..2]; + let w: &str = s[..2]; +} diff --git a/src/test/ui/suggestions/str-array-assignment.stderr b/src/test/ui/suggestions/str-array-assignment.stderr new file mode 100644 index 0000000000000..225dfbd98fddf --- /dev/null +++ b/src/test/ui/suggestions/str-array-assignment.stderr @@ -0,0 +1,44 @@ +error[E0308]: if and else have incompatible types + --> $DIR/str-array-assignment.rs:13:11 + | +13 | let t = if true { s[..2] } else { s }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected str, found &str + | + = note: expected type `str` + found type `&str` + +error[E0308]: mismatched types + --> $DIR/str-array-assignment.rs:14:27 + | +11 | fn main() { + | - expected `()` because of default return type +... +14 | let u: &str = if true { s[..2] } else { s }; + | ^^^^^^ expected &str, found str + | + = note: expected type `&str` + found type `str` + +error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied + --> $DIR/str-array-assignment.rs:15:7 + | +15 | let v = s[..2]; + | ^ ------ help: consider a slice instead: `&s[..2]` + | | + | `str` does not have a constant size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `str` + = note: all local variables must have a statically known size + +error[E0308]: mismatched types + --> $DIR/str-array-assignment.rs:16:17 + | +16 | let w: &str = s[..2]; + | ^^^^^^ expected &str, found str + | + = note: expected type `&str` + found type `str` + = help: try with `&s[..2]` + +error: aborting due to 4 previous errors + From cde0023b5b71eb4ceafef31dd9036a268ba3b08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 25 Nov 2017 06:19:39 -0800 Subject: [PATCH 07/29] Add `compile-fail` style comments to tests --- src/test/ui/suggestions/str-array-assignment.rs | 17 ++++++++++++++++- .../ui/suggestions/str-array-assignment.stderr | 14 +++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/test/ui/suggestions/str-array-assignment.rs b/src/test/ui/suggestions/str-array-assignment.rs index 523e7bea6224b..52b39d390d62b 100644 --- a/src/test/ui/suggestions/str-array-assignment.rs +++ b/src/test/ui/suggestions/str-array-assignment.rs @@ -8,10 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { +fn main() { //~ NOTE expected `()` because of default return type let s = "abc"; let t = if true { s[..2] } else { s }; + //~^ ERROR if and else have incompatible types + //~| NOTE expected str, found &str + //~| NOTE expected type let u: &str = if true { s[..2] } else { s }; + //~^ ERROR mismatched types + //~| NOTE expected &str, found str + //~| NOTE expected type let v = s[..2]; + //~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied + //~| NOTE consider a slice instead + //~| NOTE `str` does not have a constant size known at compile-time + //~| HELP the trait `std::marker::Sized` is not implemented for `str` + //~| NOTE all local variables must have a statically known size let w: &str = s[..2]; + //~^ ERROR mismatched types + //~| NOTE expected &str, found str + //~| NOTE expected type + //~| HELP try with `&s[..2]` } diff --git a/src/test/ui/suggestions/str-array-assignment.stderr b/src/test/ui/suggestions/str-array-assignment.stderr index 225dfbd98fddf..55006b2760cca 100644 --- a/src/test/ui/suggestions/str-array-assignment.stderr +++ b/src/test/ui/suggestions/str-array-assignment.stderr @@ -8,21 +8,21 @@ error[E0308]: if and else have incompatible types found type `&str` error[E0308]: mismatched types - --> $DIR/str-array-assignment.rs:14:27 + --> $DIR/str-array-assignment.rs:17:27 | -11 | fn main() { +11 | fn main() { //~ NOTE expected `()` because of default return type | - expected `()` because of default return type ... -14 | let u: &str = if true { s[..2] } else { s }; +17 | let u: &str = if true { s[..2] } else { s }; | ^^^^^^ expected &str, found str | = note: expected type `&str` found type `str` error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied - --> $DIR/str-array-assignment.rs:15:7 + --> $DIR/str-array-assignment.rs:21:7 | -15 | let v = s[..2]; +21 | let v = s[..2]; | ^ ------ help: consider a slice instead: `&s[..2]` | | | `str` does not have a constant size known at compile-time @@ -31,9 +31,9 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied = note: all local variables must have a statically known size error[E0308]: mismatched types - --> $DIR/str-array-assignment.rs:16:17 + --> $DIR/str-array-assignment.rs:27:17 | -16 | let w: &str = s[..2]; +27 | let w: &str = s[..2]; | ^^^^^^ expected &str, found str | = note: expected type `&str` From aabacf791abb5d50ca1cf0239268b8ef72f8faaa Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sat, 25 Nov 2017 08:38:30 -0700 Subject: [PATCH 08/29] Remove semicolon note Added note that specifies a semicolon should be removed after a given struct --- src/libsyntax/parse/parser.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0b03429ea2e52..7a3009215f277 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5486,7 +5486,11 @@ impl<'a> Parser<'a> { if !self.eat(term) { let token_str = self.this_token_to_string(); - return Err(self.fatal(&format!("expected item, found `{}`", token_str))); + let mut err = self.fatal(&format!("expected item, found `{}`", token_str)); + if token_str == ";" { + err.note("consider removing the semicolon"); + } + return Err(); } let hi = if self.span == syntax_pos::DUMMY_SP { From ba40f5c4ef4e2292ff92546236ef507438459eee Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sat, 25 Nov 2017 08:40:42 -0700 Subject: [PATCH 09/29] Test for issue #46186 --- src/test/parse-fail/issue-46186.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/parse-fail/issue-46186.rs diff --git a/src/test/parse-fail/issue-46186.rs b/src/test/parse-fail/issue-46186.rs new file mode 100644 index 0000000000000..3f3dceeec5e9c --- /dev/null +++ b/src/test/parse-fail/issue-46186.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +struct Struct { + a: usize, +} //~ ERROR expected item, found ';' +//~| NOTE consider removing the semicolon + +fn main() {} From 306f4da69a89f45b9c06ac742f337e6de0445845 Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sat, 25 Nov 2017 08:47:05 -0700 Subject: [PATCH 10/29] Fixed Err by passing "err" --- src/libsyntax/parse/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7a3009215f277..1c64b36d960c4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5490,7 +5490,7 @@ impl<'a> Parser<'a> { if token_str == ";" { err.note("consider removing the semicolon"); } - return Err(); + return Err(err); } let hi = if self.span == syntax_pos::DUMMY_SP { From 97d8d04f3fffd0984a2d2af2f24c104e75be8f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 25 Nov 2017 06:20:07 -0800 Subject: [PATCH 11/29] Remove index type check (review comment) --- src/librustc/hir/mod.rs | 17 ----------------- src/librustc/traits/error_reporting.rs | 16 +++++----------- src/test/ui/suggestions/str-array-assignment.rs | 2 +- 3 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 986f1b9e4196f..39ec33eef1fec 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -244,23 +244,6 @@ impl Path { pub fn is_global(&self) -> bool { !self.segments.is_empty() && self.segments[0].name == keywords::CrateRoot.name() } - - /// Wether this path is any of `::std::ops::{Range, RangeTo, RangeFrom}`. - pub fn is_range(&self) -> bool { - let mut base = ["{{root}}", "std", "ops"].iter().map(|p| p.to_string()).collect::>(); - let range_paths = ["Range", "RangeTo", "RangeFrom"]; - let segments = self.segments.iter() - .map(|segment| format!("{}", segment.name)) - .collect::>(); - for path in &range_paths { - base.push(path.to_string()); - if base == segments { - return true; - } - base.pop(); - } - false - } } impl fmt::Debug for Path { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index a8a8b20012b7a..46e2c3af5e632 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -832,17 +832,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let parent_node = self.tcx.hir.get_parent_node(node_id); if let Some(hir::map::NodeLocal(ref local)) = self.tcx.hir.find(parent_node) { if let Some(ref expr) = local.init { - if let hir::ExprIndex(_, ref index) = expr.node { - if let hir::ExprStruct(hir::QPath::Resolved(None, ref path), - ..) = index.node { - if let (Ok(snippet), true) = ( - self.tcx.sess.codemap().span_to_snippet(expr.span), - path.is_range() - ) { - err.span_suggestion(expr.span, - "consider a slice instead", - format!("&{}", snippet)); - } + if let hir::ExprIndex(_, _) = expr.node { + if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(expr.span) { + err.span_suggestion(expr.span, + "consider a slice instead", + format!("&{}", snippet)); } } } diff --git a/src/test/ui/suggestions/str-array-assignment.rs b/src/test/ui/suggestions/str-array-assignment.rs index 52b39d390d62b..adec495e72a9f 100644 --- a/src/test/ui/suggestions/str-array-assignment.rs +++ b/src/test/ui/suggestions/str-array-assignment.rs @@ -20,7 +20,7 @@ fn main() { //~ NOTE expected `()` because of default return type //~| NOTE expected type let v = s[..2]; //~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied - //~| NOTE consider a slice instead + //~| HELP consider a slice instead //~| NOTE `str` does not have a constant size known at compile-time //~| HELP the trait `std::marker::Sized` is not implemented for `str` //~| NOTE all local variables must have a statically known size From 8e60f720fb6cf18e9530f4301c2f599357b8a277 Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sat, 25 Nov 2017 09:06:06 -0700 Subject: [PATCH 12/29] Added ; --- src/test/parse-fail/issue-46186.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/parse-fail/issue-46186.rs b/src/test/parse-fail/issue-46186.rs index 3f3dceeec5e9c..49ecc76886499 100644 --- a/src/test/parse-fail/issue-46186.rs +++ b/src/test/parse-fail/issue-46186.rs @@ -12,7 +12,7 @@ struct Struct { a: usize, -} //~ ERROR expected item, found ';' +}; //~ ERROR expected item, found ';' //~| NOTE consider removing the semicolon fn main() {} From de41d84ddfda90c9cc439ca12fce455fe2f7aaf1 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sat, 25 Nov 2017 18:35:30 +0100 Subject: [PATCH 13/29] Introduce LinkedList::remove_if --- src/liballoc/linked_list.rs | 79 +++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs index fac6acaca6125..689a267199430 100644 --- a/src/liballoc/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -220,6 +220,28 @@ impl LinkedList { node }) } + + /// Unlinks the specified node from the current list. + /// + /// Warning: this will not check that the provided node belongs to the current list. + #[inline] + unsafe fn unlink_node(&mut self, mut node: Shared>) { + let node = node.as_mut(); + + match node.prev { + Some(mut prev) => prev.as_mut().next = node.next.clone(), + // this node is the head node + None => self.head = node.next.clone(), + }; + + match node.next { + Some(mut next) => next.as_mut().prev = node.prev.clone(), + // this node is the tail node + None => self.tail = node.prev.clone(), + }; + + self.len -= 1; + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -722,6 +744,50 @@ impl LinkedList { second_part } + /// Removes any element matching the given predicate. Returns the elements which were removed + /// in a new list. + /// + /// This operation should compute in O(n) time. + /// + /// # Examples + /// + /// ``` + /// #![feature(linked_list_remove_if)] + /// + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// d.push_back(1); + /// d.push_back(2); + /// d.push_back(3); + /// assert_eq!(d.remove_if(|v| *v < 3).len(), 2); + /// assert_eq!(d.len(), 1); + /// ``` + #[unstable(feature = "linked_list_remove_if", + reason = "experimental method", + issue = "0")] + pub fn remove_if

(&mut self, predicate: P) -> LinkedList + where P: Fn(&T) -> bool + { + let mut deleted = LinkedList::new(); + + let mut it = self.head; + + while let Some(node) = it { + unsafe { + it = node.as_ref().next; + + if predicate(&node.as_ref().element) { + self.unlink_node(node); + // move the unlinked node into the deleted list. + deleted.push_back_node(Box::from_raw(node.as_ptr())); + } + } + } + + deleted + } + /// Returns a place for insertion at the front of the list. /// /// Using this method with placement syntax is equivalent to @@ -1502,4 +1568,17 @@ mod tests { } assert_eq!(i, v.len()); } + + #[test] + fn remove_if_test() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let deleted = m.remove_if(|v| *v < 4); + + check_links(&m); + check_links(&deleted); + + assert_eq!(deleted.into_iter().collect::>(), &[1, 2, 3]); + assert_eq!(m.into_iter().collect::>(), &[4, 5, 6]); + } } From 60aa8347f51fddaaed61d8304689111f6ac3e0af Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sat, 25 Nov 2017 21:14:37 +0100 Subject: [PATCH 14/29] Implement LinkedList::drain_filter Relates to rust-lang/rfcs#2140 - drain_filter for all collections `drain_filter` is implemented instead of `LinkedList::remove_if` based on review feedback. --- src/liballoc/linked_list.rs | 130 +++++++++++++++------ src/liballoc/tests/linked_list.rs | 188 ++++++++++++++++++++++++++++++ 2 files changed, 283 insertions(+), 35 deletions(-) diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs index 689a267199430..7bd1e1f050447 100644 --- a/src/liballoc/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -744,48 +744,47 @@ impl LinkedList { second_part } - /// Removes any element matching the given predicate. Returns the elements which were removed - /// in a new list. + /// Creates an iterator which uses a closure to determine if an element should be removed. /// - /// This operation should compute in O(n) time. + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, it will try again, and call the closure on the next element, + /// seeing if it passes the test. + /// + /// Note that `drain_filter` lets you mutate every element in the filter closure, regardless of + /// whether you choose to keep or remove it. /// /// # Examples /// - /// ``` - /// #![feature(linked_list_remove_if)] + /// Splitting a list into evens and odds, reusing the original list: /// + /// ``` + /// #![feature(drain_filter)] /// use std::collections::LinkedList; /// - /// let mut d = LinkedList::new(); - /// d.push_back(1); - /// d.push_back(2); - /// d.push_back(3); - /// assert_eq!(d.remove_if(|v| *v < 3).len(), 2); - /// assert_eq!(d.len(), 1); + /// let mut numbers: LinkedList = LinkedList::new(); + /// numbers.extend(&[1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]); + /// + /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::>(); + /// let odds = numbers; + /// + /// assert_eq!(evens.into_iter().collect::>(), vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 9, 11, 13, 15]); /// ``` - #[unstable(feature = "linked_list_remove_if", - reason = "experimental method", - issue = "0")] - pub fn remove_if

(&mut self, predicate: P) -> LinkedList - where P: Fn(&T) -> bool + #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] + pub fn drain_filter(&mut self, filter: F) -> DrainFilter + where F: FnMut(&mut T) -> bool { - let mut deleted = LinkedList::new(); - - let mut it = self.head; - - while let Some(node) = it { - unsafe { - it = node.as_ref().next; + // avoid borrow issues. + let it = self.head; + let old_len = self.len; - if predicate(&node.as_ref().element) { - self.unlink_node(node); - // move the unlinked node into the deleted list. - deleted.push_back_node(Box::from_raw(node.as_ptr())); - } - } + DrainFilter { + list: self, + it: it, + pred: filter, + idx: 0, + old_len: old_len, } - - deleted } /// Returns a place for insertion at the front of the list. @@ -1033,6 +1032,56 @@ impl<'a, T> IterMut<'a, T> { } } +/// An iterator produced by calling `drain_filter` on LinkedList. +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +pub struct DrainFilter<'a, T: 'a, F: 'a> + where F: FnMut(&mut T) -> bool, +{ + list: &'a mut LinkedList, + it: Option>>, + pred: F, + idx: usize, + old_len: usize, +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl<'a, T, F> Iterator for DrainFilter<'a, T, F> + where F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + while let Some(mut node) = self.it { + unsafe { + self.it = node.as_ref().next; + self.idx += 1; + + if (self.pred)(&mut node.as_mut().element) { + self.list.unlink_node(node); + return Some(Box::from_raw(node.as_ptr()).element); + } + } + } + + None + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl<'a, T: 'a + fmt::Debug, F> fmt::Debug for DrainFilter<'a, T, F> + where F: FnMut(&mut T) -> bool +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("DrainFilter") + .field(&self.list) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = T; @@ -1570,15 +1619,26 @@ mod tests { } #[test] - fn remove_if_test() { + fn drain_filter_test() { let mut m: LinkedList = LinkedList::new(); m.extend(&[1, 2, 3, 4, 5, 6]); - let deleted = m.remove_if(|v| *v < 4); + let deleted = m.drain_filter(|v| *v < 4).collect::>(); check_links(&m); - check_links(&deleted); - assert_eq!(deleted.into_iter().collect::>(), &[1, 2, 3]); + assert_eq!(deleted, &[1, 2, 3]); assert_eq!(m.into_iter().collect::>(), &[4, 5, 6]); } + + #[test] + fn drain_to_empty_test() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let deleted = m.drain_filter(|_| true).collect::>(); + + check_links(&m); + + assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]); + assert_eq!(m.into_iter().collect::>(), &[]); + } } diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs index a59724a017b12..4e3e855105eb8 100644 --- a/src/liballoc/tests/linked_list.rs +++ b/src/liballoc/tests/linked_list.rs @@ -366,3 +366,191 @@ fn test_contains() { assert!(!l.contains(&3)); } + +#[test] +fn drain_filter_empty() { + let mut list: LinkedList = LinkedList::new(); + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn drain_filter_zst() { + let mut list: LinkedList<_> = vec![(), (), (), (), ()].into_iter().collect(); + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn drain_filter_false() { + let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| false); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + for _ in iter.by_ref() { + count += 1; + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, 0); + assert_eq!(list.len(), initial_len); + assert_eq!(list.into_iter().collect::>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +} + +#[test] +fn drain_filter_true() { + let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn drain_filter_complex() { + + { // [+xxx++++++xxxxx++++x+x++] + let mut list = vec![ + 1, + 2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36, + 37, 39 + ].into_iter().collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 14); + assert_eq!( + list.into_iter().collect::>(), + vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] + ); + } + + { // [xxx++++++xxxxx++++x+x++] + let mut list = vec![ + 2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36, + 37, 39 + ].into_iter().collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 13); + assert_eq!( + list.into_iter().collect::>(), + vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] + ); + } + + { // [xxx++++++xxxxx++++x+x] + let mut list = vec![ + 2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36 + ].into_iter().collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 11); + assert_eq!( + list.into_iter().collect::>(), + vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35] + ); + } + + { // [xxxxxxxxxx+++++++++++] + let mut list = vec![ + 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 + ].into_iter().collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(list.len(), 10); + assert_eq!(list.into_iter().collect::>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } + + { // [+++++++++++xxxxxxxxxx] + let mut list = vec![ + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, + 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 + ].into_iter().collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(list.len(), 10); + assert_eq!(list.into_iter().collect::>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } +} From 3e8883e2aa425147d219e174788e2c1062d7d61f Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sat, 25 Nov 2017 18:34:20 -0700 Subject: [PATCH 15/29] Changed from note to span_suggestion_short --- src/libsyntax/parse/parser.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1c64b36d960c4..0f32d588b372f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5487,8 +5487,9 @@ impl<'a> Parser<'a> { if !self.eat(term) { let token_str = self.this_token_to_string(); let mut err = self.fatal(&format!("expected item, found `{}`", token_str)); + let msg = "consider removing this semicolon"; if token_str == ";" { - err.note("consider removing the semicolon"); + err.span_suggestion_short(self.span, msg, "".to_string()); } return Err(err); } From 477989933ddcab1c5a007a3b65a495ec3081047a Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sat, 25 Nov 2017 19:26:47 -0700 Subject: [PATCH 16/29] UI test 46186 --- src/test/ui/issue-46186 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/ui/issue-46186 diff --git a/src/test/ui/issue-46186 b/src/test/ui/issue-46186 new file mode 100644 index 0000000000000..2924bec567fb4 --- /dev/null +++ b/src/test/ui/issue-46186 @@ -0,0 +1,15 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Struct { + a: usize, +}; //~ ERROR expected item, found ';' + +fn main() {} From bbe4c85cfce314057afee571a4f5bd5333b56f6a Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sat, 25 Nov 2017 19:30:15 -0700 Subject: [PATCH 17/29] Added 46186 stderr --- src/test/ui/issue-46186.stderr | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/test/ui/issue-46186.stderr diff --git a/src/test/ui/issue-46186.stderr b/src/test/ui/issue-46186.stderr new file mode 100644 index 0000000000000..3cc9531bb5b86 --- /dev/null +++ b/src/test/ui/issue-46186.stderr @@ -0,0 +1,8 @@ +error: expected item, found `;` + --> $DIR/issue-46186.rs:13:2 + | +13 | }; //~ ERROR expected item, found `;` + | ^ help: consider removing this semicolon + +error: aborting due to previous error + From 50537e37f0c51b0ade967c7e6ad76395eb9c9be2 Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sat, 25 Nov 2017 21:14:15 -0700 Subject: [PATCH 18/29] Delete bad test file --- src/test/parse-fail/issue-46186.rs | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 src/test/parse-fail/issue-46186.rs diff --git a/src/test/parse-fail/issue-46186.rs b/src/test/parse-fail/issue-46186.rs deleted file mode 100644 index 49ecc76886499..0000000000000 --- a/src/test/parse-fail/issue-46186.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z parse-only - -struct Struct { - a: usize, -}; //~ ERROR expected item, found ';' -//~| NOTE consider removing the semicolon - -fn main() {} From 5d8d04ab4a055aab8e8537a3c6f1fdcf05c87261 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 26 Nov 2017 05:08:23 -0800 Subject: [PATCH 19/29] Compiletest libc dependency can be unix-only In main.rs libc is imported as: #[cfg(unix)] extern crate libc; --- src/tools/compiletest/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index d4d567e63c017..6fc9423a4139a 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -10,6 +10,8 @@ filetime = "0.1" getopts = "0.2" log = "0.3" rustc-serialize = "0.3" + +[target.'cfg(unix)'.dependencies] libc = "0.2" [target.'cfg(windows)'.dependencies] From 1be38e0316398f3dd409bdc4e1d14f33186599cb Mon Sep 17 00:00:00 2001 From: Ritiek Malhotra Date: Thu, 23 Nov 2017 17:06:48 +0530 Subject: [PATCH 20/29] MIR: Fix value moved diagnose messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIR: adopt borrowck test Fix trailing whitespace span_bug! on unexpected action Make RegionVid use newtype_index! Closes #45843 Check rvalue aggregates during check_stmt in tycheck, add initial, (not passing) test Fix failing test Remove attributes and test comments accidentally left behind, add in span_mirbugs Normalize LvalueTy for ops and format code to satisfy tidy check only normalize operand types when in an ADT constructor avoid early return handle the active field index in unions normalize types in ADT constructor Fixes #45940 Fix borrowck compiler errors for upvars contain "spurious" dereferences Fixes #46003 added associated function Box::leak Box::leak - improve documentation Box::leak - fixed bug in documentation Box::leak - relaxed constraints wrt. lifetimes Box::leak - updated documentation Box::leak - made an oops, fixed now =) Box::leak: update unstable issue number (46179). Add test for #44953 Add missing Debug impls to std_unicode Also adds #![deny(missing_debug_implementations)] so they don't get missed again. Amend RELEASES for 1.22.1 and fix the date for 1.22.0 Rename param in `[T]::swap_with_slice` from `src` to `other`. The idea of ‘source’ and ‘destination’ aren’t very applicable for this operation since both slices can both be considered sources and destinations. Clarify stdin behavior of `Command::output`. Fixes #44929. Add hints for the case of confusing enum with its variants Add failing testcases Add module population and case of enum in place of expression Use for_each_child_stable in find_module Use multiline text for crate conflict diagnostics Make float::from_bits transmute (and update the documentation to reflect this). The current implementation/documentation was made to avoid sNaN because of potential safety issues implied by old/bad LLVM documentation. These issues aren't real, so we can just make the implementation transmute (as permitted by the existing documentation of this method). Also the documentation didn't actually match the behaviour: it said we may change sNaNs, but in fact we canonicalized *all* NaNs. Also an example in the documentation was wrong: it said we *always* change sNaNs, when the documentation was explicitly written to indicate it was implementation-defined. This makes to_bits and from_bits perfectly roundtrip cross-platform, except for one caveat: although the 2008 edition of IEEE-754 specifies how to interpet the signaling bit, earlier editions didn't. This lead to some platforms picking the opposite interpretation, so all signaling NaNs on x86/ARM are quiet on MIPS, and vice-versa. NaN-boxing is a fairly important optimization, while we don't even guarantee that float operations properly preserve signalingness. As such, this seems like the more natural strategy to take (as opposed to trying to mangle the signaling bit on a per-platform basis). This implementation is also, of course, faster. Simplify an Iterator::fold to Iterator::any This method of once-diagnostics doesn't allow nesting UI tests extract the regular output from the 'rendered' field in json Merge cfail and ui tests into ui tests Add a MIR pass to lower 128-bit operators to lang item calls Runs only with `-Z lower_128bit_ops` since it's not hooked into targets yet. Include tuple projections in MIR tests Add type checking for the lang item As part of doing so, add more lang items instead of passing u128 to the i128 ones where it doesn't matter in twos-complement. Handle shifts properly * The overflow-checking shift items need to take a full 128-bit type, since they need to be able to detect idiocy like `1i128 << (1u128 << 127)` * The unchecked ones just take u32, like the `*_sh?` methods in core * Because shift-by-anything is allowed, cast into a new local for every shift incr.comp.: Make sure we don't lose unused green results from the query cache. rustbuild: Update LLVM and enable ThinLTO This commit updates LLVM to fix #45511 (https://reviews.llvm.org/D39981) and also reenables ThinLTO for libtest now that we shouldn't hit #45768. This also opportunistically enables ThinLTO for libstd which was previously blocked (#45661) on test failures related to debuginfo with a presumed cause of #45511. Closes #45511 std: Flag Windows TLS dtor symbol as #[used] Turns out ThinLTO was internalizing this symbol and eliminating it. Worse yet if you compiled with LTO turns out no TLS destructors would run on Windows! The `#[used]` annotation should be a more bulletproof implementation (in the face of LTO) of preserving this symbol all the way through in LLVM and ensuring it makes it all the way to the linker which will take care of it. Add enum InitializationRequiringAction Fix tidy tests --- src/librustc_mir/borrow_check.rs | 55 +++++++++++++++++---- src/test/ui/borrowck/borrowck-reinit.stderr | 2 +- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index ddaade98be108..6ec665549f8ea 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -444,6 +444,34 @@ enum WriteKind { Move, } +#[derive(Copy, Clone)] +enum InitializationRequiringAction { + Update, + Borrow, + Use, + Assignment, +} + +impl InitializationRequiringAction { + fn as_noun(self) -> &'static str { + match self { + InitializationRequiringAction::Update => "update", + InitializationRequiringAction::Borrow => "borrow", + InitializationRequiringAction::Use => "use", + InitializationRequiringAction::Assignment => "assign" + } + } + + fn as_verb_in_past_tense(self) -> &'static str { + match self { + InitializationRequiringAction::Update => "updated", + InitializationRequiringAction::Borrow => "borrowed", + InitializationRequiringAction::Use => "used", + InitializationRequiringAction::Assignment => "assigned" + } + } +} + impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Checks an access to the given lvalue to see if it is allowed. Examines the set of borrows /// that are in scope, as well as which paths have been initialized, to ensure that (a) the @@ -534,7 +562,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Write of P[i] or *P, or WriteAndRead of any P, requires P init'd. match mode { MutateMode::WriteAndRead => { - self.check_if_path_is_moved(context, "update", lvalue_span, flow_state); + self.check_if_path_is_moved(context, InitializationRequiringAction::Update, + lvalue_span, flow_state); } MutateMode::JustWrite => { self.check_if_assigned_path_is_moved(context, lvalue_span, flow_state); @@ -560,7 +589,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { BorrowKind::Mut => (Deep, Write(WriteKind::MutableBorrow(bk))), }; self.access_lvalue(context, (lvalue, span), access_kind, flow_state); - self.check_if_path_is_moved(context, "borrow", (lvalue, span), flow_state); + self.check_if_path_is_moved(context, InitializationRequiringAction::Borrow, + (lvalue, span), flow_state); } Rvalue::Use(ref operand) | @@ -579,7 +609,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }; self.access_lvalue( context, (lvalue, span), (Shallow(Some(af)), Read(ReadKind::Copy)), flow_state); - self.check_if_path_is_moved(context, "use", (lvalue, span), flow_state); + self.check_if_path_is_moved(context, InitializationRequiringAction::Use, + (lvalue, span), flow_state); } Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2) | @@ -680,7 +711,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // skip this check in that case). } ConsumeKind::Consume => { - self.check_if_path_is_moved(context, "use", lvalue_span, flow_state); + self.check_if_path_is_moved(context, InitializationRequiringAction::Use, + lvalue_span, flow_state); } } } @@ -741,7 +773,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn check_if_path_is_moved(&mut self, context: Context, - desired_action: &str, + desired_action: InitializationRequiringAction, lvalue_span: (&Lvalue<'tcx>, Span), flow_state: &InProgress<'cx, 'gcx, 'tcx>) { // FIXME: analogous code in check_loans first maps `lvalue` to @@ -912,7 +944,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // `base` to its base_path. self.check_if_path_is_moved( - context, "assignment", (base, span), flow_state); + context, InitializationRequiringAction::Assignment, + (base, span), flow_state); // (base initialized; no need to // recur further) @@ -1316,7 +1349,7 @@ mod prefixes { impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn report_use_of_moved_or_uninitialized(&mut self, _context: Context, - desired_action: &str, + desired_action: InitializationRequiringAction, (lvalue, span): (&Lvalue<'tcx>, Span), mpi: MovePathIndex, curr_move_out: &IdxSetBuf) { @@ -1326,7 +1359,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if mois.is_empty() { self.tcx.cannot_act_on_uninitialized_variable(span, - desired_action, + desired_action.as_noun(), &self.describe_lvalue(lvalue), Origin::Mir) .span_label(span, format!("use of possibly uninitialized `{}`", @@ -1336,11 +1369,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let msg = ""; //FIXME: add "partially " or "collaterally " let mut err = self.tcx.cannot_act_on_moved_value(span, - desired_action, + desired_action.as_noun(), msg, &self.describe_lvalue(lvalue), Origin::Mir); - err.span_label(span, format!("value {} here after move", desired_action)); + + err.span_label(span, format!("value {} here after move", + desired_action.as_verb_in_past_tense())); for moi in mois { let move_msg = ""; //FIXME: add " (into closure)" let move_span = self.mir.source_info(self.move_data.moves[*moi].source).span; diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr index 12511030579a2..9f08bd198223e 100644 --- a/src/test/ui/borrowck/borrowck-reinit.stderr +++ b/src/test/ui/borrowck/borrowck-reinit.stderr @@ -14,7 +14,7 @@ error[E0382]: use of moved value: `x` (Mir) 17 | drop(x); | - value moved here 18 | let _ = (1,x); //~ ERROR use of moved value: `x` (Ast) - | ^ value use here after move + | ^ value used here after move error: aborting due to 2 previous errors From f6b80d4164f5ef21c66164e56ddbb5743c0f1011 Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sun, 26 Nov 2017 07:36:56 -0700 Subject: [PATCH 21/29] Added .rs extension --- src/test/ui/{issue-46186 => issue-46186.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{issue-46186 => issue-46186.rs} (100%) diff --git a/src/test/ui/issue-46186 b/src/test/ui/issue-46186.rs similarity index 100% rename from src/test/ui/issue-46186 rename to src/test/ui/issue-46186.rs From 096e698e4e8e48bd38a2002107616f4ad194e8eb Mon Sep 17 00:00:00 2001 From: colinmarsh19 <32608057+colinmarsh19@users.noreply.github.com> Date: Sun, 26 Nov 2017 07:40:29 -0700 Subject: [PATCH 22/29] Changed to correct quotes ` ` --- src/test/ui/issue-46186.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/issue-46186.rs b/src/test/ui/issue-46186.rs index 2924bec567fb4..1440b9e8cdc5f 100644 --- a/src/test/ui/issue-46186.rs +++ b/src/test/ui/issue-46186.rs @@ -10,6 +10,6 @@ struct Struct { a: usize, -}; //~ ERROR expected item, found ';' +}; //~ ERROR expected item, found `;` fn main() {} From aabb6043137f71c686a77bf4bda4eb37f1a9fe22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 26 Nov 2017 12:32:30 -0800 Subject: [PATCH 23/29] Move "auto trait leak" impl-trait cycle dependency test to ui --- .../impl-trait/auto-trait-leak.rs | 0 src/test/ui/impl-trait/auto-trait-leak.stderr | 70 +++++++++++++++++++ 2 files changed, 70 insertions(+) rename src/test/{compile-fail => ui}/impl-trait/auto-trait-leak.rs (100%) create mode 100644 src/test/ui/impl-trait/auto-trait-leak.stderr diff --git a/src/test/compile-fail/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs similarity index 100% rename from src/test/compile-fail/impl-trait/auto-trait-leak.rs rename to src/test/ui/impl-trait/auto-trait-leak.rs diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr new file mode 100644 index 0000000000000..90476eb2d0d7a --- /dev/null +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -0,0 +1,70 @@ +error[E0277]: the trait bound `std::rc::Rc>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>` + --> $DIR/auto-trait-leak.rs:27:5 + | +27 | send(before()); + | ^^^^ `std::rc::Rc>` cannot be sent between threads safely + | + = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` + = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:21:5: 21:22 p:std::rc::Rc>]` + = note: required because it appears within the type `impl std::ops::Fn<(i32,)>` + = note: required by `send` + +error[E0277]: the trait bound `std::rc::Rc>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>` + --> $DIR/auto-trait-leak.rs:34:5 + | +34 | send(after()); + | ^^^^ `std::rc::Rc>` cannot be sent between threads safely + | + = help: within `impl std::ops::Fn<(i32,)>`, the trait `std::marker::Send` is not implemented for `std::rc::Rc>` + = note: required because it appears within the type `[closure@$DIR/auto-trait-leak.rs:46:5: 46:22 p:std::rc::Rc>]` + = note: required because it appears within the type `impl std::ops::Fn<(i32,)>` + = note: required by `send` + +error[E0391]: unsupported cyclic reference between types/traits detected + --> $DIR/auto-trait-leak.rs:52:1 + | +52 | / fn cycle1() -> impl Clone { +53 | | //~^ ERROR unsupported cyclic reference between types/traits detected +54 | | //~| cyclic reference +55 | | //~| NOTE the cycle begins when processing `cycle1`... +... | +60 | | Rc::new(Cell::new(5)) +61 | | } + | |_^ cyclic reference + | +note: the cycle begins when processing `cycle1`... + --> $DIR/auto-trait-leak.rs:52:1 + | +52 | / fn cycle1() -> impl Clone { +53 | | //~^ ERROR unsupported cyclic reference between types/traits detected +54 | | //~| cyclic reference +55 | | //~| NOTE the cycle begins when processing `cycle1`... +... | +60 | | Rc::new(Cell::new(5)) +61 | | } + | |_^ +note: ...which then requires processing `cycle2::{{impl-Trait}}`... + --> $DIR/auto-trait-leak.rs:63:16 + | +63 | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: ...which then requires processing `cycle2`... + --> $DIR/auto-trait-leak.rs:63:1 + | +63 | / fn cycle2() -> impl Clone { +64 | | //~^ NOTE ...which then requires processing `cycle2::{{impl-Trait}}`... +65 | | //~| NOTE ...which then requires processing `cycle2`... +66 | | send(cycle1().clone()); +67 | | +68 | | Rc::new(String::from("foo")) +69 | | } + | |_^ +note: ...which then requires processing `cycle1::{{impl-Trait}}`... + --> $DIR/auto-trait-leak.rs:52:16 + | +52 | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ + = note: ...which then again requires processing `cycle1`, completing the cycle. + +error: aborting due to 3 previous errors + From 0b2d21e32b40dfc25f09db5a12864d060ac1070a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 26 Nov 2017 12:35:19 -0800 Subject: [PATCH 24/29] Make impl-trait ciclical reference error point to def_span --- src/librustc/ty/maps/plumbing.rs | 8 ++++---- src/test/ui/impl-trait/auto-trait-leak.stderr | 20 ++++--------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 739537c7c3a71..3440282db2d66 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -86,12 +86,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { "unsupported cyclic reference between types/traits detected"); err.span_label(span, "cyclic reference"); - err.span_note(stack[0].0, &format!("the cycle begins when {}...", - stack[0].1.describe(self))); + err.span_note(self.sess.codemap().def_span(stack[0].0), + &format!("the cycle begins when {}...", stack[0].1.describe(self))); for &(span, ref query) in &stack[1..] { - err.span_note(span, &format!("...which then requires {}...", - query.describe(self))); + err.span_note(self.sess.codemap().def_span(span), + &format!("...which then requires {}...", query.describe(self))); } err.note(&format!("...which then again requires {}, completing the cycle.", diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 90476eb2d0d7a..ac5c79be6a93e 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -35,14 +35,8 @@ error[E0391]: unsupported cyclic reference between types/traits detected note: the cycle begins when processing `cycle1`... --> $DIR/auto-trait-leak.rs:52:1 | -52 | / fn cycle1() -> impl Clone { -53 | | //~^ ERROR unsupported cyclic reference between types/traits detected -54 | | //~| cyclic reference -55 | | //~| NOTE the cycle begins when processing `cycle1`... -... | -60 | | Rc::new(Cell::new(5)) -61 | | } - | |_^ +52 | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which then requires processing `cycle2::{{impl-Trait}}`... --> $DIR/auto-trait-leak.rs:63:16 | @@ -51,14 +45,8 @@ note: ...which then requires processing `cycle2::{{impl-Trait}}`... note: ...which then requires processing `cycle2`... --> $DIR/auto-trait-leak.rs:63:1 | -63 | / fn cycle2() -> impl Clone { -64 | | //~^ NOTE ...which then requires processing `cycle2::{{impl-Trait}}`... -65 | | //~| NOTE ...which then requires processing `cycle2`... -66 | | send(cycle1().clone()); -67 | | -68 | | Rc::new(String::from("foo")) -69 | | } - | |_^ +63 | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which then requires processing `cycle1::{{impl-Trait}}`... --> $DIR/auto-trait-leak.rs:52:16 | From a326d8d1ba6286b1641b8c89d5ae1383fbfac76a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 26 Nov 2017 22:53:03 +0100 Subject: [PATCH 25/29] Document non-obvious behavior of fmt::UpperHex & co for negative integers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before stabilization I’d have suggested changing the behavior, but that time is past. --- src/libcore/fmt/mod.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 897222747f5e6..28d78d596e1c4 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -624,6 +624,9 @@ pub trait Display { /// /// The `Octal` trait should format its output as a number in base-8. /// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// /// The alternate flag, `#`, adds a `0o` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. @@ -639,6 +642,8 @@ pub trait Display { /// /// assert_eq!(format!("{:o}", x), "52"); /// assert_eq!(format!("{:#o}", x), "0o52"); +/// +/// assert_eq!(format!("{:o}", -16), "37777777760"); /// ``` /// /// Implementing `Octal` on a type: @@ -671,6 +676,9 @@ pub trait Octal { /// /// The `Binary` trait should format its output as a number in binary. /// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// /// The alternate flag, `#`, adds a `0b` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. @@ -686,6 +694,8 @@ pub trait Octal { /// /// assert_eq!(format!("{:b}", x), "101010"); /// assert_eq!(format!("{:#b}", x), "0b101010"); +/// +/// assert_eq!(format!("{:b}", -16), "11111111111111111111111111110000"); /// ``` /// /// Implementing `Binary` on a type: @@ -719,6 +729,9 @@ pub trait Binary { /// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f` /// in lower case. /// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// /// The alternate flag, `#`, adds a `0x` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. @@ -734,6 +747,8 @@ pub trait Binary { /// /// assert_eq!(format!("{:x}", x), "2a"); /// assert_eq!(format!("{:#x}", x), "0x2a"); +/// +/// assert_eq!(format!("{:x}", -16), "fffffff0"); /// ``` /// /// Implementing `LowerHex` on a type: @@ -767,6 +782,9 @@ pub trait LowerHex { /// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F` /// in upper case. /// +/// For primitive signed integers (`i8` to `i128`, and `isize`), +/// negative values are formatted as the two’s complement representation. +/// /// The alternate flag, `#`, adds a `0x` in front of the output. /// /// For more information on formatters, see [the module-level documentation][module]. @@ -782,6 +800,8 @@ pub trait LowerHex { /// /// assert_eq!(format!("{:X}", x), "2A"); /// assert_eq!(format!("{:#X}", x), "0x2A"); +/// +/// assert_eq!(format!("{:X}", -16), "FFFFFFF0"); /// ``` /// /// Implementing `UpperHex` on a type: From 8a93deca9a41e7c185b96ca55f132b18d7e22f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 26 Nov 2017 12:37:13 -0800 Subject: [PATCH 26/29] Make main span in impl-trait ciclic reference point to def_span --- src/librustc/ty/maps/plumbing.rs | 1 + src/test/ui/impl-trait/auto-trait-leak.stderr | 10 ++-------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 3440282db2d66..e292862faa05c 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -81,6 +81,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // (And cycle errors around impls tend to occur during the // collect/coherence phases anyhow.) item_path::with_forced_impl_filename_line(|| { + let span = self.sess.codemap().def_span(span); let mut err = struct_span_err!(self.sess, span, E0391, "unsupported cyclic reference between types/traits detected"); diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index ac5c79be6a93e..1c03e9d852645 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -23,14 +23,8 @@ error[E0277]: the trait bound `std::rc::Rc>: std::marker::S error[E0391]: unsupported cyclic reference between types/traits detected --> $DIR/auto-trait-leak.rs:52:1 | -52 | / fn cycle1() -> impl Clone { -53 | | //~^ ERROR unsupported cyclic reference between types/traits detected -54 | | //~| cyclic reference -55 | | //~| NOTE the cycle begins when processing `cycle1`... -... | -60 | | Rc::new(Cell::new(5)) -61 | | } - | |_^ cyclic reference +52 | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic reference | note: the cycle begins when processing `cycle1`... --> $DIR/auto-trait-leak.rs:52:1 From 487daabb529b437e99342c0d49db2401376e1a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 27 Nov 2017 06:01:16 -0800 Subject: [PATCH 27/29] Fix test --- src/test/ui/resolve/issue-23305.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index fda87de9b9c50..5bba9fc41e276 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -8,7 +8,7 @@ note: the cycle begins when processing ` $DIR/issue-23305.rs:15:1 | 15 | impl ToNbt {} - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ = note: ...which then again requires processing ``, completing the cycle. error: aborting due to previous error From fa44927d2c017359a7d4b14a31e96ee35472b406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 26 Nov 2017 12:52:00 -0800 Subject: [PATCH 28/29] reword to "consider borrowing here: `{suggestion}`" --- src/librustc/traits/error_reporting.rs | 2 +- src/test/ui/suggestions/str-array-assignment.rs | 2 +- src/test/ui/suggestions/str-array-assignment.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 46e2c3af5e632..5703c5c870e88 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -835,7 +835,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let hir::ExprIndex(_, _) = expr.node { if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(expr.span) { err.span_suggestion(expr.span, - "consider a slice instead", + "consider borrowing here", format!("&{}", snippet)); } } diff --git a/src/test/ui/suggestions/str-array-assignment.rs b/src/test/ui/suggestions/str-array-assignment.rs index adec495e72a9f..6c7f4852a4ae5 100644 --- a/src/test/ui/suggestions/str-array-assignment.rs +++ b/src/test/ui/suggestions/str-array-assignment.rs @@ -20,7 +20,7 @@ fn main() { //~ NOTE expected `()` because of default return type //~| NOTE expected type let v = s[..2]; //~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied - //~| HELP consider a slice instead + //~| HELP consider borrowing here //~| NOTE `str` does not have a constant size known at compile-time //~| HELP the trait `std::marker::Sized` is not implemented for `str` //~| NOTE all local variables must have a statically known size diff --git a/src/test/ui/suggestions/str-array-assignment.stderr b/src/test/ui/suggestions/str-array-assignment.stderr index 55006b2760cca..14b744c2e469c 100644 --- a/src/test/ui/suggestions/str-array-assignment.stderr +++ b/src/test/ui/suggestions/str-array-assignment.stderr @@ -23,7 +23,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied --> $DIR/str-array-assignment.rs:21:7 | 21 | let v = s[..2]; - | ^ ------ help: consider a slice instead: `&s[..2]` + | ^ ------ help: consider borrowing here: `&s[..2]` | | | `str` does not have a constant size known at compile-time | From d5e8b61054018799c09d0e4c7166a6c4f198cbc5 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Mon, 27 Nov 2017 19:24:13 +0100 Subject: [PATCH 29/29] Change the stabilization version to 1.24.0 --- src/libcore/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 5486cb2926650..8a261b8f07737 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -103,7 +103,7 @@ use fmt; /// /// On some platforms this function may not do anything at all. #[inline] -#[stable(feature = "spin_loop_hint", since = "1.23.0")] +#[stable(feature = "spin_loop_hint", since = "1.24.0")] pub fn spin_loop_hint() { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] unsafe {