diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index caa4843da4d..ef1b6e217a2 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.39.0"; +pub const CFG_RELEASE_NUM: &str = "1.40.0"; pub struct GitInfo { inner: Option, diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index a39fcd5ad4c..9bc76f51570 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -240,7 +240,6 @@ pub(crate) unsafe fn box_free(ptr: Unique) { #[stable(feature = "global_alloc", since = "1.28.0")] #[rustc_allocator_nounwind] pub fn handle_alloc_error(layout: Layout) -> ! { - #[cfg_attr(bootstrap, allow(improper_ctypes))] extern "Rust" { #[lang = "oom"] fn oom_impl(layout: Layout) -> !; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 9e6ed92ffb5..247cd9a0201 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -117,7 +117,6 @@ #![feature(allocator_internals)] #![feature(on_unimplemented)] #![feature(rustc_const_unstable)] -#![cfg_attr(bootstrap, feature(const_vec_new))] #![feature(slice_partition_dedup)] #![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index e5f96ada6d5..abe50fdb7a3 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -369,7 +369,6 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_string_new"))] pub const fn new() -> String { String { vec: Vec::new() } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 405969a550b..e5672f8542f 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -291,7 +291,7 @@ use crate::raw_vec::RawVec; /// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve /// [owned slice]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(all(not(bootstrap), not(test)), rustc_diagnostic_item = "vec_type")] +#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")] pub struct Vec { buf: RawVec, len: usize, @@ -314,7 +314,6 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_vec_new"))] pub const fn new() -> Vec { Vec { buf: RawVec::NEW, diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs index f751ccb4280..617bdd238f4 100644 --- a/src/libcore/bool.rs +++ b/src/libcore/bool.rs @@ -1,6 +1,5 @@ //! impl bool {} -#[cfg(not(bootstrap))] #[lang = "bool"] impl bool { /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise. diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 6bdae1b557d..14d947ccf24 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -135,7 +135,6 @@ pub trait Clone : Sized { /// Derive macro generating an impl of the trait `Clone`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Clone($item:item) { /* compiler built-in */ } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index fc7329f57d4..d0ea75c7623 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -210,7 +210,6 @@ pub trait PartialEq { /// Derive macro generating an impl of the trait `PartialEq`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialEq($item:item) { /* compiler built-in */ } @@ -273,7 +272,6 @@ pub trait Eq: PartialEq { /// Derive macro generating an impl of the trait `Eq`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_eq)] pub macro Eq($item:item) { /* compiler built-in */ } @@ -624,7 +622,6 @@ pub trait Ord: Eq + PartialOrd { /// Derive macro generating an impl of the trait `Ord`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Ord($item:item) { /* compiler built-in */ } @@ -873,7 +870,6 @@ pub trait PartialOrd: PartialEq { /// Derive macro generating an impl of the trait `PartialOrd`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialOrd($item:item) { /* compiler built-in */ } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 806d4783107..1aadc77cfb8 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -117,7 +117,6 @@ pub trait Default: Sized { /// Derive macro generating an impl of the trait `Default`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Default($item:item) { /* compiler built-in */ } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 65e2f8b9be6..aafa35873bb 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -518,8 +518,7 @@ impl Display for Arguments<'_> { label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", )] #[doc(alias = "{:?}")] -#[cfg_attr(bootstrap, lang = "debug_trait")] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "debug_trait")] +#[rustc_diagnostic_item = "debug_trait"] pub trait Debug { /// Formats the value using the given formatter. /// @@ -550,7 +549,6 @@ pub trait Debug { pub(crate) mod macros { /// Derive macro generating an impl of the trait `Debug`. #[rustc_builtin_macro] - #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Debug($item:item) { /* compiler built-in */ } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index aaaa6f9c575..020e085abf8 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -202,7 +202,6 @@ pub trait Hash { pub(crate) mod macros { /// Derive macro generating an impl of the trait `Hash`. #[rustc_builtin_macro] - #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Hash($item:item) { /* compiler built-in */ } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 905375eb60f..b240d059114 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1299,38 +1299,16 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) - #[cfg(bootstrap)] - pub fn overflowing_add(a: T, b: T) -> T; - /// Returns (a - b) mod 2N, where N is the width of T in bits. - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_sub` method. For example, - /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) - #[cfg(bootstrap)] - pub fn overflowing_sub(a: T, b: T) -> T; - /// Returns (a * b) mod 2N, where N is the width of T in bits. - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_mul` method. For example, - /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) - #[cfg(bootstrap)] - pub fn overflowing_mul(a: T, b: T) -> T; - - /// Returns (a + b) mod 2N, where N is the width of T in bits. - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_add` method. For example, - /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) - #[cfg(not(bootstrap))] pub fn wrapping_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) - #[cfg(not(bootstrap))] pub fn wrapping_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) - #[cfg(not(bootstrap))] pub fn wrapping_mul(a: T, b: T) -> T; /// Computes `a + b`, while saturating at numeric bounds. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 8221df56a51..e8c76b49a8e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -87,7 +87,6 @@ #![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(nll)] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(on_unimplemented)] @@ -120,9 +119,6 @@ #![feature(rtm_target_feature)] #![feature(f16c_target_feature)] #![feature(hexagon_target_feature)] -#![cfg_attr(bootstrap, feature(const_slice_len))] -#![cfg_attr(bootstrap, feature(const_str_as_bytes))] -#![cfg_attr(bootstrap, feature(const_str_len))] #![feature(const_int_conversion)] #![feature(const_transmute)] #![feature(non_exhaustive)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index c6f5fb0b163..ef91c3559d8 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -1236,10 +1236,8 @@ pub(crate) mod builtin { pub macro test($item:item) { /* compiler built-in */ } /// Attribute macro applied to a function to turn it into a benchmark test. - #[cfg_attr(not(bootstrap), unstable(soft, feature = "test", issue = "50297", - reason = "`bench` is a part of custom test frameworks which are unstable"))] - #[cfg_attr(bootstrap, unstable(feature = "test", issue = "50297", - reason = "`bench` is a part of custom test frameworks which are unstable"))] + #[unstable(soft, feature = "test", issue = "50297", + reason = "`bench` is a part of custom test frameworks which are unstable")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] pub macro bench($item:item) { /* compiler built-in */ } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index a2cfb320e76..7f3d958f5dc 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -290,7 +290,6 @@ pub trait Copy : Clone { /// Derive macro generating an impl of the trait `Copy`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Copy($item:item) { /* compiler built-in */ } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 5d99c10e738..933a2a12473 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1112,13 +1112,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_add(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_add(self, rhs) - } + intrinsics::wrapping_add(self, rhs) } } @@ -1141,13 +1135,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_sub(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_sub(self, rhs) - } + intrinsics::wrapping_sub(self, rhs) } } @@ -1169,13 +1157,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_mul(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_mul(self, rhs) - } + intrinsics::wrapping_mul(self, rhs) } } @@ -1402,7 +1384,16 @@ $EndFeature, " #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] pub const fn wrapping_abs(self) -> Self { - (self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1)) + // sign is -1 (all ones) for negative numbers, 0 otherwise. + let sign = self >> ($BITS - 1); + // For positive self, sign == 0 so the expression is simply + // (self ^ 0).wrapping_sub(0) == self == abs(self). + // + // For negative self, self ^ sign == self ^ all_ones. + // But all_ones ^ self == all_ones - self == -1 - self. + // So for negative numbers, (self ^ sign).wrapping_sub(sign) is + // (-1 - self).wrapping_sub(-1) == -self == abs(self). + (self ^ sign).wrapping_sub(sign) } } @@ -1761,7 +1752,7 @@ $EndFeature, " #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] pub const fn overflowing_abs(self) -> (Self, bool) { - (self ^ (self >> ($BITS - 1))).overflowing_sub(self >> ($BITS - 1)) + (self.wrapping_abs(), self == Self::min_value()) } } @@ -1969,7 +1960,21 @@ $EndFeature, " // Note that the #[inline] above means that the overflow // semantics of the subtraction depend on the crate we're being // inlined into. - (self ^ (self >> ($BITS - 1))) - (self >> ($BITS - 1)) + + // sign is -1 (all ones) for negative numbers, 0 otherwise. + let sign = self >> ($BITS - 1); + // For positive self, sign == 0 so the expression is simply + // (self ^ 0) - 0 == self == abs(self). + // + // For negative self, self ^ sign == self ^ all_ones. + // But all_ones ^ self == all_ones - self == -1 - self. + // So for negative numbers, (self ^ sign) - sign is + // (-1 - self) - -1 == -self == abs(self). + // + // The subtraction overflows when self is min_value(), because + // (-1 - min_value()) - -1 is max_value() - -1 which overflows. + // This is exactly when we want self.abs() to overflow. + (self ^ sign) - sign } } @@ -3040,13 +3045,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_add(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_add(self, rhs) - } + intrinsics::wrapping_add(self, rhs) } } @@ -3068,13 +3067,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_sub(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_sub(self, rhs) - } + intrinsics::wrapping_sub(self, rhs) } } @@ -3097,13 +3090,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_mul(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_mul(self, rhs) - } + intrinsics::wrapping_mul(self, rhs) } doc_comment! { diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 7b7253419b1..e8f0561604a 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -71,7 +71,6 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3 } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - #[cfg_attr(bootstrap, allow(improper_ctypes))] extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 0c2a4e08672..5ec21e6d928 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -62,9 +62,8 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) - #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))] + #[allow_internal_unstable(const_fn_union)] pub const fn len(&self) -> usize { unsafe { crate::ptr::Repr { rust: self }.raw.len @@ -81,7 +80,6 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))] pub const fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index a6ec757faf1..ece61dde490 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2090,7 +2090,6 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))] pub const fn len(&self) -> usize { self.as_bytes().len() } @@ -2110,7 +2109,6 @@ impl str { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -2168,9 +2166,8 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_as_bytes"))] // SAFETY: const sound because we transmute two types with the same layout - #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))] + #[allow_internal_unstable(const_fn_union)] pub const fn as_bytes(&self) -> &[u8] { #[repr(C)] union Slices<'a> { diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index d408fef7515..d5cdc266acb 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -227,7 +227,7 @@ pub mod token_stream { /// To quote `$` itself, use `$$`. #[unstable(feature = "proc_macro_quote", issue = "54722")] #[allow_internal_unstable(proc_macro_def_site)] -#[cfg_attr(not(bootstrap), rustc_builtin_macro)] +#[rustc_builtin_macro] pub macro quote ($($t:tt)*) { /* compiler built-in */ } #[unstable(feature = "proc_macro_internals", issue = "27812")] diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 1f125de9672..91fc004b893 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1103,7 +1103,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { visitor.visit_id(arm.hir_id); - walk_list!(visitor, visit_pat, &arm.pats); + visitor.visit_pat(&arm.pat); if let Some(ref g) = arm.guard { match g { Guard::If(ref e) => visitor.visit_expr(e), diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1e05018007a..f861499cfe4 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -97,7 +97,7 @@ pub struct LoweringContext<'a> { trait_impls: BTreeMap>, - modules: BTreeMap, + modules: BTreeMap, generator_kind: Option, @@ -141,7 +141,7 @@ pub struct LoweringContext<'a> { /// vector. in_scope_lifetimes: Vec, - current_module: NodeId, + current_module: hir::HirId, type_def_lifetime_params: DefIdMap, @@ -262,7 +262,7 @@ pub fn lower_crate( is_in_dyn_type: false, anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, type_def_lifetime_params: Default::default(), - current_module: CRATE_NODE_ID, + current_module: hir::CRATE_HIR_ID, current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)], item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), @@ -434,35 +434,6 @@ impl<'a> LoweringContext<'a> { visit::walk_pat(self, p) } - // HACK(or_patterns; Centril | dlrobertson): Avoid creating - // HIR nodes for `PatKind::Or` for the top level of a `ast::Arm`. - // This is a temporary hack that should go away once we push down - // `arm.pats: HirVec>` -> `arm.pat: P` to HIR. // Centril - fn visit_arm(&mut self, arm: &'tcx Arm) { - match &arm.pat.node { - PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)), - _ => self.visit_pat(&arm.pat), - } - walk_list!(self, visit_expr, &arm.guard); - self.visit_expr(&arm.body); - walk_list!(self, visit_attribute, &arm.attrs); - } - - // HACK(or_patterns; Centril | dlrobertson): Same as above. // Centril - fn visit_expr(&mut self, e: &'tcx Expr) { - if let ExprKind::Let(pat, scrutinee) = &e.node { - walk_list!(self, visit_attribute, e.attrs.iter()); - match &pat.node { - PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)), - _ => self.visit_pat(&pat), - } - self.visit_expr(scrutinee); - self.visit_expr_post(e); - return; - } - visit::walk_expr(self, e) - } - fn visit_item(&mut self, item: &'tcx Item) { let hir_id = self.lctx.allocate_hir_id_counter(item.id); diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index 990728fa0e6..90b6c9474ac 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -247,14 +247,14 @@ impl LoweringContext<'_> { // 4. The return type of the block is `bool` which seems like what the user wanted. let scrutinee = self.lower_expr(scrutinee); let then_arm = { - let pat = self.lower_pat_top_hack(pat); + let pat = self.lower_pat(pat); let expr = self.expr_bool(span, true); self.arm(pat, P(expr)) }; let else_arm = { let pat = self.pat_wild(span); let expr = self.expr_bool(span, false); - self.arm(hir_vec![pat], P(expr)) + self.arm(pat, P(expr)) }; hir::ExprKind::Match( P(scrutinee), @@ -278,7 +278,7 @@ impl LoweringContext<'_> { None => (self.expr_block_empty(span), false), Some(els) => (self.lower_expr(els), true), }; - let else_arm = self.arm(hir_vec![else_pat], P(else_expr)); + let else_arm = self.arm(else_pat, P(else_expr)); // Handle then + scrutinee: let then_expr = self.lower_block_expr(then); @@ -286,7 +286,7 @@ impl LoweringContext<'_> { // ` => `: ExprKind::Let(ref pat, ref scrutinee) => { let scrutinee = self.lower_expr(scrutinee); - let pat = self.lower_pat_top_hack(pat); + let pat = self.lower_pat(pat); (pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause }) } // `true => `: @@ -303,7 +303,7 @@ impl LoweringContext<'_> { // let temporaries live outside of `cond`. let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new()); let pat = self.pat_bool(span, true); - (hir_vec![pat], cond, hir::MatchSource::IfDesugar { contains_else_clause }) + (pat, cond, hir::MatchSource::IfDesugar { contains_else_clause }) } }; let then_arm = self.arm(then_pat, P(then_expr)); @@ -327,7 +327,7 @@ impl LoweringContext<'_> { let else_arm = { let else_pat = self.pat_wild(span); let else_expr = self.expr_break(span, ThinVec::new()); - self.arm(hir_vec![else_pat], else_expr) + self.arm(else_pat, else_expr) }; // Handle then + scrutinee: @@ -343,7 +343,7 @@ impl LoweringContext<'_> { // } // } let scrutinee = self.with_loop_condition_scope(|t| t.lower_expr(scrutinee)); - let pat = self.lower_pat_top_hack(pat); + let pat = self.lower_pat(pat); (pat, scrutinee, hir::MatchSource::WhileLetDesugar, hir::LoopSource::WhileLet) } _ => { @@ -371,7 +371,7 @@ impl LoweringContext<'_> { let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new()); // `true => `: let pat = self.pat_bool(span, true); - (hir_vec![pat], cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While) + (pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While) } }; let then_arm = self.arm(then_pat, P(then_expr)); @@ -424,7 +424,7 @@ impl LoweringContext<'_> { hir::Arm { hir_id: self.next_id(), attrs: self.lower_attrs(&arm.attrs), - pats: self.lower_pat_top_hack(&arm.pat), + pat: self.lower_pat(&arm.pat), guard: match arm.guard { Some(ref x) => Some(hir::Guard::If(P(self.lower_expr(x)))), _ => None, @@ -434,16 +434,6 @@ impl LoweringContext<'_> { } } - /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns - /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready - /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR. - fn lower_pat_top_hack(&mut self, pat: &Pat) -> HirVec> { - match pat.node { - PatKind::Or(ref ps) => ps.iter().map(|x| self.lower_pat(x)).collect(), - _ => hir_vec![self.lower_pat(pat)], - } - } - pub(super) fn make_async_expr( &mut self, capture_clause: CaptureBy, @@ -592,7 +582,7 @@ impl LoweringContext<'_> { ); P(this.expr(await_span, expr_break, ThinVec::new())) }); - self.arm(hir_vec![ready_pat], break_x) + self.arm(ready_pat, break_x) }; // `::std::task::Poll::Pending => {}` @@ -603,7 +593,7 @@ impl LoweringContext<'_> { hir_vec![], ); let empty_block = P(self.expr_block_empty(span)); - self.arm(hir_vec![pending_pat], empty_block) + self.arm(pending_pat, empty_block) }; let inner_match_stmt = { @@ -645,7 +635,7 @@ impl LoweringContext<'_> { }); // mut pinned => loop { ... } - let pinned_arm = self.arm(hir_vec![pinned_pat], loop_expr); + let pinned_arm = self.arm(pinned_pat, loop_expr); // match { // mut pinned => loop { .. } @@ -1079,7 +1069,7 @@ impl LoweringContext<'_> { ThinVec::new(), )); let some_pat = self.pat_some(pat.span, val_pat); - self.arm(hir_vec![some_pat], assign) + self.arm(some_pat, assign) }; // `::std::option::Option::None => break` @@ -1087,7 +1077,7 @@ impl LoweringContext<'_> { let break_expr = self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new())); let pat = self.pat_none(e.span); - self.arm(hir_vec![pat], break_expr) + self.arm(pat, break_expr) }; // `mut iter` @@ -1158,7 +1148,7 @@ impl LoweringContext<'_> { }); // `mut iter => { ... }` - let iter_arm = self.arm(hir_vec![iter_pat], loop_expr); + let iter_arm = self.arm(iter_pat, loop_expr); // `match ::std::iter::IntoIterator::into_iter() { ... }` let into_iter_expr = { @@ -1244,7 +1234,7 @@ impl LoweringContext<'_> { ThinVec::from(attrs.clone()), )); let ok_pat = self.pat_ok(span, val_pat); - self.arm(hir_vec![ok_pat], val_expr) + self.arm(ok_pat, val_expr) }; // `Err(err) => #[allow(unreachable_code)] @@ -1279,7 +1269,7 @@ impl LoweringContext<'_> { }; let err_pat = self.pat_err(try_span, err_local); - self.arm(hir_vec![err_pat], ret_expr) + self.arm(err_pat, ret_expr) }; hir::ExprKind::Match( @@ -1474,14 +1464,11 @@ impl LoweringContext<'_> { } } - /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns - /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready - /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR. - fn arm(&mut self, pats: HirVec>, expr: P) -> hir::Arm { + fn arm(&mut self, pat: P, expr: P) -> hir::Arm { hir::Arm { hir_id: self.next_id(), attrs: hir_vec![], - pats, + pat, guard: None, span: expr.span, body: expr, diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 61be40a6b90..5a8d5daaf09 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -45,14 +45,16 @@ impl<'tcx, 'interner> ItemLowerer<'tcx, 'interner> { impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) { - self.lctx.modules.insert(n, hir::ModuleItems { + let hir_id = self.lctx.lower_node_id(n); + + self.lctx.modules.insert(hir_id, hir::ModuleItems { items: BTreeSet::new(), trait_items: BTreeSet::new(), impl_items: BTreeSet::new(), }); let old = self.lctx.current_module; - self.lctx.current_module = n; + self.lctx.current_module = hir_id; visit::walk_mod(self, m); self.lctx.current_module = old; } diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 889659382d0..b66c2ce1178 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -10,7 +10,7 @@ pub fn check_crate(hir_map: &hir::map::Map<'_>) { let errors = Lock::new(Vec::new()); par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { - let local_def_id = hir_map.local_def_id_from_node_id(*module_id); + let local_def_id = hir_map.local_def_id(*module_id); hir_map.visit_item_likes_in_module(local_def_id, &mut OuterVisitor { hir_map, errors: &errors, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 5cec8a593f1..956cb36c6b1 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -536,9 +536,7 @@ impl<'hir> Map<'hir> { // in the expect_* calls the loops below self.read(hir_id); - let node_id = self.hir_to_node_id[&hir_id]; - - let module = &self.forest.krate.modules[&node_id]; + let module = &self.forest.krate.modules[&hir_id]; for id in &module.items { visitor.visit_item(self.expect_item(*id)); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 92a8c008047..6fdc126e216 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -766,7 +766,7 @@ pub struct Crate { /// A list of modules written out in the order in which they /// appear in the crate. This includes the main crate module. - pub modules: BTreeMap, + pub modules: BTreeMap, } impl Crate { @@ -882,44 +882,61 @@ impl fmt::Debug for Pat { impl Pat { // FIXME(#19596) this is a workaround, but there should be a better way - fn walk_(&self, it: &mut G) -> bool - where G: FnMut(&Pat) -> bool - { + fn walk_short_(&self, it: &mut impl FnMut(&Pat) -> bool) -> bool { if !it(self) { return false; } - match self.node { - PatKind::Binding(.., Some(ref p)) => p.walk_(it), - PatKind::Struct(_, ref fields, _) => { - fields.iter().all(|field| field.pat.walk_(it)) - } - PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => { - s.iter().all(|p| p.walk_(it)) - } - PatKind::Or(ref pats) => pats.iter().all(|p| p.walk_(it)), - PatKind::Box(ref s) | PatKind::Ref(ref s, _) => { - s.walk_(it) - } - PatKind::Slice(ref before, ref slice, ref after) => { + use PatKind::*; + match &self.node { + Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, + Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it), + Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), + TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), + Slice(before, slice, after) => { before.iter() .chain(slice.iter()) .chain(after.iter()) - .all(|p| p.walk_(it)) - } - PatKind::Wild | - PatKind::Lit(_) | - PatKind::Range(..) | - PatKind::Binding(..) | - PatKind::Path(_) => { - true + .all(|p| p.walk_short_(it)) } } } - pub fn walk(&self, mut it: F) -> bool - where F: FnMut(&Pat) -> bool - { + /// Walk the pattern in left-to-right order, + /// short circuiting (with `.all(..)`) if `false` is returned. + /// + /// Note that when visiting e.g. `Tuple(ps)`, + /// if visiting `ps[0]` returns `false`, + /// then `ps[1]` will not be visited. + pub fn walk_short(&self, mut it: impl FnMut(&Pat) -> bool) -> bool { + self.walk_short_(&mut it) + } + + // FIXME(#19596) this is a workaround, but there should be a better way + fn walk_(&self, it: &mut impl FnMut(&Pat) -> bool) { + if !it(self) { + return; + } + + use PatKind::*; + match &self.node { + Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}, + Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it), + Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), + TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), + Slice(before, slice, after) => { + before.iter() + .chain(slice.iter()) + .chain(after.iter()) + .for_each(|p| p.walk_(it)) + } + } + } + + /// Walk the pattern in left-to-right order. + /// + /// If `it(pat)` returns `false`, the children are not visited. + pub fn walk(&self, mut it: impl FnMut(&Pat) -> bool) { self.walk_(&mut it) } } @@ -1259,21 +1276,32 @@ pub struct Local { } /// Represents a single arm of a `match` expression, e.g. -/// ` (if ) => `. +/// ` (if ) => `. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Arm { #[stable_hasher(ignore)] pub hir_id: HirId, pub span: Span, pub attrs: HirVec, - /// Multiple patterns can be combined with `|` - pub pats: HirVec>, + /// If this pattern and the optional guard matches, then `body` is evaluated. + pub pat: P, /// Optional guard clause. pub guard: Option, /// The expression the arm evaluates to if this arm matches. pub body: P, } +impl Arm { + // HACK(or_patterns; Centril | dlrobertson): Remove this and + // correctly handle each case in which this method is used. + pub fn top_pats_hack(&self) -> &[P] { + match &self.pat.node { + PatKind::Or(pats) => pats, + _ => std::slice::from_ref(&self.pat), + } + } +} + #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum Guard { If(P), diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 0d2c7d393bb..118e168f877 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -66,9 +66,7 @@ impl hir::Pat { /// Call `f` on every "binding" in a pattern, e.g., on `a` in /// `match foo() { Some(a) => (), None => () }` - pub fn each_binding(&self, mut f: F) - where F: FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident), - { + pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident)) { self.walk(|p| { if let PatKind::Binding(binding_mode, _, ident, _) = p.node { f(binding_mode, p.hir_id, p.span, ident); @@ -77,35 +75,57 @@ impl hir::Pat { }); } + /// Call `f` on every "binding" in a pattern, e.g., on `a` in + /// `match foo() { Some(a) => (), None => () }`. + /// + /// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited. + pub fn each_binding_or_first( + &self, + f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident), + ) { + self.walk(|p| match &p.node { + PatKind::Or(ps) => { + ps[0].each_binding_or_first(f); + false + }, + PatKind::Binding(bm, _, ident, _) => { + f(*bm, p.hir_id, p.span, *ident); + true + } + _ => true, + }) + } + /// Checks if the pattern contains any patterns that bind something to /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`. pub fn contains_bindings(&self) -> bool { - let mut contains_bindings = false; - self.walk(|p| { - if let PatKind::Binding(..) = p.node { - contains_bindings = true; - false // there's at least one binding, can short circuit now. - } else { - true - } - }); - contains_bindings + self.satisfies(|p| match p.node { + PatKind::Binding(..) => true, + _ => false, + }) } /// Checks if the pattern contains any patterns that bind something to /// an ident or wildcard, e.g., `foo`, or `Foo(_)`, `foo @ Bar(..)`, pub fn contains_bindings_or_wild(&self) -> bool { - let mut contains_bindings = false; - self.walk(|p| { - match p.node { - PatKind::Binding(..) | PatKind::Wild => { - contains_bindings = true; - false // there's at least one binding/wildcard, can short circuit now. - } - _ => true + self.satisfies(|p| match p.node { + PatKind::Binding(..) | PatKind::Wild => true, + _ => false, + }) + } + + /// Checks if the pattern satisfies the given predicate on some sub-pattern. + fn satisfies(&self, pred: impl Fn(&Self) -> bool) -> bool { + let mut satisfies = false; + self.walk_short(|p| { + if pred(p) { + satisfies = true; + false // Found one, can short circuit now. + } else { + true } }); - contains_bindings + satisfies } pub fn simple_ident(&self) -> Option { @@ -119,20 +139,20 @@ impl hir::Pat { /// Returns variants that are necessary to exist for the pattern to match. pub fn necessary_variants(&self) -> Vec { let mut variants = vec![]; - self.walk(|p| { - match p.node { - PatKind::Path(hir::QPath::Resolved(_, ref path)) | - PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) | - PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { - match path.res { - Res::Def(DefKind::Variant, id) => variants.push(id), - Res::Def(DefKind::Ctor(CtorOf::Variant, ..), id) => variants.push(id), - _ => () - } + self.walk(|p| match &p.node { + PatKind::Or(_) => false, + PatKind::Path(hir::QPath::Resolved(_, path)) | + PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..) | + PatKind::Struct(hir::QPath::Resolved(_, path), ..) => { + if let Res::Def(DefKind::Variant, id) + | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), id) + = path.res + { + variants.push(id); } - _ => () + true } - true + _ => true, }); variants.sort(); variants.dedup(); @@ -148,33 +168,14 @@ impl hir::Pat { let mut result = None; self.each_binding(|annotation, _, _, _| { match annotation { - hir::BindingAnnotation::Ref => { - match result { - None | Some(hir::MutImmutable) => result = Some(hir::MutImmutable), - _ => (), - } + hir::BindingAnnotation::Ref => match result { + None | Some(hir::MutImmutable) => result = Some(hir::MutImmutable), + _ => {} } hir::BindingAnnotation::RefMut => result = Some(hir::MutMutable), - _ => (), + _ => {} } }); result } } - -impl hir::Arm { - /// Checks if the patterns for this arm contain any `ref` or `ref mut` - /// bindings, and if yes whether its containing mutable ones or just immutables ones. - pub fn contains_explicit_ref_binding(&self) -> Option { - // FIXME(tschottdorf): contains_explicit_ref_binding() must be removed - // for #42640 (default match binding modes). - // - // See #44848. - self.pats.iter() - .filter_map(|pat| pat.contains_explicit_ref_binding()) - .max_by_key(|m| match *m { - hir::MutMutable => 1, - hir::MutImmutable => 0, - }) - } -} diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index cfbfb5eceb5..3cbc9ebec0a 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1790,16 +1790,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Arm(arm)); self.ibox(0); self.print_outer_attributes(&arm.attrs); - let mut first = true; - for p in &arm.pats { - if first { - first = false; - } else { - self.s.space(); - self.word_space("|"); - } - self.print_pat(&p); - } + self.print_pat(&arm.pat); self.s.space(); if let Some(ref g) = arm.guard { match g { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index c658120b95d..f6063875ac4 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1510,7 +1510,7 @@ pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( time(tcx.sess, "module lints", || { // Run per-module lints par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().lint_mod(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); }); }); }); diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index d4805a7c783..2746794e2a2 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -259,19 +259,13 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { } fn visit_arm(&mut self, arm: &'tcx hir::Arm) { - if arm.pats.len() == 1 { - let variants = arm.pats[0].necessary_variants(); - - // Inside the body, ignore constructions of variants - // necessary for the pattern to match. Those construction sites - // can't be reached unless the variant is constructed elsewhere. - let len = self.ignore_variant_stack.len(); - self.ignore_variant_stack.extend_from_slice(&variants); - intravisit::walk_arm(self, arm); - self.ignore_variant_stack.truncate(len); - } else { - intravisit::walk_arm(self, arm); - } + // Inside the body, ignore constructions of variants + // necessary for the pattern to match. Those construction sites + // can't be reached unless the variant is constructed elsewhere. + let len = self.ignore_variant_stack.len(); + self.ignore_variant_stack.extend(arm.pat.necessary_variants()); + intravisit::walk_arm(self, arm); + self.ignore_variant_stack.truncate(len); } fn visit_pat(&mut self, pat: &'tcx hir::Pat) { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index de6dadabcbf..a3110c000fb 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -779,16 +779,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm) -> TrackMatchMode { let mut mode = Unknown; - for pat in &arm.pats { - self.determine_pat_move_mode(discr_cmt.clone(), &pat, &mut mode); - } + self.determine_pat_move_mode(discr_cmt.clone(), &arm.pat, &mut mode); mode } fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm, mode: MatchMode) { - for pat in &arm.pats { - self.walk_pat(discr_cmt.clone(), &pat, mode); - } + self.walk_pat(discr_cmt.clone(), &arm.pat, mode); if let Some(hir::Guard::If(ref e)) = arm.guard { self.consume_expr(e) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 00013bfc574..9f6611712a8 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -96,7 +96,11 @@ use self::LiveNodeKind::*; use self::VarKind::*; +use crate::hir; +use crate::hir::{Expr, HirId}; use crate::hir::def::*; +use crate::hir::def_id::DefId; +use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; use crate::hir::Node; use crate::hir::ptr::P; use crate::ty::{self, TyCtxt}; @@ -105,20 +109,16 @@ use crate::lint; use crate::util::nodemap::{HirIdMap, HirIdSet}; use errors::Applicability; -use std::collections::{BTreeMap, VecDeque}; +use rustc_data_structures::fx::FxIndexMap; +use std::collections::VecDeque; use std::{fmt, u32}; use std::io::prelude::*; use std::io; use std::rc::Rc; use syntax::ast; -use syntax::symbol::{kw, sym}; +use syntax::symbol::sym; use syntax_pos::Span; -use crate::hir; -use crate::hir::{Expr, HirId}; -use crate::hir::def_id::DefId; -use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; - #[derive(Copy, Clone, PartialEq)] struct Variable(u32); @@ -404,7 +404,7 @@ fn visit_fn<'tcx>( lsets.warn_about_unused_args(body, entry_ln); } -fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P) { +fn add_from_pat(ir: &mut IrMaps<'_>, pat: &P) { // For struct patterns, take note of which fields used shorthand // (`x` rather than `x: x`). let mut shorthand_field_ids = HirIdSet::default(); @@ -412,26 +412,21 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P) { pats.push_back(pat); while let Some(pat) = pats.pop_front() { use crate::hir::PatKind::*; - match pat.node { - Binding(_, _, _, ref inner_pat) => { + match &pat.node { + Binding(.., inner_pat) => { pats.extend(inner_pat.iter()); } - Struct(_, ref fields, _) => { - for field in fields { - if field.is_shorthand { - shorthand_field_ids.insert(field.pat.hir_id); - } - } + Struct(_, fields, _) => { + let ids = fields.iter().filter(|f| f.is_shorthand).map(|f| f.pat.hir_id); + shorthand_field_ids.extend(ids); } - Ref(ref inner_pat, _) | - Box(ref inner_pat) => { + Ref(inner_pat, _) | Box(inner_pat) => { pats.push_back(inner_pat); } - TupleStruct(_, ref inner_pats, _) | - Tuple(ref inner_pats, _) => { + TupleStruct(_, inner_pats, _) | Tuple(inner_pats, _) | Or(inner_pats) => { pats.extend(inner_pats.iter()); } - Slice(ref pre_pats, ref inner_pat, ref post_pats) => { + Slice(pre_pats, inner_pat, post_pats) => { pats.extend(pre_pats.iter()); pats.extend(inner_pat.iter()); pats.extend(post_pats.iter()); @@ -440,7 +435,7 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P) { } } - pat.each_binding(|_bm, hir_id, _sp, ident| { + pat.each_binding(|_, hir_id, _, ident| { ir.add_live_node_for_node(hir_id, VarDefNode(ident.span)); ir.add_variable(Local(LocalInfo { id: hir_id, @@ -456,9 +451,7 @@ fn visit_local<'tcx>(ir: &mut IrMaps<'tcx>, local: &'tcx hir::Local) { } fn visit_arm<'tcx>(ir: &mut IrMaps<'tcx>, arm: &'tcx hir::Arm) { - for pat in &arm.pats { - add_from_pat(ir, pat); - } + add_from_pat(ir, &arm.pat); intravisit::walk_arm(ir, arm); } @@ -734,35 +727,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.ir.variable(hir_id, span) } - fn pat_bindings(&mut self, pat: &hir::Pat, mut f: F) where - F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, HirId), - { - pat.each_binding(|_bm, hir_id, sp, n| { - let ln = self.live_node(hir_id, sp); - let var = self.variable(hir_id, n.span); - f(self, ln, var, n.span, hir_id); - }) - } - - fn arm_pats_bindings(&mut self, pat: Option<&hir::Pat>, f: F) where - F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, HirId), - { - if let Some(pat) = pat { - self.pat_bindings(pat, f); - } - } - - fn define_bindings_in_pat(&mut self, pat: &hir::Pat, succ: LiveNode) - -> LiveNode { - self.define_bindings_in_arm_pats(Some(pat), succ) - } - - fn define_bindings_in_arm_pats(&mut self, pat: Option<&hir::Pat>, succ: LiveNode) - -> LiveNode { - let mut succ = succ; - self.arm_pats_bindings(pat, |this, ln, var, _sp, _id| { - this.init_from_succ(ln, succ); - this.define(ln, var); + fn define_bindings_in_pat(&mut self, pat: &hir::Pat, mut succ: LiveNode) -> LiveNode { + // In an or-pattern, only consider the first pattern; any later patterns + // must have the same bindings, and we also consider the first pattern + // to be the "authoritative" set of ids. + pat.each_binding_or_first(&mut |_, hir_id, pat_sp, ident| { + let ln = self.live_node(hir_id, pat_sp); + let var = self.variable(hir_id, ident.span); + self.init_from_succ(ln, succ); + self.define(ln, var); succ = ln; }); succ @@ -1076,12 +1049,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { arm.guard.as_ref().map(|hir::Guard::If(e)| &**e), body_succ ); - // only consider the first pattern; any later patterns must have - // the same bindings, and we also consider the first pattern to be - // the "authoritative" set of ids - let arm_succ = - self.define_bindings_in_arm_pats(arm.pats.first().map(|p| &**p), - guard_succ); + let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ); self.merge_from_succ(ln, arm_succ, first_merge); first_merge = false; }; @@ -1388,74 +1356,36 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { NestedVisitorMap::None } - fn visit_local(&mut self, l: &'tcx hir::Local) { - check_local(self, l); + fn visit_local(&mut self, local: &'tcx hir::Local) { + self.check_unused_vars_in_pat(&local.pat, None, |spans, hir_id, ln, var| { + if local.init.is_some() { + self.warn_about_dead_assign(spans, hir_id, ln, var); + } + }); + + intravisit::walk_local(self, local); } + fn visit_expr(&mut self, ex: &'tcx Expr) { check_expr(self, ex); } - fn visit_arm(&mut self, a: &'tcx hir::Arm) { - check_arm(self, a); + + fn visit_arm(&mut self, arm: &'tcx hir::Arm) { + self.check_unused_vars_in_pat(&arm.pat, None, |_, _, _, _| {}); + intravisit::walk_arm(self, arm); } } -fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local) { - match local.init { - Some(_) => { - this.warn_about_unused_or_dead_vars_in_pat(&local.pat); - }, - None => { - this.pat_bindings(&local.pat, |this, ln, var, sp, id| { - let span = local.pat.simple_ident().map_or(sp, |ident| ident.span); - this.warn_about_unused(vec![span], id, ln, var); - }) - } - } - - intravisit::walk_local(this, local); -} - -fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) { - // Only consider the variable from the first pattern; any later patterns must have - // the same bindings, and we also consider the first pattern to be the "authoritative" set of - // ids. However, we should take the spans of variables with the same name from the later - // patterns so the suggestions to prefix with underscores will apply to those too. - let mut vars: BTreeMap)> = Default::default(); - - for pat in &arm.pats { - this.arm_pats_bindings(Some(&*pat), |this, ln, var, sp, id| { - let name = this.ir.variable_name(var); - vars.entry(name) - .and_modify(|(.., spans)| { - spans.push(sp); - }) - .or_insert_with(|| { - (ln, var, id, vec![sp]) - }); - }); - } - - for (_, (ln, var, id, spans)) in vars { - this.warn_about_unused(spans, id, ln, var); - } - - intravisit::walk_arm(this, arm); -} - -fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { +fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr) { match expr.node { hir::ExprKind::Assign(ref l, _) => { this.check_place(&l); - - intravisit::walk_expr(this, expr); } hir::ExprKind::AssignOp(_, ref l, _) => { if !this.tables.is_method_call(expr) { this.check_place(&l); } - - intravisit::walk_expr(this, expr); } hir::ExprKind::InlineAsm(ref ia, ref outputs, ref inputs) => { @@ -1470,8 +1400,6 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } this.visit_expr(output); } - - intravisit::walk_expr(this, expr); } // no correctness conditions related to liveness @@ -1484,13 +1412,13 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Lit(_) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) | - hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => { - intravisit::walk_expr(this, expr); - } + hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => {} } + + intravisit::walk_expr(this, expr); } -impl<'a, 'tcx> Liveness<'a, 'tcx> { +impl<'tcx> Liveness<'_, 'tcx> { fn check_place(&mut self, expr: &'tcx Expr) { match expr.node { hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => { @@ -1503,7 +1431,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // as being used. let ln = self.live_node(expr.hir_id, expr.span); let var = self.variable(var_hid, expr.span); - self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var); + self.warn_about_dead_assign(vec![expr.span], expr.hir_id, ln, var); } } } @@ -1525,109 +1453,112 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) { - for param in &body.params { - param.pat.each_binding(|_bm, hir_id, _, ident| { - let sp = ident.span; - let var = self.variable(hir_id, sp); - // Ignore unused self. - if ident.name != kw::SelfLower { - if !self.warn_about_unused(vec![sp], hir_id, entry_ln, var) { - if self.live_on_entry(entry_ln, var).is_none() { - self.report_dead_assign(hir_id, sp, var, true); - } - } + for p in &body.params { + self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| { + if self.live_on_entry(ln, var).is_none() { + self.report_dead_assign(hir_id, spans, var, true); } - }) + }); } } - fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &hir::Pat) { - self.pat_bindings(pat, |this, ln, var, sp, id| { - if !this.warn_about_unused(vec![sp], id, ln, var) { - this.warn_about_dead_assign(sp, id, ln, var); + fn check_unused_vars_in_pat( + &self, + pat: &hir::Pat, + entry_ln: Option, + on_used_on_entry: impl Fn(Vec, HirId, LiveNode, Variable), + ) { + // In an or-pattern, only consider the variable; any later patterns must have the same + // bindings, and we also consider the first pattern to be the "authoritative" set of ids. + // However, we should take the spans of variables with the same name from the later + // patterns so the suggestions to prefix with underscores will apply to those too. + let mut vars: FxIndexMap)> = <_>::default(); + + pat.each_binding(|_, hir_id, pat_sp, ident| { + let ln = entry_ln.unwrap_or_else(|| self.live_node(hir_id, pat_sp)); + let var = self.variable(hir_id, ident.span); + vars.entry(self.ir.variable_name(var)) + .and_modify(|(.., spans)| spans.push(ident.span)) + .or_insert_with(|| (ln, var, hir_id, vec![ident.span])); + }); + + for (_, (ln, var, id, spans)) in vars { + if self.used_on_entry(ln, var) { + on_used_on_entry(spans, id, ln, var); + } else { + self.report_unused(spans, id, ln, var); } - }) + } } - fn warn_about_unused(&self, - spans: Vec, - hir_id: HirId, - ln: LiveNode, - var: Variable) - -> bool { - if !self.used_on_entry(ln, var) { - let r = self.should_warn(var); - if let Some(name) = r { - // annoying: for parameters in funcs like `fn(x: i32) - // {ret}`, there is only one node, so asking about - // assigned_on_exit() is not meaningful. - let is_assigned = if ln == self.s.exit_ln { - false - } else { - self.assigned_on_exit(ln, var).is_some() - }; + fn report_unused(&self, spans: Vec, hir_id: HirId, ln: LiveNode, var: Variable) { + if let Some(name) = self.should_warn(var).filter(|name| name != "self") { + // annoying: for parameters in funcs like `fn(x: i32) + // {ret}`, there is only one node, so asking about + // assigned_on_exit() is not meaningful. + let is_assigned = if ln == self.s.exit_ln { + false + } else { + self.assigned_on_exit(ln, var).is_some() + }; - if is_assigned { - self.ir.tcx.lint_hir_note( - lint::builtin::UNUSED_VARIABLES, - hir_id, - spans, - &format!("variable `{}` is assigned to, but never used", name), - &format!("consider using `_{}` instead", name), - ); - } else if name != "self" { - let mut err = self.ir.tcx.struct_span_lint_hir( - lint::builtin::UNUSED_VARIABLES, - hir_id, - spans.clone(), - &format!("unused variable: `{}`", name), - ); + if is_assigned { + self.ir.tcx.lint_hir_note( + lint::builtin::UNUSED_VARIABLES, + hir_id, + spans, + &format!("variable `{}` is assigned to, but never used", name), + &format!("consider using `_{}` instead", name), + ); + } else { + let mut err = self.ir.tcx.struct_span_lint_hir( + lint::builtin::UNUSED_VARIABLES, + hir_id, + spans.clone(), + &format!("unused variable: `{}`", name), + ); - if self.ir.variable_is_shorthand(var) { - if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) { - // Handle `ref` and `ref mut`. - let spans = spans.iter() - .map(|_span| (pat.span, format!("{}: _", name))) - .collect(); + if self.ir.variable_is_shorthand(var) { + if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) { + // Handle `ref` and `ref mut`. + let spans = spans.iter() + .map(|_span| (pat.span, format!("{}: _", name))) + .collect(); - err.multipart_suggestion( - "try ignoring the field", - spans, - Applicability::MachineApplicable, - ); - } - } else { err.multipart_suggestion( - "consider prefixing with an underscore", - spans.iter().map(|span| (*span, format!("_{}", name))).collect(), + "try ignoring the field", + spans, Applicability::MachineApplicable, ); } - - err.emit() + } else { + err.multipart_suggestion( + "consider prefixing with an underscore", + spans.iter().map(|span| (*span, format!("_{}", name))).collect(), + Applicability::MachineApplicable, + ); } + + err.emit() } - true - } else { - false } } - fn warn_about_dead_assign(&self, sp: Span, hir_id: HirId, ln: LiveNode, var: Variable) { + fn warn_about_dead_assign(&self, spans: Vec, hir_id: HirId, ln: LiveNode, var: Variable) { if self.live_on_exit(ln, var).is_none() { - self.report_dead_assign(hir_id, sp, var, false); + self.report_dead_assign(hir_id, spans, var, false); } } - fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) { + fn report_dead_assign(&self, hir_id: HirId, spans: Vec, var: Variable, is_param: bool) { if let Some(name) = self.should_warn(var) { - if is_argument { - self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp, + if is_param { + self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans, &format!("value passed to `{}` is never read", name)) .help("maybe it is overwritten before being read?") .emit(); } else { - self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp, + self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans, &format!("value assigned to `{}` is never read", name)) .help("maybe it is overwritten before being read?") .emit(); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c03dbb2b1ed..a25ef21d697 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -974,7 +974,7 @@ pub struct FreeRegionInfo { /// /// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html #[derive(Copy, Clone)] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyCtxt")] +#[rustc_diagnostic_item = "TyCtxt"] pub struct TyCtxt<'tcx> { gcx: &'tcx GlobalCtxt<'tcx>, } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ef8bdfb583e..61483fa8a49 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -581,7 +581,7 @@ impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { } } -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "Ty")] +#[rustc_diagnostic_item = "Ty"] pub type Ty<'tcx> = &'tcx TyS<'tcx>; impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {} diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e73a51e6f78..036f41a4043 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -86,7 +86,7 @@ impl BoundRegion { /// AST structure in `libsyntax/ast.rs` as well. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable, Debug)] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyKind")] +#[rustc_diagnostic_item = "TyKind"] pub enum TyKind<'tcx> { /// The primitive boolean type. Written as `bool`. Bool, diff --git a/src/librustc_ast_borrowck/cfg/construct.rs b/src/librustc_ast_borrowck/cfg/construct.rs index 0dc999083a9..e2c5de648a2 100644 --- a/src/librustc_ast_borrowck/cfg/construct.rs +++ b/src/librustc_ast_borrowck/cfg/construct.rs @@ -390,7 +390,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // patterns and the guard (if there is one) in the arm. let bindings_exit = self.add_dummy_node(&[]); - for pat in &arm.pats { + for pat in arm.top_pats_hack() { // Visit the pattern, coming from the discriminant exit let mut pat_exit = self.pat(&pat, discr_exit); diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 56db695f254..37b33466d70 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -905,10 +905,10 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { }); }, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().check_mod_loops(tcx.hir().local_def_id_from_node_id(module)); - tcx.ensure().check_mod_attrs(tcx.hir().local_def_id_from_node_id(module)); - tcx.ensure().check_mod_unstable_api_usage( - tcx.hir().local_def_id_from_node_id(module)); + let local_def_id = tcx.hir().local_def_id(module); + tcx.ensure().check_mod_loops(local_def_id); + tcx.ensure().check_mod_attrs(local_def_id); + tcx.ensure().check_mod_unstable_api_usage(local_def_id); }); }); }); @@ -931,9 +931,10 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { // "not all control paths return a value" is reported here. // // maybe move the check to a MIR pass? - tcx.ensure().check_mod_liveness(tcx.hir().local_def_id_from_node_id(module)); + let local_def_id = tcx.hir().local_def_id(module); - tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().check_mod_liveness(local_def_id); + tcx.ensure().check_mod_intrinsics(local_def_id); }); }); }); @@ -993,7 +994,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { }, { time(sess, "privacy checking modules", || { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().check_mod_privacy(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module)); }); }); }); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 2b0237c7c08..5f1bd3e9115 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -142,7 +142,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Step 2. Create the otherwise and prebinding blocks. // create binding start block for link them by false edges - let candidate_count = arms.iter().map(|c| c.patterns.len()).sum::(); + let candidate_count = arms.iter().map(|c| c.top_pats_hack().len()).sum::(); let pre_binding_blocks: Vec<_> = (0..candidate_count) .map(|_| self.cfg.start_new_block()) .collect(); @@ -159,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .map(|arm| { let arm_has_guard = arm.guard.is_some(); match_has_guard |= arm_has_guard; - let arm_candidates: Vec<_> = arm.patterns + let arm_candidates: Vec<_> = arm.top_pats_hack() .iter() .zip(candidate_pre_binding_blocks.by_ref()) .map( @@ -238,7 +238,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let scope = this.declare_bindings( None, arm.span, - &arm.patterns[0], + &arm.top_pats_hack()[0], ArmHasGuard(arm.guard.is_some()), Some((Some(&scrutinee_place), scrutinee_span)), ); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index a33d7207ed4..bdfcacd0f46 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -860,9 +860,9 @@ impl ToBorrowKind for hir::Mutability { } } -fn convert_arm<'a, 'tcx>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { +fn convert_arm<'tcx>(cx: &mut Cx<'_, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { Arm { - patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(), + pattern: cx.pattern_from_hir(&arm.pat), guard: match arm.guard { Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())), _ => None, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 0638cb462f7..63a9a83154b 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -293,7 +293,7 @@ pub struct FruInfo<'tcx> { #[derive(Clone, Debug)] pub struct Arm<'tcx> { - pub patterns: Vec>, + pub pattern: Pattern<'tcx>, pub guard: Option>, pub body: ExprRef<'tcx>, pub lint_level: LintLevel, @@ -301,6 +301,17 @@ pub struct Arm<'tcx> { pub span: Span, } +impl Arm<'tcx> { + // HACK(or_patterns; Centril | dlrobertson): Remove this and + // correctly handle each case in which this method is used. + pub fn top_pats_hack(&self) -> &[Pattern<'tcx>] { + match &*self.pattern.kind { + PatternKind::Or { pats } => pats, + _ => std::slice::from_ref(&self.pattern), + } + } +} + #[derive(Clone, Debug)] pub enum Guard<'tcx> { If(ExprRef<'tcx>), diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 161c58a1755..6301d9c390b 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -14,7 +14,6 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc::hir::def::*; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::ptr::P; use rustc::hir::{self, Pat, PatKind}; use smallvec::smallvec; @@ -76,7 +75,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { }); // Check legality of move bindings and `@` patterns. - self.check_patterns(false, slice::from_ref(&loc.pat)); + self.check_patterns(false, &loc.pat); } fn visit_body(&mut self, body: &'tcx hir::Body) { @@ -84,7 +83,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { for param in &body.params { self.check_irrefutable(¶m.pat, "function argument"); - self.check_patterns(false, slice::from_ref(¶m.pat)); + self.check_patterns(false, ¶m.pat); } } } @@ -122,11 +121,9 @@ impl PatternContext<'_, '_> { } impl<'tcx> MatchVisitor<'_, 'tcx> { - fn check_patterns(&mut self, has_guard: bool, pats: &[P]) { - check_legality_of_move_bindings(self, has_guard, pats); - for pat in pats { - check_legality_of_bindings_in_at_patterns(self, pat); - } + fn check_patterns(&mut self, has_guard: bool, pat: &Pat) { + check_legality_of_move_bindings(self, has_guard, pat); + check_legality_of_bindings_in_at_patterns(self, pat); } fn check_match( @@ -137,7 +134,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { ) { for arm in arms { // First, check legality of move bindings. - self.check_patterns(arm.guard.is_some(), &arm.pats); + self.check_patterns(arm.guard.is_some(), &arm.pat); // Second, if there is a guard on each arm, make sure it isn't // assigning or borrowing anything mutably. @@ -146,9 +143,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { } // Third, perform some lints. - for pat in &arm.pats { - check_for_bindings_named_same_as_variants(self, pat); - } + check_for_bindings_named_same_as_variants(self, &arm.pat); } let module = self.tcx.hir().get_module_parent(scrut.hir_id); @@ -156,7 +151,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { let mut have_errors = false; let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| ( - arm.pats.iter().map(|pat| { + arm.top_pats_hack().iter().map(|pat| { let mut patcx = PatternContext::new(self.tcx, self.param_env.and(self.identity_substs), self.tables); @@ -545,78 +540,60 @@ fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[Pattern<'_>]) -> Vec { covered } -// Legality of move bindings checking -fn check_legality_of_move_bindings( - cx: &mut MatchVisitor<'_, '_>, - has_guard: bool, - pats: &[P], -) { +// Check the legality of legality of by-move bindings. +fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pat: &Pat) { let mut by_ref_span = None; - for pat in pats { - pat.each_binding(|_, hir_id, span, _path| { - if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) { - if let ty::BindByReference(..) = bm { - by_ref_span = Some(span); + pat.each_binding(|_, hir_id, span, _| { + if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) { + if let ty::BindByReference(..) = bm { + by_ref_span = Some(span); + } + } else { + cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); + } + }); + + let span_vec = &mut Vec::new(); + let mut check_move = |p: &Pat, sub: Option<&Pat>| { + // Check legality of moving out of the enum. + // + // `x @ Foo(..)` is legal, but `x @ Foo(y)` isn't. + if sub.map_or(false, |p| p.contains_bindings()) { + struct_span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings") + .span_label(p.span, "binds an already bound by-move value by moving it") + .emit(); + } else if !has_guard && by_ref_span.is_some() { + span_vec.push(p.span); + } + }; + + pat.walk(|p| { + if let PatKind::Binding(.., sub) = &p.node { + if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { + if let ty::BindByValue(..) = bm { + let pat_ty = cx.tables.node_type(p.hir_id); + if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { + check_move(p, sub.as_deref()); + } } } else { cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } - }) - } - let span_vec = &mut Vec::new(); - let check_move = | - cx: &mut MatchVisitor<'_, '_>, - p: &Pat, - sub: Option<&Pat>, - span_vec: &mut Vec, - | { - // check legality of moving out of the enum - - // x @ Foo(..) is legal, but x @ Foo(y) isn't. - if sub.map_or(false, |p| p.contains_bindings()) { - struct_span_err!(cx.tcx.sess, p.span, E0007, - "cannot bind by-move with sub-bindings") - .span_label(p.span, "binds an already bound by-move value by moving it") - .emit(); - } else if !has_guard { - if let Some(_by_ref_span) = by_ref_span { - span_vec.push(p.span); - } } - }; + true + }); - for pat in pats { - pat.walk(|p| { - if let PatKind::Binding(_, _, _, ref sub) = p.node { - if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { - match bm { - ty::BindByValue(..) => { - let pat_ty = cx.tables.node_type(p.hir_id); - if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { - check_move(cx, p, sub.as_ref().map(|p| &**p), span_vec); - } - } - _ => {} - } - } else { - cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); - } - } - true - }); - } - if !span_vec.is_empty(){ - let span = MultiSpan::from_spans(span_vec.clone()); + if !span_vec.is_empty() { let mut err = struct_span_err!( cx.tcx.sess, - span, + MultiSpan::from_spans(span_vec.clone()), E0009, "cannot bind by-move and by-ref in the same pattern", ); if let Some(by_ref_span) = by_ref_span { err.span_label(by_ref_span, "both by-ref and by-move used"); } - for span in span_vec.iter(){ + for span in span_vec.iter() { err.span_label(*span, "by-move pattern here"); } err.emit(); @@ -627,7 +604,7 @@ fn check_legality_of_move_bindings( /// because of the way rvalues are handled in the borrow check. (See issue /// #14587.) fn check_legality_of_bindings_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat) { - AtBindingPatternVisitor { cx: cx, bindings_allowed: true }.visit_pat(pat); + AtBindingPatternVisitor { cx, bindings_allowed: true }.visit_pat(pat); } struct AtBindingPatternVisitor<'a, 'b, 'tcx> { diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index ec09e69ec85..5fc23b4a69e 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -239,7 +239,52 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "transmute" => { self.copy_op_transmute(args[0], dest)?; } + "simd_insert" => { + let index = self.read_scalar(args[1])?.to_u32()? as u64; + let scalar = args[2]; + let input = args[0]; + let (len, e_ty) = self.read_vector_ty(input); + assert!( + index < len, + "Index `{}` must be in bounds of vector type `{}`: `[0, {})`", + index, e_ty, len + ); + assert_eq!( + input.layout, dest.layout, + "Return type `{}` must match vector type `{}`", + dest.layout.ty, input.layout.ty + ); + assert_eq!( + scalar.layout.ty, e_ty, + "Scalar type `{}` must match vector element type `{}`", + scalar.layout.ty, e_ty + ); + for i in 0..len { + let place = self.place_field(dest, i)?; + let value = if i == index { + scalar + } else { + self.operand_field(input, i)? + }; + self.copy_op(value, place)?; + } + } + "simd_extract" => { + let index = self.read_scalar(args[1])?.to_u32()? as _; + let (len, e_ty) = self.read_vector_ty(args[0]); + assert!( + index < len, + "index `{}` is out-of-bounds of vector type `{}` with length `{}`", + index, e_ty, len + ); + assert_eq!( + e_ty, dest.layout.ty, + "Return type `{}` must match vector element type `{}`", + dest.layout.ty, e_ty + ); + self.copy_op(self.operand_field(args[0], index)?, dest)?; + } _ => return Ok(false), } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index dd214c4a031..afaf9d7ed9d 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -335,6 +335,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } + /// Read vector length and element type + pub fn read_vector_ty( + &self, op: OpTy<'tcx, M::PointerTag> + ) -> (u64, &rustc::ty::TyS<'tcx>) { + if let layout::Abi::Vector { .. } = op.layout.abi { + (op.layout.ty.simd_size(*self.tcx) as _, op.layout.ty.simd_type(*self.tcx)) + } else { + bug!("Type `{}` is not a SIMD vector type", op.layout.ty) + } + } + /// Read a scalar from a place pub fn read_scalar( &self, diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 8310ef02f96..8666c937ce4 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -249,9 +249,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match instance.def { ty::InstanceDef::Intrinsic(..) => { - if caller_abi != Abi::RustIntrinsic { - throw_unsup!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic)) - } // The intrinsic itself cannot diverge, so if we got here without a return // place... (can happen e.g., for transmute returning `!`) let dest = match dest { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 9a03719ab61..938dab57181 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -6,6 +6,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(nll)] #![feature(in_band_lifetimes)] +#![feature(inner_deref)] #![feature(slice_patterns)] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 795721f3b3f..8a6dcd1d2b4 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -557,6 +557,8 @@ impl Qualif for IsNotPromotable { | "saturating_add" | "saturating_sub" | "transmute" + | "simd_insert" + | "simd_extract" => return true, _ => {} diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index a5a8315a1e7..4e29706714f 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -8,7 +8,6 @@ #![feature(in_band_lifetimes)] #![feature(nll)] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![recursion_limit="256"] diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index f2461f70161..12978cd117b 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -499,19 +499,15 @@ fn check_expr_kind<'a, 'tcx>( } // Conditional control flow (possible to implement). - hir::ExprKind::Match(ref expr, ref hirvec_arm, ref _match_source) => { + hir::ExprKind::Match(ref expr, ref arms, ref _match_source) => { // Compute the most demanding borrow from all the arms' // patterns and set that on the discriminator. - let mut mut_borrow = false; - for pat in hirvec_arm.iter().flat_map(|arm| &arm.pats) { - mut_borrow = v.remove_mut_rvalue_borrow(pat); - } - if mut_borrow { + if arms.iter().fold(false, |_, arm| v.remove_mut_rvalue_borrow(&arm.pat)) { v.mut_rvalue_borrows.insert(expr.hir_id); } let _ = v.check_expr(expr); - for index in hirvec_arm.iter() { + for index in arms.iter() { let _ = v.check_expr(&*index.body); if let Some(hir::Guard::If(ref expr)) = index.guard { let _ = v.check_expr(&expr); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 50fd72f0613..14a07c8c9c7 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -58,11 +58,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // collection into `Vec`), so we get types for all bindings. let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| { let mut all_pats_diverge = Diverges::WarnedAlways; - for p in &arm.pats { - self.diverges.set(Diverges::Maybe); - self.check_pat_top(&p, discrim_ty, Some(discrim.span)); - all_pats_diverge &= self.diverges.get(); - } + self.diverges.set(Diverges::Maybe); + self.check_pat_top(&arm.pat, discrim_ty, Some(discrim.span)); + all_pats_diverge &= self.diverges.get(); // As discussed with @eddyb, this is for disabling unreachable_code // warnings on patterns (they're now subsumed by unreachable_patterns @@ -428,11 +426,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // See #44848. let contains_ref_bindings = arms.iter() - .filter_map(|a| a.contains_explicit_ref_binding()) - .max_by_key(|m| match *m { - hir::MutMutable => 1, - hir::MutImmutable => 0, - }); + .filter_map(|a| a.pat.contains_explicit_ref_binding()) + .max_by_key(|m| match *m { + hir::MutMutable => 1, + hir::MutImmutable => 0, + }); if let Some(m) = contains_ref_bindings { self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m)) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 2cd8507d753..a2f7a8fe4fe 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -97,11 +97,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_struct(pat, qpath, fields, *etc, expected, def_bm, discrim_span) } PatKind::Or(pats) => { - let expected_ty = self.structurally_resolved_type(pat.span, expected); for pat in pats { self.check_pat(pat, expected, def_bm, discrim_span); } - expected_ty + expected } PatKind::Tuple(elements, ddpos) => { self.check_pat_tuple(pat.span, elements, *ddpos, expected, def_bm, discrim_span) @@ -208,7 +207,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match pat.node { PatKind::Struct(..) | PatKind::TupleStruct(..) | - PatKind::Or(_) | PatKind::Tuple(..) | PatKind::Box(_) | PatKind::Range(..) | @@ -226,6 +224,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => true, } } + // FIXME(or_patterns; Centril | dlrobertson): To keep things compiling + // for or-patterns at the top level, we need to make `p_0 | ... | p_n` + // a "non reference pattern". For example the following currently compiles: + // ``` + // match &1 { + // e @ &(1...2) | e @ &(3...4) => {} + // _ => {} + // } + // ``` + // + // We should consider whether we should do something special in nested or-patterns. + PatKind::Or(_) | PatKind::Wild | PatKind::Binding(..) | PatKind::Ref(..) => false, @@ -426,12 +436,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the binding is like `ref x | ref const x | ref mut x` // then `x` is assigned a value of type `&M T` where M is the // mutability and T is the expected type. - let region_ty = self.new_ref_ty(pat.span, mutbl, expected); - + // // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` // is required. However, we use equality, which is stronger. // See (note_1) for an explanation. - region_ty + self.new_ref_ty(pat.span, mutbl, expected) } // Otherwise, the type of x is the expected type `T`. ty::BindByValue(_) => { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index fc01a820e23..6fa8a016b54 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -488,9 +488,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { fn visit_arm(&mut self, arm: &'tcx hir::Arm) { // see above - for p in &arm.pats { - self.constrain_bindings_in_pat(p); - } + self.constrain_bindings_in_pat(&arm.pat); intravisit::walk_arm(self, arm); } @@ -1069,9 +1067,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr)))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { - for root_pat in &arm.pats { - self.link_pattern(discr_cmt.clone(), &root_pat); - } + self.link_pattern(discr_cmt.clone(), &arm.pat); } } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index bc0f17c3bf0..854549bb66b 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -54,7 +54,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { // but it's one that we must perform earlier than the rest of // WfCheck. for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id(module)); } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 959483e4439..e97d6db5db0 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -303,7 +303,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { time(tcx.sess, "type collecting", || { for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module)); } }); })?; @@ -338,7 +338,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { time(tcx.sess, "item-types checking", || { for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); } }); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0b9e717221f..2985e7f70b5 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/")] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(rustc_private)] #![feature(arbitrary_self_types)] #![feature(box_patterns)] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 21aeb9c26f8..5d9683f8ded 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -238,7 +238,6 @@ #![feature(array_error_internals)] #![feature(asm)] #![feature(associated_type_bounds)] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_target_has_atomic)] diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs index b51384d3b15..8f49ba9572d 100644 --- a/src/libsyntax/ext/mbe/macro_parser.rs +++ b/src/libsyntax/ext/mbe/macro_parser.rs @@ -413,18 +413,6 @@ fn nameize>( Success(ret_val) } -/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For -/// other tokens, this is "unexpected token...". -crate fn parse_failure_msg(tok: &Token) -> String { - match tok.kind { - token::Eof => "unexpected end of macro invocation".to_string(), - _ => format!( - "no rules expected the token `{}`", - pprust::token_to_string(tok) - ), - } -} - /// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison) fn token_name_eq(t1: &Token, t2: &Token) -> bool { if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) { diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs index 816baadb12f..c24f6a66603 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -6,7 +6,7 @@ use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::ext::expand::{AstFragment, AstFragmentKind}; use crate::ext::mbe; use crate::ext::mbe::macro_check; -use crate::ext::mbe::macro_parser::{parse, parse_failure_msg}; +use crate::ext::mbe::macro_parser::parse; use crate::ext::mbe::macro_parser::{Error, Failure, Success}; use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult}; use crate::ext::mbe::transcribe::transcribe; @@ -15,6 +15,7 @@ use crate::parse::parser::Parser; use crate::parse::token::TokenKind::*; use crate::parse::token::{self, NtTT, Token}; use crate::parse::{Directory, ParseSess}; +use crate::print::pprust; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; @@ -371,10 +372,6 @@ pub fn compile_declarative_macro( tt.clone().into(), true, sess, - features, - &def.attrs, - edition, - def.id, ) .pop() .unwrap(); @@ -398,10 +395,6 @@ pub fn compile_declarative_macro( tt.clone().into(), false, sess, - features, - &def.attrs, - edition, - def.id, ) .pop() .unwrap(); @@ -1184,3 +1177,15 @@ impl TokenTree { parse(cx.parse_sess(), tts, mtch, Some(directory), true) } } + +/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For +/// other tokens, this is "unexpected token...". +fn parse_failure_msg(tok: &Token) -> String { + match tok.kind { + token::Eof => "unexpected end of macro invocation".to_string(), + _ => format!( + "no rules expected the token `{}`", + pprust::token_to_string(tok), + ), + } +} diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs index 3952e29a5f0..8cb85bdef76 100644 --- a/src/libsyntax/ext/mbe/quoted.rs +++ b/src/libsyntax/ext/mbe/quoted.rs @@ -1,18 +1,15 @@ use crate::ast; -use crate::ast::NodeId; use crate::ext::mbe::macro_parser; use crate::ext::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited}; -use crate::feature_gate::Features; use crate::parse::token::{self, Token}; use crate::parse::ParseSess; use crate::print::pprust; use crate::symbol::kw; use crate::tokenstream; -use syntax_pos::{edition::Edition, Span}; +use syntax_pos::Span; use rustc_data_structures::sync::Lrc; -use std::iter::Peekable; /// Takes a `tokenstream::TokenStream` and returns a `Vec`. Specifically, this /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a @@ -39,17 +36,13 @@ pub(super) fn parse( input: tokenstream::TokenStream, expect_matchers: bool, sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - edition: Edition, - macro_node_id: NodeId, ) -> Vec { // Will contain the final collection of `self::TokenTree` let mut result = Vec::new(); // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming // additional trees if need be. - let mut trees = input.trees().peekable(); + let mut trees = input.trees(); while let Some(tree) = trees.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). @@ -58,10 +51,6 @@ pub(super) fn parse( &mut trees, expect_matchers, sess, - features, - attrs, - edition, - macro_node_id, ); match tree { TokenTree::MetaVar(start_sp, ident) if expect_matchers => { @@ -109,13 +98,9 @@ pub(super) fn parse( /// unstable features or not. fn parse_tree( tree: tokenstream::TokenTree, - trees: &mut Peekable>, + trees: &mut impl Iterator, expect_matchers: bool, sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - edition: Edition, - macro_node_id: NodeId, ) -> TokenTree { // Depending on what `tree` is, we could be parsing different parts of a macro match tree { @@ -135,10 +120,6 @@ fn parse_tree( tts.into(), expect_matchers, sess, - features, - attrs, - edition, - macro_node_id, ); // Get the Kleene operator and optional separator let (separator, kleene) = parse_sep_and_kleene_op(trees, span.entire(), sess); @@ -192,10 +173,6 @@ fn parse_tree( tts.into(), expect_matchers, sess, - features, - attrs, - edition, - macro_node_id, ), }), ), @@ -244,7 +221,7 @@ fn parse_kleene_op( /// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an /// error with the appropriate span is emitted to `sess` and a dummy value is returned. fn parse_sep_and_kleene_op( - input: &mut Peekable>, + input: &mut impl Iterator, span: Span, sess: &ParseSess, ) -> (Option, KleeneToken) { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index b0833010fe0..2c10220c766 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -7,7 +7,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(box_syntax)] #![feature(const_fn)] #![feature(const_transmute)] diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index d7c537be896..4fc29d70540 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -834,8 +834,6 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) { pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) { visitor.visit_pat(&arm.pat); - // NOTE(or_patterns; Centril | dlrobertson): - // If you change this, also change the hack in `lowering.rs`. walk_list!(visitor, visit_expr, &arm.guard); visitor.visit_expr(&arm.body); walk_list!(visitor, visit_attribute, &arm.attrs); diff --git a/src/stage0.txt b/src/stage0.txt index 1a9e64a1862..9509d3e9961 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2019-08-13 +date: 2019-09-25 rustc: beta cargo: beta diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs new file mode 100644 index 00000000000..d3462d802ea --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -0,0 +1,53 @@ +// run-pass +#![feature(const_fn)] +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); +#[repr(simd)] struct u16x2(u16, u16); +#[repr(simd)] struct f32x3(f32, f32, f32); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, val: U) -> T; + fn simd_extract(x: T, idx: u32) -> U; +} + +fn main() { + { + const U: i8x1 = i8x1(13); + const V: i8x1 = unsafe { simd_insert(U, 0_u32, 42_i8) }; + const X0: i8 = V.0; + const Y0: i8 = unsafe { simd_extract(V, 0) }; + assert_eq!(X0, 42); + assert_eq!(Y0, 42); + } + { + const U: u16x2 = u16x2(13, 14); + const V: u16x2 = unsafe { simd_insert(U, 1_u32, 42_u16) }; + const X0: u16 = V.0; + const X1: u16 = V.1; + const Y0: u16 = unsafe { simd_extract(V, 0) }; + const Y1: u16 = unsafe { simd_extract(V, 1) }; + assert_eq!(X0, 13); + assert_eq!(X1, 42); + assert_eq!(Y0, 13); + assert_eq!(Y1, 42); + } + { + const U: f32x3 = f32x3(13., 14., 15.); + const V: f32x3 = unsafe { simd_insert(U, 1_u32, 42_f32) }; + const X0: f32 = V.0; + const X1: f32 = V.1; + const X2: f32 = V.2; + const Y0: f32 = unsafe { simd_extract(V, 0) }; + const Y1: f32 = unsafe { simd_extract(V, 1) }; + const Y2: f32 = unsafe { simd_extract(V, 2) }; + assert_eq!(X0, 13.); + assert_eq!(X1, 42.); + assert_eq!(X2, 15.); + assert_eq!(Y0, 13.); + assert_eq!(Y1, 42.); + assert_eq!(Y2, 15.); + } +} diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index 4cb35e907c8..7870d394c8b 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -33,6 +33,9 @@ fn main() { let mut mut_unused_var = 1; let (mut var, unused_var) = (1, 2); + // NOTE: `var` comes after `unused_var` lexicographically yet the warning + // for `var` will be emitted before the one for `unused_var`. We use an + // `IndexMap` to ensure this is the case instead of a `BTreeMap`. if let SoulHistory { corridors_of_light, mut hours_are_suns, diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index a0b34d220c8..74bbef8adad 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -30,13 +30,13 @@ LL | let (mut var, unused_var) = (1, 2); | ^^^^^^^^^^ help: consider prefixing with an underscore: `_unused_var` warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:30 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:30 | LL | mut hours_are_suns, | ^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | mut hours_are_suns, = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:43:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ @@ -58,43 +58,43 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = help: maybe it is overwritten before being read? warning: unused variable: `fire` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:44:32 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:47:32 | LL | let LovelyAmbition { lips, fire } = the_spirit; | ^^^^ help: try ignoring the field: `fire: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:53:23 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:56:23 | LL | Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:58:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:61:24 | LL | &Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:63:27 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:66:27 | LL | box Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:68:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:71:24 | LL | (Large::Suit { case },) => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:73:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:76:24 | LL | [Large::Suit { case }] => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:78:29 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:81:29 | LL | Tuple(Large::Suit { case }, ()) => {} | ^^^^ help: try ignoring the field: `case: _`