diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 49e488702b4b9..9dd43601cf02e 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -97,6 +97,9 @@ use self::Entry::*; /// } /// } /// +/// // Look up the value for a key (will panic if the key is not found). +/// println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]); +/// /// // iterate over everything. /// for (movie, review) in &movie_reviews { /// println!("{}: \"{}\"", movie, review); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 3ca6de191de2d..c0a947e701108 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1187,8 +1187,9 @@ impl, U: ?Sized> DispatchFromDyn> for Weak {} impl Weak { /// Constructs a new `Weak`, without allocating any memory. - /// Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`]. + /// Calling [`upgrade`] on the return value always gives [`None`]. /// + /// [`upgrade`]: #method.upgrade /// [`None`]: ../../std/option/enum.Option.html /// /// # Examples @@ -1260,6 +1261,52 @@ impl Weak { Some(unsafe { self.ptr.as_ref() }) } } + + /// Returns true if the two `Weak`s point to the same value (not just values + /// that compare as equal). + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any value. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_ptr_eq)] + /// use std::rc::{Rc, Weak}; + /// + /// let first_rc = Rc::new(5); + /// let first = Rc::downgrade(&first_rc); + /// let second = Rc::downgrade(&first_rc); + /// + /// assert!(Weak::ptr_eq(&first, &second)); + /// + /// let third_rc = Rc::new(5); + /// let third = Rc::downgrade(&third_rc); + /// + /// assert!(!Weak::ptr_eq(&first, &third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// #![feature(weak_ptr_eq)] + /// use std::rc::{Rc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(Weak::ptr_eq(&first, &second)); + /// + /// let third_rc = Rc::new(()); + /// let third = Rc::downgrade(&third_rc); + /// assert!(!Weak::ptr_eq(&first, &third)); + /// ``` + #[inline] + #[unstable(feature = "weak_ptr_eq", issue = "55981")] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + this.ptr.as_ptr() == other.ptr.as_ptr() + } } #[stable(feature = "rc_weak", since = "1.4.0")] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 4f4031e3c4e32..0a397f79103db 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1130,6 +1130,53 @@ impl Weak { Some(unsafe { self.ptr.as_ref() }) } } + + /// Returns true if the two `Weak`s point to the same value (not just values + /// that compare as equal). + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any value. + /// + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_ptr_eq)] + /// use std::sync::{Arc, Weak}; + /// + /// let first_rc = Arc::new(5); + /// let first = Arc::downgrade(&first_rc); + /// let second = Arc::downgrade(&first_rc); + /// + /// assert!(Weak::ptr_eq(&first, &second)); + /// + /// let third_rc = Arc::new(5); + /// let third = Arc::downgrade(&third_rc); + /// + /// assert!(!Weak::ptr_eq(&first, &third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// #![feature(weak_ptr_eq)] + /// use std::sync::{Arc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(Weak::ptr_eq(&first, &second)); + /// + /// let third_rc = Arc::new(()); + /// let third = Arc::downgrade(&third_rc); + /// assert!(!Weak::ptr_eq(&first, &third)); + /// ``` + #[inline] + #[unstable(feature = "weak_ptr_eq", issue = "55981")] + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + this.ptr.as_ptr() == other.ptr.as_ptr() + } } #[stable(feature = "arc_weak", since = "1.4.0")] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 8b1855800c2fd..5ba0e949483ae 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -238,6 +238,10 @@ macro_rules! debug_assert_ne { /// with converting downstream errors. /// /// The `?` operator was added to replace `try!` and should be used instead. +/// Furthermore, `try` is a reserved word in Rust 2018, so if you must use +/// it, you will need to use the [raw-identifier syntax][ris]: `r#try`. +/// +/// [ris]: https://doc.rust-lang.org/nightly/rust-by-example/compatibility/raw_identifiers.html /// /// `try!` matches the given [`Result`]. In case of the `Ok` variant, the /// expression has the value of the wrapped value. diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 89efa120a6fab..6c953d1b9a0ac 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -536,10 +536,9 @@ fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option where I: DoubleEndedIterator, { // Decode UTF-8 - let w = match bytes.next_back() { - None => return None, - Some(&next_byte) if next_byte < 128 => return Some(next_byte as u32), - Some(&back_byte) => back_byte, + let w = match *bytes.next_back()? { + next_byte if next_byte < 128 => return Some(next_byte as u32), + back_byte => back_byte, }; // Multibyte case follows diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 282b5d13e2c61..bb7a6a6ee7b72 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -166,6 +166,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) | hir::ItemKind::Static(..) + | hir::ItemKind::Existential(..) | hir::ItemKind::Const(..) => { intravisit::walk_item(self, &item); } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 35d1a4dd2cb7c..3c2551f5cd436 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -592,10 +592,7 @@ impl<'tcx> ScopeTree { return Some(scope.item_local_id()); } - match self.opt_encl_scope(scope) { - None => return None, - Some(parent) => scope = parent, - } + scope = self.opt_encl_scope(scope)?; } } diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 768d4f1e5fb65..6b0a8a0af2b9d 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -67,14 +67,13 @@ impl<'a> Iterator for Iter<'a> { fn next(&mut self) -> Option<(&'a Path, PathKind)> { loop { - match self.iter.next() { - Some(&(kind, ref p)) if self.kind == PathKind::All || - kind == PathKind::All || - kind == self.kind => { + match *self.iter.next()? { + (kind, ref p) if self.kind == PathKind::All || + kind == PathKind::All || + kind == self.kind => { return Some((p, kind)) } - Some(..) => {} - None => return None, + _ => {} } } } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index a802729e3fbdb..e47e95afb1643 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -615,7 +615,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let new_loan_str = &new_loan.kind.to_user_str(); self.bccx.cannot_reborrow_already_uniquely_borrowed( new_loan.span, "closure", &nl, &new_loan_msg, new_loan_str, - old_loan.span, &old_loan_msg, previous_end_span, Origin::Ast) + old_loan.span, &old_loan_msg, previous_end_span, "", Origin::Ast) } (..) => self.bccx.cannot_reborrow_already_borrowed( diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 96cb235a93362..8e0ecb70c6896 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -81,7 +81,6 @@ pub mod sync; pub mod tiny_list; pub mod thin_vec; pub mod transitive_relation; -pub mod tuple_slice; pub use ena::unify; pub mod vec_linked_list; pub mod work_queue; diff --git a/src/librustc_data_structures/tuple_slice.rs b/src/librustc_data_structures/tuple_slice.rs deleted file mode 100644 index b7c71dd366469..0000000000000 --- a/src/librustc_data_structures/tuple_slice.rs +++ /dev/null @@ -1,70 +0,0 @@ -// 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 std::slice; - -/// Allows to view uniform tuples as slices -pub trait TupleSlice { - fn as_slice(&self) -> &[T]; - fn as_mut_slice(&mut self) -> &mut [T]; -} - -macro_rules! impl_tuple_slice { - ($tuple_type:ty, $size:expr) => { - impl TupleSlice for $tuple_type { - fn as_slice(&self) -> &[T] { - unsafe { - let ptr = &self.0 as *const T; - slice::from_raw_parts(ptr, $size) - } - } - - fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { - let ptr = &mut self.0 as *mut T; - slice::from_raw_parts_mut(ptr, $size) - } - } - } - } -} - -impl_tuple_slice!((T, T), 2); -impl_tuple_slice!((T, T, T), 3); -impl_tuple_slice!((T, T, T, T), 4); -impl_tuple_slice!((T, T, T, T, T), 5); -impl_tuple_slice!((T, T, T, T, T, T), 6); -impl_tuple_slice!((T, T, T, T, T, T, T), 7); -impl_tuple_slice!((T, T, T, T, T, T, T, T), 8); - -#[test] -fn test_sliced_tuples() { - let t2 = (100, 101); - assert_eq!(t2.as_slice(), &[100, 101]); - - let t3 = (102, 103, 104); - assert_eq!(t3.as_slice(), &[102, 103, 104]); - - let t4 = (105, 106, 107, 108); - assert_eq!(t4.as_slice(), &[105, 106, 107, 108]); - - let t5 = (109, 110, 111, 112, 113); - assert_eq!(t5.as_slice(), &[109, 110, 111, 112, 113]); - - let t6 = (114, 115, 116, 117, 118, 119); - assert_eq!(t6.as_slice(), &[114, 115, 116, 117, 118, 119]); - - let t7 = (120, 121, 122, 123, 124, 125, 126); - assert_eq!(t7.as_slice(), &[120, 121, 122, 123, 124, 125, 126]); - - let t8 = (127, 128, 129, 130, 131, 132, 133, 134); - assert_eq!(t8.as_slice(), &[127, 128, 129, 130, 131, 132, 133, 134]); - -} diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index cfe59b1f67262..ddd28eb5393ec 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -29,7 +29,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( return None } - let saved_files: Option> = + let saved_files = files.iter() .map(|&(kind, ref path)| { let extension = match kind { @@ -51,11 +51,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( } } }) - .collect(); - let saved_files = match saved_files { - None => return None, - Some(v) => v, - }; + .collect::>>()?; let work_product = WorkProduct { cgu_name: cgu_name.to_string(), diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index fd7dc7fc4bd3a..947c32df0f6a3 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -16,7 +16,7 @@ use rustc::mir::traversal; use rustc::mir::visit::{ PlaceContext, Visitor, NonUseContext, MutatingUseContext, NonMutatingUseContext }; -use rustc::mir::{self, Location, Mir, Place, Local}; +use rustc::mir::{self, Location, Mir, Local}; use rustc::ty::{RegionVid, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; @@ -41,10 +41,6 @@ crate struct BorrowSet<'tcx> { /// only need to store one borrow index crate activation_map: FxHashMap>, - /// Every borrow has a region; this maps each such regions back to - /// its borrow-indexes. - crate region_map: FxHashMap>, - /// Map from local to all the borrows on that local crate local_map: FxHashMap>, @@ -149,7 +145,6 @@ impl<'tcx> BorrowSet<'tcx> { idx_vec: IndexVec::new(), location_map: Default::default(), activation_map: Default::default(), - region_map: Default::default(), local_map: Default::default(), pending_activations: Default::default(), locals_state_at_exit: @@ -164,7 +159,6 @@ impl<'tcx> BorrowSet<'tcx> { borrows: visitor.idx_vec, location_map: visitor.location_map, activation_map: visitor.activation_map, - region_map: visitor.region_map, local_map: visitor.local_map, locals_state_at_exit: visitor.locals_state_at_exit, } @@ -184,7 +178,6 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { idx_vec: IndexVec>, location_map: FxHashMap, activation_map: FxHashMap>, - region_map: FxHashMap>, local_map: FxHashMap>, /// When we encounter a 2-phase borrow statement, it will always @@ -229,7 +222,6 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { self.insert_as_pending_if_two_phase(location, &assigned_place, kind, idx); - self.region_map.entry(region).or_default().insert(idx); if let Some(local) = borrowed_place.root_local() { self.local_map.entry(local).or_default().insert(idx); } @@ -238,68 +230,68 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { self.super_assign(block, assigned_place, rvalue, location) } - fn visit_place( + fn visit_local( &mut self, - place: &mir::Place<'tcx>, + temp: &Local, context: PlaceContext<'tcx>, location: Location, ) { - self.super_place(place, context, location); - - // We found a use of some temporary TEMP... - if let Place::Local(temp) = place { - // ... check whether we (earlier) saw a 2-phase borrow like - // - // TMP = &mut place - if let Some(&borrow_index) = self.pending_activations.get(temp) { - let borrow_data = &mut self.idx_vec[borrow_index]; - - // Watch out: the use of TMP in the borrow itself - // doesn't count as an activation. =) - if borrow_data.reserve_location == location && - context == PlaceContext::MutatingUse(MutatingUseContext::Store) - { - return; - } + if !context.is_use() { + return; + } - if let TwoPhaseActivation::ActivatedAt(other_location) = - borrow_data.activation_location { - span_bug!( - self.mir.source_info(location).span, - "found two uses for 2-phase borrow temporary {:?}: \ - {:?} and {:?}", - temp, - location, - other_location, - ); - } + // We found a use of some temporary TMP + // check whether we (earlier) saw a 2-phase borrow like + // + // TMP = &mut place + if let Some(&borrow_index) = self.pending_activations.get(temp) { + let borrow_data = &mut self.idx_vec[borrow_index]; - // Otherwise, this is the unique later use - // that we expect. - borrow_data.activation_location = match context { - // The use of TMP in a shared borrow does not - // count as an actual activation. - PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | - PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) => - TwoPhaseActivation::NotActivated, - _ => { - // Double check: This borrow is indeed a two-phase borrow (that is, - // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and - // we've not found any other activations (checked above). - assert_eq!( - borrow_data.activation_location, - TwoPhaseActivation::NotActivated, - "never found an activation for this borrow!", - ); - - self.activation_map - .entry(location) - .or_default() - .push(borrow_index); - TwoPhaseActivation::ActivatedAt(location) - } - }; + // Watch out: the use of TMP in the borrow itself + // doesn't count as an activation. =) + if borrow_data.reserve_location == location && + context == PlaceContext::MutatingUse(MutatingUseContext::Store) + { + return; + } + + if let TwoPhaseActivation::ActivatedAt(other_location) = + borrow_data.activation_location { + span_bug!( + self.mir.source_info(location).span, + "found two uses for 2-phase borrow temporary {:?}: \ + {:?} and {:?}", + temp, + location, + other_location, + ); } + + // Otherwise, this is the unique later use + // that we expect. + borrow_data.activation_location = match context { + // The use of TMP in a shared borrow does not + // count as an actual activation. + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) => + TwoPhaseActivation::NotActivated, + _ => { + // Double check: This borrow is indeed a two-phase borrow (that is, + // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and + // we've not found any other activations (checked above). + assert_eq!( + borrow_data.activation_location, + TwoPhaseActivation::NotActivated, + "never found an activation for this borrow!", + ); + + self.activation_map + .entry(location) + .or_default() + .push(borrow_index); + TwoPhaseActivation::ActivatedAt(location) + } + }; } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 4ccd26bee8b88..ba26ed36c20f4 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -344,6 +344,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let first_borrow_desc; + let explanation = self.explain_why_borrow_contains_point(context, issued_borrow, None); + let second_borrow_desc = if explanation.is_explained() { + "second " + } else { + "" + }; + // FIXME: supply non-"" `opt_via` when appropriate let mut err = match ( gen_borrow_kind, @@ -454,6 +461,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { issued_span, "", None, + second_borrow_desc, Origin::Mir, ) } @@ -469,6 +477,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { issued_span, "", None, + second_borrow_desc, Origin::Mir, ) } @@ -513,7 +522,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - self.explain_why_borrow_contains_point(context, issued_borrow, None) + explanation .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc); err.buffer(&mut self.errors_buffer); diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index bb9a29b055b7f..477b78926084e 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -52,6 +52,12 @@ pub(in borrow_check) enum LaterUseKind { } impl BorrowExplanation { + pub(in borrow_check) fn is_explained(&self) -> bool { + match self { + BorrowExplanation::Unexplained => false, + _ => true, + } + } pub(in borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx, 'tcx>( &self, tcx: TyCtxt<'cx, 'gcx, 'tcx>, diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index f73e08eb13521..7d583b4f54191 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -87,10 +87,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> { type Item = &'cx Place<'tcx>; fn next(&mut self) -> Option { - let mut cursor = match self.next { - None => return None, - Some(place) => place, - }; + let mut cursor = self.next?; // Post-processing `place`: Enqueue any remaining // work. Also, `place` may not be a prefix itself, but diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 27bc28ac81d84..3a9e4fc9e4ab9 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -246,7 +246,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { // re-consider the current implementations of the // propagate_call_return method. - if let mir::Rvalue::Ref(region, _, ref place) = **rhs { + if let mir::Rvalue::Ref(_, _, ref place) = **rhs { if place.ignore_borrow( self.tcx, self.mir, @@ -258,13 +258,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { panic!("could not find BorrowIndex for location {:?}", location); }); - assert!(self.borrow_set.region_map - .get(®ion.to_region_vid()) - .unwrap_or_else(|| { - panic!("could not find BorrowIndexs for RegionVid {:?}", region); - }) - .contains(&index) - ); sets.gen(*index); // Issue #46746: Two-phase borrows handles diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 3a6ee6da42215..528942df29fee 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -585,7 +585,7 @@ fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, // smallest into each other) we're sure to start off with a deterministic // order (sorted by name). This'll mean that if two cgus have the same size // the stable sort below will keep everything nice and deterministic. - codegen_units.sort_by_key(|cgu| cgu.name().clone()); + codegen_units.sort_by_key(|cgu| *cgu.name()); // Merge the two smallest codegen units until the target size is reached. while codegen_units.len() > target_cgu_count { @@ -985,7 +985,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>( output.push_str(" @@"); let mut empty = Vec::new(); let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); - cgus.as_mut_slice().sort_by_cached_key(|&(ref name, _)| name.clone()); + cgus.sort_by_key(|(name, _)| *name); cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push_str(" "); diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index c0edd3926d32d..6d7fc404edbb1 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -10,17 +10,25 @@ //! This module provides two passes: //! -//! - [CleanAscribeUserType], that replaces all -//! [StatementKind::AscribeUserType] statements with [StatementKind::Nop]. -//! - [CleanFakeReadsAndBorrows], that replaces all [FakeRead] statements and -//! borrows that are read by [FakeReadCause::ForMatchGuard] fake reads with -//! [StatementKind::Nop]. +//! - [`CleanAscribeUserType`], that replaces all [`AscribeUserType`] +//! statements with [`Nop`]. +//! - [`CleanFakeReadsAndBorrows`], that replaces all [`FakeRead`] statements +//! and borrows that are read by [`ForMatchGuard`] fake reads with [`Nop`]. //! -//! The [CleanFakeReadsAndBorrows] "pass" is actually implemented as two +//! The `CleanFakeReadsAndBorrows` "pass" is actually implemented as two //! traversals (aka visits) of the input MIR. The first traversal, -//! [DeleteAndRecordFakeReads], deletes the fake reads and finds the temporaries -//! read by [ForMatchGuard] reads, and [DeleteFakeBorrows] deletes the -//! initialization of those temporaries. +//! [`DeleteAndRecordFakeReads`], deletes the fake reads and finds the +//! temporaries read by [`ForMatchGuard`] reads, and [`DeleteFakeBorrows`] +//! deletes the initialization of those temporaries. +//! +//! [`CleanAscribeUserType`]: cleanup_post_borrowck::CleanAscribeUserType +//! [`CleanFakeReadsAndBorrows`]: cleanup_post_borrowck::CleanFakeReadsAndBorrows +//! [`DeleteAndRecordFakeReads`]: cleanup_post_borrowck::DeleteAndRecordFakeReads +//! [`DeleteFakeBorrows`]: cleanup_post_borrowck::DeleteFakeBorrows +//! [`AscribeUserType`]: rustc::mir::StatementKind::AscribeUserType +//! [`Nop`]: rustc::mir::StatementKind::Nop +//! [`FakeRead`]: rustc::mir::StatementKind::FakeRead +//! [`ForMatchGuard`]: rustc::mir::FakeReadCause::ForMatchGuard use rustc_data_structures::fx::FxHashSet; diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index ae0483e3c140c..8566f845f23e3 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -261,6 +261,7 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { old_loan_span: Span, old_opt_via: &str, previous_end_span: Option, + second_borrow_desc: &str, o: Origin, ) -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!( @@ -274,7 +275,10 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { kind_new, OGN = o ); - err.span_label(new_loan_span, format!("borrow occurs here{}", opt_via)); + err.span_label( + new_loan_span, + format!("{}borrow occurs here{}", second_borrow_desc, opt_via), + ); err.span_label( old_loan_span, format!("{} construction occurs here{}", container_name, old_opt_via), diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 0fa41cb484fc9..da4cd73923ede 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -318,7 +318,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // This particular use tree &tree, id, &prefix, true, // The whole `use` item - parent_scope.clone(), item, ty::Visibility::Invisible, root_span, + parent_scope, item, ty::Visibility::Invisible, root_span, ); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fd8f70b19e7ec..1d903476f16f9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3948,10 +3948,7 @@ pub fn path_to_def_local(tcx: &TyCtxt, path: &[&str]) -> Option { let mut path_it = path.iter().peekable(); loop { - let segment = match path_it.next() { - Some(segment) => segment, - None => return None, - }; + let segment = path_it.next()?; for item_id in mem::replace(&mut items, HirVec::new()).iter() { let item = tcx.hir.expect_item(item_id.id); @@ -3986,10 +3983,7 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option { let mut path_it = path.iter().skip(1).peekable(); loop { - let segment = match path_it.next() { - Some(segment) => segment, - None => return None, - }; + let segment = path_it.next()?; for item in mem::replace(&mut items, Lrc::new(vec![])).iter() { if item.ident.name == *segment { diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 5263cfe7b0e4f..fa5d015e5b72d 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -57,6 +57,9 @@ pub fn render( {css_extension}\ {favicon}\ {in_header}\ + \ \ \ $DIR/borrowck-insert-during-each.rs:27:9 diff --git a/src/test/ui/existential_types/private_unused.rs b/src/test/ui/existential_types/private_unused.rs new file mode 100644 index 0000000000000..736d812bc0aff --- /dev/null +++ b/src/test/ui/existential_types/private_unused.rs @@ -0,0 +1,13 @@ +// compile-pass + +#[deny(warnings)] + +enum Empty { } +trait Bar {} +impl Bar for () {} + +fn boo() -> impl Bar {} + +fn main() { + boo(); +} diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr index 8dabb3c2505b6..60163d78e78f9 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr +++ b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr @@ -7,7 +7,7 @@ LL | let a = &mut *x; | - first borrow occurs due to use of `x` in generator ... LL | println!("{}", x); //~ ERROR - | ^ borrow occurs here + | ^ second borrow occurs here LL | b.resume(); | - first borrow later used here diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr index 3e423dadd192c..98a261657b1e7 100644 --- a/src/test/ui/nll/closure-borrow-spans.stderr +++ b/src/test/ui/nll/closure-borrow-spans.stderr @@ -126,7 +126,7 @@ LL | let f = || *x = 0; | | | closure construction occurs here LL | let y = &x; //~ ERROR - | ^^ borrow occurs here + | ^^ second borrow occurs here LL | f.use_ref(); | - first borrow later used here @@ -138,7 +138,7 @@ LL | let f = || *x = 0; | | | closure construction occurs here LL | let y = &mut x; //~ ERROR - | ^^^^^^ borrow occurs here + | ^^^^^^ second borrow occurs here LL | f.use_ref(); | - first borrow later used here diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index dd2e5557c16d4..8d20a9e271705 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -119,10 +119,7 @@ fn parse_expected( line: &str, tag: &str, ) -> Option<(WhichLine, Error)> { - let start = match line.find(tag) { - Some(i) => i, - None => return None, - }; + let start = line.find(tag)?; let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' { (true, 0) } else { diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ed2114b653015..f4a82aeb307dc 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -707,14 +707,8 @@ impl Config { fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> { if self.parse_cfg_name_directive(line, prefix) == ParsedNameDirective::Match { - let from = match parse_normalization_string(&mut line) { - Some(s) => s, - None => return None, - }; - let to = match parse_normalization_string(&mut line) { - Some(s) => s, - None => return None, - }; + let from = parse_normalization_string(&mut line)?; + let to = parse_normalization_string(&mut line)?; Some((from, to)) } else { None @@ -873,14 +867,8 @@ fn expand_variables(mut value: String, config: &Config) -> String { /// ``` fn parse_normalization_string(line: &mut &str) -> Option { // FIXME support escapes in strings. - let begin = match line.find('"') { - Some(i) => i + 1, - None => return None, - }; - let end = match line[begin..].find('"') { - Some(i) => i + begin, - None => return None, - }; + let begin = line.find('"')? + 1; + let end = line[begin..].find('"')? + begin; let result = line[begin..end].to_owned(); *line = &line[end + 1..]; Some(result) diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 11c83819eaa93..e6bf9a285723b 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -332,10 +332,7 @@ fn maybe_redirect(source: &str) -> Option { const REDIRECT: &'static str = "

Redirecting to