From 4130a323b6aa1df5466d3b0d13c0e51039b6827d Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Thu, 19 Aug 2021 20:21:41 +0800 Subject: [PATCH 01/23] bootstrap.py: recognize riscv64 when auto-detect The architecture auto-detect table has no entry for riscv64 (which rustc uses riscv64gc for the first part of triplet, assuming it's a generic Linux distro). Add it to the table to allow riscv64 systems to bootstrap Rust. Signed-off-by: Icenowy Zheng --- src/bootstrap/bootstrap.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 3faf38c66ec8b..e34768bc2c906 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -301,6 +301,7 @@ def default_build_triple(verbose): 'ppc': 'powerpc', 'ppc64': 'powerpc64', 'ppc64le': 'powerpc64le', + 'riscv64': 'riscv64gc', 's390x': 's390x', 'x64': 'x86_64', 'x86': 'i686', From 51d598ec285fc8aa29e2a1c64dc90394ccbd4130 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Thu, 19 Aug 2021 12:35:20 +0200 Subject: [PATCH 02/23] Adjust documentation of `Arc::make_mut` Related discussion in the users forum: https://users.rust-lang.org/t/what-s-this-alleged-difference-between-arc-make-mut-and-rc-make-mut/63747?u=steffahn Also includes small formatting improvement in the documentation of `Rc::make_mut`. This commit makes the two documentations in question complete analogs. The previously claimed point in which one "differs from the behavior of" the other turns out to be incorrect, AFAIK. One remaining inaccuracy: `Weak` pointers aren't disassociated from the allocation but only from the contained value, i.e. in case of outstanding `Weak` pointers there still is a new allocation created, just the call to `.clone()` is avoided, instead the value is moved from one allocation to the other. --- library/alloc/src/rc.rs | 10 +++++----- library/alloc/src/sync.rs | 34 +++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0b3079fa59db6..90b077210a475 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1115,11 +1115,11 @@ impl Rc { /// /// let mut data = Rc::new(5); /// - /// *Rc::make_mut(&mut data) += 1; // Won't clone anything - /// let mut other_data = Rc::clone(&data); // Won't clone inner data - /// *Rc::make_mut(&mut data) += 1; // Clones inner data - /// *Rc::make_mut(&mut data) += 1; // Won't clone anything - /// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything + /// *Rc::make_mut(&mut data) += 1; // Won't clone anything + /// let mut other_data = Rc::clone(&data); // Won't clone inner data + /// *Rc::make_mut(&mut data) += 1; // Clones inner data + /// *Rc::make_mut(&mut data) += 1; // Won't clone anything + /// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything /// /// // Now `data` and `other_data` point to different allocations. /// assert_eq!(*data, 8); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 3183a6db410b8..7e4cb6d2c60f2 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1346,18 +1346,17 @@ impl Receiver for Arc {} impl Arc { /// Makes a mutable reference into the given `Arc`. /// - /// If there are other `Arc` or [`Weak`] pointers to the same allocation, - /// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value - /// to ensure unique ownership. This is also referred to as clone-on-write. + /// If there are other `Arc` pointers to the same allocation, then `make_mut` will + /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also + /// referred to as clone-on-write. /// - /// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates - /// any remaining `Weak` pointers. + /// If there are no other `Arc` pointers to this allocation, then [`Weak`] + /// pointers to this allocation will be disassociated. /// - /// See also [`get_mut`][get_mut], which will fail rather than cloning. + /// See also [`get_mut`], which will fail rather than cloning. /// - /// [clone]: Clone::clone - /// [get_mut]: Arc::get_mut - /// [`Rc::make_mut`]: super::rc::Rc::make_mut + /// [`clone`]: Clone::clone + /// [`get_mut`]: Arc::get_mut /// /// # Examples /// @@ -1376,6 +1375,23 @@ impl Arc { /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` + /// + /// [`Weak`] pointers will be disassociated: + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut data = Arc::new(75); + /// let weak = Arc::downgrade(&data); + /// + /// assert!(75 == *data); + /// assert!(75 == *weak.upgrade().unwrap()); + /// + /// *Arc::make_mut(&mut data) += 1; + /// + /// assert!(76 == *data); + /// assert!(weak.upgrade().is_none()); + /// ``` #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "arc_unique", since = "1.4.0")] From 65bfc3130a782464d301c85b3edcbed5732b8a52 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 21 Aug 2021 15:09:03 -0700 Subject: [PATCH 03/23] Remove the `TryV2` alias Post-bootstrap-update cleanup. --- library/core/src/iter/traits/iterator.rs | 4 ++-- library/core/src/ops/control_flow.rs | 4 ++-- library/core/src/ops/mod.rs | 8 +------- library/core/src/option.rs | 2 +- library/core/src/result.rs | 2 +- library/core/src/task/poll.rs | 4 ++-- 6 files changed, 9 insertions(+), 15 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 524d8f857e2a5..75987d18fe00e 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2442,14 +2442,14 @@ pub trait Iterator { R: Try, // FIXME: This bound is rather strange, but means minimal breakage on nightly. // See #85115 for the issue tracking a holistic solution for this and try_map. - R: crate::ops::TryV2>, + R: Try>, { #[inline] fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> where F: FnMut(&T) -> R, R: Try, - R: crate::ops::TryV2>, + R: Try>, { move |(), x| match f(&x).branch() { ControlFlow::Continue(false) => ControlFlow::CONTINUE, diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index c2270c864dfae..cd2d57699c92c 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -63,7 +63,7 @@ pub enum ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::TryV2 for ControlFlow { +impl ops::Try for ControlFlow { type Output = C; type Residual = ControlFlow; @@ -165,7 +165,7 @@ impl ControlFlow { /// These are used only as part of implementing the iterator adapters. /// They have mediocre names and non-obvious semantics, so aren't /// currently on a path to potential stabilization. -impl ControlFlow { +impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. #[inline] pub(crate) fn from_try(r: R) -> Self { diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 85e04740d96a4..bd7feb8b183ce 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -182,13 +182,7 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; #[unstable(feature = "try_trait_v2", issue = "84277")] -pub use self::try_trait::FromResidual; - -#[unstable(feature = "try_trait_v2", issue = "84277")] -pub use self::try_trait::Try; - -#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")] -pub(crate) use self::try_trait::Try as TryV2; +pub use self::try_trait::{FromResidual, Try}; #[unstable(feature = "generator_trait", issue = "43122")] pub use self::generator::{Generator, GeneratorState}; diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 78f5954532ff0..47865240f6a6f 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -2013,7 +2013,7 @@ impl> FromIterator> for Option { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::TryV2 for Option { +impl ops::Try for Option { type Output = T; type Residual = Option; diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 861790e8a4099..092e6544342b7 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1889,7 +1889,7 @@ impl> FromIterator> for Result { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::TryV2 for Result { +impl ops::Try for Result { type Output = T; type Residual = Result; diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index fc0a4e747973a..2507046099632 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -222,7 +222,7 @@ impl From for Poll { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::TryV2 for Poll> { +impl ops::Try for Poll> { type Output = Poll; type Residual = Result; @@ -252,7 +252,7 @@ impl> ops::FromResidual> for Pol } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::TryV2 for Poll>> { +impl ops::Try for Poll>> { type Output = Poll>; type Residual = Result; From 41f9f38d6e19c669a14432b9ec56f26425c6c9e2 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 21 Aug 2021 18:45:56 -0500 Subject: [PATCH 04/23] Remove `Session.trait_methods_not_found` Instead, avoid registering the problematic well-formed obligation to begin with. This removes global untracked mutable state, and avoids potential issues with incremental compilation. --- .../src/traits/error_reporting/mod.rs | 6 ----- compiler/rustc_session/src/session.rs | 4 ---- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 23 ++++++++++++++++++- .../rustc_typeck/src/check/method/suggest.rs | 5 +--- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 0ac4b6b25bbfe..d0bd508bc257f 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -104,11 +104,5 @@ pub fn report_object_safety_error( to be resolvable dynamically; for more information visit \ ", ); - - if tcx.sess.trait_methods_not_found.borrow().iter().any(|full_span| full_span.contains(span)) { - // Avoid emitting error caused by non-existing method (#58734) - err.cancel(); - } - err } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 5b163603d5ffb..fabdebfb2127b 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -189,9 +189,6 @@ pub struct Session { /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap, - /// `Span`s of trait methods that weren't found to avoid emitting object safety errors - pub trait_methods_not_found: Lock>, - /// Mapping from ident span to path span for paths that don't exist as written, but that /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. pub confused_type_with_std_module: Lock>, @@ -1353,7 +1350,6 @@ pub fn build_session( print_fuel, jobserver: jobserver::client(), driver_lint_caps, - trait_methods_not_found: Lock::new(Default::default()), confused_type_with_std_module: Lock::new(Default::default()), ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index bb80f0879a4aa..8be57e4b3cab9 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -858,13 +858,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { path.segments, ); } - QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment), + QPath::TypeRelative(ref qself, ref segment) => { + // Don't use `self.to_ty`, since this will register a WF obligation. + // If we're trying to call a non-existent method on a trait + // (e.g. `MyTrait::missing_method`), then resolution will + // give us a `QPath::TypeRelative` with a trait object as + // `qself`. In that case, we want to avoid registering a WF obligation + // for `dyn MyTrait`, since we don't actually need the trait + // to be object-safe. + // We manually call `register_wf_obligation` in the success path + // below. + (>::ast_ty_to_ty(self, qself), qself, segment) + } QPath::LangItem(..) => { bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") } }; if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id) { + self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); // Return directly on cache hit. This is useful to avoid doubly reporting // errors with default match binding modes. See #44614. let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)); @@ -878,6 +890,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), _ => Err(ErrorReported), }; + + // If we have a path like `MyTrait::missing_method`, then don't register + // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise, + // register a WF obligation so that we can detect any additional + // errors in the self type. + if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) { + self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); + } if item_name.name != kw::Empty { if let Some(mut e) = self.report_method_error( span, @@ -895,6 +915,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if result.is_ok() { self.maybe_lint_bare_trait(qpath, hir_id); + self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); } // Write back the new resolution. diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 1d5a9e3e1f968..afe274a2a796e 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -70,15 +70,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn report_method_error( &self, - span: Span, + mut span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, source: SelfSource<'tcx>, error: MethodError<'tcx>, args: Option<&'tcx [hir::Expr<'tcx>]>, ) -> Option> { - let orig_span = span; - let mut span = span; // Avoid suggestions when we don't know what's going on. if rcvr_ty.references_error() { return None; @@ -545,7 +543,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds")); } - self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span); }; // If the method name is the name of a field with a function or closure type, From 9c44d80c83eb250594ecad05ea5340e0b51af525 Mon Sep 17 00:00:00 2001 From: Jack O'Connor Date: Wed, 11 Aug 2021 14:38:20 -0400 Subject: [PATCH 05/23] add Cell::as_array_of_cells, similar to Cell::as_slice_of_cells Previously, converting `&mut [T; N]` to `&[Cell; N]` looks like this: let array = &mut [1, 2, 3]; let cells: &[Cell; 3] = Cell::from_mut(&mut array[..]) .as_slice_of_cells() .try_into() .unwrap(); With this new helper method, it looks like this: let array = &mut [1, 2, 3]; let cells: &[Cell; 3] = Cell::from_mut(array).as_array_of_cells(); --- library/core/src/cell.rs | 20 +++++++++++++++++++ src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs | 9 +++++++++ 2 files changed, 29 insertions(+) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index f0c934edf3977..85b43f4884760 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -576,6 +576,26 @@ impl Cell<[T]> { } } +impl Cell<[T; N]> { + /// Returns a `&[Cell; N]` from a `&Cell<[T; N]>` + /// + /// # Examples + /// + /// ``` + /// #![feature(as_array_of_cells)] + /// use std::cell::Cell; + /// + /// let mut array: [i32; 3] = [1, 2, 3]; + /// let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array); + /// let array_cell: &[Cell; 3] = cell_array.as_array_of_cells(); + /// ``` + #[unstable(feature = "as_array_of_cells", issue = "88248")] + pub fn as_array_of_cells(&self) -> &[Cell; N] { + // SAFETY: `Cell` has the same memory layout as `T`. + unsafe { &*(self as *const Cell<[T; N]> as *const [Cell; N]) } + } +} + /// A mutable memory location with dynamically checked borrow rules /// /// See the [module-level documentation](self) for more. diff --git a/src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs b/src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs index ea3ad7aed4926..329fadb150fcd 100644 --- a/src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs +++ b/src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs @@ -1,5 +1,7 @@ // run-pass +#![feature(as_array_of_cells)] + use std::cell::Cell; fn main() { @@ -8,4 +10,11 @@ fn main() { let slice_cell: &[Cell] = cell_slice.as_slice_of_cells(); assert_eq!(slice_cell.len(), 3); + + let mut array: [i32; 3] = [1, 2, 3]; + let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array); + let array_cell: &[Cell; 3] = cell_array.as_array_of_cells(); + + array_cell[0].set(99); + assert_eq!(array, [99, 2, 3]); } From ed43e02e8c9766206404768096132f10c796745a Mon Sep 17 00:00:00 2001 From: Aman Arora Date: Mon, 23 Aug 2021 15:59:46 -0400 Subject: [PATCH 06/23] 2229: Update signature for truncate function --- compiler/rustc_typeck/src/check/upvar.rs | 118 +++++++++-------------- 1 file changed, 48 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 34176623ebc45..d3d8e73e19a3b 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -489,7 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut root_var_min_capture_list = typeck_results.closure_min_captures.remove(&closure_def_id).unwrap_or_default(); - for (place, capture_info) in capture_information.into_iter() { + for (mut place, capture_info) in capture_information.into_iter() { let var_hir_id = match place.base { PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, base => bug!("Expected upvar, found={:?}", base), @@ -530,14 +530,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Truncate the descendant (already in min_captures) to be same as the ancestor to handle any // possible change in capture mode. - let (_, descendant_capture_kind) = truncate_place_to_len( - possible_descendant.place, - possible_descendant.info.capture_kind, + truncate_place_to_len_and_update_capture_kind( + &mut possible_descendant.place, + &mut possible_descendant.info.capture_kind, place.projections.len(), ); - possible_descendant.info.capture_kind = descendant_capture_kind; - updated_capture_info = determine_capture_info(updated_capture_info, possible_descendant.info); @@ -561,14 +559,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Truncate the descendant (current place) to be same as the ancestor to handle any // possible change in capture mode. - let (_, descendant_capture_kind) = truncate_place_to_len( - place.clone(), - updated_capture_info.capture_kind, + truncate_place_to_len_and_update_capture_kind( + &mut place, + &mut updated_capture_info.capture_kind, possible_ancestor.place.projections.len(), ); - updated_capture_info.capture_kind = descendant_capture_kind; - possible_ancestor.info = determine_capture_info( possible_ancestor.info, updated_capture_info, @@ -1476,7 +1472,7 @@ fn restrict_repr_packed_field_ref_capture<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, place: &Place<'tcx>, - curr_borrow_kind: ty::UpvarCapture<'tcx>, + mut curr_borrow_kind: ty::UpvarCapture<'tcx>, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { let pos = place.projections.iter().enumerate().position(|(i, p)| { let ty = place.ty_before_projection(i); @@ -1508,13 +1504,13 @@ fn restrict_repr_packed_field_ref_capture<'tcx>( } }); - let place = place.clone(); + let mut place = place.clone(); if let Some(pos) = pos { - truncate_place_to_len(place, curr_borrow_kind, pos) - } else { - (place, curr_borrow_kind) + truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_borrow_kind, pos); } + + (place, curr_borrow_kind) } /// Returns a Ty that applies the specified capture kind on the provided capture Ty @@ -1841,31 +1837,28 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { /// them completely. /// - No projections are applied on top of Union ADTs, since these require unsafe blocks. fn restrict_precision_for_unsafe( - place: Place<'tcx>, - curr_mode: ty::UpvarCapture<'tcx>, + mut place: Place<'tcx>, + mut curr_mode: ty::UpvarCapture<'tcx>, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { - if place.projections.is_empty() { - // Nothing to do here - return (place, curr_mode); - } - if place.base_ty.is_unsafe_ptr() { - return truncate_place_to_len(place, curr_mode, 0); + truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0); } if place.base_ty.is_union() { - return truncate_place_to_len(place, curr_mode, 0); + truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0); } for (i, proj) in place.projections.iter().enumerate() { if proj.ty.is_unsafe_ptr() { // Don't apply any projections on top of an unsafe ptr. - return truncate_place_to_len(place, curr_mode, i + 1); + truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i + 1); + break; } if proj.ty.is_union() { // Don't capture preicse fields of a union. - return truncate_place_to_len(place, curr_mode, i + 1); + truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i + 1); + break; } } @@ -1880,7 +1873,7 @@ fn restrict_capture_precision<'tcx>( place: Place<'tcx>, curr_mode: ty::UpvarCapture<'tcx>, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { - let (place, curr_mode) = restrict_precision_for_unsafe(place, curr_mode); + let (mut place, mut curr_mode) = restrict_precision_for_unsafe(place, curr_mode); if place.projections.is_empty() { // Nothing to do here @@ -1891,7 +1884,8 @@ fn restrict_capture_precision<'tcx>( match proj.kind { ProjectionKind::Index => { // Arrays are completely captured, so we drop Index projections - return truncate_place_to_len(place, curr_mode, i); + truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i); + return (place, curr_mode); } ProjectionKind::Deref => {} ProjectionKind::Field(..) => {} // ignore @@ -1906,8 +1900,8 @@ fn restrict_capture_precision<'tcx>( /// (or if closure attempts to move data that it doesn’t own). /// Note: When taking ownership, only capture data found on the stack. fn adjust_for_move_closure<'tcx>( - place: Place<'tcx>, - kind: ty::UpvarCapture<'tcx>, + mut place: Place<'tcx>, + mut kind: ty::UpvarCapture<'tcx>, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref()); let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref); @@ -1917,52 +1911,38 @@ fn adjust_for_move_closure<'tcx>( // If there's any Deref and the data needs to be moved into the closure body, // or it's a Deref of a Box, truncate the path to the first deref - _ if first_deref.is_some() => { - let place = match first_deref { - Some(idx) => { - let (place, _) = truncate_place_to_len(place, kind, idx); - place - } - None => place, - }; + _ => { + if let Some(idx) = first_deref { + truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx); + } // AMAN: I think we don't need the span inside the ByValue anymore // we have more detailed span in CaptureInfo (place, ty::UpvarCapture::ByValue(None)) } - - _ => (place, ty::UpvarCapture::ByValue(None)), } } /// Adjust closure capture just that if taking ownership of data, only move data /// from enclosing stack frame. fn adjust_for_non_move_closure<'tcx>( - place: Place<'tcx>, + mut place: Place<'tcx>, mut kind: ty::UpvarCapture<'tcx>, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { let contains_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref); match kind { - ty::UpvarCapture::ByValue(..) if contains_deref.is_some() => { - let place = match contains_deref { - Some(idx) => { - let (place, new_kind) = truncate_place_to_len(place, kind, idx); - - kind = new_kind; - place - } - // Because of the if guard on the match on `kind`, we should never get here. - None => unreachable!(), - }; - - (place, kind) + ty::UpvarCapture::ByValue(..) => { + if let Some(idx) = contains_deref { + truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx); + } } - ty::UpvarCapture::ByValue(..) => (place, kind), - ty::UpvarCapture::ByRef(..) => (place, kind), + ty::UpvarCapture::ByRef(..) => {} } + + (place, kind) } fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { @@ -2157,15 +2137,13 @@ fn determine_capture_info( /// /// Note: Capture kind changes from `MutBorrow` to `UniqueImmBorrow` if the truncated part of the `place` /// contained `Deref` of `&mut`. -fn truncate_place_to_len( - mut place: Place<'tcx>, - curr_mode: ty::UpvarCapture<'tcx>, +fn truncate_place_to_len_and_update_capture_kind( + place: &mut Place<'tcx>, + curr_mode: &mut ty::UpvarCapture<'tcx>, len: usize, -) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { +) { let is_mut_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Mut)); - let mut capture_kind = curr_mode; - // If the truncated part of the place contains `Deref` of a `&mut` then convert MutBorrow -> // UniqueImmBorrow // Note that if the place contained Deref of a raw pointer it would've not been MutBorrow, so @@ -2176,7 +2154,7 @@ fn truncate_place_to_len( if place.projections[i].kind == ProjectionKind::Deref && is_mut_ref(place.ty_before_projection(i)) { - capture_kind = ty::UpvarCapture::ByRef(ty::UpvarBorrow { + *curr_mode = ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: ty::BorrowKind::UniqueImmBorrow, region, }); @@ -2190,8 +2168,6 @@ fn truncate_place_to_len( } place.projections.truncate(len); - - (place, capture_kind) } /// Determines the Ancestry relationship of Place A relative to Place B @@ -2256,8 +2232,8 @@ fn determine_place_ancestry_relation( /// } /// ``` fn truncate_capture_for_optimization<'tcx>( - place: Place<'tcx>, - curr_mode: ty::UpvarCapture<'tcx>, + mut place: Place<'tcx>, + mut curr_mode: ty::UpvarCapture<'tcx>, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not)); @@ -2269,10 +2245,12 @@ fn truncate_capture_for_optimization<'tcx>( match idx { // If that pointer is a shared reference, then we don't need those fields. Some(idx) if is_shared_ref(place.ty_before_projection(idx)) => { - truncate_place_to_len(place, curr_mode, idx + 1) + truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, idx + 1) } - None | Some(_) => (place, curr_mode), + None | Some(_) => {} } + + (place, curr_mode) } /// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if From bc33861c2240c966e01d6f3e0431d192c9c720c1 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Mon, 23 Aug 2021 20:02:17 -0400 Subject: [PATCH 07/23] Fix references to `ControlFlow` in docs --- library/core/src/iter/traits/iterator.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 524d8f857e2a5..746548a96a477 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1957,8 +1957,8 @@ pub trait Iterator { /// assert_eq!(it.next(), Some(&40)); /// ``` /// - /// While you cannot `break` from a closure, the [`crate::ops::ControlFlow`] - /// type allows a similar idea: + /// While you cannot `break` from a closure, the [`ControlFlow`] type allows + /// a similar idea: /// /// ``` /// use std::ops::ControlFlow; @@ -2024,8 +2024,8 @@ pub trait Iterator { /// assert_eq!(it.next(), Some("stale_bread.json")); /// ``` /// - /// The [`crate::ops::ControlFlow`] type can be used with this method for the - /// situations in which you'd use `break` and `continue` in a normal loop: + /// The [`ControlFlow`] type can be used with this method for the situations + /// in which you'd use `break` and `continue` in a normal loop: /// /// ``` /// use std::ops::ControlFlow; From 04fa1d81dd435fc5eaf22ed72efdfd699e1d6c97 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Sun, 22 Aug 2021 12:33:27 +0200 Subject: [PATCH 08/23] =?UTF-8?q?Fix=20typo=20=E2=80=9Ca=20Rc=E2=80=9D=20?= =?UTF-8?q?=E2=86=92=20=E2=80=9Can=20Rc=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_data_structures/src/owning_ref/mod.rs | 2 +- library/alloc/src/rc.rs | 2 +- library/std/src/ffi/c_str.rs | 2 +- library/std/src/ffi/os_str.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs index 5b27a407ad422..251195204da4e 100644 --- a/compiler/rustc_data_structures/src/owning_ref/mod.rs +++ b/compiler/rustc_data_structures/src/owning_ref/mod.rs @@ -1146,7 +1146,7 @@ pub type VecRef = OwningRef, U>; /// Typedef of an owning reference that uses a `String` as the owner. pub type StringRef = OwningRef; -/// Typedef of an owning reference that uses a `Rc` as the owner. +/// Typedef of an owning reference that uses an `Rc` as the owner. pub type RcRef = OwningRef, U>; /// Typedef of an owning reference that uses an `Arc` as the owner. pub type ArcRef = OwningRef, U>; diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0b3079fa59db6..c19c61b65cd0f 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1743,7 +1743,7 @@ impl fmt::Pointer for Rc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Rc { - /// Converts a generic type `T` into a `Rc` + /// Converts a generic type `T` into an `Rc` /// /// The conversion allocates on the heap and moves `t` /// from the stack into it. diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 0d082648591ce..de05c37785295 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -958,7 +958,7 @@ impl From<&CStr> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a [`CString`] into a [`Rc`]`` without copying or allocating. + /// Converts a [`CString`] into an [`Rc`]`` without copying or allocating. #[inline] fn from(s: CString) -> Rc { let rc: Rc<[u8]> = Rc::from(s.into_inner()); diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index f05295f89af1f..21f354caf6ae9 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -916,7 +916,7 @@ impl From<&OsStr> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts an [`OsString`] into a [`Rc`]`` without copying or allocating. + /// Converts an [`OsString`] into an [`Rc`]`` without copying or allocating. #[inline] fn from(s: OsString) -> Rc { let rc = s.inner.into_rc(); From b823dc1bbd57c6525b2cc2420c87795a7264edb4 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Sun, 22 Aug 2021 12:39:39 +0200 Subject: [PATCH 09/23] =?UTF-8?q?Also=20fix=20=E2=80=9Ca=20RwLock*?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_data_structures/src/owning_ref/mod.rs | 6 +++--- src/test/ui/drop/dropck_legal_cycles.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs index 251195204da4e..4689a027895c2 100644 --- a/compiler/rustc_data_structures/src/owning_ref/mod.rs +++ b/compiler/rustc_data_structures/src/owning_ref/mod.rs @@ -1157,9 +1157,9 @@ pub type RefRef<'a, T, U = T> = OwningRef, U>; pub type RefMutRef<'a, T, U = T> = OwningRef, U>; /// Typedef of an owning reference that uses a `MutexGuard` as the owner. pub type MutexGuardRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of an owning reference that uses a `RwLockReadGuard` as the owner. +/// Typedef of an owning reference that uses an `RwLockReadGuard` as the owner. pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef, U>; -/// Typedef of an owning reference that uses a `RwLockWriteGuard` as the owner. +/// Typedef of an owning reference that uses an `RwLockWriteGuard` as the owner. pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef, U>; /// Typedef of a mutable owning reference that uses a `Box` as the owner. @@ -1173,7 +1173,7 @@ pub type StringRefMut = OwningRefMut; pub type RefMutRefMut<'a, T, U = T> = OwningRefMut, U>; /// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner. pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut, U>; -/// Typedef of a mutable owning reference that uses a `RwLockWriteGuard` as the owner. +/// Typedef of a mutable owning reference that uses an `RwLockWriteGuard` as the owner. pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef, U>; unsafe impl<'a, T: 'a> IntoErased<'a> for Box { diff --git a/src/test/ui/drop/dropck_legal_cycles.rs b/src/test/ui/drop/dropck_legal_cycles.rs index fb13fd764bfaf..27a599315dc1c 100644 --- a/src/test/ui/drop/dropck_legal_cycles.rs +++ b/src/test/ui/drop/dropck_legal_cycles.rs @@ -368,7 +368,7 @@ pub fn main() { // We can use refcells if we're single-threaded (as this test is). // If one were to generalize these constructions to a // multi-threaded context, then it might seem like we could choose - // between either a RwLock or a Mutex to hold the owned arcs on + // between either an RwLock or a Mutex to hold the owned arcs on // each node. // // Part of the point of this test is to actually confirm that the From 6248dbcf70fbae9cf6fda9e2b2ba55aeb5837b36 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Sun, 22 Aug 2021 12:41:53 +0200 Subject: [PATCH 10/23] =?UTF-8?q?Also=20fix=20=E2=80=9Ca=20`OwningRef`?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_data_structures/src/owning_ref/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs index 4689a027895c2..e7397bf13bad4 100644 --- a/compiler/rustc_data_structures/src/owning_ref/mod.rs +++ b/compiler/rustc_data_structures/src/owning_ref/mod.rs @@ -5,7 +5,7 @@ This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut` that enables it to bundle a reference together with the owner of the data it points to. -This allows moving and dropping of a `OwningRef` without needing to recreate the reference. +This allows moving and dropping of an `OwningRef` without needing to recreate the reference. This can sometimes be useful because Rust borrowing rules normally prevent moving a type that has been moved from. For example, this kind of code gets rejected: From 2af3b20ad8f3601cf6b21fb8bfa7dce59e17c5fe Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 23 Aug 2021 19:42:31 -0700 Subject: [PATCH 11/23] Update books --- src/doc/book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index 7e49659102f09..687e21bde2ea1 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 7e49659102f0977d9142190e1ba23345c0f00eb1 +Subproject commit 687e21bde2ea10c261f79fa14797c5137425098d diff --git a/src/doc/reference b/src/doc/reference index 4884fe45c14f8..da6ea9b03f74c 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 4884fe45c14f8b22121760fb117181bb4da8dfe0 +Subproject commit da6ea9b03f74cae0a292f40315723d7a3a973637 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 0dc9cd4e89f00..04f489c889235 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 0dc9cd4e89f00cb5230f120e1a083916386e422b +Subproject commit 04f489c889235fe3b6dfe678ae5410d07deda958 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index c4644b427cbda..cf0e151b7925a 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit c4644b427cbdaafc7a87be0ccdf5d8aaa07ac35f +Subproject commit cf0e151b7925a40f13fbc6573c6f97d5f94c7c17 From 0b81c2eb82c3663e691c568394455f80dd532fa1 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Thu, 19 Aug 2021 16:34:01 -0400 Subject: [PATCH 12/23] Move `named_asm_labels` to a HIR lint --- compiler/rustc_ast/src/ast.rs | 1 + compiler/rustc_ast/src/visit.rs | 6 +- compiler/rustc_ast_lowering/src/asm.rs | 4 +- compiler/rustc_builtin_macros/src/asm.rs | 90 +++------------- compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_lint/src/builtin.rs | 124 +++++++++++++++++++++- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint_defs/src/builtin.rs | 33 ------ src/test/ui/asm/named-asm-labels.rs | 66 +++++++++++- src/test/ui/asm/named-asm-labels.stderr | 125 +++++++++++++++++------ 10 files changed, 304 insertions(+), 147 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 575a00cdd0e43..2c2d30d872e20 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2028,6 +2028,7 @@ pub enum InlineAsmOperand { #[derive(Clone, Encodable, Decodable, Debug)] pub struct InlineAsm { pub template: Vec, + pub template_strs: Box<[(Symbol, Option, Span)]>, pub operands: Vec<(InlineAsmOperand, Span)>, pub clobber_abi: Option<(Symbol, Span)>, pub options: InlineAsmOptions, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index a377763983a4b..774d5cb2dda9d 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -19,20 +19,20 @@ use crate::token; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::Span; -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum AssocCtxt { Trait, Impl, } -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum FnCtxt { Free, Foreign, Assoc(AssocCtxt), } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>), diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index d94fb48d7cb88..b9b27855a0b88 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -392,8 +392,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let operands = self.arena.alloc_from_iter(operands); let template = self.arena.alloc_from_iter(asm.template.iter().cloned()); + let template_strs = self.arena.alloc_from_iter(asm.template_strs.iter().cloned()); let line_spans = self.arena.alloc_slice(&asm.line_spans[..]); - let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans }; + let hir_asm = + hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans }; self.arena.alloc(hir_asm) } } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index cb0cfdcefdc22..652165fb9b60b 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -7,10 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_expand::base::{self, *}; use rustc_parse::parser::Parser; use rustc_parse_format as parse; -use rustc_session::lint::{self, BuiltinLintDiagnostics}; +use rustc_session::lint; use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{InnerSpan, MultiSpan, Span}; +use rustc_span::{InnerSpan, Span}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; @@ -484,11 +484,7 @@ fn parse_reg<'a>( Ok(result) } -fn expand_preparsed_asm( - ecx: &mut ExtCtxt<'_>, - args: AsmArgs, - is_local_asm: bool, -) -> Option { +fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option { let mut template = vec![]; // Register operands are implicitly used since they are not allowed to be // referenced in the template string. @@ -501,6 +497,8 @@ fn expand_preparsed_asm( let mut line_spans = Vec::with_capacity(args.templates.len()); let mut curarg = 0; + let mut template_strs = Vec::with_capacity(args.templates.len()); + for template_expr in args.templates.into_iter() { if !template.is_empty() { template.push(ast::InlineAsmTemplatePiece::String("\n".to_string())); @@ -524,8 +522,13 @@ fn expand_preparsed_asm( ast::StrStyle::Raw(raw) => Some(raw as usize), }; - let template_str = &template_str.as_str(); let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok(); + template_strs.push(( + template_str, + template_snippet.as_ref().map(|s| Symbol::intern(s)), + template_sp, + )); + let template_str = &template_str.as_str(); if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch { let find_span = |needle: &str| -> Span { @@ -560,72 +563,6 @@ fn expand_preparsed_asm( } } - // Lint against the use of named labels in inline `asm!` but not `global_asm!` - if is_local_asm { - let find_label_span = |needle: &str| -> Option { - if let Some(snippet) = &template_snippet { - if let Some(pos) = snippet.find(needle) { - let end = pos - + &snippet[pos..] - .find(|c| c == ':') - .unwrap_or(snippet[pos..].len() - 1); - let inner = InnerSpan::new(pos, end); - return Some(template_sp.from_inner(inner)); - } - } - - None - }; - - let mut found_labels = Vec::new(); - - // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always - let statements = template_str.split(|c| matches!(c, '\n' | ';')); - for statement in statements { - // If there's a comment, trim it from the statement - let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]); - let mut start_idx = 0; - for (idx, _) in statement.match_indices(':') { - let possible_label = statement[start_idx..idx].trim(); - let mut chars = possible_label.chars(); - if let Some(c) = chars.next() { - // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $ - if (c.is_alphabetic() || matches!(c, '.' | '_')) - && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$')) - { - found_labels.push(possible_label); - } else { - // If we encounter a non-label, there cannot be any further labels, so stop checking - break; - } - } else { - // Empty string means a leading ':' in this section, which is not a label - break; - } - - start_idx = idx + 1; - } - } - - if found_labels.len() > 0 { - let spans = - found_labels.into_iter().filter_map(find_label_span).collect::>(); - // If there were labels but we couldn't find a span, combine the warnings and use the template span - let target_spans: MultiSpan = - if spans.len() > 0 { spans.into() } else { template_sp.into() }; - ecx.parse_sess().buffer_lint_with_diagnostic( - lint::builtin::NAMED_ASM_LABELS, - target_spans, - ecx.current_expansion.lint_node_id, - "avoid using named labels in inline assembly", - BuiltinLintDiagnostics::NamedAsmLabel( - "only local labels of the form `:` should be used in inline asm" - .to_string(), - ), - ); - } - } - // Don't treat raw asm as a format string. if args.options.contains(ast::InlineAsmOptions::RAW) { template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string())); @@ -819,6 +756,7 @@ fn expand_preparsed_asm( Some(ast::InlineAsm { template, + template_strs: template_strs.into_boxed_slice(), operands: args.operands, clobber_abi: args.clobber_abi, options: args.options, @@ -833,7 +771,7 @@ pub fn expand_asm<'cx>( ) -> Box { match parse_args(ecx, sp, tts, false) { Ok(args) => { - let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args, true) { + let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args) { P(ast::Expr { id: ast::DUMMY_NODE_ID, kind: ast::ExprKind::InlineAsm(P(inline_asm)), @@ -860,7 +798,7 @@ pub fn expand_global_asm<'cx>( ) -> Box { match parse_args(ecx, sp, tts, true) { Ok(args) => { - if let Some(inline_asm) = expand_preparsed_asm(ecx, args, false) { + if let Some(inline_asm) = expand_preparsed_asm(ecx, args) { MacEager::items(smallvec![P(ast::Item { ident: Ident::invalid(), attrs: Vec::new(), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 888d1c1832b09..38deb8eaaae6b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2386,6 +2386,7 @@ impl<'hir> InlineAsmOperand<'hir> { #[derive(Debug, HashStable_Generic)] pub struct InlineAsm<'hir> { pub template: &'hir [InlineAsmTemplatePiece], + pub template_strs: &'hir [(Symbol, Option, Span)], pub operands: &'hir [(InlineAsmOperand<'hir>, Span)], pub options: InlineAsmOptions, pub line_spans: &'hir [Span], diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index afa2cfca1880f..add0c0ff332f2 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -45,11 +45,11 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt}; -use rustc_session::lint::FutureIncompatibilityReason; +use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, Span}; +use rustc_span::{BytePos, InnerSpan, MultiSpan, Span}; use rustc_target::abi::{LayoutOf, VariantIdx}; use rustc_trait_selection::traits::misc::can_type_implement_copy; @@ -3140,3 +3140,123 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { } } } + +declare_lint! { + /// The `named_asm_labels` lint detects the use of named labels in the + /// inline `asm!` macro. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![feature(asm)] + /// fn main() { + /// unsafe { + /// asm!("foo: bar"); + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// LLVM is allowed to duplicate inline assembly blocks for any + /// reason, for example when it is in a function that gets inlined. Because + /// of this, GNU assembler [local labels] *must* be used instead of labels + /// with a name. Using named labels might cause assembler or linker errors. + /// + /// See the [unstable book] for more details. + /// + /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels + /// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels + pub NAMED_ASM_LABELS, + Deny, + "named labels in inline assembly", +} + +declare_lint_pass!(NamedAsmLabels => [NAMED_ASM_LABELS]); + +impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + if let hir::Expr { + kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, .. }), + .. + } = expr + { + for (template_sym, template_snippet, template_span) in template_strs.iter() { + let template_str = &template_sym.as_str(); + let find_label_span = |needle: &str| -> Option { + if let Some(template_snippet) = template_snippet { + let snippet = template_snippet.as_str(); + if let Some(pos) = snippet.find(needle) { + let end = pos + + &snippet[pos..] + .find(|c| c == ':') + .unwrap_or(snippet[pos..].len() - 1); + let inner = InnerSpan::new(pos, end); + return Some(template_span.from_inner(inner)); + } + } + + None + }; + + let mut found_labels = Vec::new(); + + // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always + let statements = template_str.split(|c| matches!(c, '\n' | ';')); + for statement in statements { + // If there's a comment, trim it from the statement + let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]); + let mut start_idx = 0; + for (idx, _) in statement.match_indices(':') { + let possible_label = statement[start_idx..idx].trim(); + let mut chars = possible_label.chars(); + if let Some(c) = chars.next() { + // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $ + if (c.is_alphabetic() || matches!(c, '.' | '_')) + && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$')) + { + found_labels.push(possible_label); + } else { + // If we encounter a non-label, there cannot be any further labels, so stop checking + break; + } + } else { + // Empty string means a leading ':' in this section, which is not a label + break; + } + + start_idx = idx + 1; + } + } + + debug!("NamedAsmLabels::check_expr(): found_labels: {:#?}", &found_labels); + + if found_labels.len() > 0 { + let spans = found_labels + .into_iter() + .filter_map(|label| find_label_span(label)) + .collect::>(); + // If there were labels but we couldn't find a span, combine the warnings and use the template span + let target_spans: MultiSpan = + if spans.len() > 0 { spans.into() } else { (*template_span).into() }; + + cx.lookup_with_diagnostics( + NAMED_ASM_LABELS, + Some(target_spans), + |diag| { + let mut err = + diag.build("avoid using named labels in inline assembly"); + err.emit(); + }, + BuiltinLintDiagnostics::NamedAsmLabel( + "only local labels of the form `:` should be used in inline asm" + .to_string(), + ), + ); + } + } + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c4008e77bab7c..24ac723f2c913 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -168,6 +168,7 @@ macro_rules! late_lint_passes { NonPanicFmt: NonPanicFmt, NoopMethodCall: NoopMethodCall, InvalidAtomicOrdering: InvalidAtomicOrdering, + NamedAsmLabels: NamedAsmLabels, ] ); }; diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a1c507b4c847f..1d978b6c82923 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2468,38 +2468,6 @@ declare_lint! { "incorrect use of inline assembly", } -declare_lint! { - /// The `named_asm_labels` lint detects the use of named labels in the - /// inline `asm!` macro. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// fn main() { - /// unsafe { - /// asm!("foo: bar"); - /// } - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// LLVM is allowed to duplicate inline assembly blocks for any - /// reason, for example when it is in a function that gets inlined. Because - /// of this, GNU assembler [local labels] *must* be used instead of labels - /// with a name. Using named labels might cause assembler or linker errors. - /// - /// See the [unstable book] for more details. - /// - /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels - /// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels - pub NAMED_ASM_LABELS, - Deny, - "named labels in inline assembly", -} - declare_lint! { /// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe /// functions without an explicit unsafe block. @@ -3020,7 +2988,6 @@ declare_lint_pass! { INLINE_NO_SANITIZE, BAD_ASM_STYLE, ASM_SUB_REGISTER, - NAMED_ASM_LABELS, UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, CENUM_IMPL_DROP_CAST, diff --git a/src/test/ui/asm/named-asm-labels.rs b/src/test/ui/asm/named-asm-labels.rs index 803501b40b68e..9f487bd8061fc 100644 --- a/src/test/ui/asm/named-asm-labels.rs +++ b/src/test/ui/asm/named-asm-labels.rs @@ -1,6 +1,14 @@ // only-x86_64 -#![feature(asm, global_asm)] +// Tests that the use of named labels in the `asm!` macro are linted against +// except for in `#[naked]` fns. +// Using a named label is incorrect as per the RFC because for most cases +// the compiler cannot ensure that inline asm is emitted exactly once per +// codegen unit (except for naked fns) and so the label could be duplicated +// which causes less readable LLVM errors and in the worst cases causes ICEs +// or segfaults based on system dependent behavior and codegen flags. + +#![feature(asm, global_asm, naked_functions)] #[no_mangle] pub static FOO: usize = 42; @@ -126,5 +134,61 @@ fn main() { } } +// Trigger on naked fns too, even though they can't be inlined, reusing a +// label or LTO can cause labels to break +#[naked] +pub extern "C" fn foo() -> i32 { + unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } //~ ERROR avoid using named labels +} + +// Make sure that non-naked attributes *do* still let the lint happen +#[no_mangle] +pub extern "C" fn bar() { + unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + //~^ ERROR avoid using named labels +} + +#[naked] +pub extern "C" fn aaa() { + fn _local() {} + + unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels +} + +pub fn normal() { + fn _local1() {} + + #[naked] + pub extern "C" fn bbb() { + fn _very_local() {} + + unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels + } + + fn _local2() {} +} + +// Make sure that the lint happens within closures +fn closures() { + || unsafe { + asm!("closure1: nop"); //~ ERROR avoid using named labels + }; + + move || unsafe { + asm!("closure2: nop"); //~ ERROR avoid using named labels + }; + + || { + #[naked] + unsafe extern "C" fn _nested() { + asm!("ret;", options(noreturn)); + } + + unsafe { + asm!("closure3: nop"); //~ ERROR avoid using named labels + } + }; +} + // Don't trigger on global asm global_asm!("aaaaaaaa: nop"); diff --git a/src/test/ui/asm/named-asm-labels.stderr b/src/test/ui/asm/named-asm-labels.stderr index 3c4a4db75e02d..396f0a1942428 100644 --- a/src/test/ui/asm/named-asm-labels.stderr +++ b/src/test/ui/asm/named-asm-labels.stderr @@ -1,5 +1,5 @@ error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:11:15 + --> $DIR/named-asm-labels.rs:19:15 | LL | asm!("bar: nop"); | ^^^ @@ -9,7 +9,7 @@ LL | asm!("bar: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:14:15 + --> $DIR/named-asm-labels.rs:22:15 | LL | asm!("abcd:"); | ^^^^ @@ -18,7 +18,7 @@ LL | asm!("abcd:"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:17:15 + --> $DIR/named-asm-labels.rs:25:15 | LL | asm!("foo: bar1: nop"); | ^^^ ^^^^ @@ -27,7 +27,7 @@ LL | asm!("foo: bar1: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:21:15 + --> $DIR/named-asm-labels.rs:29:15 | LL | asm!("foo1: nop", "nop"); | ^^^^ @@ -36,7 +36,7 @@ LL | asm!("foo1: nop", "nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:22:15 + --> $DIR/named-asm-labels.rs:30:15 | LL | asm!("foo2: foo3: nop", "nop"); | ^^^^ ^^^^ @@ -45,7 +45,7 @@ LL | asm!("foo2: foo3: nop", "nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:24:22 + --> $DIR/named-asm-labels.rs:32:22 | LL | asm!("nop", "foo4: nop"); | ^^^^ @@ -54,7 +54,7 @@ LL | asm!("nop", "foo4: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:25:15 + --> $DIR/named-asm-labels.rs:33:15 | LL | asm!("foo5: nop", "foo6: nop"); | ^^^^ @@ -63,7 +63,7 @@ LL | asm!("foo5: nop", "foo6: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:25:28 + --> $DIR/named-asm-labels.rs:33:28 | LL | asm!("foo5: nop", "foo6: nop"); | ^^^^ @@ -72,7 +72,7 @@ LL | asm!("foo5: nop", "foo6: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:30:15 + --> $DIR/named-asm-labels.rs:38:15 | LL | asm!("foo7: nop; foo8: nop"); | ^^^^ ^^^^ @@ -81,7 +81,7 @@ LL | asm!("foo7: nop; foo8: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:32:15 + --> $DIR/named-asm-labels.rs:40:15 | LL | asm!("foo9: nop; nop"); | ^^^^ @@ -90,7 +90,7 @@ LL | asm!("foo9: nop; nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:33:20 + --> $DIR/named-asm-labels.rs:41:20 | LL | asm!("nop; foo10: nop"); | ^^^^^ @@ -99,7 +99,7 @@ LL | asm!("nop; foo10: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:36:15 + --> $DIR/named-asm-labels.rs:44:15 | LL | asm!("bar2: nop\n bar3: nop"); | ^^^^ ^^^^ @@ -108,7 +108,7 @@ LL | asm!("bar2: nop\n bar3: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:38:15 + --> $DIR/named-asm-labels.rs:46:15 | LL | asm!("bar4: nop\n nop"); | ^^^^ @@ -117,7 +117,7 @@ LL | asm!("bar4: nop\n nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:39:21 + --> $DIR/named-asm-labels.rs:47:21 | LL | asm!("nop\n bar5: nop"); | ^^^^ @@ -126,7 +126,7 @@ LL | asm!("nop\n bar5: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:40:21 + --> $DIR/named-asm-labels.rs:48:21 | LL | asm!("nop\n bar6: bar7: nop"); | ^^^^ ^^^^ @@ -135,7 +135,7 @@ LL | asm!("nop\n bar6: bar7: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:46:13 + --> $DIR/named-asm-labels.rs:54:13 | LL | blah2: nop | ^^^^^ @@ -146,7 +146,7 @@ LL | blah3: nop = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:55:19 + --> $DIR/named-asm-labels.rs:63:19 | LL | nop ; blah4: nop | ^^^^^ @@ -155,7 +155,7 @@ LL | nop ; blah4: nop = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:69:15 + --> $DIR/named-asm-labels.rs:77:15 | LL | asm!("blah1: 2bar: nop"); | ^^^^^ @@ -164,7 +164,7 @@ LL | asm!("blah1: 2bar: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:72:15 + --> $DIR/named-asm-labels.rs:80:15 | LL | asm!("def: def: nop"); | ^^^ @@ -173,7 +173,7 @@ LL | asm!("def: def: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:73:15 + --> $DIR/named-asm-labels.rs:81:15 | LL | asm!("def: nop\ndef: nop"); | ^^^ @@ -182,7 +182,7 @@ LL | asm!("def: nop\ndef: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:74:15 + --> $DIR/named-asm-labels.rs:82:15 | LL | asm!("def: nop; def: nop"); | ^^^ @@ -191,7 +191,7 @@ LL | asm!("def: nop; def: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:82:15 + --> $DIR/named-asm-labels.rs:90:15 | LL | asm!("fooo\u{003A} nop"); | ^^^^^^^^^^^^^^^^ @@ -200,7 +200,7 @@ LL | asm!("fooo\u{003A} nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:83:15 + --> $DIR/named-asm-labels.rs:91:15 | LL | asm!("foooo\x3A nop"); | ^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | asm!("foooo\x3A nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:86:15 + --> $DIR/named-asm-labels.rs:94:15 | LL | asm!("fooooo:\u{000A} nop"); | ^^^^^^ @@ -218,7 +218,7 @@ LL | asm!("fooooo:\u{000A} nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:87:15 + --> $DIR/named-asm-labels.rs:95:15 | LL | asm!("foooooo:\x0A nop"); | ^^^^^^^ @@ -227,7 +227,7 @@ LL | asm!("foooooo:\x0A nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:91:14 + --> $DIR/named-asm-labels.rs:99:14 | LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -236,7 +236,7 @@ LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:102:13 + --> $DIR/named-asm-labels.rs:110:13 | LL | ab: nop // ab: does foo | ^^ @@ -245,7 +245,7 @@ LL | ab: nop // ab: does foo = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:114:14 + --> $DIR/named-asm-labels.rs:122:14 | LL | asm!(include_str!("named-asm-labels.s")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -254,18 +254,81 @@ LL | asm!(include_str!("named-asm-labels.s")); = note: see the asm section of the unstable book for more information warning: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:124:19 + --> $DIR/named-asm-labels.rs:132:19 | LL | asm!("warned: nop"); | ^^^^^^ | note: the lint level is defined here - --> $DIR/named-asm-labels.rs:122:16 + --> $DIR/named-asm-labels.rs:130:16 | LL | #[warn(named_asm_labels)] | ^^^^^^^^^^^^^^^^ = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of the unstable book for more information -error: aborting due to 28 previous errors; 1 warning emitted +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:141:20 + | +LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of the unstable book for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:147:20 + | +LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of the unstable book for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:155:20 + | +LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of the unstable book for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:165:24 + | +LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of the unstable book for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:174:15 + | +LL | asm!("closure1: nop"); + | ^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of the unstable book for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:178:15 + | +LL | asm!("closure2: nop"); + | ^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of the unstable book for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:188:19 + | +LL | asm!("closure3: nop"); + | ^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of the unstable book for more information + +error: aborting due to 35 previous errors; 1 warning emitted From 54df693dd7e6668b78f0636e269f7f928d4932d2 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 24 Aug 2021 16:51:58 +0100 Subject: [PATCH 13/23] io::Error: alphabeticise the match in as_str() There was no rationale for the previous ordering. Signed-off-by: Ian Jackson --- library/std/src/io/error.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 829ef3d98bbc9..3f8f34793af33 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -307,13 +307,13 @@ pub enum ErrorKind { impl ErrorKind { pub(crate) fn as_str(&self) -> &'static str { use ErrorKind::*; + // Strictly alphabetical, please. (Sadly rustfmt cannot do this yet.) match *self { AddrInUse => "address in use", AddrNotAvailable => "address not available", AlreadyExists => "entity already exists", ArgumentListTooLong => "argument list too long", BrokenPipe => "broken pipe", - ResourceBusy => "resource busy", ConnectionAborted => "connection aborted", ConnectionRefused => "connection refused", ConnectionReset => "connection reset", @@ -321,9 +321,10 @@ impl ErrorKind { Deadlock => "deadlock", DirectoryNotEmpty => "directory not empty", ExecutableFileBusy => "executable file busy", + FileTooLarge => "file too large", FilenameTooLong => "filename too long", + FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", FilesystemQuotaExceeded => "filesystem quota exceeded", - FileTooLarge => "file too large", HostUnreachable => "host unreachable", Interrupted => "operation interrupted", InvalidData => "invalid data", @@ -332,16 +333,16 @@ impl ErrorKind { NetworkDown => "network down", NetworkUnreachable => "network unreachable", NotADirectory => "not a directory", - StorageFull => "no storage space", NotConnected => "not connected", NotFound => "entity not found", + NotSeekable => "seek on unseekable file", Other => "other error", OutOfMemory => "out of memory", PermissionDenied => "permission denied", ReadOnlyFilesystem => "read-only filesystem or storage medium", + ResourceBusy => "resource busy", StaleNetworkFileHandle => "stale network file handle", - FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", - NotSeekable => "seek on unseekable file", + StorageFull => "no storage space", TimedOut => "timed out", TooManyLinks => "too many links", Uncategorized => "uncategorized error", From 4c0203eb4b3406cd2088c5d0092a0445294e2f6c Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 24 Aug 2021 16:53:58 +0100 Subject: [PATCH 14/23] io::ErrorKind: rationalise ordering in main enum It is useful to keep some coherent structure to this ordering. In particular, Other and Uncategorized should be next to each other, at the end. Also it seems to make sense to treat UnexpectedEof and OutOfMemory specially, since they are not like the other errors (despite OutOfMemory also being generatable by some OS errors). So: * Move Other to the end, just before Uncategorized * Move Unsupported to between Interrupted and UnexpectedEof * Add some comments documenting where to add things Signed-off-by: Ian Jackson --- library/std/src/io/error.rs | 41 ++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 3f8f34793af33..6880106a94371 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -261,18 +261,14 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] Interrupted, - /// A custom error that does not fall under any other I/O error kind. - /// - /// This can be used to construct your own [`Error`]s that do not match any - /// [`ErrorKind`]. - /// - /// This [`ErrorKind`] is not used by the standard library. + /// This operation is unsupported on this platform. /// - /// Errors from the standard library that do not fall under any of the I/O - /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. - /// New [`ErrorKind`]s might be added in the future for some of those. - #[stable(feature = "rust1", since = "1.0.0")] - Other, + /// This means that the operation can never succeed. + #[stable(feature = "unsupported_error", since = "1.53.0")] + Unsupported, + + // ErrorKinds which are primarily categorisations for OS error + // codes should be added above. /// An error returned when an operation could not be completed because an /// "end of file" was reached prematurely. @@ -283,17 +279,28 @@ pub enum ErrorKind { #[stable(feature = "read_exact", since = "1.6.0")] UnexpectedEof, - /// This operation is unsupported on this platform. - /// - /// This means that the operation can never succeed. - #[stable(feature = "unsupported_error", since = "1.53.0")] - Unsupported, - /// An operation could not be completed, because it failed /// to allocate enough memory. #[stable(feature = "out_of_memory_error", since = "1.54.0")] OutOfMemory, + // "Unusual" error kinds which do not correspond simply to (sets + // of) OS error codes, should be added just above this comment. + // `Other` and `Uncategorised` should remain at the end: + + /// A custom error that does not fall under any other I/O error kind. + /// + /// This can be used to construct your own [`Error`]s that do not match any + /// [`ErrorKind`]. + /// + /// This [`ErrorKind`] is not used by the standard library. + /// + /// Errors from the standard library that do not fall under any of the I/O + /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. + /// New [`ErrorKind`]s might be added in the future for some of those. + #[stable(feature = "rust1", since = "1.0.0")] + Other, + /// Any I/O error from the standard library that's not part of this list. /// /// Errors that are `Uncategorized` now may move to a different or a new From 8f7007991e7fa1a1a6795f81e5d7efbdd503a8c1 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 24 Aug 2021 17:56:39 +0200 Subject: [PATCH 15/23] Fix grammar --- library/alloc/tests/boxed.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index 6a83f5da87cc8..a38b5c471bf06 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -35,11 +35,11 @@ fn box_clone_and_clone_from_equivalence() { } } -/// This test might give a false positive in case the box realocates, but the alocator keeps the -/// original pointer. +/// This test might give a false positive in case the box reallocates, +/// but the allocator keeps the original pointer. /// -/// On the other hand it won't give a false negative, if it fails than the memory was definitely not -/// reused +/// On the other hand, it won't give a false negative: If it fails, then the +/// memory was definitely not reused. #[test] fn box_clone_from_ptr_stability() { for size in (0..8).map(|i| 2usize.pow(i)) { From 7b5c0ecb3d902149fd6caa1d673ad5f7751320f3 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 24 Aug 2021 17:44:16 +0100 Subject: [PATCH 16/23] Fix tidy Signed-off-by: Ian Jackson --- library/std/src/io/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 6880106a94371..51666c0a3c7f1 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -269,7 +269,7 @@ pub enum ErrorKind { // ErrorKinds which are primarily categorisations for OS error // codes should be added above. - + // /// An error returned when an operation could not be completed because an /// "end of file" was reached prematurely. /// @@ -287,7 +287,7 @@ pub enum ErrorKind { // "Unusual" error kinds which do not correspond simply to (sets // of) OS error codes, should be added just above this comment. // `Other` and `Uncategorised` should remain at the end: - + // /// A custom error that does not fall under any other I/O error kind. /// /// This can be used to construct your own [`Error`]s that do not match any From db13636f036db4b7988fafd2288dc73ce46a1e53 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 1 May 2021 00:38:01 +0100 Subject: [PATCH 17/23] Stabilise BufWriter::into_parts Signed-off-by: Ian Jackson --- library/std/src/io/buffered/bufwriter.rs | 14 ++++++-------- library/std/src/io/buffered/mod.rs | 2 +- library/std/src/io/mod.rs | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 9da5fbff9cf02..df60af7c36a3e 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -323,7 +323,6 @@ impl BufWriter { /// # Examples /// /// ``` - /// #![feature(bufwriter_into_parts)] /// use std::io::{BufWriter, Write}; /// /// let mut buffer = [0u8; 10]; @@ -334,7 +333,7 @@ impl BufWriter { /// assert_eq!(recovered_writer.len(), 0); /// assert_eq!(&buffered_data.unwrap(), b"ata"); /// ``` - #[unstable(feature = "bufwriter_into_parts", issue = "80690")] + #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] pub fn into_parts(mut self) -> (W, Result, WriterPanicked>) { let buf = mem::take(&mut self.buf); let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; @@ -444,14 +443,13 @@ impl BufWriter { } } -#[unstable(feature = "bufwriter_into_parts", issue = "80690")] +#[stable(feature = "bufwriter_into_parts", since = "1.56.0")] /// Error returned for the buffered data from `BufWriter::into_parts`, when the underlying /// writer has previously panicked. Contains the (possibly partly written) buffered data. /// /// # Example /// /// ``` -/// #![feature(bufwriter_into_parts)] /// use std::io::{self, BufWriter, Write}; /// use std::panic::{catch_unwind, AssertUnwindSafe}; /// @@ -478,7 +476,7 @@ pub struct WriterPanicked { impl WriterPanicked { /// Returns the perhaps-unwritten data. Some of this data may have been written by the /// panicking call(s) to the underlying writer, so simply writing it again is not a good idea. - #[unstable(feature = "bufwriter_into_parts", issue = "80690")] + #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] pub fn into_inner(self) -> Vec { self.buf } @@ -487,7 +485,7 @@ impl WriterPanicked { "BufWriter inner writer panicked, what data remains unwritten is not known"; } -#[unstable(feature = "bufwriter_into_parts", issue = "80690")] +#[stable(feature = "bufwriter_into_parts", since = "1.56.0")] impl error::Error for WriterPanicked { #[allow(deprecated, deprecated_in_future)] fn description(&self) -> &str { @@ -495,14 +493,14 @@ impl error::Error for WriterPanicked { } } -#[unstable(feature = "bufwriter_into_parts", issue = "80690")] +#[stable(feature = "bufwriter_into_parts", since = "1.56.0")] impl fmt::Display for WriterPanicked { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", Self::DESCRIPTION) } } -#[unstable(feature = "bufwriter_into_parts", issue = "80690")] +#[stable(feature = "bufwriter_into_parts", since = "1.56.0")] impl fmt::Debug for WriterPanicked { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("WriterPanicked") diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs index 8cfffc2fd35a4..179bdf7fe553a 100644 --- a/library/std/src/io/buffered/mod.rs +++ b/library/std/src/io/buffered/mod.rs @@ -14,7 +14,7 @@ use crate::io::Error; pub use bufreader::BufReader; pub use bufwriter::BufWriter; -#[unstable(feature = "bufwriter_into_parts", issue = "80690")] +#[stable(feature = "bufwriter_into_parts", since = "1.56.0")] pub use bufwriter::WriterPanicked; pub use linewriter::LineWriter; use linewritershim::LineWriterShim; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 28254fea0d374..e8466fa06b899 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -264,7 +264,7 @@ use crate::sys_common::memchr; #[stable(feature = "rust1", since = "1.0.0")] pub use self::buffered::IntoInnerError; -#[unstable(feature = "bufwriter_into_parts", issue = "80690")] +#[stable(feature = "bufwriter_into_parts", since = "1.56.0")] pub use self::buffered::WriterPanicked; #[stable(feature = "rust1", since = "1.0.0")] pub use self::buffered::{BufReader, BufWriter, LineWriter}; From 335bf7ca6b2e63ffc5b7ee732819b7bf228a179e Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Tue, 24 Aug 2021 21:15:26 +0200 Subject: [PATCH 18/23] =?UTF-8?q?Clarifiy=20weak=20pointers=20being=20dias?= =?UTF-8?q?sociated=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …noting the fact that `clone` is not called. Co-authored-by: Mark Rousskov --- library/alloc/src/rc.rs | 5 +++-- library/alloc/src/sync.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 90b077210a475..272fc119f4edd 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1100,8 +1100,9 @@ impl Rc { /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also /// referred to as clone-on-write. /// - /// If there are no other `Rc` pointers to this allocation, then [`Weak`] - /// pointers to this allocation will be disassociated. + /// However, if there are no other `Rc` pointers to this allocation, but some [`Weak`] + /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not + /// be cloned. /// /// See also [`get_mut`], which will fail rather than cloning. /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 7e4cb6d2c60f2..2367eaec4b938 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1350,8 +1350,9 @@ impl Arc { /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also /// referred to as clone-on-write. /// - /// If there are no other `Arc` pointers to this allocation, then [`Weak`] - /// pointers to this allocation will be disassociated. + /// However, if there are no other `Arc` pointers to this allocation, but some [`Weak`] + /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not + /// be cloned. /// /// See also [`get_mut`], which will fail rather than cloning. /// From 90354c719a94db7d393134c00b2a91bd651b5e7a Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Tue, 24 Aug 2021 21:34:12 +0200 Subject: [PATCH 19/23] Make explanations of cross-references between `make_mut` and `get_mut` more accurate --- library/alloc/src/rc.rs | 5 +++-- library/alloc/src/sync.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 272fc119f4edd..a9d147fa1a55c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1011,7 +1011,7 @@ impl Rc { /// mutate a shared value. /// /// See also [`make_mut`][make_mut], which will [`clone`][clone] - /// the inner value when there are other pointers. + /// the inner value when there are other `Rc` pointers. /// /// [make_mut]: Rc::make_mut /// [clone]: Clone::clone @@ -1104,7 +1104,8 @@ impl Rc { /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not /// be cloned. /// - /// See also [`get_mut`], which will fail rather than cloning. + /// See also [`get_mut`], which will fail rather than cloning the inner value + /// or diassociating [`Weak`] pointers. /// /// [`clone`]: Clone::clone /// [`get_mut`]: Rc::get_mut diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 2367eaec4b938..a066e0b49e25c 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1354,7 +1354,8 @@ impl Arc { /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not /// be cloned. /// - /// See also [`get_mut`], which will fail rather than cloning. + /// See also [`get_mut`], which will fail rather than cloning the inner value + /// or diassociating [`Weak`] pointers. /// /// [`clone`]: Clone::clone /// [`get_mut`]: Arc::get_mut @@ -1458,7 +1459,7 @@ impl Arc { /// mutate a shared value. /// /// See also [`make_mut`][make_mut], which will [`clone`][clone] - /// the inner value when there are other pointers. + /// the inner value when there are other `Arc` pointers. /// /// [make_mut]: Arc::make_mut /// [clone]: Clone::clone From 09e02a891963d7418f1db4d8d4cf9a8d177d2cf9 Mon Sep 17 00:00:00 2001 From: Mariano Casco Date: Tue, 24 Aug 2021 12:04:02 -0300 Subject: [PATCH 20/23] Add SAFETY comments to core::slice::sort::partition_in_blocks --- library/core/src/slice/sort.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 36c2c4abdb4c5..8a31388fbdbbc 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -369,6 +369,22 @@ where // Instead of swapping one pair at the time, it is more efficient to perform a cyclic // permutation. This is not strictly equivalent to swapping, but produces a similar // result using fewer memory operations. + + // SAFETY: The use of `ptr::read` is valid because there is at least one element in + // both `offsets_l` and `offsets_r`, so `left!` is a valid pointer to read from. + // + // The uses of `left!` involve calls to `offset` on `l`, which points to the + // beginning of `v`. All the offsets pointed-to by `start_l` are at most `block_l`, so + // these `offset` calls are safe as all reads are within the block. The same argument + // applies for the uses of `right!`. + // + // The calls to `start_l.offset` are valid because there are at most `count-1` of them, + // plus the final one at the end of the unsafe block, where `count` is the minimum number + // of collected offsets in `offsets_l` and `offsets_r`, so there is no risk of there not + // being enough elements. The same reasoning applies to the calls to `start_r.offset`. + // + // The calls to `copy_nonoverlapping` are safe because `left!` and `right!` are guaranteed + // not to overlap, and are valid because of the reasoning above. unsafe { let tmp = ptr::read(left!()); ptr::copy_nonoverlapping(right!(), left!(), 1); @@ -389,11 +405,21 @@ where if start_l == end_l { // All out-of-order elements in the left block were moved. Move to the next block. + + // block-width-guarantee + // SAFETY: if `!is_done` then the slice width is guaranteed to be at least `2*BLOCK` wide. There + // are at most `BLOCK` elements in `offsets_l` because of its size, so the `offset` operation is + // safe. Otherwise, the debug assertions in the `is_done` case guarantee that + // `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account + // for the smaller number of remaining elements. l = unsafe { l.offset(block_l as isize) }; } if start_r == end_r { // All out-of-order elements in the right block were moved. Move to the previous block. + + // SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide, + // or `block_r` has been adjusted for the last handful of elements. r = unsafe { r.offset(-(block_r as isize)) }; } From 08e20d9b28685d438839bd695a9309a8947a61fa Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 24 Aug 2021 22:10:38 -0300 Subject: [PATCH 21/23] Add type of a let tait test --- .../ui/type-alias-impl-trait/type_of_a_let.rs | 29 ++++++++ .../type_of_a_let.stderr | 67 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/type_of_a_let.rs create mode 100644 src/test/ui/type-alias-impl-trait/type_of_a_let.stderr diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs new file mode 100644 index 0000000000000..7f8e6127cca3b --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs @@ -0,0 +1,29 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// FIXME This should compile, but it currently doesn't + +use std::fmt::Debug; + +type Foo = impl Debug; +//~^ ERROR: could not find defining uses + +fn foo1() -> u32 { + let x: Foo = 22_u32; + //~^ ERROR: mismatched types [E0308] + x + //~^ ERROR: mismatched types [E0308] +} + +fn foo2() -> u32 { + let x: Foo = 22_u32; + //~^ ERROR: mismatched types [E0308] + let y: Foo = x; + same_type((x, y)); + y + //~^ ERROR: mismatched types [E0308] +} + +fn same_type(x: (T, T)) {} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr new file mode 100644 index 0000000000000..cac8d6841afda --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr @@ -0,0 +1,67 @@ +error[E0308]: mismatched types + --> $DIR/type_of_a_let.rs:12:18 + | +LL | type Foo = impl Debug; + | ---------- the expected opaque type +... +LL | let x: Foo = 22_u32; + | --- ^^^^^^ expected opaque type, found `u32` + | | + | expected due to this + | + = note: expected opaque type `impl Debug` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/type_of_a_let.rs:14:5 + | +LL | type Foo = impl Debug; + | ---------- the found opaque type +... +LL | fn foo1() -> u32 { + | --- expected `u32` because of return type +... +LL | x + | ^ expected `u32`, found opaque type + | + = note: expected type `u32` + found opaque type `impl Debug` + +error[E0308]: mismatched types + --> $DIR/type_of_a_let.rs:19:18 + | +LL | type Foo = impl Debug; + | ---------- the expected opaque type +... +LL | let x: Foo = 22_u32; + | --- ^^^^^^ expected opaque type, found `u32` + | | + | expected due to this + | + = note: expected opaque type `impl Debug` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/type_of_a_let.rs:23:5 + | +LL | type Foo = impl Debug; + | ---------- the found opaque type +... +LL | fn foo2() -> u32 { + | --- expected `u32` because of return type +... +LL | y + | ^ expected `u32`, found opaque type + | + = note: expected type `u32` + found opaque type `impl Debug` + +error: could not find defining uses + --> $DIR/type_of_a_let.rs:8:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. From dbadab54df148b55b2e884440bfaeaa38517e6e8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 24 Aug 2021 22:52:41 -0300 Subject: [PATCH 22/23] Add type of a let tait test impl trait straight in let --- .../type-alias-impl-trait/type_of_a_let2.rs | 25 +++++++++++++++++++ .../type_of_a_let2.stderr | 21 ++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/type_of_a_let2.rs create mode 100644 src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let2.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let2.rs new file mode 100644 index 0000000000000..33d3f164ce15e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let2.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// FIXME This should be under a feature flag + +use std::fmt::Debug; + +fn foo1() -> u32 { + let x: impl Debug = 22_u32; + //~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562] + x // ERROR: we only know x: Debug, we don't know x = u32 +} + +fn foo2() -> u32 { + let x: impl Debug = 22_u32; + //~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562] + let y: impl Debug = x; + //~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562] + same_type((x, y)); // ERROR + x +} + +fn same_type(x: (T, T)) {} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr new file mode 100644 index 0000000000000..7a1825a8e2d9a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr @@ -0,0 +1,21 @@ +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/type_of_a_let2.rs:9:12 + | +LL | let x: impl Debug = 22_u32; + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/type_of_a_let2.rs:15:12 + | +LL | let x: impl Debug = 22_u32; + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` not allowed outside of function and method return types + --> $DIR/type_of_a_let2.rs:17:12 + | +LL | let y: impl Debug = x; + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0562`. From f858c7c30062696c163d4ee341010b0b3c655665 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 25 Aug 2021 07:11:48 -0500 Subject: [PATCH 23/23] Add mutable-noalias to the release notes for 1.54 --- RELEASES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 2e7077ed2065e..dd299ca936ace 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -175,6 +175,7 @@ Compiler - [Improved debugger output for enums on Windows MSVC platforms.][85292] - [Added tier 3\* support for `bpfel-unknown-none` and `bpfeb-unknown-none`.][79608] +- [`-Zmutable-noalias=yes`][82834] is enabled by default when using LLVM 12 or above. \* Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. @@ -244,6 +245,7 @@ Compatibility Notes [83366]: https://github.com/rust-lang/rust/pull/83366 [83278]: https://github.com/rust-lang/rust/pull/83278 [85292]: https://github.com/rust-lang/rust/pull/85292 +[82834]: https://github.com/rust-lang/rust/pull/82834 [cargo/9520]: https://github.com/rust-lang/cargo/pull/9520 [cargo/9499]: https://github.com/rust-lang/cargo/pull/9499 [cargo/9488]: https://github.com/rust-lang/cargo/pull/9488