diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index a8a1646183c86..a3139ce5a3455 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -129,6 +129,13 @@ pub fn time_trace_profiler_finish(file_name: &str) { // WARNING: the features after applying `to_llvm_feature` must be known // to LLVM or the feature detection code will walk past the end of the feature // array, leading to crashes. +// To find a list of LLVM's names, check llvm-project/llvm/include/llvm/Support/*TargetParser.def +// where the * matches the architecture's name +// Beware to not use the llvm github project for this, but check the git submodule +// found in src/llvm-project +// Though note that Rust can also be build with an external precompiled version of LLVM +// which might lead to failures if the oldest tested / supported LLVM version +// doesn't yet support the relevant intrinsics pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; match (arch, s) { @@ -136,6 +143,9 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { ("x86", "rdrand") => "rdrnd", ("x86", "bmi1") => "bmi", ("x86", "cmpxchg16b") => "cx16", + ("x86", "avx512vaes") => "vaes", + ("x86", "avx512gfni") => "gfni", + ("x86", "avx512vpclmulqdq") => "vpclmulqdq", ("aarch64", "fp") => "fp-armv8", ("aarch64", "fp16") => "fullfp16", (_, s) => s, diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 000ddf4260429..fd18f42f2dd4f 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -4,6 +4,11 @@ use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::symbol::Symbol; +// When adding features to the below lists +// check whether they're named already elsewhere in rust +// e.g. in stdarch and whether the given name matches LLVM's +// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted + const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("aclass", Some(sym::arm_target_feature)), ("mclass", Some(sym::arm_target_feature)), @@ -50,15 +55,23 @@ const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("aes", None), ("avx", None), ("avx2", None), + ("avx512bf16", Some(sym::avx512_target_feature)), + ("avx512bitalg", Some(sym::avx512_target_feature)), ("avx512bw", Some(sym::avx512_target_feature)), ("avx512cd", Some(sym::avx512_target_feature)), ("avx512dq", Some(sym::avx512_target_feature)), ("avx512er", Some(sym::avx512_target_feature)), ("avx512f", Some(sym::avx512_target_feature)), + ("avx512gfni", Some(sym::avx512_target_feature)), ("avx512ifma", Some(sym::avx512_target_feature)), ("avx512pf", Some(sym::avx512_target_feature)), + ("avx512vaes", Some(sym::avx512_target_feature)), ("avx512vbmi", Some(sym::avx512_target_feature)), + ("avx512vbmi2", Some(sym::avx512_target_feature)), ("avx512vl", Some(sym::avx512_target_feature)), + ("avx512vnni", Some(sym::avx512_target_feature)), + ("avx512vp2intersect", Some(sym::avx512_target_feature)), + ("avx512vpclmulqdq", Some(sym::avx512_target_feature)), ("avx512vpopcntdq", Some(sym::avx512_target_feature)), ("bmi1", None), ("bmi2", None), diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 978f08927c6ef..47c140e0b1882 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -4,7 +4,7 @@ pub use self::StabilityLevel::*; use crate::ty::{self, TyCtxt}; -use rustc_ast::CRATE_NODE_ID; +use rustc_ast::NodeId; use rustc_attr::{self as attr, ConstStability, Deprecation, Stability}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder}; @@ -211,13 +211,14 @@ pub fn early_report_deprecation( suggestion: Option, lint: &'static Lint, span: Span, + node_id: NodeId, ) { if span.in_derive_expansion() { return; } let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span); - lint_buffer.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag); + lint_buffer.buffer_lint_with_diagnostic(lint, node_id, span, message, diag); } fn late_report_deprecation( diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index d8d639ab73451..638dd8ce9706f 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1,70 +1,70 @@ +//! # The MIR Visitor +//! +//! ## Overview +//! +//! There are two visitors, one for immutable and one for mutable references, +//! but both are generated by the following macro. The code is written according +//! to the following conventions: +//! +//! - introduce a `visit_foo` and a `super_foo` method for every MIR type +//! - `visit_foo`, by default, calls `super_foo` +//! - `super_foo`, by default, destructures the `foo` and calls `visit_foo` +//! +//! This allows you as a user to override `visit_foo` for types are +//! interested in, and invoke (within that method) call +//! `self.super_foo` to get the default behavior. Just as in an OO +//! language, you should never call `super` methods ordinarily except +//! in that circumstance. +//! +//! For the most part, we do not destructure things external to the +//! MIR, e.g., types, spans, etc, but simply visit them and stop. This +//! avoids duplication with other visitors like `TypeFoldable`. +//! +//! ## Updating +//! +//! The code is written in a very deliberate style intended to minimize +//! the chance of things being overlooked. You'll notice that we always +//! use pattern matching to reference fields and we ensure that all +//! matches are exhaustive. +//! +//! For example, the `super_basic_block_data` method begins like this: +//! +//! ```rust +//! fn super_basic_block_data(&mut self, +//! block: BasicBlock, +//! data: & $($mutability)? BasicBlockData<'tcx>) { +//! let BasicBlockData { +//! statements, +//! terminator, +//! is_cleanup: _ +//! } = *data; +//! +//! for statement in statements { +//! self.visit_statement(block, statement); +//! } +//! +//! ... +//! } +//! ``` +//! +//! Here we used `let BasicBlockData { } = *data` deliberately, +//! rather than writing `data.statements` in the body. This is because if one +//! adds a new field to `BasicBlockData`, one will be forced to revise this code, +//! and hence one will (hopefully) invoke the correct visit methods (if any). +//! +//! For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS. +//! That means you never write `..` to skip over fields, nor do you write `_` +//! to skip over variants in a `match`. +//! +//! The only place that `_` is acceptable is to match a field (or +//! variant argument) that does not require visiting, as in +//! `is_cleanup` above. + use crate::mir::*; use crate::ty::subst::SubstsRef; use crate::ty::{CanonicalUserTypeAnnotation, Ty}; use rustc_span::Span; -// # The MIR Visitor -// -// ## Overview -// -// There are two visitors, one for immutable and one for mutable references, -// but both are generated by the following macro. The code is written according -// to the following conventions: -// -// - introduce a `visit_foo` and a `super_foo` method for every MIR type -// - `visit_foo`, by default, calls `super_foo` -// - `super_foo`, by default, destructures the `foo` and calls `visit_foo` -// -// This allows you as a user to override `visit_foo` for types are -// interested in, and invoke (within that method) call -// `self.super_foo` to get the default behavior. Just as in an OO -// language, you should never call `super` methods ordinarily except -// in that circumstance. -// -// For the most part, we do not destructure things external to the -// MIR, e.g., types, spans, etc, but simply visit them and stop. This -// avoids duplication with other visitors like `TypeFoldable`. -// -// ## Updating -// -// The code is written in a very deliberate style intended to minimize -// the chance of things being overlooked. You'll notice that we always -// use pattern matching to reference fields and we ensure that all -// matches are exhaustive. -// -// For example, the `super_basic_block_data` method begins like this: -// -// ```rust -// fn super_basic_block_data(&mut self, -// block: BasicBlock, -// data: & $($mutability)? BasicBlockData<'tcx>) { -// let BasicBlockData { -// statements, -// terminator, -// is_cleanup: _ -// } = *data; -// -// for statement in statements { -// self.visit_statement(block, statement); -// } -// -// ... -// } -// ``` -// -// Here we used `let BasicBlockData { } = *data` deliberately, -// rather than writing `data.statements` in the body. This is because if one -// adds a new field to `BasicBlockData`, one will be forced to revise this code, -// and hence one will (hopefully) invoke the correct visit methods (if any). -// -// For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS. -// That means you never write `..` to skip over fields, nor do you write `_` -// to skip over variants in a `match`. -// -// The only place that `_` is acceptable is to match a field (or -// variant argument) that does not require visiting, as in -// `is_cleanup` above. - macro_rules! make_mir_visitor { ($visitor_trait_name:ident, $($mutability:ident)?) => { pub trait $visitor_trait_name<'tcx> { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index acc7d3c4960e8..5626c864fe175 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -176,7 +176,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { match *self { LayoutError::Unknown(ty) => write!(f, "the type `{}` has an unknown layout", ty), LayoutError::SizeOverflow(ty) => { - write!(f, "the type `{}` is too big for the current architecture", ty) + write!(f, "values of the type `{}` are too big for the current architecture", ty) } } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index e052b6b334529..21e43be20456b 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1034,6 +1034,7 @@ impl<'a> Resolver<'a> { depr.suggestion, lint, span, + node_id, ); } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 873d300a5e309..54743ef9ce911 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -97,6 +97,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { self.infcx.tcx } + #[instrument(skip(self))] fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { if !ty.has_projections() { return ty; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 41202546566a7..d67f9c15a1916 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -80,6 +80,7 @@ #![feature(const_mut_refs)] #![feature(const_int_pow)] #![feature(constctlz)] +#![feature(const_cttz)] #![feature(const_panic)] #![feature(const_pin)] #![feature(const_fn)] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 5a9fd902c9ca1..716b4a90e5ec2 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -6,6 +6,7 @@ use crate::str::FromStr; use super::from_str_radix; use super::{IntErrorKind, ParseIntError}; +use crate::intrinsics; macro_rules! doc_comment { ($x:expr, $($tt:tt)*) => { @@ -189,3 +190,76 @@ macro_rules! from_str_radix_nzint_impl { from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } + +macro_rules! nonzero_leading_trailing_zeros { + ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { + $( + impl $Ty { + doc_comment! { + concat!("Returns the number of leading zeros in the binary representation of `self`. + +On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. + +# Examples + +Basic usage: + +``` +#![feature(nonzero_leading_trailing_zeros)] +let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap(); + +assert_eq!(n.leading_zeros(), 0); +```"), + #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[inline] + pub const fn leading_zeros(self) -> u32 { + // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero + unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 } + } + } + + doc_comment! { + concat!("Returns the number of trailing zeros in the binary representation +of `self`. + +On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. + +# Examples + +Basic usage: + +``` +#![feature(nonzero_leading_trailing_zeros)] +let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap(); + +assert_eq!(n.trailing_zeros(), 3); +```"), + #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero + unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 } + } + } + + } + )+ + } +} + +nonzero_leading_trailing_zeros! { + NonZeroU8(u8), u8::MAX; + NonZeroU16(u16), u16::MAX; + NonZeroU32(u32), u32::MAX; + NonZeroU64(u64), u64::MAX; + NonZeroU128(u128), u128::MAX; + NonZeroUsize(usize), usize::MAX; + NonZeroI8(u8), -1i8; + NonZeroI16(u16), -1i16; + NonZeroI32(u32), -1i32; + NonZeroI64(u64), -1i64; + NonZeroI128(u128), -1i128; + NonZeroIsize(usize), -1isize; +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c9f9b890c3938..14ef03fd53eba 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -60,6 +60,8 @@ #![feature(once_cell)] #![feature(unsafe_block_in_unsafe_fn)] #![feature(int_bits_const)] +#![feature(nonzero_leading_trailing_zeros)] +#![feature(const_option)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index fb1293c99bba9..ca449b4350ede 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -1,5 +1,8 @@ use core::convert::TryFrom; -use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8}; +use core::num::{ + IntErrorKind, NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, + NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, +}; use core::option::Option::{self, None, Some}; use std::mem::size_of; @@ -212,3 +215,100 @@ fn nonzero_const() { const ONE: Option = NonZeroU8::new(1); assert!(ONE.is_some()); } + +#[test] +fn nonzero_leading_zeros() { + assert_eq!(NonZeroU8::new(1).unwrap().leading_zeros(), 7); + assert_eq!(NonZeroI8::new(1).unwrap().leading_zeros(), 7); + assert_eq!(NonZeroU16::new(1).unwrap().leading_zeros(), 15); + assert_eq!(NonZeroI16::new(1).unwrap().leading_zeros(), 15); + assert_eq!(NonZeroU32::new(1).unwrap().leading_zeros(), 31); + assert_eq!(NonZeroI32::new(1).unwrap().leading_zeros(), 31); + assert_eq!(NonZeroU64::new(1).unwrap().leading_zeros(), 63); + assert_eq!(NonZeroI64::new(1).unwrap().leading_zeros(), 63); + assert_eq!(NonZeroU128::new(1).unwrap().leading_zeros(), 127); + assert_eq!(NonZeroI128::new(1).unwrap().leading_zeros(), 127); + assert_eq!(NonZeroUsize::new(1).unwrap().leading_zeros(), usize::BITS - 1); + assert_eq!(NonZeroIsize::new(1).unwrap().leading_zeros(), usize::BITS - 1); + + assert_eq!(NonZeroU8::new(u8::MAX >> 2).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroI8::new((u8::MAX >> 2) as i8).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroU16::new(u16::MAX >> 2).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroI16::new((u16::MAX >> 2) as i16).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroU32::new(u32::MAX >> 2).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroI32::new((u32::MAX >> 2) as i32).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroU64::new(u64::MAX >> 2).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroI64::new((u64::MAX >> 2) as i64).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroU128::new(u128::MAX >> 2).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroI128::new((u128::MAX >> 2) as i128).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroUsize::new(usize::MAX >> 2).unwrap().leading_zeros(), 2); + assert_eq!(NonZeroIsize::new((usize::MAX >> 2) as isize).unwrap().leading_zeros(), 2); + + assert_eq!(NonZeroU8::new(u8::MAX).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroI8::new(-1i8).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroU16::new(u16::MAX).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroI16::new(-1i16).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroU32::new(u32::MAX).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroI32::new(-1i32).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroU64::new(u64::MAX).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroI64::new(-1i64).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroU128::new(u128::MAX).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroI128::new(-1i128).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroUsize::new(usize::MAX).unwrap().leading_zeros(), 0); + assert_eq!(NonZeroIsize::new(-1isize).unwrap().leading_zeros(), 0); + + const LEADING_ZEROS: u32 = NonZeroU16::new(1).unwrap().leading_zeros(); + assert_eq!(LEADING_ZEROS, 15); +} + +#[test] +fn nonzero_trailing_zeros() { + assert_eq!(NonZeroU8::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroI8::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroU16::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroI16::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroU32::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroI32::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroU64::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroI64::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroU128::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroI128::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroUsize::new(1).unwrap().trailing_zeros(), 0); + assert_eq!(NonZeroIsize::new(1).unwrap().trailing_zeros(), 0); + + assert_eq!(NonZeroU8::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroI8::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroU16::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroI16::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroU32::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroI32::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroU64::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroI64::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroU128::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroI128::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroUsize::new(1 << 2).unwrap().trailing_zeros(), 2); + assert_eq!(NonZeroIsize::new(1 << 2).unwrap().trailing_zeros(), 2); + + assert_eq!(NonZeroU8::new(1 << 7).unwrap().trailing_zeros(), 7); + assert_eq!(NonZeroI8::new(1 << 7).unwrap().trailing_zeros(), 7); + assert_eq!(NonZeroU16::new(1 << 15).unwrap().trailing_zeros(), 15); + assert_eq!(NonZeroI16::new(1 << 15).unwrap().trailing_zeros(), 15); + assert_eq!(NonZeroU32::new(1 << 31).unwrap().trailing_zeros(), 31); + assert_eq!(NonZeroI32::new(1 << 31).unwrap().trailing_zeros(), 31); + assert_eq!(NonZeroU64::new(1 << 63).unwrap().trailing_zeros(), 63); + assert_eq!(NonZeroI64::new(1 << 63).unwrap().trailing_zeros(), 63); + assert_eq!(NonZeroU128::new(1 << 127).unwrap().trailing_zeros(), 127); + assert_eq!(NonZeroI128::new(1 << 127).unwrap().trailing_zeros(), 127); + + assert_eq!( + NonZeroUsize::new(1 << (usize::BITS - 1)).unwrap().trailing_zeros(), + usize::BITS - 1 + ); + assert_eq!( + NonZeroIsize::new(1 << (usize::BITS - 1)).unwrap().trailing_zeros(), + usize::BITS - 1 + ); + + const TRAILING_ZEROS: u32 = NonZeroU16::new(1 << 2).unwrap().trailing_zeros(); + assert_eq!(TRAILING_ZEROS, 2); +} diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 703c3755b6383..dfbf6c3f24443 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1307,10 +1307,10 @@ pub trait Write { default_write_vectored(|b| self.write(b), bufs) } - /// Determines if this `Write`er has an efficient [`write_vectored`] + /// Determines if this `Write`r has an efficient [`write_vectored`] /// implementation. /// - /// If a `Write`er does not override the default [`write_vectored`] + /// If a `Write`r does not override the default [`write_vectored`] /// implementation, code using it may want to avoid the method all together /// and coalesce writes into a single buffer for higher performance. /// diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index ac2fcfcb53f72..1dc16ef099367 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -445,15 +445,15 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> // We store the availability in a global to avoid unnecessary syscalls static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true); - unsafe fn copy_file_range( - fd_in: libc::c_int, - off_in: *mut libc::loff_t, - fd_out: libc::c_int, - off_out: *mut libc::loff_t, - len: libc::size_t, - flags: libc::c_uint, - ) -> libc::c_long { - libc::syscall(libc::SYS_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags) + syscall! { + fn copy_file_range( + fd_in: libc::c_int, + off_in: *mut libc::loff_t, + fd_out: libc::c_int, + off_out: *mut libc::loff_t, + len: libc::size_t, + flags: libc::c_uint + ) -> libc::ssize_t } let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed); diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs index eed6fbf13b7d2..38ddb41700c4b 100644 --- a/library/std/src/sys/unix/rand.rs +++ b/library/std/src/sys/unix/rand.rs @@ -25,10 +25,19 @@ mod imp { use crate::io::Read; #[cfg(any(target_os = "linux", target_os = "android"))] - fn getrandom(buf: &mut [u8]) -> libc::c_long { - unsafe { - libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr(), buf.len(), libc::GRND_NONBLOCK) + fn getrandom(buf: &mut [u8]) -> libc::ssize_t { + // A weak symbol allows interposition, e.g. for perf measurements that want to + // disable randomness for consistency. Otherwise, we'll try a raw syscall. + // (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28) + syscall! { + fn getrandom( + buffer: *mut libc::c_void, + length: libc::size_t, + flags: libc::c_uint + ) -> libc::ssize_t } + + unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) } } #[cfg(not(any(target_os = "linux", target_os = "android")))] diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index f4b33a00f7c85..53d95dca4cd82 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -24,7 +24,7 @@ use crate::ffi::CStr; use crate::marker; use crate::mem; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{self, AtomicUsize, Ordering}; macro_rules! weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( @@ -47,15 +47,49 @@ impl Weak { pub fn get(&self) -> Option { assert_eq!(mem::size_of::(), mem::size_of::()); unsafe { - if self.addr.load(Ordering::SeqCst) == 1 { - self.addr.store(fetch(self.name), Ordering::SeqCst); - } - match self.addr.load(Ordering::SeqCst) { + // Relaxed is fine here because we fence before reading through the + // pointer (see the comment below). + match self.addr.load(Ordering::Relaxed) { + 1 => self.initialize(), 0 => None, - addr => Some(mem::transmute_copy::(&addr)), + addr => { + let func = mem::transmute_copy::(&addr); + // The caller is presumably going to read through this value + // (by calling the function we've dlsymed). This means we'd + // need to have loaded it with at least C11's consume + // ordering in order to be guaranteed that the data we read + // from the pointer isn't from before the pointer was + // stored. Rust has no equivalent to memory_order_consume, + // so we use an acquire fence (sorry, ARM). + // + // Now, in practice this likely isn't needed even on CPUs + // where relaxed and consume mean different things. The + // symbols we're loading are probably present (or not) at + // init, and even if they aren't the runtime dynamic loader + // is extremely likely have sufficient barriers internally + // (possibly implicitly, for example the ones provided by + // invoking `mprotect`). + // + // That said, none of that's *guaranteed*, and so we fence. + atomic::fence(Ordering::Acquire); + Some(func) + } } } } + + // Cold because it should only happen during first-time initalization. + #[cold] + unsafe fn initialize(&self) -> Option { + let val = fetch(self.name); + // This synchronizes with the acquire fence in `get`. + self.addr.store(val, Ordering::Release); + + match val { + 0 => None, + addr => Some(mem::transmute_copy::(&addr)), + } + } } unsafe fn fetch(name: &str) -> usize { @@ -66,7 +100,7 @@ unsafe fn fetch(name: &str) -> usize { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize } -#[cfg(not(target_os = "linux"))] +#[cfg(not(any(target_os = "linux", target_os = "android")))] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name: $t),*) -> $ret { @@ -84,7 +118,7 @@ macro_rules! syscall { ) } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name:$t),*) -> $ret { @@ -92,10 +126,18 @@ macro_rules! syscall { // (not paths). use libc::*; - syscall( - concat_idents!(SYS_, $name), - $($arg_name as c_long),* - ) as $ret + weak! { fn $name($($t),*) -> $ret } + + // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` + // interposition, but if it's not found just use a raw syscall. + if let Some(fun) = $name.get() { + fun($($arg_name),*) + } else { + syscall( + concat_idents!(SYS_, $name), + $($arg_name as c_long),* + ) as $ret + } } ) } diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 8dd1a8ac0d2df..61a04c467224b 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -54,42 +54,62 @@ fn powerpc64_linux() { #[test] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn x86_all() { + // the below is the set of features we can test at runtime, but don't actually + // use to gate anything and are thus not part of the X86_ALLOWED_FEATURES list + + println!("abm: {:?}", is_x86_feature_detected!("abm")); // this is a synonym for lzcnt but we test it anyways + println!("mmx: {:?}", is_x86_feature_detected!("mmx")); + println!("tsc: {:?}", is_x86_feature_detected!("tsc")); + + // the below is in alphabetical order and matches + // the order of X86_ALLOWED_FEATURES in rustc_codegen_ssa's target_features.rs + + println!("adx: {:?}", is_x86_feature_detected!("adx")); println!("aes: {:?}", is_x86_feature_detected!("aes")); - println!("pcmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq")); + println!("avx: {:?}", is_x86_feature_detected!("avx")); + println!("avx2: {:?}", is_x86_feature_detected!("avx2")); + println!("avx512bf16: {:?}", is_x86_feature_detected!("avx512bf16")); + println!("avx512bitalg: {:?}", is_x86_feature_detected!("avx512bitalg")); + println!("avx512bw: {:?}", is_x86_feature_detected!("avx512bw")); + println!("avx512cd: {:?}", is_x86_feature_detected!("avx512cd")); + println!("avx512dq: {:?}", is_x86_feature_detected!("avx512dq")); + println!("avx512er: {:?}", is_x86_feature_detected!("avx512er")); + println!("avx512f: {:?}", is_x86_feature_detected!("avx512f")); + println!("avx512gfni: {:?}", is_x86_feature_detected!("avx512gfni")); + println!("avx512ifma: {:?}", is_x86_feature_detected!("avx512ifma")); + println!("avx512pf: {:?}", is_x86_feature_detected!("avx512pf")); + println!("avx512vaes: {:?}", is_x86_feature_detected!("avx512vaes")); + println!("avx512vbmi: {:?}", is_x86_feature_detected!("avx512vbmi")); + println!("avx512vbmi2: {:?}", is_x86_feature_detected!("avx512vbmi2")); + println!("avx512vl: {:?}", is_x86_feature_detected!("avx512vl")); + println!("avx512vnni: {:?}", is_x86_feature_detected!("avx512vnni")); + println!("avx512vp2intersect: {:?}", is_x86_feature_detected!("avx512vp2intersect")); + println!("avx512vpclmulqdq: {:?}", is_x86_feature_detected!("avx512vpclmulqdq")); + println!("avx512vpopcntdq: {:?}", is_x86_feature_detected!("avx512vpopcntdq")); + println!("bmi1: {:?}", is_x86_feature_detected!("bmi1")); + println!("bmi2: {:?}", is_x86_feature_detected!("bmi2")); + println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b")); + println!("f16c: {:?}", is_x86_feature_detected!("f16c")); + println!("fma: {:?}", is_x86_feature_detected!("fma")); + println!("fxsr: {:?}", is_x86_feature_detected!("fxsr")); + println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt")); + //println!("movbe: {:?}", is_x86_feature_detected!("movbe")); // movbe is unsupported as a target feature + println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq")); + println!("popcnt: {:?}", is_x86_feature_detected!("popcnt")); println!("rdrand: {:?}", is_x86_feature_detected!("rdrand")); println!("rdseed: {:?}", is_x86_feature_detected!("rdseed")); - println!("tsc: {:?}", is_x86_feature_detected!("tsc")); - println!("mmx: {:?}", is_x86_feature_detected!("mmx")); + println!("rtm: {:?}", is_x86_feature_detected!("rtm")); + println!("sha: {:?}", is_x86_feature_detected!("sha")); println!("sse: {:?}", is_x86_feature_detected!("sse")); println!("sse2: {:?}", is_x86_feature_detected!("sse2")); println!("sse3: {:?}", is_x86_feature_detected!("sse3")); - println!("ssse3: {:?}", is_x86_feature_detected!("ssse3")); println!("sse4.1: {:?}", is_x86_feature_detected!("sse4.1")); println!("sse4.2: {:?}", is_x86_feature_detected!("sse4.2")); println!("sse4a: {:?}", is_x86_feature_detected!("sse4a")); - println!("sha: {:?}", is_x86_feature_detected!("sha")); - println!("avx: {:?}", is_x86_feature_detected!("avx")); - println!("avx2: {:?}", is_x86_feature_detected!("avx2")); - println!("avx512f {:?}", is_x86_feature_detected!("avx512f")); - println!("avx512cd {:?}", is_x86_feature_detected!("avx512cd")); - println!("avx512er {:?}", is_x86_feature_detected!("avx512er")); - println!("avx512pf {:?}", is_x86_feature_detected!("avx512pf")); - println!("avx512bw {:?}", is_x86_feature_detected!("avx512bw")); - println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq")); - println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl")); - println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma")); - println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi")); - println!("avx512_vpopcntdq {:?}", is_x86_feature_detected!("avx512vpopcntdq")); - println!("fma: {:?}", is_x86_feature_detected!("fma")); - println!("bmi1: {:?}", is_x86_feature_detected!("bmi1")); - println!("bmi2: {:?}", is_x86_feature_detected!("bmi2")); - println!("abm: {:?}", is_x86_feature_detected!("abm")); - println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt")); + println!("ssse3: {:?}", is_x86_feature_detected!("ssse3")); println!("tbm: {:?}", is_x86_feature_detected!("tbm")); - println!("popcnt: {:?}", is_x86_feature_detected!("popcnt")); - println!("fxsr: {:?}", is_x86_feature_detected!("fxsr")); println!("xsave: {:?}", is_x86_feature_detected!("xsave")); + println!("xsavec: {:?}", is_x86_feature_detected!("xsavec")); println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt")); println!("xsaves: {:?}", is_x86_feature_detected!("xsaves")); - println!("xsavec: {:?}", is_x86_feature_detected!("xsavec")); } diff --git a/library/stdarch b/library/stdarch index 3c3664355ef46..777efaf564470 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit 3c3664355ef46e788b53080e521d6542fbddfd84 +Subproject commit 777efaf5644706b36706a7a5c51edb63835e05ca diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 54d0a23dec58d..4fb58034ce216 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -360,7 +360,6 @@ def output(filepath): class RustBuild(object): """Provide all the methods required to build Rust""" def __init__(self): - self.cargo_channel = '' self.date = '' self._download_url = '' self.rustc_channel = '' @@ -387,7 +386,6 @@ def download_stage0(self): will move all the content to the right place. """ rustc_channel = self.rustc_channel - cargo_channel = self.cargo_channel rustfmt_channel = self.rustfmt_channel if self.rustc().startswith(self.bin_root()) and \ @@ -400,12 +398,15 @@ def download_stage0(self): rustc_channel, self.build, tarball_suffix) pattern = "rust-std-{}".format(self.build) self._download_stage0_helper(filename, pattern, tarball_suffix) - filename = "rustc-{}-{}{}".format(rustc_channel, self.build, tarball_suffix) self._download_stage0_helper(filename, "rustc", tarball_suffix) + filename = "cargo-{}-{}{}".format(rustc_channel, self.build, + tarball_suffix) + self._download_stage0_helper(filename, "cargo", tarball_suffix) self.fix_bin_or_dylib("{}/bin/rustc".format(self.bin_root())) self.fix_bin_or_dylib("{}/bin/rustdoc".format(self.bin_root())) + self.fix_bin_or_dylib("{}/bin/cargo".format(self.bin_root())) lib_dir = "{}/lib".format(self.bin_root()) for lib in os.listdir(lib_dir): if lib.endswith(".so"): @@ -413,17 +414,6 @@ def download_stage0(self): with output(self.rustc_stamp()) as rust_stamp: rust_stamp.write(self.date) - if self.cargo().startswith(self.bin_root()) and \ - (not os.path.exists(self.cargo()) or - self.program_out_of_date(self.cargo_stamp())): - tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz' - filename = "cargo-{}-{}{}".format(cargo_channel, self.build, - tarball_suffix) - self._download_stage0_helper(filename, "cargo", tarball_suffix) - self.fix_bin_or_dylib("{}/bin/cargo".format(self.bin_root())) - with output(self.cargo_stamp()) as cargo_stamp: - cargo_stamp.write(self.date) - if self.rustfmt() and self.rustfmt().startswith(self.bin_root()) and ( not os.path.exists(self.rustfmt()) or self.program_out_of_date(self.rustfmt_stamp(), self.rustfmt_channel) @@ -601,16 +591,6 @@ def rustc_stamp(self): """ return os.path.join(self.bin_root(), '.rustc-stamp') - def cargo_stamp(self): - """Return the path for .cargo-stamp - - >>> rb = RustBuild() - >>> rb.build_dir = "build" - >>> rb.cargo_stamp() == os.path.join("build", "stage0", ".cargo-stamp") - True - """ - return os.path.join(self.bin_root(), '.cargo-stamp') - def rustfmt_stamp(self): """Return the path for .rustfmt-stamp @@ -1056,7 +1036,6 @@ def bootstrap(help_triggered): data = stage0_data(build.rust_root) build.date = data['date'] build.rustc_channel = data['rustc'] - build.cargo_channel = data['cargo'] if "rustfmt" in data: build.rustfmt_channel = data['rustfmt'] diff --git a/src/stage0.txt b/src/stage0.txt index 9eaa58dd43869..dae9d219b7b9b 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -1,6 +1,5 @@ # This file describes the stage0 compiler that's used to then bootstrap the Rust -# compiler itself. For the rustbuild build system, this also describes the -# relevant Cargo revision that we're using. +# compiler itself. # # Currently Rust always bootstraps from the previous stable release, and in our # train model this means that the master branch bootstraps from beta, beta @@ -8,13 +7,13 @@ # release. # # If you're looking at this file on the master branch, you'll likely see that -# rustc and cargo are configured to `beta`, whereas if you're looking at a -# source tarball for a stable release you'll likely see `1.x.0` for rustc and -# `0.(x+1).0` for Cargo where they were released on `date`. +# rustc is configured to `beta`, whereas if you're looking at a source tarball +# for a stable release you'll likely see `1.x.0` for rustc, with the previous +# stable release's version number. `date` is the date where the release we're +# bootstrapping off was released. date: 2020-10-16 rustc: beta -cargo: beta # We use a nightly rustfmt to format the source because it solves some # bootstrapping issues with use of new syntax in this repo. If you're looking at diff --git a/src/test/compile-fail/consts/issue-55878.rs b/src/test/compile-fail/consts/issue-55878.rs index aa1dd58d2463d..541befa7b1310 100644 --- a/src/test/compile-fail/consts/issue-55878.rs +++ b/src/test/compile-fail/consts/issue-55878.rs @@ -1,7 +1,7 @@ // normalize-stderr-64bit "18446744073709551615" -> "SIZE" // normalize-stderr-32bit "4294967295" -> "SIZE" -// error-pattern: is too big for the current architecture +// error-pattern: are too big for the current architecture fn main() { println!("Size: {}", std::mem::size_of::<[u8; std::u64::MAX as usize]>()); } diff --git a/src/test/ui/huge-array-simple-32.stderr b/src/test/ui/huge-array-simple-32.stderr index d734a9689e05c..31e120df626de 100644 --- a/src/test/ui/huge-array-simple-32.stderr +++ b/src/test/ui/huge-array-simple-32.stderr @@ -1,4 +1,4 @@ -error: the type `[u8; 2147516416]` is too big for the current architecture +error: values of the type `[u8; 2147516416]` are too big for the current architecture --> $DIR/huge-array-simple-32.rs:10:9 | LL | let _fat: [u8; (1<<31)+(1<<15)] = diff --git a/src/test/ui/huge-array-simple-64.stderr b/src/test/ui/huge-array-simple-64.stderr index 791baa8468747..c5d3fe85d0d83 100644 --- a/src/test/ui/huge-array-simple-64.stderr +++ b/src/test/ui/huge-array-simple-64.stderr @@ -1,4 +1,4 @@ -error: the type `[u8; 2305843011361177600]` is too big for the current architecture +error: values of the type `[u8; 2305843011361177600]` are too big for the current architecture --> $DIR/huge-array-simple-64.rs:10:9 | LL | let _fat: [u8; (1<<61)+(1<<31)] = diff --git a/src/test/ui/huge-array.rs b/src/test/ui/huge-array.rs index 846380586a009..3070801f86576 100644 --- a/src/test/ui/huge-array.rs +++ b/src/test/ui/huge-array.rs @@ -6,7 +6,7 @@ fn generic(t: T) { let s: [T; 1518600000] = [t; 1518600000]; - //~^ ERROR the type `[[u8; 1518599999]; 1518600000]` is too big for the current architecture + //~^ ERROR values of the type `[[u8; 1518599999]; 1518600000]` are too big } fn main() { diff --git a/src/test/ui/huge-array.stderr b/src/test/ui/huge-array.stderr index 23d9e87ae0054..817458b73e47b 100644 --- a/src/test/ui/huge-array.stderr +++ b/src/test/ui/huge-array.stderr @@ -1,4 +1,4 @@ -error: the type `[[u8; 1518599999]; 1518600000]` is too big for the current architecture +error: values of the type `[[u8; 1518599999]; 1518600000]` are too big for the current architecture --> $DIR/huge-array.rs:8:9 | LL | let s: [T; 1518600000] = [t; 1518600000]; diff --git a/src/test/ui/huge-enum.rs b/src/test/ui/huge-enum.rs index 8a713c3a26eda..39ea6e11b1ff7 100644 --- a/src/test/ui/huge-enum.rs +++ b/src/test/ui/huge-enum.rs @@ -14,5 +14,5 @@ type BIG = Option<[u32; (1<<45)-1]>; fn main() { let big: BIG = None; - //~^ ERROR is too big for the current architecture + //~^ ERROR are too big for the current architecture } diff --git a/src/test/ui/huge-enum.stderr b/src/test/ui/huge-enum.stderr index a069c37b80a21..a1456e1a8ab0a 100644 --- a/src/test/ui/huge-enum.stderr +++ b/src/test/ui/huge-enum.stderr @@ -1,4 +1,4 @@ -error: the type `Option` is too big for the current architecture +error: values of the type `Option` are too big for the current architecture --> $DIR/huge-enum.rs:16:9 | LL | let big: BIG = None; diff --git a/src/test/ui/huge-struct.rs b/src/test/ui/huge-struct.rs index 71169a1104798..02f38d860b496 100644 --- a/src/test/ui/huge-struct.rs +++ b/src/test/ui/huge-struct.rs @@ -48,6 +48,6 @@ struct S1M { val: S1k> } fn main() { let fat: Option>>> = None; - //~^ ERROR is too big for the current architecture + //~^ ERROR are too big for the current architecture } diff --git a/src/test/ui/huge-struct.stderr b/src/test/ui/huge-struct.stderr index 72e32a8593b18..f0ee88e595539 100644 --- a/src/test/ui/huge-struct.stderr +++ b/src/test/ui/huge-struct.stderr @@ -1,4 +1,4 @@ -error: the type `SXX>>` is too big for the current architecture +error: values of the type `SXX>>` are too big for the current architecture --> $DIR/huge-struct.rs:50:9 | LL | let fat: Option>>> = None; diff --git a/src/test/ui/issues/issue-15919-32.stderr b/src/test/ui/issues/issue-15919-32.stderr index 8411313fc81b3..133637f9a058b 100644 --- a/src/test/ui/issues/issue-15919-32.stderr +++ b/src/test/ui/issues/issue-15919-32.stderr @@ -1,4 +1,4 @@ -error: the type `[usize; 4294967295]` is too big for the current architecture +error: values of the type `[usize; 4294967295]` are too big for the current architecture --> $DIR/issue-15919-32.rs:9:9 | LL | let x = [0usize; 0xffff_ffff]; diff --git a/src/test/ui/issues/issue-15919-64.stderr b/src/test/ui/issues/issue-15919-64.stderr index f624c96ce84da..193b823035c09 100644 --- a/src/test/ui/issues/issue-15919-64.stderr +++ b/src/test/ui/issues/issue-15919-64.stderr @@ -1,4 +1,4 @@ -error: the type `[usize; 18446744073709551615]` is too big for the current architecture +error: values of the type `[usize; 18446744073709551615]` are too big for the current architecture --> $DIR/issue-15919-64.rs:9:9 | LL | let x = [0usize; 0xffff_ffff_ffff_ffff]; diff --git a/src/test/ui/issues/issue-17913.stderr b/src/test/ui/issues/issue-17913.stderr index ae388c4d491df..9a6431d447004 100644 --- a/src/test/ui/issues/issue-17913.stderr +++ b/src/test/ui/issues/issue-17913.stderr @@ -1,4 +1,4 @@ -error: the type `[&usize; N]` is too big for the current architecture +error: values of the type `[&usize; N]` are too big for the current architecture error: aborting due to previous error diff --git a/src/test/ui/issues/issue-56762.rs b/src/test/ui/issues/issue-56762.rs index 5ba5b9847d085..fb0a270f18bef 100644 --- a/src/test/ui/issues/issue-56762.rs +++ b/src/test/ui/issues/issue-56762.rs @@ -17,8 +17,8 @@ impl TooBigArray { } static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); -//~^ ERROR the type `[u8; 2305843009213693951]` is too big for the current architecture +//~^ ERROR values of the type `[u8; 2305843009213693951]` are too big static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; -//~^ ERROR the type `[u8; 2305843009213693951]` is too big for the current architecture +//~^ ERROR values of the type `[u8; 2305843009213693951]` are too big fn main() { } diff --git a/src/test/ui/issues/issue-56762.stderr b/src/test/ui/issues/issue-56762.stderr index 69626d4bc7a9e..f26ef280b20b7 100644 --- a/src/test/ui/issues/issue-56762.stderr +++ b/src/test/ui/issues/issue-56762.stderr @@ -1,10 +1,10 @@ -error[E0080]: the type `[u8; 2305843009213693951]` is too big for the current architecture +error[E0080]: values of the type `[u8; 2305843009213693951]` are too big for the current architecture --> $DIR/issue-56762.rs:19:1 | LL | static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0080]: the type `[u8; 2305843009213693951]` is too big for the current architecture +error[E0080]: values of the type `[u8; 2305843009213693951]` are too big for the current architecture --> $DIR/issue-56762.rs:21:1 | LL | static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; diff --git a/src/test/ui/layout/big-type-no-err.rs b/src/test/ui/layout/big-type-no-err.rs new file mode 100644 index 0000000000000..af8191a9cb919 --- /dev/null +++ b/src/test/ui/layout/big-type-no-err.rs @@ -0,0 +1,13 @@ +// Enormous types are allowed if they are never actually instantiated. +// run-pass +trait Foo { + type Assoc; +} + +impl Foo for [u16; usize::MAX] { + type Assoc = u32; +} + +fn main() { + let _a: Option<<[u16; usize::MAX] as Foo>::Assoc> = None; +} diff --git a/src/test/ui/lint/expansion-time.rs b/src/test/ui/lint/expansion-time.rs index c98ecc980dd3d..a9c7ac363b0b3 100644 --- a/src/test/ui/lint/expansion-time.rs +++ b/src/test/ui/lint/expansion-time.rs @@ -12,6 +12,16 @@ mod benches { fn foo() {} } +#[deprecated = "reason"] +macro_rules! deprecated { + () => {} +} + +#[allow(deprecated)] +mod deprecated { + deprecated!(); // No warning +} + #[warn(incomplete_include)] fn main() { // WARN see in the stderr file, the warning points to the included file. diff --git a/src/test/ui/lint/expansion-time.stderr b/src/test/ui/lint/expansion-time.stderr index bc48d64e7e6b7..24e2733064e48 100644 --- a/src/test/ui/lint/expansion-time.stderr +++ b/src/test/ui/lint/expansion-time.stderr @@ -33,7 +33,7 @@ LL | 2 | ^ | note: the lint level is defined here - --> $DIR/expansion-time.rs:15:8 + --> $DIR/expansion-time.rs:25:8 | LL | #[warn(incomplete_include)] | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs index 0895f4c18e387..2560ffe168be5 100644 --- a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs @@ -3,7 +3,7 @@ // compile-flags: -Zmir-opt-level=0 fn main() { - Bug::V([0; !0]); //~ ERROR is too big for the current + Bug::V([0; !0]); //~ ERROR are too big for the current } enum Bug { diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr index 51eac95afb9ce..c229458da47da 100644 --- a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr @@ -1,4 +1,4 @@ -error: the type `[u8; 18446744073709551615]` is too big for the current architecture +error: values of the type `[u8; 18446744073709551615]` are too big for the current architecture --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:12 | LL | Bug::V([0; !0]); diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs index 982d5ecf8d02f..a2ccb0369c4a4 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs @@ -1,6 +1,5 @@ use crate::consts::{constant, Constant}; -use crate::utils::paths; -use crate::utils::{is_direct_expn_of, is_expn_of, match_function_call, snippet_opt, span_lint_and_help}; +use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, snippet_opt, span_lint_and_help}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind, PatKind, UnOp}; @@ -133,7 +132,7 @@ fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) if let ExprKind::Block(ref inner_block, _) = block_expr.kind; if let Some(begin_panic_call) = &inner_block.expr; // function call - if let Some(args) = match_function_call(cx, begin_panic_call, &paths::BEGIN_PANIC); + if let Some(args) = match_panic_call(cx, begin_panic_call); if args.len() == 1; // bind the second argument of the `assert!` macro if it exists if let panic_message = snippet_opt(cx, args[0].span); diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 55904a0ec0a84..57702dafa6a0c 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -1,7 +1,7 @@ //! checks for attributes use crate::utils::{ - first_line_of_span, is_present_in_source, match_def_path, paths, snippet_opt, span_lint, span_lint_and_help, + first_line_of_span, is_present_in_source, match_panic_def_id, snippet_opt, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, without_block_comments, }; use if_chain::if_chain; @@ -513,7 +513,7 @@ fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_> typeck_results .qpath_res(qpath, path_expr.hir_id) .opt_def_id() - .map_or(true, |fun_id| !match_def_path(cx, fun_id, &paths::BEGIN_PANIC)) + .map_or(true, |fun_id| !match_panic_def_id(cx, fun_id)) } else { true } diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index fe817fe94f2e4..509a4a4e15f62 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -1,5 +1,7 @@ -use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT}; -use crate::utils::{is_expn_of, is_type_diagnostic_item, match_def_path, method_chain_args, span_lint_and_then}; +use crate::utils::paths::FROM_TRAIT; +use crate::utils::{ + is_expn_of, is_type_diagnostic_item, match_def_path, match_panic_def_id, method_chain_args, span_lint_and_then, +}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -84,8 +86,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h if let ExprKind::Call(ref func_expr, _) = expr.kind; if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.kind; if let Some(path_def_id) = path.res.opt_def_id(); - if match_def_path(self.lcx, path_def_id, &BEGIN_PANIC) || - match_def_path(self.lcx, path_def_id, &BEGIN_PANIC_FMT); + if match_panic_def_id(self.lcx, path_def_id); if is_expn_of(expr.span, "unreachable").is_none(); then { self.result.push(expr.span); diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index 22c4fef32a32b..ed7f3b9293dbf 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -1,8 +1,4 @@ -use crate::utils::{ - fn_has_unsatisfiable_preds, match_def_path, - paths::{BEGIN_PANIC, BEGIN_PANIC_FMT}, - snippet_opt, span_lint_and_then, -}; +use crate::utils::{fn_has_unsatisfiable_preds, match_panic_def_id, snippet_opt, span_lint_and_then}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; @@ -109,8 +105,7 @@ fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) { if_chain! { if let ExprKind::Path(qpath) = &expr.kind; if let Some(path_def_id) = cx.qpath_res(qpath, expr.hir_id).opt_def_id(); - if match_def_path(cx, path_def_id, &BEGIN_PANIC) || - match_def_path(cx, path_def_id, &BEGIN_PANIC_FMT); + if match_panic_def_id(cx, path_def_id); then { } else { lint(cx, expr.span, expr.span, LINT_RETURN) diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs index 6379dffd22e37..3d888fe732573 100644 --- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs +++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_direct_expn_of, is_expn_of, match_function_call, paths, span_lint}; +use crate::utils::{is_direct_expn_of, is_expn_of, match_panic_call, span_lint}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; @@ -93,27 +93,27 @@ declare_lint_pass!(PanicUnimplemented => [PANIC_PARAMS, UNIMPLEMENTED, UNREACHAB impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Block(ref block, _) = expr.kind; - if let Some(ref ex) = block.expr; - if let Some(params) = match_function_call(cx, ex, &paths::BEGIN_PANIC) - .or_else(|| match_function_call(cx, ex, &paths::BEGIN_PANIC_FMT)); - then { - let span = get_outer_span(expr); - if is_expn_of(expr.span, "unimplemented").is_some() { - span_lint(cx, UNIMPLEMENTED, span, - "`unimplemented` should not be present in production code"); - } else if is_expn_of(expr.span, "todo").is_some() { - span_lint(cx, TODO, span, - "`todo` should not be present in production code"); - } else if is_expn_of(expr.span, "unreachable").is_some() { - span_lint(cx, UNREACHABLE, span, - "`unreachable` should not be present in production code"); - } else if is_expn_of(expr.span, "panic").is_some() { - span_lint(cx, PANIC, span, - "`panic` should not be present in production code"); - match_panic(params, expr, cx); - } + if let Some(params) = match_panic_call(cx, expr) { + let span = get_outer_span(expr); + if is_expn_of(expr.span, "unimplemented").is_some() { + span_lint( + cx, + UNIMPLEMENTED, + span, + "`unimplemented` should not be present in production code", + ); + } else if is_expn_of(expr.span, "todo").is_some() { + span_lint(cx, TODO, span, "`todo` should not be present in production code"); + } else if is_expn_of(expr.span, "unreachable").is_some() { + span_lint( + cx, + UNREACHABLE, + span, + "`unreachable` should not be present in production code", + ); + } else if is_expn_of(expr.span, "panic").is_some() { + span_lint(cx, PANIC, span, "`panic` should not be present in production code"); + match_panic(params, expr, cx); } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index b027bfebacb6a..270fdc9bf462f 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -1196,7 +1196,7 @@ pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option< /// Usage: /// /// ```rust,ignore -/// if let Some(args) = match_function_call(cx, begin_panic_call, &paths::BEGIN_PANIC); +/// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX); /// ``` pub fn match_function_call<'tcx>( cx: &LateContext<'tcx>, @@ -1231,6 +1231,24 @@ pub fn match_def_path<'tcx>(cx: &LateContext<'tcx>, did: DefId, syms: &[&str]) - cx.match_def_path(did, &syms) } +pub fn match_panic_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx [Expr<'tcx>]> { + match_function_call(cx, expr, &paths::BEGIN_PANIC) + .or_else(|| match_function_call(cx, expr, &paths::BEGIN_PANIC_FMT)) + .or_else(|| match_function_call(cx, expr, &paths::PANIC_ANY)) + .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC)) + .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC_FMT)) + .or_else(|| match_function_call(cx, expr, &paths::PANICKING_PANIC_STR)) +} + +pub fn match_panic_def_id(cx: &LateContext<'_>, did: DefId) -> bool { + match_def_path(cx, did, &paths::BEGIN_PANIC) + || match_def_path(cx, did, &paths::BEGIN_PANIC_FMT) + || match_def_path(cx, did, &paths::PANIC_ANY) + || match_def_path(cx, did, &paths::PANICKING_PANIC) + || match_def_path(cx, did, &paths::PANICKING_PANIC_FMT) + || match_def_path(cx, did, &paths::PANICKING_PANIC_STR) +} + /// Returns the list of condition expressions and the list of blocks in a /// sequence of `if/else`. /// E.g., this returns `([a, b], [c, d, e])` for the expression diff --git a/src/tools/clippy/clippy_lints/src/utils/paths.rs b/src/tools/clippy/clippy_lints/src/utils/paths.rs index 1ad8c6029860b..8f5fbfd9f846a 100644 --- a/src/tools/clippy/clippy_lints/src/utils/paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/paths.rs @@ -8,8 +8,8 @@ pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"]; pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"]; pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"]; -pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"]; -pub const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"]; +pub(super) const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"]; +pub(super) const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"]; pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"]; pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; pub const BOX: [&str; 3] = ["alloc", "boxed", "Box"]; @@ -78,6 +78,10 @@ pub const ORD: [&str; 3] = ["core", "cmp", "Ord"]; pub const OS_STRING: [&str; 4] = ["std", "ffi", "os_str", "OsString"]; pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"]; pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"]; +pub(super) const PANICKING_PANIC: [&str; 3] = ["core", "panicking", "panic"]; +pub(super) const PANICKING_PANIC_FMT: [&str; 3] = ["core", "panicking", "panic_fmt"]; +pub(super) const PANICKING_PANIC_STR: [&str; 3] = ["core", "panicking", "panic_str"]; +pub(super) const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"]; pub const PARKING_LOT_MUTEX_GUARD: [&str; 2] = ["parking_lot", "MutexGuard"]; pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 2] = ["parking_lot", "RwLockReadGuard"]; pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 2] = ["parking_lot", "RwLockWriteGuard"]; diff --git a/src/tools/clippy/tests/ui/panicking_macros.rs b/src/tools/clippy/tests/ui/panicking_macros.rs index f91ccfaed743d..77fcb8dfd02fd 100644 --- a/src/tools/clippy/tests/ui/panicking_macros.rs +++ b/src/tools/clippy/tests/ui/panicking_macros.rs @@ -1,6 +1,8 @@ #![warn(clippy::unimplemented, clippy::unreachable, clippy::todo, clippy::panic)] #![allow(clippy::assertions_on_constants)] +extern crate core; + fn panic() { let a = 2; panic!(); @@ -33,9 +35,18 @@ fn unreachable() { let b = a + 2; } +fn core_versions() { + use core::{panic, todo, unimplemented, unreachable}; + panic!(); + todo!(); + unimplemented!(); + unreachable!(); +} + fn main() { panic(); todo(); unimplemented(); unreachable(); + core_versions(); } diff --git a/src/tools/clippy/tests/ui/panicking_macros.stderr b/src/tools/clippy/tests/ui/panicking_macros.stderr index 37c11d72a574a..83234c0ed92cc 100644 --- a/src/tools/clippy/tests/ui/panicking_macros.stderr +++ b/src/tools/clippy/tests/ui/panicking_macros.stderr @@ -1,5 +1,5 @@ error: `panic` should not be present in production code - --> $DIR/panicking_macros.rs:6:5 + --> $DIR/panicking_macros.rs:8:5 | LL | panic!(); | ^^^^^^^^^ @@ -7,7 +7,7 @@ LL | panic!(); = note: `-D clippy::panic` implied by `-D warnings` error: `panic` should not be present in production code - --> $DIR/panicking_macros.rs:7:5 + --> $DIR/panicking_macros.rs:9:5 | LL | panic!("message"); | ^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | panic!("message"); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `panic` should not be present in production code - --> $DIR/panicking_macros.rs:8:5 + --> $DIR/panicking_macros.rs:10:5 | LL | panic!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | panic!("{} {}", "panic with", "multiple arguments"); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `todo` should not be present in production code - --> $DIR/panicking_macros.rs:14:5 + --> $DIR/panicking_macros.rs:16:5 | LL | todo!(); | ^^^^^^^^ @@ -31,19 +31,19 @@ LL | todo!(); = note: `-D clippy::todo` implied by `-D warnings` error: `todo` should not be present in production code - --> $DIR/panicking_macros.rs:15:5 + --> $DIR/panicking_macros.rs:17:5 | LL | todo!("message"); | ^^^^^^^^^^^^^^^^^ error: `todo` should not be present in production code - --> $DIR/panicking_macros.rs:16:5 + --> $DIR/panicking_macros.rs:18:5 | LL | todo!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panicking_macros.rs:22:5 + --> $DIR/panicking_macros.rs:24:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^^ @@ -51,19 +51,19 @@ LL | unimplemented!(); = note: `-D clippy::unimplemented` implied by `-D warnings` error: `unimplemented` should not be present in production code - --> $DIR/panicking_macros.rs:23:5 + --> $DIR/panicking_macros.rs:25:5 | LL | unimplemented!("message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> $DIR/panicking_macros.rs:24:5 + --> $DIR/panicking_macros.rs:26:5 | LL | unimplemented!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unreachable` should not be present in production code - --> $DIR/panicking_macros.rs:30:5 + --> $DIR/panicking_macros.rs:32:5 | LL | unreachable!(); | ^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | unreachable!(); = note: `-D clippy::unreachable` implied by `-D warnings` error: `unreachable` should not be present in production code - --> $DIR/panicking_macros.rs:31:5 + --> $DIR/panicking_macros.rs:33:5 | LL | unreachable!("message"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,10 +79,34 @@ LL | unreachable!("message"); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: `unreachable` should not be present in production code - --> $DIR/panicking_macros.rs:32:5 + --> $DIR/panicking_macros.rs:34:5 | LL | unreachable!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: `panic` should not be present in production code + --> $DIR/panicking_macros.rs:40:5 + | +LL | panic!(); + | ^^^^^^^^^ + +error: `todo` should not be present in production code + --> $DIR/panicking_macros.rs:41:5 + | +LL | todo!(); + | ^^^^^^^^ + +error: `unimplemented` should not be present in production code + --> $DIR/panicking_macros.rs:42:5 + | +LL | unimplemented!(); + | ^^^^^^^^^^^^^^^^^ + +error: `unreachable` should not be present in production code + --> $DIR/panicking_macros.rs:43:5 + | +LL | unreachable!(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors