diff --git a/Cargo.lock b/Cargo.lock index d0016796d16b2..28d7784152101 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5056,6 +5056,7 @@ dependencies = [ "expect-test", "indexmap", "itertools", + "libc", "minifier", "proc-macro2", "pulldown-cmark-escape", diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs index 126f5bfa4ebf6..a408aa034e785 100644 --- a/compiler/rustc_abi/src/callconv/reg.rs +++ b/compiler/rustc_abi/src/callconv/reg.rs @@ -47,6 +47,7 @@ impl Reg { reg_ctor!(i64, Integer, 64); reg_ctor!(i128, Integer, 128); + reg_ctor!(f16, Float, 16); reg_ctor!(f32, Float, 32); reg_ctor!(f64, Float, 64); reg_ctor!(f128, Float, 128); diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 3b3a58697b205..5033f887a60f9 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -156,26 +156,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty::ty_and_layout_pointee_info_at(self, cx, offset) } - pub fn is_single_fp_element(self, cx: &C) -> bool - where - Ty: TyAbiInterface<'a, C>, - C: HasDataLayout, - { - match self.backend_repr { - BackendRepr::Scalar(scalar) => { - matches!(scalar.primitive(), Primitive::Float(Float::F32 | Float::F64)) - } - BackendRepr::Memory { .. } => { - if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 { - self.field(cx, 0).is_single_fp_element(cx) - } else { - false - } - } - _ => false, - } - } - pub fn is_single_vector_element(self, cx: &C, expected_size: Size) -> bool where Ty: TyAbiInterface<'a, C>, @@ -309,6 +289,29 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { found } + /// Finds the one field that is not a ZST. + /// Returns `None` if there are multiple non-ZST fields or only ZST-fields. + /// + /// Note that this function checks for ZSTs, not just 1-ZSTs. + pub fn non_zst_field_ignore_alignment(&self, cx: &C) -> Option<(FieldIdx, Self)> + where + Ty: TyAbiInterface<'a, C> + Copy, + { + let mut found = None; + for field_idx in 0..self.fields.count() { + let field = self.field(cx, field_idx); + if field.is_zst() { + continue; + } + if found.is_some() { + // More than one non-ZST field. + return None; + } + found = Some((FieldIdx::from_usize(field_idx), field)); + } + found + } + /// If this type should match the ABI of the C `_Complex` type, returns the primitive that is /// used for its components. /// diff --git a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs index 8a9102a78e25b..fc75f0285bda1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs @@ -4,7 +4,7 @@ use super::prelude::*; pub(crate) struct CfiEncodingParser; impl SingleAttributeParser for CfiEncodingParser { const PATH: &[Symbol] = &[sym::cfi_encoding]; - const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[ + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Struct), Allow(Target::ForeignTy), Allow(Target::Enum), diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 4229a0723ce49..5ebf950358c4f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -74,20 +74,6 @@ pub(super) struct DescribePlaceOpt { pub(super) struct IncludingTupleField(pub(super) bool); -pub(crate) enum BufferedDiag<'diag> { - Error(Diag<'diag>), - NonError(Diag<'diag, ()>), -} - -impl<'diag> BufferedDiag<'diag> { - fn sort_span(&self) -> Span { - match self { - BufferedDiag::Error(diag) => diag.sort_span, - BufferedDiag::NonError(diag) => diag.sort_span, - } - } -} - #[derive(Default)] pub(crate) struct BorrowckDiagnosticsBuffer<'diag, 'tcx> { /// This field keeps track of move errors that are to be reported for given move indices. @@ -108,16 +94,13 @@ pub(crate) struct BorrowckDiagnosticsBuffer<'diag, 'tcx> { buffered_mut_errors: FxIndexMap, usize)>, - /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics. - buffered_diags: Vec>, + /// Buffer of diagnostics to be reported. + buffered_diags: Vec>, } impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> { - pub(crate) fn buffer_non_error(&mut self, diag: Diag<'diag, ()>) { - self.buffered_diags.push(BufferedDiag::NonError(diag)); - } pub(crate) fn buffer_error(&mut self, diag: Diag<'diag>) { - self.buffered_diags.push(BufferedDiag::Error(diag)); + self.buffered_diags.push(diag); } pub(crate) fn emit_errors(&mut self) { @@ -134,14 +117,9 @@ impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> { } if !self.buffered_diags.is_empty() { - self.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span()); - for buffered_diag in self.buffered_diags.drain(..) { - match buffered_diag { - BufferedDiag::Error(diag) => { - diag.emit(); - } - BufferedDiag::NonError(diag) => diag.emit(), - } + self.buffered_diags.sort_by_key(|diag| diag.sort_span); + for diag in self.buffered_diags.drain(..) { + diag.emit(); } } } @@ -152,10 +130,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { self.diags_buffer.buffer_error(diag.with_dcx(self.dcx())); } - pub(crate) fn buffer_non_error(&mut self, diag: Diag<'_, ()>) { - self.diags_buffer.buffer_non_error(diag.with_dcx(self.dcx())); - } - pub(crate) fn buffer_move_error( &mut self, move_out_indices: Vec, diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index b1e16717466b5..75c666f49a2f7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -14,9 +14,6 @@ use crate::MirBorrowckCtxt; /// The different things we could suggest. enum SuggestedConstraint { - /// Outlives(a, [b, c, d, ...]) => 'a: 'b + 'c + 'd + ... - Outlives(RegionName, SmallVec<[RegionName; 2]>), - /// 'a = 'b Equal(RegionName, RegionName), @@ -106,11 +103,10 @@ impl OutlivesSuggestionBuilder { continue; } - // There are three types of suggestions we can make: - // 1) Suggest a bound: 'a: 'b - // 2) Suggest replacing 'a with 'static. If any of `outlived` is `'static`, then we + // There are two types of suggestions we can make: + // 1) Suggest replacing 'a with 'static. If any of `outlived` is `'static`, then we // should just replace 'a with 'static. - // 3) Suggest unifying 'a with 'b if we have both 'a: 'b and 'b: 'a + // 2) Suggest unifying 'a with 'b if we have both 'a: 'b and 'b: 'a if outlived .iter() @@ -121,7 +117,7 @@ impl OutlivesSuggestionBuilder { // We want to isolate out all lifetimes that should be unified and print out // separate messages for them. - let (unified, other): (Vec<_>, Vec<_>) = outlived.into_iter().partition( + let unified = outlived.into_iter().filter( // Do we have both 'fr: 'r and 'r: 'fr? |(r, _)| { self.constraints_to_add @@ -130,17 +126,12 @@ impl OutlivesSuggestionBuilder { }, ); - for (r, bound) in unified.into_iter() { + for (r, bound) in unified { if !unified_already.contains(fr) { suggested.push(SuggestedConstraint::Equal(fr_name, bound)); unified_already.insert(r); } } - - if !other.is_empty() { - let other = other.iter().map(|(_, rname)| *rname).collect::>(); - suggested.push(SuggestedConstraint::Outlives(fr_name, other)) - } } } @@ -202,54 +193,36 @@ impl OutlivesSuggestionBuilder { return; } - // If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a - // list of diagnostics. - let mut diag = if let [constraint] = suggested.as_slice() { - mbcx.dcx().struct_help(match constraint { - SuggestedConstraint::Outlives(a, bs) => { - let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect(); - format!("add bound `{a}: {}`", bs.join(" + ")) - } - + // Emit an error with a list of one or more help suggestions. This is a weird error because + // it's just there to provide somewhere to put the help suggestions that describe how to + // fix the one or more borrow errors already reported within the item. + let tcx = mbcx.infcx.tcx; + let def_id = mbcx.mir_def_id(); + let span = tcx.def_ident_span(def_id).unwrap_or_else(|| tcx.def_span(def_id)); + let mut diag = tcx + .dcx() + .struct_err("one or more lifetime errors were found in this item") + .with_span(span); + + // Add suggestions. + for constraint in suggested { + match constraint { SuggestedConstraint::Equal(a, b) => { - format!("`{a}` and `{b}` must be the same: replace one with the other") + diag.help(format!( + "`{a}` and `{b}` must be the same: replace one with the other", + )); } - SuggestedConstraint::Static(a) => format!("replace `{a}` with `'static`"), - }) - } else { - // Create a new diagnostic. - let mut diag = mbcx - .infcx - .tcx - .dcx() - .struct_help("the following changes may resolve your lifetime errors"); - - // Add suggestions. - for constraint in suggested { - match constraint { - SuggestedConstraint::Outlives(a, bs) => { - let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect(); - diag.help(format!("add bound `{a}: {}`", bs.join(" + "))); - } - SuggestedConstraint::Equal(a, b) => { - diag.help(format!( - "`{a}` and `{b}` must be the same: replace one with the other", - )); - } - SuggestedConstraint::Static(a) => { - diag.help(format!("replace `{a}` with `'static`")); - } + SuggestedConstraint::Static(a) => { + diag.help(format!("replace `{a}` with `'static`")); } } - - diag - }; + } // We want this message to appear after other messages on the mir def. let mir_span = mbcx.body.span; diag.sort_span = mir_span.shrink_to_hi(); // Buffer the diagnostic - mbcx.buffer_non_error(diag); + mbcx.buffer_error(diag); } } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 3cfea4b80eb2b..125ed8d3e63d2 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -584,6 +584,15 @@ pub(crate) unsafe fn create_module<'ll>( ); } + if llvm_version >= (24, 0, 0) && sess.target.singlethread(&sess.internal_target_features) { + llvm::add_module_flag_str( + llmod, + llvm::ModuleFlagMergeBehavior::Error, + "thread-model", + "single", + ); + } + // Add module flags specified via -Z llvm_module_flag for (key, value, merge_behavior) in &sess.opts.unstable_opts.llvm_module_flag { let merge_behavior = match merge_behavior.as_str() { diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 0ba5024853075..ca57bee3e6271 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -474,7 +474,19 @@ fn emit_s390x_va_arg<'ll, 'tcx>( let padded_size = 8; let padding = padded_size - unpadded_size; - let gpr_type = indirect || !layout.is_single_fp_element(bx.cx); + // NOTE: if we ever allow aggregate types, this should handle structs with a single fp element. + let is_single_fp_element = |layout: TyAndLayout<'_>| -> bool { + match layout.layout.backend_repr() { + BackendRepr::Scalar(scalar) => match scalar.primitive() { + Primitive::Float(Float::F16 | Float::F32 | Float::F64) => true, + Primitive::Float(Float::F128) => false, + Primitive::Int(_, _) | Primitive::Pointer(_) => false, + }, + _ => false, + } + }; + + let gpr_type = indirect || !is_single_fp_element(layout); let (max_regs, reg_count, reg_save_index, reg_padding) = if gpr_type { (5, gpr, 2, padding) } else { (4, fpr, 16, 0) }; diff --git a/compiler/rustc_data_structures/src/flock.rs b/compiler/rustc_data_structures/src/flock.rs index 3e3aa32f52eaa..9bd7d06c27f5e 100644 --- a/compiler/rustc_data_structures/src/flock.rs +++ b/compiler/rustc_data_structures/src/flock.rs @@ -21,7 +21,7 @@ pub enum Lock { } impl Lock { - pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result { + pub fn try_lock(p: &Path, create: bool, exclusive: bool) -> io::Result { let mut open_options = OpenOptions::new(); open_options.read(true).write(true).create(create); #[cfg(unix)] @@ -32,17 +32,16 @@ impl Lock { let file = open_options.open(p)?; - let res = match (wait, exclusive) { - (true, true) => file.lock(), - (true, false) => file.lock_shared(), - (false, true) => file.try_lock().map_err(io::Error::from), - (false, false) => file.try_lock_shared().map_err(io::Error::from), + let res = if exclusive { + file.try_lock().map_err(io::Error::from) + } else { + file.try_lock_shared().map_err(io::Error::from) }; match res { Ok(()) => Ok(Lock::FdLocked { _file: file }), Err(err) if matches!(err.kind(), io::ErrorKind::Unsupported) => { - Ok(Lock::Fallback(fallback::Lock::new(p, wait, create, exclusive)?)) + Ok(Lock::Fallback(fallback::Lock::try_lock(p, file, exclusive)?)) } Err(err) => Err(err), } diff --git a/compiler/rustc_data_structures/src/flock/unix.rs b/compiler/rustc_data_structures/src/flock/unix.rs index af1a6b1479531..35f865b68a7ce 100644 --- a/compiler/rustc_data_structures/src/flock/unix.rs +++ b/compiler/rustc_data_structures/src/flock/unix.rs @@ -1,22 +1,100 @@ -use std::fs::{File, OpenOptions}; +use std::collections::hash_map::Entry; +use std::fs::File; use std::os::unix::prelude::*; -use std::path::Path; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, LazyLock, Mutex}; use std::{io, mem}; +use rustc_hash::FxHashMap; + +static LOCK_REGISTRY: LazyLock>> = + LazyLock::new(|| Mutex::new(FxHashMap::default())); + +enum LockState { + /// Lock exclusively held. `Lock.file` contains an `Arc` with a single reference. + /// + /// The `extra_files` fields contains files we opened while the lock was held. We have to + /// persist them until we actually want to unlock the file to prevent unlocking on close. + Exclusive { extra_files: Vec }, + /// Lock can be shared. When there are N lock holders, the `Arc` has N+1 references + /// with the last one being held by `LockState` and getting removed in the drop impl of `Lock` + /// if it is the remaining reference. + Shared(Arc), +} + #[derive(Debug)] pub struct Lock { - file: File, + path: PathBuf, + file: Option>, } impl Lock { - pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result { - let file = OpenOptions::new() - .read(true) - .write(true) - .create(create) - .mode(libc::S_IRWXU as u32) - .open(p)?; + pub fn try_lock(p: &Path, file: File, exclusive: bool) -> io::Result { + let mut locks = LOCK_REGISTRY.lock().unwrap(); + + let file = match locks.entry(p.to_owned()) { + Entry::Occupied(mut state) => { + // We must not open the file again if there is an existing lock to prevent the close + // from unlocking the file even when another `Lock` already had the lock held before + // this `Lock::try_lock` call. + match state.get_mut() { + LockState::Exclusive { extra_files } => { + // Retain file to prevent unlock on close + extra_files.push(file); + + return Err(io::ErrorKind::WouldBlock.into()); + } + LockState::Shared(file) => { + if exclusive { + return Err(io::ErrorKind::WouldBlock.into()); + } else { + Arc::clone(file) + } + } + } + } + Entry::Vacant(vacant) => { + let file = Arc::new(UnlockGuard::try_lock(file, exclusive)?); + + if exclusive { + vacant.insert(LockState::Exclusive { extra_files: vec![] }); + } else { + vacant.insert(LockState::Shared(Arc::clone(&file))); + } + + file + } + }; + + Ok(Lock { path: p.to_owned(), file: Some(file) }) + } +} +impl Drop for Lock { + fn drop(&mut self) { + let mut locks = LOCK_REGISTRY.lock().unwrap(); + self.file.take().unwrap(); + match locks.get_mut(&self.path).unwrap() { + LockState::Exclusive { extra_files: _ } => { + locks.remove(&self.path); + } + LockState::Shared(file) => { + if Arc::strong_count(file) == 1 { + locks.remove(&self.path); + } + } + } + } +} + +/// A file guard which will unlock the file when dropped. +#[derive(Debug)] +struct UnlockGuard { + file: File, +} + +impl UnlockGuard { + fn try_lock(file: File, exclusive: bool) -> io::Result { let lock_type = if exclusive { libc::F_WRLCK } else { libc::F_RDLCK }; let mut flock: libc::flock = unsafe { mem::zeroed() }; @@ -33,13 +111,12 @@ impl Lock { flock.l_start = 0; flock.l_len = 0; - let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK }; - let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &flock) }; - if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { file }) } + let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_SETLK, &flock) }; + if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Self { file }) } } } -impl Drop for Lock { +impl Drop for UnlockGuard { fn drop(&mut self) { let mut flock: libc::flock = unsafe { mem::zeroed() }; #[cfg(not(all(target_os = "hurd", target_arch = "x86")))] diff --git a/compiler/rustc_data_structures/src/flock/unsupported.rs b/compiler/rustc_data_structures/src/flock/unsupported.rs index 6775784749763..17b83e252d243 100644 --- a/compiler/rustc_data_structures/src/flock/unsupported.rs +++ b/compiler/rustc_data_structures/src/flock/unsupported.rs @@ -1,3 +1,4 @@ +use std::fs::File; use std::io; use std::path::Path; @@ -5,7 +6,7 @@ use std::path::Path; pub struct Lock(()); impl Lock { - pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool) -> io::Result { + pub fn try_lock(_p: &Path, _f: File, _exclusive: bool) -> io::Result { let msg = "file locks not supported on this platform"; Err(io::Error::new(io::ErrorKind::Unsupported, msg)) } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9ca0344058d7f..e1fd8344e73fd 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1148,11 +1148,6 @@ impl<'a> DiagCtxtHandle<'a> { self.create_note(note).emit() } - #[track_caller] - pub fn struct_help(self, msg: impl Into) -> Diag<'a, ()> { - Diag::new(self, Help, msg) - } - #[track_caller] pub fn struct_failure_note(self, msg: impl Into) -> Diag<'a, ()> { Diag::new(self, FailureNote, msg) @@ -1572,7 +1567,7 @@ impl DelayedDiagInner { /// | ForceWarning | - | () | yes | lint-only /// | Warning | - | () | yes | yes /// | Note | - | () | rare | - -/// | Help | - | () | rare | - +/// | Help | - | () | don't use | - /// | FailureNote | - | () | rare | - /// | Allow | - | () | yes | lint-only /// | Expect | - | () | yes | lint-only @@ -1607,14 +1602,18 @@ pub enum Level { /// Will be skipped if `can_emit_warnings` is false. Warning, - /// A message giving additional context. + /// A rarely-used level for output that isn't an error or a warning. Note, /// A message suggesting how to fix something. + /// + /// FIXME(nnethercote) Do not use this! Currently only exists to support `proc_macro::Help`, + /// part of the unstable `proc_macro_diagnostic` feature (see #54140). Should be removed + /// because help messages are fine as subdiagnostics but are silly as top-level diagnostics. Help, - /// Similar to `Note`, but used in cases where compilation has failed. When printed for human - /// consumption, it doesn't have any kind of `note:` label. + /// Similar to `Note`, but even rarer. Lacks the a trailing blank line that all other + /// diagnostics have. Also, when printed for human consumption it doesn't have a `note:` label. FailureNote, /// Only used for lints. @@ -1666,13 +1665,13 @@ pub enum Sublevel { /// See `Level::Warning`. Warning, - /// See `Level::Note`. + /// A message giving additional context. Note, /// A note that is only emitted once. OnceNote, - /// See `Level::Help`. + /// A message suggesting how to fix something. Help, /// A help that is only emitted once. diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 7493653987a91..504e93cf2aaef 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -115,6 +115,8 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::{base_n, flock}; use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize}; +use rustc_middle::dep_graph::WorkProduct; +use rustc_session::config::OutputType; use rustc_session::{IncrCompSession, Session, StableCrateId}; use rustc_span::{Symbol, bug}; use tracing::debug; @@ -332,7 +334,31 @@ pub fn finalize_session_directory( let new_path = incr_comp_session_dir.parent().unwrap().join(&*sub_dir_name); debug!("finalize_session_directory() - new path: {}", new_path.display()); - match rename_path_with_retry(&*incr_comp_session_dir, &new_path, 3) { + let result = std_fs::rename(&*incr_comp_session_dir, &new_path).or_else(|e| { + if !cfg!(windows) || e.kind() != ErrorKind::PermissionDenied { + return Err(e); + } + + // On ReFS, renaming a directory that contains a hard link to the metadata workproduct file + // can fail if it is being used by another process (such as another rustc instance). + // As a fallback, we try to replace the hard link with a copy, which should allow the + // rename to succeed. + // See https://github.com/rust-lang/rust/issues/151181 + if let Err(err) = replace_hard_link_with_copy(&in_incr_comp_dir_sess( + &incr_comp_session, + &format!( + "{}.{}", + WorkProduct::METADATA_WORKPRODUCT_CGU_NAME, + OutputType::Metadata.extension() + ), + )) { + debug!("finalize_session_directory() - error replacing hard link with copy: {}", err); + } + + rename_path_with_retry(&*incr_comp_session_dir, &new_path, 3) + }); + + match result { Ok(_) => { debug!("finalize_session_directory() - directory renamed successfully"); } @@ -366,9 +392,8 @@ fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result (flock::Lock, PathBuf) let lock_file_path = lock_file_path(session_dir); debug!("lock_directory() - lock_file: {}", lock_file_path.display()); - match flock::Lock::new( + match flock::Lock::try_lock( &lock_file_path, - false, // don't wait - true, // create the lock file + true, // create the lock file true, ) { // the lock should be exclusive @@ -712,9 +736,8 @@ pub(crate) fn garbage_collect_session_directories( if is_finalized(directory_name) { let lock_file_path = crate_directory.join(lock_file_name); - match flock::Lock::new( + match flock::Lock::try_lock( &lock_file_path, - false, // don't wait false, // don't create the lock-file true, ) { @@ -781,9 +804,8 @@ pub(crate) fn garbage_collect_session_directories( // means that the owning process is still alive and we // leave this directory alone. let lock_file_path = crate_directory.join(lock_file_name); - match flock::Lock::new( + match flock::Lock::try_lock( &lock_file_path, - false, // don't wait false, // don't create the lock-file true, ) { @@ -893,3 +915,15 @@ fn rename_path_with_retry(from: &Path, to: &Path, mut retries_left: usize) -> st } } } + +/// Turns a hard link of the file at `path` into a copy. +fn replace_hard_link_with_copy(path: &Path) -> std::io::Result<()> { + let tmp_name = path.with_added_extension("tmp"); + + // In case a stale temporary file was linked from a previous failed attempt. + safe_remove_file(&tmp_name)?; + + std_fs::copy(path, &tmp_name).and_then(|_| std_fs::rename(&tmp_name, path)).inspect_err(|_| { + let _ = safe_remove_file(&tmp_name); + }) +} diff --git a/compiler/rustc_incremental/src/persist/fs/tests.rs b/compiler/rustc_incremental/src/persist/fs/tests.rs index 644b8187621c9..3652656b7c48f 100644 --- a/compiler/rustc_incremental/src/persist/fs/tests.rs +++ b/compiler/rustc_incremental/src/persist/fs/tests.rs @@ -75,3 +75,18 @@ fn test_find_source_directory_in_iter() { None ); } + +#[test] +fn test_replace_hard_link_with_copy_unshares_hard_link() { + let dir = rustc_fs_util::TempDirBuilder::new().tempdir_in(std::env::temp_dir()).unwrap(); + let file = dir.path().join("file"); + let link = dir.path().join("link"); + std_fs::write(&file, b"original").unwrap(); + std_fs::hard_link(&file, &link).unwrap(); + + replace_hard_link_with_copy(&link).unwrap(); + + std_fs::write(&file, b"changed").unwrap(); + assert_eq!(std_fs::read(&link).unwrap(), b"original"); + assert!(!link.with_added_extension("tmp").exists()); +} diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 51e26d4ba5044..2f196c5e5d609 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -7,7 +7,7 @@ use rustc_data_structures::svh::Svh; use rustc_errors::timings::TimingSection; use rustc_hir::def_id::LOCAL_CRATE; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{DepGraph, WorkProductMap}; +use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, OutputFilenames, OutputType}; use rustc_session::{IncrCompSession, Session}; @@ -99,8 +99,8 @@ impl Linker { let (id, product) = rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( sess, incr_comp_session.as_ref().unwrap(), - "metadata", - &[("rmeta", path)], + WorkProduct::METADATA_WORKPRODUCT_CGU_NAME, + &[(OutputType::Metadata.extension(), path)], &[], ); work_products.insert(id, product); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 4263618011f4c..494521ce18582 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -425,9 +425,11 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( } } +#if LLVM_VERSION_LT(24, 0) if (Singlethread) { Options.ThreadModel = ThreadModel::Single; } +#endif if (UseWasmEH) Options.ExceptionModel = ExceptionHandling::Wasm; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 12c8fac8cc2eb..8481db9d3c523 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -18,7 +18,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; use rustc_hir::definitions::DefPathData; use rustc_hir::find_attr; use rustc_hir_pretty::id_to_string; -use rustc_middle::dep_graph::WorkProductId; +use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::mir::interpret; use rustc_middle::query::Providers; @@ -28,7 +28,7 @@ use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, TreatParams}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque}; use rustc_session::config::mitigation_coverage::DeniedPartialMitigation; -use rustc_session::config::{OptLevel, TargetModifier}; +use rustc_session::config::{OptLevel, OutputType, TargetModifier}; use rustc_span::def_id::CRATE_MOD_ID; use rustc_span::hygiene::HygieneEncodeContext; use rustc_span::{ @@ -2502,11 +2502,12 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { // If the metadata dep-node is green, try to reuse the saved work product. if tcx.dep_graph.is_fully_enabled() - && let work_product_id = WorkProductId::from_cgu_name("metadata") + && let work_product_id = + WorkProductId::from_cgu_name(WorkProduct::METADATA_WORKPRODUCT_CGU_NAME) && let Some(work_product) = tcx.dep_graph.previous_work_product(&work_product_id) && tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() { - let saved_path = &work_product.saved_files["rmeta"]; + let saved_path = &work_product.saved_files[OutputType::Metadata.extension()]; let incr_comp_session_dir = &tcx.incr_comp_session.unwrap().session_directory; let source_file_in_incr_dir = &incr_comp_session_dir.join(saved_path); debug!("copying preexisting metadata from {source_file_in_incr_dir:?} to {path:?}"); diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index a4165d793069d..dcb5775f20595 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -1143,6 +1143,13 @@ pub struct WorkProduct { pub saved_files: UnordMap, } +impl WorkProduct { + /// The metadata work product is not produced by any CGU and thus its + /// name cannot be derived from `CodegenUnit`. Both the writers and readers + /// of the metadata work product use this constant to agree on the name. + pub const METADATA_WORKPRODUCT_CGU_NAME: &str = "metadata"; +} + pub type WorkProductMap = UnordMap; // Index type for `DepNodeData`'s edges. diff --git a/compiler/rustc_target/src/callconv/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs index f0d9675de34f4..0d29bc658b56d 100644 --- a/compiler/rustc_target/src/callconv/s390x.rs +++ b/compiler/rustc_target/src/callconv/s390x.rs @@ -1,11 +1,44 @@ // Reference: ELF Application Binary Interface s390x Supplement // https://github.com/IBM/s390x-abi -use rustc_abi::{BackendRepr, HasDataLayout, TyAbiInterface}; +use rustc_abi::{BackendRepr, FieldsShape, HasDataLayout, Primitive, TyAbiInterface, TyAndLayout}; use crate::callconv::{ArgAbi, FnAbi, Reg}; use crate::spec::{Env, HasTargetSpec, Os}; +/// Is this a struct with a single float field? +fn is_single_fp_element<'a, Ty, C>(mut layout: TyAndLayout<'a, Ty>, cx: &C) -> bool +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout, +{ + // Contrary to X86, trailing padding is allowed on s390x. + + loop { + layout = layout.peel_transparent_wrappers(cx); + + return match layout.backend_repr { + BackendRepr::Scalar(scalar) => match scalar.primitive() { + Primitive::Float(_) => true, + Primitive::Int(_, _) | Primitive::Pointer(_) => false, + }, + BackendRepr::Memory { .. } => { + // A single-element array or union does not qualify. + if let FieldsShape::Arbitrary { .. } = layout.fields + && layout.fields.count() == 1 + && layout.fields.offset(0).bytes() == 0 + { + layout = layout.field(cx, 0); + continue; + } else { + false + } + } + _ => false, + }; + } +} + fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { let size = ret.layout.size; if size.bits() <= 128 && matches!(ret.layout.backend_repr, BackendRepr::SimdVector { .. }) { @@ -65,8 +98,19 @@ where return; } - if arg.layout.is_single_fp_element(cx) { + if is_single_fp_element(arg.layout, cx) { + // Match GCC and Clang by explicitly passing padding, even though their behavior violates + // (our reading of) the specification, which says that: + // + // > Structures equivalent to a floating point type are passed in floating point registers. + // > A structure is equivalent to a floating point type if and only if it has exactly one + // > member, which is either of floating point type of itself a structure equivalent to a + // > floating point type. + // + // When the alignment is higher than 8, we pass the argument indirectly, which violates + // the specification but is consistent with GCC and Clang. match size.bytes() { + 2 => arg.cast_to(Reg::f16()), 4 => arg.cast_to(Reg::f32()), 8 => arg.cast_to(Reg::f64()), _ => arg.make_indirect(), diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index fd608fcf62919..a1c59d885b7fc 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -5,6 +5,38 @@ use rustc_abi::{ use crate::callconv::{ArgAttribute, FnAbi, PassMode, TyAbiInterface}; use crate::spec::{HasTargetSpec, RustcAbi}; +/// Is this a struct with a single float field? +fn is_single_fp_element<'a, Ty, C>(mut layout: TyAndLayout<'a, Ty>, cx: &C) -> bool +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout, +{ + // On X86 over-aligned structs are disqualified. + let outer_size = layout.layout.size(); + + loop { + layout = layout.peel_transparent_wrappers(cx); + + return match layout.backend_repr { + BackendRepr::Scalar(scalar) => match scalar.primitive() { + Primitive::Float(float) => float.size() == outer_size, + Primitive::Int(_, _) | Primitive::Pointer(_) => false, + }, + BackendRepr::Memory { .. } => { + // Structs, unions and arrays all qualify. + if let Some((_idx, field)) = layout.non_zst_field_ignore_alignment(cx) { + // NOTE: alignment is not relevant here, checking for 1-ZST is incorrect. + layout = field; + continue; + } else { + false + } + } + _ => false, + }; + } +} + #[derive(PartialEq)] pub(crate) enum Flavor { General, @@ -42,8 +74,9 @@ where { // According to Clang, everyone but MSVC returns single-element // float aggregates directly in a floating-point register. - if fn_abi.ret.layout.is_single_fp_element(cx) { + if is_single_fp_element(fn_abi.ret.layout, cx) { match fn_abi.ret.layout.size.bytes() { + 2 => fn_abi.ret.cast_to(Reg::f16()), 4 => fn_abi.ret.cast_to(Reg::f32()), 8 => fn_abi.ret.cast_to(Reg::f64()), _ => fn_abi.ret.make_indirect(), diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 9826633d47033..2ee7dea9f8af3 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -692,7 +692,14 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ }, &[], ), - ("m", Stable, &[]), + // According to the RISC-V spec, the M ISA extension (integer multiplication/division) is supported only when the M bit + // of the misa register is 1, while Zmmul means integer multiplication is always supported. + // + // The Rust/LLVM "m" target feature means something slightly different: with "m" enabled, it is assumed that integer + // multiplication and division will always be available (M bit will be 1 in misa), so "m" implies "zmmul". + // + // See discussion in the PR adding Zmmul: https://github.com/rust-lang/rust/pull/162552 + ("m", Stable, &["zmmul"]), ("relax", Unstable(sym::riscv_target_feature), &[]), ( "rva23u64", @@ -793,6 +800,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("zksed", Stable, &[]), ("zksh", Stable, &[]), ("zkt", Stable, &[]), + ("zmmul", Unstable(sym::riscv_target_feature), &[]), ("ztso", Stable, &[]), ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), // Zvbb ⊃ Zvkb ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 76567e4d27d1d..8de0514b9ef27 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5088,6 +5088,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::Adt(adt, args) if adt.did().is_local() => (adt, args), _ => return false, }; + if !self.tcx.def_span(adt.did()).can_be_used_for_suggestions() { + return false; + } let is_derivable_trait = match diagnostic_name { sym::Copy | sym::Clone => true, _ if adt.is_union() => false, diff --git a/library/compiler-builtins/compiler-builtins/src/math/mod.rs b/library/compiler-builtins/compiler-builtins/src/math/mod.rs index 3dfa3863bb770..03a564ca0e543 100644 --- a/library/compiler-builtins/compiler-builtins/src/math/mod.rs +++ b/library/compiler-builtins/compiler-builtins/src/math/mod.rs @@ -27,6 +27,7 @@ pub mod full_availability { fn fabsf16(x: f16) -> f16; fn fdimf16(x: f16, y: f16) -> f16; fn floorf16(x: f16) -> f16; + fn fmaf16(x: f16, y: f16, z: f16) -> f16; fn fmaxf16(x: f16, y: f16) -> f16; fn fmaximum_numf16(x: f16, y: f16) -> f16; fn fmaximumf16(x: f16, y: f16) -> f16; diff --git a/library/compiler-builtins/libm/src/math/fmaf16.rs b/library/compiler-builtins/libm/src/math/fmaf16.rs index 8d1c5bccf8527..6d00832065e18 100644 --- a/library/compiler-builtins/libm/src/math/fmaf16.rs +++ b/library/compiler-builtins/libm/src/math/fmaf16.rs @@ -88,11 +88,22 @@ pub fn fmaf16(x: f16, y: f16, z: f16) -> f16 { // create a U21.43 fixed-point value. At the maximum exponent, there are five zeros before // the explicit leading 1 (intentional so this truncates to the final repr). if let Some(mshift) = mexp.checked_sub(5) { - debug_assert_eq!( - unbounded_shr_u64(m64, 64 - mshift), - 0, - "data shifted out {m} {mshift}" - ); + cfg_select_nofmt! { + feature = "compiler-builtins" => { + // Avoid formatting calls to `core` when building as compiler-builtins + debug_assert!( + unbounded_shr_u64(m64, 64 - mshift) == 0, + "data shifted out" + ); + } + _ => { + debug_assert_eq!( + unbounded_shr_u64(m64, 64 - mshift), + 0, + "data shifted out {m} {mshift}" + ); + } + } m64 <<= mshift; } else { // The lower few bits here would be on the order of 2^-43, which is too small to show up diff --git a/library/core/src/num/imp/libm.rs b/library/core/src/num/imp/libm.rs index 388f1479b2461..a8d6bdc0b5d7c 100644 --- a/library/core/src/num/imp/libm.rs +++ b/library/core/src/num/imp/libm.rs @@ -33,6 +33,7 @@ unsafe extern "C" { pub(crate) safe fn fma(x: f64, y: f64, z: f64) -> f64; pub(crate) safe fn fmaf(x: f32, y: f32, z: f32) -> f32; pub(crate) safe fn fmaf128(x: f128, y: f128, z: f128) -> f128; + pub(crate) safe fn fmaf16(x: f16, y: f16, z: f16) -> f16; pub(crate) safe fn fmax(x: f64, y: f64) -> f64; pub(crate) safe fn fmaxf(x: f32, y: f32) -> f32; pub(crate) safe fn fmaxf128(x: f128, y: f128) -> f128; diff --git a/library/std_detect/src/detect/arch/riscv.rs b/library/std_detect/src/detect/arch/riscv.rs index 0e6bab512ac15..9e8648823e7a3 100644 --- a/library/std_detect/src/detect/arch/riscv.rs +++ b/library/std_detect/src/detect/arch/riscv.rs @@ -104,6 +104,7 @@ features! { /// | `"zksed"` | Zksed | 6.8 | /// | `"zksh"` | Zksh | 6.8 | /// | `"zkt"` | Zkt | 6.8 | + /// | `"zmmul"` | Zmmul | No [^ima] [^dep] | /// | `"ztso"` | Ztso | 6.8 | /// | `"zvbb"` | Zvbb | 6.8 | /// | `"zvbc"` | Zvbc | 6.8 | @@ -220,6 +221,8 @@ features! { @FEATURE: #[stable(feature = "riscv_ratified", since = "1.78.0")] m: "m"; /// "M" Extension for Integer Multiplication and Division + @FEATURE: #[unstable(feature = "stdarch_riscv_feature_detection", issue = "111192")] zmmul: "zmmul"; + /// "Zmmul" Extension for Integer Multiplication @FEATURE: #[stable(feature = "riscv_ratified", since = "1.78.0")] a: "a"; /// "A" Extension for Atomic Instructions diff --git a/library/std_detect/src/detect/os/riscv.rs b/library/std_detect/src/detect/os/riscv.rs index 9b9e0cba09d1c..d4315f5cc1d87 100644 --- a/library/std_detect/src/detect/os/riscv.rs +++ b/library/std_detect/src/detect/os/riscv.rs @@ -147,6 +147,8 @@ pub(crate) fn imply_features(mut value: cache::Initializer) -> cache::Initialize imply!(zicntr | zihpm | f | zfinx | zve32x => zicsr); + imply!(m => zmmul); + // Loop until the feature flags converge. if prev == value { return value; diff --git a/library/std_detect/tests/cpu-detection.rs b/library/std_detect/tests/cpu-detection.rs index f0b276072108d..a381d84cfbbc3 100644 --- a/library/std_detect/tests/cpu-detection.rs +++ b/library/std_detect/tests/cpu-detection.rs @@ -243,6 +243,7 @@ fn riscv_linux() { println!("zicboz: {}", is_riscv_feature_detected!("zicboz")); println!("zicond: {}", is_riscv_feature_detected!("zicond")); println!("m: {}", is_riscv_feature_detected!("m")); + println!("zmmul: {}", is_riscv_feature_detected!("zmmul")); println!("a: {}", is_riscv_feature_detected!("a")); println!("zalrsc: {}", is_riscv_feature_detected!("zalrsc")); println!("zaamo: {}", is_riscv_feature_detected!("zaamo")); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index f89ccb4c2a6a8..096184ee9e5b4 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1409,6 +1409,21 @@ impl CommandLineStep for OmpOffload { ldflags.push_all(format!("-L{}", dir.display())); } + if builder.config.rpath_enabled(target) + && helpers::use_host_linker(target) + && llvm_output.link_shared() + && target.contains("linux") + { + // Same logic as in Lld::run + // We inform libomptarget.so where it can find LLVM's libraries + // by adding an rpath entry to the expected parent `lib` directory. + // + // Be careful when changing this path, we need to ensure it's quoted or escaped: + // `$ORIGIN` would otherwise be expanded when the `LdFlags` are passed verbatim to + // cmake. + ldflags.push_all("-Wl,-rpath,'$ORIGIN/../../../'"); + } + configure_cmake(builder, target, &mut cfg, true, ldflags, cflags, &[]); cfg.define("CMAKE_C_COMPILER", &clang) diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 19600ff2bb63e..4d7895264c158 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,6 +14,7 @@ askama = { version = "0.16.1", default-features = false, features = ["alloc", "c base64 = "0.21.7" indexmap = { version = "2", features = ["serde"] } itertools = "0.15" +libc = "0.2" minifier = { version = "0.4.0", default-features = false } proc-macro2 = "1.0.103" pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index ab72edacae296..5c963afd3a221 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -26,7 +26,6 @@ use std::{fmt, fs}; use indexmap::IndexMap; use rustc_ast::join_path_syms; -use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt; @@ -57,6 +56,8 @@ use crate::html::static_files::{self, suffix_path}; use crate::visit::DocVisitor; use crate::{DOC_RUST_LANG_ORG_VERSION, try_err, try_none}; +mod flock; + pub(crate) fn write_shared( cx: &mut Context<'_>, krate: &Crate, @@ -67,7 +68,7 @@ pub(crate) fn write_shared( cx.shared.fs.set_sync_only(true); let lock_file = cx.dst.join(".lock"); // Write shared runs within a flock; disable thread dispatching of IO temporarily. - let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); + let _lock = try_err!(flock::Lock::new(&lock_file), &lock_file); let search_index = build_index( krate, diff --git a/src/librustdoc/html/render/write_shared/flock.rs b/src/librustdoc/html/render/write_shared/flock.rs new file mode 100644 index 0000000000000..385c0bcc84cd3 --- /dev/null +++ b/src/librustdoc/html/render/write_shared/flock.rs @@ -0,0 +1,92 @@ +use std::fs::{File, OpenOptions}; +use std::io; +#[cfg(unix)] +use std::os::unix::prelude::*; +use std::path::Path; + +#[derive(Debug)] +pub(super) enum Lock { + /// A well behaved lock scoped to a single fd/handle and unlocked when closing it. + #[doc(hidden)] + FdLocked { _file: File }, + /// A fallback implementation using the legacy `fcntl(F_SETLK)` which is scoped to + /// an entire process. This should only be used when `flock()` or equivalent sane + /// locking mechanism is unsupported by the OS. + #[doc(hidden)] + #[cfg(unix)] + FcntlFallback { _lock: FcntlLock }, +} + +impl Lock { + pub(super) fn new(p: &Path) -> io::Result { + let mut open_options = OpenOptions::new(); + open_options.read(true).write(true).create(true); + #[cfg(unix)] + { + use std::os::unix::fs::OpenOptionsExt; + open_options.mode(0o600); + } + + let file = open_options.open(p)?; + + match file.lock() { + Ok(()) => Ok(Lock::FdLocked { _file: file }), + #[cfg(unix)] + Err(err) if matches!(err.kind(), io::ErrorKind::Unsupported) => { + Ok(Lock::FcntlFallback { _lock: FcntlLock::new(file)? }) + } + Err(err) => Err(err), + } + } +} + +#[derive(Debug)] +#[cfg(unix)] +pub(super) struct FcntlLock { + file: File, +} + +#[cfg(unix)] +impl FcntlLock { + fn new(file: File) -> io::Result { + let mut flock: libc::flock = unsafe { std::mem::zeroed() }; + #[cfg(not(all(target_os = "hurd", target_arch = "x86")))] + { + flock.l_type = libc::F_WRLCK as libc::c_short; + flock.l_whence = libc::SEEK_SET as libc::c_short; + } + #[cfg(all(target_os = "hurd", target_arch = "x86"))] + { + flock.l_type = libc::F_WRLCK as libc::c_int; + flock.l_whence = libc::SEEK_SET as libc::c_int; + } + flock.l_start = 0; + flock.l_len = 0; + + let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_SETLKW, &flock) }; + if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(FcntlLock { file }) } + } +} + +#[cfg(unix)] +impl Drop for FcntlLock { + fn drop(&mut self) { + let mut flock: libc::flock = unsafe { std::mem::zeroed() }; + #[cfg(not(all(target_os = "hurd", target_arch = "x86")))] + { + flock.l_type = libc::F_UNLCK as libc::c_short; + flock.l_whence = libc::SEEK_SET as libc::c_short; + } + #[cfg(all(target_os = "hurd", target_arch = "x86"))] + { + flock.l_type = libc::F_UNLCK as libc::c_int; + flock.l_whence = libc::SEEK_SET as libc::c_int; + } + flock.l_start = 0; + flock.l_len = 0; + + unsafe { + libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock); + } + } +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs index 29a933f922630..7664d87cdee3e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs @@ -204,6 +204,7 @@ const TARGET_FEATURE_IMPLICATIONS_RAW: &[(&str, &[&str])] = &[ // RISC-V ("a", &["zaamo", "zalrsc"]), ("d", &["f"]), + ("m", &["zmmul"]), ("zabha", &["zaamo"]), ("zdinx", &["zfinx"]), ("zfh", &["zfhmin"]), diff --git a/tests/codegen-llvm/s390x-abi/single-fp-element.rs b/tests/codegen-llvm/s390x-abi/single-fp-element.rs new file mode 100644 index 0000000000000..857fa7e3b2737 --- /dev/null +++ b/tests/codegen-llvm/s390x-abi/single-fp-element.rs @@ -0,0 +1,129 @@ +//@ add-minicore +//@ needs-llvm-components: systemz +//@ compile-flags: --target=s390x-unknown-linux-gnu -Copt-level=3 -Zmerge-functions=disabled +#![crate_type = "lib"] +#![feature(no_core, f16, f128)] +#![no_core] + +extern crate minicore; +use minicore::hint::black_box; +use minicore::*; + +#[repr(C)] +struct Wrapper(T); + +// CHECK-LABEL: define void @plain_f16(half noundef %x) +#[unsafe(no_mangle)] +extern "C" fn plain_f16(x: f16) { + black_box(x); +} + +// CHECK-LABEL: define void @wrapped_f16(half %0) +#[unsafe(no_mangle)] +extern "C" fn wrapped_f16(x: Wrapper) { + black_box(x); +} + +// CHECK-LABEL: define void @plain_f32(float noundef %x) +#[unsafe(no_mangle)] +extern "C" fn plain_f32(x: f32) { + black_box(x); +} + +// CHECK-LABEL: define void @wrapped_f32(float %0) +#[unsafe(no_mangle)] +extern "C" fn wrapped_f32(x: Wrapper) { + black_box(x); +} + +// CHECK-LABEL: define void @plain_f64(double noundef %x) +#[unsafe(no_mangle)] +extern "C" fn plain_f64(x: f64) { + black_box(x); +} + +// CHECK-LABEL: define void @wrapped_f64(double %0) +#[unsafe(no_mangle)] +extern "C" fn wrapped_f64(x: Wrapper) { + black_box(x); +} + +// CHECK-LABEL: define void @plain_f128(ptr {{.*}}dereferenceable(16) %x) +#[unsafe(no_mangle)] +extern "C" fn plain_f128(x: f128) { + black_box(x); +} + +// CHECK-LABEL: define void @wrapped_f128(ptr {{.*}}dereferenceable(16) %x) +#[unsafe(no_mangle)] +extern "C" fn wrapped_f128(x: Wrapper) { + black_box(x); +} + +#[repr(transparent)] +struct Transparent(T); + +// CHECK-LABEL: define void @transparent_wrapped_f32(float %0) +#[unsafe(no_mangle)] +extern "C" fn transparent_wrapped_f32(x: Transparent>) { + black_box(x); +} + +// CHECK-LABEL: define void @transparent_transparent_wrapped_f32(float %0) +#[unsafe(no_mangle)] +extern "C" fn transparent_transparent_wrapped_f32(x: Transparent>>) { + black_box(x); +} + +#[repr(C, align(8))] +struct Aligned8Wrapper(T); + +// CHECK-LABEL: define void @aligned_8_wrapped_f16(double %0) +#[unsafe(no_mangle)] +extern "C" fn aligned_8_wrapped_f16(x: Aligned8Wrapper) { + black_box(x); +} + +// CHECK-LABEL: define void @aligned_8_wrapped_f32(double %0) +#[unsafe(no_mangle)] +extern "C" fn aligned_8_wrapped_f32(x: Aligned8Wrapper) { + black_box(x); +} + +#[repr(C, align(16))] +struct Aligned16Wrapper(T); + +// CHECK-LABEL: define void @aligned_16_wrapped_f32(ptr {{.*}}dereferenceable(16) +#[unsafe(no_mangle)] +extern "C" fn aligned_16_wrapped_f32(x: Aligned16Wrapper) { + black_box(x); +} + +#[repr(C)] +union UnionWrapper { + a: T, +} + +// A repr(C) union does not count. +// +// CHECK-LABEL: define void @union_wrapped_f32(i32 %0) +#[unsafe(no_mangle)] +extern "C" fn union_wrapped_f32(x: UnionWrapper) { + black_box(x); +} + +// But a repr(transparent) union does. +// +// CHECK-LABEL: define void @maybe_uninit_f32(float %x) +#[unsafe(no_mangle)] +extern "C" fn maybe_uninit_f32(x: MaybeUninit) { + black_box(x); +} + +// A single-element array also does not count. +// +// CHECK-LABEL: define void @array_f32(i32 %0) +#[unsafe(no_mangle)] +extern "C" fn array_f32(x: [f32; 1]) { + black_box(x); +} diff --git a/tests/codegen-llvm/x86-abi/single-fp-element.rs b/tests/codegen-llvm/x86-abi/single-fp-element.rs new file mode 100644 index 0000000000000..1aa2531570bb8 --- /dev/null +++ b/tests/codegen-llvm/x86-abi/single-fp-element.rs @@ -0,0 +1,146 @@ +//@ add-minicore +//@ needs-llvm-components: x86 +//@ revisions: win linux +//@[win] compile-flags: --target i686-pc-windows-gnu +//@[linux] compile-flags: --target i686-unknown-linux-gnu -Zreg-struct-return=true +//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled +#![crate_type = "lib"] +#![feature(no_core, f16, f128)] +#![no_core] + +extern crate minicore; +use minicore::hint::black_box; +use minicore::*; + +#[repr(C)] +struct Wrapper(T); + +// CHECK-LABEL: define noundef half @plain_f16( +#[unsafe(no_mangle)] +extern "C" fn plain_f16(x: f16) -> f16 { + x +} + +// CHECK-LABEL: define half @wrapped_f16( +#[unsafe(no_mangle)] +extern "C" fn wrapped_f16(x: Wrapper) -> Wrapper { + x +} + +// CHECK-LABEL: define noundef float @plain_f32( +#[unsafe(no_mangle)] +extern "C" fn plain_f32(x: f32) -> f32 { + x +} + +// CHECK-LABEL: define float @wrapped_f32( +#[unsafe(no_mangle)] +extern "C" fn wrapped_f32(x: Wrapper) -> Wrapper { + x +} + +// CHECK-LABEL: define noundef double @plain_f64( +#[unsafe(no_mangle)] +extern "C" fn plain_f64(x: f64) -> f64 { + x +} + +// CHECK-LABEL: define double @wrapped_f64( +#[unsafe(no_mangle)] +extern "C" fn wrapped_f64(x: Wrapper) -> Wrapper { + x +} + +// CHECK-LABEL: define noundef fp128 @plain_f128( +#[unsafe(no_mangle)] +extern "C" fn plain_f128(x: f128) -> f128 { + x +} + +// CHECK-LABEL: define void @wrapped_f128(ptr {{.*}}sret([16 x i8]) +#[unsafe(no_mangle)] +extern "C" fn wrapped_f128(x: Wrapper) -> Wrapper { + x +} + +#[repr(transparent)] +struct Transparent(T); + +// CHECK-LABEL: define float @transparent_wrapped_f32( +#[unsafe(no_mangle)] +extern "C" fn transparent_wrapped_f32(x: Transparent>) -> Transparent> { + x +} + +// CHECK-LABEL: define float @transparent_transparent_wrapped_f32( +#[unsafe(no_mangle)] +extern "C" fn transparent_transparent_wrapped_f32( + x: Transparent>>, +) -> Transparent>> { + x +} + +#[repr(align(4))] +struct Empty {} + +#[repr(C)] +struct Struct { + f: f32, + a: [i32; 0], + b: Empty, +} + +// One or more aligned ZSTs are fine and do not disqualify the type. +// CHECK-LABEL: define float @aligned_zst_f32( +#[unsafe(no_mangle)] +extern "C" fn aligned_zst_f32(x: Struct) -> Struct { + x +} + +#[repr(C, align(8))] +struct AlignedWrapper(T); + +// Over-aligning disqualifies the type. +// +// CHECK-LABEL: define i64 @aligned_wrapped_f16( +#[unsafe(no_mangle)] +extern "C" fn aligned_wrapped_f16(x: AlignedWrapper) -> AlignedWrapper { + x +} + +// Over-aligning disqualifies the type. +// +// CHECK-LABEL: define i64 @aligned_wrapped_f32( +#[unsafe(no_mangle)] +extern "C" fn aligned_wrapped_f32(x: AlignedWrapper) -> AlignedWrapper { + x +} + +#[repr(C)] +union UnionWrapper { + a: T, +} + +// A repr(C) union does count. +// +// CHECK-LABEL: define float @union_wrapped_f32( +#[unsafe(no_mangle)] +extern "C" fn union_wrapped_f32(x: UnionWrapper) -> UnionWrapper { + x +} + +// A repr(transparent) union does too. +// +// CHECK-LABEL: define float @maybe_uninit_f32( +#[unsafe(no_mangle)] +extern "C" fn maybe_uninit_f32(x: MaybeUninit) -> MaybeUninit { + x +} + +// A single-element array also does count. +// +// CHECK-LABEL: define float @array_f32( +#[unsafe(no_mangle)] +extern "C" fn array_f32(x: [f32; 1]) -> [f32; 1] { + x +} diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 6071ad9bb435b..e2496726f4b3f 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -4,12 +4,24 @@ //@ revisions: i686 //@[i686] compile-flags: --target i686-unknown-linux-gnu //@[i686] needs-llvm-components: x86 +//@ revisions: i686-reg-struct-return +//@[i686-reg-struct-return] compile-flags: --target i686-unknown-linux-gnu -Zreg-struct-return=true +//@[i686-reg-struct-return] needs-llvm-components: x86 +//@ revisions: i686-win +//@[i686-win] compile-flags: --target i686-pc-windows-msvc +//@[i686-win] needs-llvm-components: x86 +//@ revisions: i686-win-gnu +//@[i686-win-gnu] compile-flags: --target i686-pc-windows-gnu +//@[i686-win-gnu] needs-llvm-components: x86 //@ revisions: x86-64 //@[x86-64] compile-flags: --target x86_64-unknown-linux-gnu //@[x86-64] needs-llvm-components: x86 //@ revisions: x86-64-win //@[x86-64-win] compile-flags: --target x86_64-pc-windows-msvc //@[x86-64-win] needs-llvm-components: x86 +//@ revisions: x86-64-win-gnu +//@[x86-64-win-gnu] compile-flags: --target x86_64-pc-windows-gnu +//@[x86-64-win-gnu] needs-llvm-components: x86 //@ revisions: arm //@[arm] compile-flags: --target arm-unknown-linux-gnueabi //@[arm] needs-llvm-components: arm @@ -19,6 +31,9 @@ //@ revisions: aarch64 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu //@[aarch64] needs-llvm-components: aarch64 +//@ revisions: aarch64-win +//@[aarch64-win] compile-flags: --target aarch64-pc-windows-msvc +//@[aarch64-win] needs-llvm-components: aarch64 //@ revisions: s390x //@[s390x] compile-flags: --target s390x-unknown-linux-gnu //@[s390x] needs-llvm-components: systemz @@ -171,6 +186,11 @@ enum Either2 { Right(U, ()), } +#[repr(C)] +struct ReprC(T); +#[repr(C)] +struct ReprC2(T, U); + #[repr(C)] enum ReprCEnum { Variant1, @@ -240,16 +260,20 @@ macro_rules! test_transparent { } test_transparent!(simple, i32); +test_transparent!(float, f32); test_transparent!(reference, &'static i32); test_transparent!(zst, Zst); test_transparent!(unit, ()); test_transparent!(enum_, Option); test_transparent!(enum_niched, Option<&'static i32>); #[cfg(not(any(target_arch = "mips64")))] -mod tuples { +mod structs_and_tuples { use super::*; + test_transparent!(float_struct, ReprC); // mixing in some floats since they often get special treatment test_transparent!(pair, (i32, f32)); + // a homogeneous repr(C) struct + test_transparent!(c_pair, ReprC2); // chosen to fit into 64bit test_transparent!(triple, (i8, i16, f32)); // Pure-float types that are not ScalarPair seem to be tricky. diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs index 069bf56004461..9646e45c55cdb 100644 --- a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs @@ -13,7 +13,7 @@ fn foo<'a, I : for<'x> Foo<&'x isize>>( let y: I::A = x; } -fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( +fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( //~ ERROR one or more lifetime errors x: >::A, y: >::A, cond: bool) diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr index 42d83fca6ca83..15567a9143a18 100644 --- a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr @@ -24,7 +24,13 @@ LL | let z: I::A = if cond { x } else { y }; | = help: consider adding the following bound: `'a: 'b` -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:16:4 + | +LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( + | ^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr b/tests/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr index 2ecee1341abd3..1cfdde9ff1057 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr +++ b/tests/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-contravariant.rs:46:4 + --> $DIR/project-fn-ret-contravariant.rs:47:4 | LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { | -- -- lifetime `'b` defined here @@ -12,7 +12,7 @@ LL | (a, b) = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/project-fn-ret-contravariant.rs:46:4 + --> $DIR/project-fn-ret-contravariant.rs:47:4 | LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { | -- -- lifetime `'b` defined here @@ -24,7 +24,13 @@ LL | (a, b) | = help: consider adding the following bound: `'b: 'a` -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/project-fn-ret-contravariant.rs:43:4 + | +LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + | ^^^^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/associated-types/cache/project-fn-ret-contravariant.rs b/tests/ui/associated-types/cache/project-fn-ret-contravariant.rs index 6763155790086..44a03a9df639e 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-contravariant.rs +++ b/tests/ui/associated-types/cache/project-fn-ret-contravariant.rs @@ -41,6 +41,7 @@ fn baz<'a,'b>(x: &'a u32) -> &'static u32 { #[cfg(krisskross)] // two instantiations, mixing and matching: BAD fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + //[krisskross]~^ ERROR one or more lifetime errors let a = bar(foo, y); let b = bar(foo, x); (a, b) //[krisskross]~ ERROR lifetime may not live long enough diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr index ada12c7ee91d0..86189e9493247 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:59:5 + --> $DIR/project-fn-ret-invariant.rs:61:5 | LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here @@ -15,7 +15,7 @@ LL | (a, b) = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:59:5 + --> $DIR/project-fn-ret-invariant.rs:61:5 | LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here @@ -30,7 +30,13 @@ LL | (a, b) = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/project-fn-ret-invariant.rs:57:4 + | +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | ^^^^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr index 3ef6b85c407af..ad17002821d71 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr @@ -1,11 +1,11 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:40:13 + --> $DIR/project-fn-ret-invariant.rs:41:13 | LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let f = foo; // <-- No consistent type can be inferred for `f` here. +... LL | let a = bar(f, x); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | @@ -15,7 +15,7 @@ LL | let a = bar(f, x); = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:42:13 + --> $DIR/project-fn-ret-invariant.rs:43:13 | LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here @@ -30,7 +30,13 @@ LL | let b = bar(f, y); = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/project-fn-ret-invariant.rs:38:4 + | +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | ^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.rs b/tests/ui/associated-types/cache/project-fn-ret-invariant.rs index 4ac642c0e04b5..b1883f45b16f5 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -36,6 +36,7 @@ fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { #[cfg(oneuse)] // one instantiation: BAD fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + //[oneuse]~^ ERROR one or more lifetime errors let f = foo; // <-- No consistent type can be inferred for `f` here. let a = bar(f, x); //[oneuse]~^ ERROR lifetime may not live long enough @@ -54,6 +55,7 @@ fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { #[cfg(krisskross)] // two instantiations, mixing and matching: BAD fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + //[krisskross]~^ ERROR one or more lifetime errors let a = bar(foo, y); let b = bar(foo, x); (a, b) diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index b8100f6dfaec0..547bde2e5a0a9 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/project-fn-ret-invariant.rs:52:5 + --> $DIR/project-fn-ret-invariant.rs:53:5 | LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { | -- lifetime `'a` defined here diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs index ce94ba657b86f..71fca8858c78b 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs @@ -3,7 +3,7 @@ trait Trait<'a> {} -fn change_lt<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> { +fn change_lt<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> { //~ ERROR one or more x as _ //~ error: lifetime may not live long enough //~| error: lifetime may not live long enough } @@ -26,14 +26,14 @@ trait Assocked { type Assoc: ?Sized; } -fn change_assoc_0<'a, 'b>( +fn change_assoc_0<'a, 'b>( //~ ERROR one or more lifetime errors x: *mut dyn Assocked, ) -> *mut dyn Assocked { x as _ //~ error: lifetime may not live long enough //~| error: lifetime may not live long enough } -fn change_assoc_1<'a, 'b>( +fn change_assoc_1<'a, 'b>( //~ ERROR one or more lifetime errors x: *mut dyn Assocked>, ) -> *mut dyn Assocked> { x as _ //~ error: lifetime may not live long enough diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr index f2c060e4b279b..74a92f459aa62 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr @@ -42,7 +42,13 @@ LL | x as _ = note: this was previously accepted by the compiler but was changed recently = help: see for more information -help: `'b` and `'a` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:6:4 + | +LL | fn change_lt<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> { + | ^^^^^^^^^ + | + = help: `'b` and `'a` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:12:5 @@ -156,9 +162,13 @@ LL | x as _ = note: this was previously accepted by the compiler but was changed recently = help: see for more information -help: `'b` and `'a` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:29:4 | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +LL | fn change_assoc_0<'a, 'b>( + | ^^^^^^^^^^^^^^ + | + = help: `'b` and `'a` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:39:5 @@ -206,9 +216,13 @@ LL | x as _ = note: this was previously accepted by the compiler but was changed recently = help: see for more information -help: `'b` and `'a` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:36:4 + | +LL | fn change_assoc_1<'a, 'b>( + | ^^^^^^^^^^^^^^ | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = help: `'b` and `'a` must be the same: replace one with the other error[E0521]: borrowed data escapes outside of function --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:46:5 @@ -233,7 +247,7 @@ LL | require_static(ptr as _) = note: this was previously accepted by the compiler but was changed recently = help: see for more information -error: aborting due to 11 previous errors +error: aborting due to 14 previous errors Some errors have detailed explanations: E0308, E0521. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 0d9aad0e4a193..13c49fe00ef1f 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -479,6 +479,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `zksed` `zksh` `zkt` +`zmmul` `zreg` `ztso` `zvbb` diff --git a/tests/ui/derives/auxiliary/generated-enum-derive.rs b/tests/ui/derives/auxiliary/generated-enum-derive.rs new file mode 100644 index 0000000000000..cdc601dc9fb77 --- /dev/null +++ b/tests/ui/derives/auxiliary/generated-enum-derive.rs @@ -0,0 +1,23 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; + +// Like a compile-time generator, emit a macro whose output uses the attribute's call site. +#[proc_macro_attribute] +pub fn generator(_: TokenStream, _: TokenStream) -> TokenStream { + "macro_rules! gen_enums_from_list { + ([\"X\"]) => { enum Position1 { X } }; + }" + .parse() + .unwrap() +} + +#[proc_macro] +pub fn generated_enum(_: TokenStream) -> TokenStream { + "enum Generated { X }".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn passthrough(_: TokenStream, item: TokenStream) -> TokenStream { + item +} diff --git a/tests/ui/derives/generated-derive-suggestion-issue-148207.generated.stderr b/tests/ui/derives/generated-derive-suggestion-issue-148207.generated.stderr new file mode 100644 index 0000000000000..db4ca4fda9fb2 --- /dev/null +++ b/tests/ui/derives/generated-derive-suggestion-issue-148207.generated.stderr @@ -0,0 +1,38 @@ +error[E0277]: `Position1` doesn't implement `Debug` + --> $DIR/generated-derive-suggestion-issue-148207.rs:33:26 + | +LL | println!("{:?}", p1); + | ---- ^^ `Position1` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter + | +help: the trait `Debug` is not implemented for `Position1` + --> $DIR/generated-derive-suggestion-issue-148207.rs:13:1 + | +LL | #[generated_enum_derive::generator] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | gen_enums_from_list!(["X"]); + | --------------------------- in this macro invocation + = note: add `#[derive(Debug)]` to `Position1` or manually `impl Debug for Position1` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `gen_enums_from_list` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `Generated` doesn't implement `Debug` + --> $DIR/generated-derive-suggestion-issue-148207.rs:35:26 + | +LL | println!("{:?}", Generated::X); + | ---- ^^^^^^^^^^^^ `Generated` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter + | +help: the trait `Debug` is not implemented for `Generated` + --> $DIR/generated-derive-suggestion-issue-148207.rs:20:1 + | +LL | generated_enum_derive::generated_enum!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: add `#[derive(Debug)]` to `Generated` or manually `impl Debug for Generated` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `generated_enum_derive::generated_enum` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/generated-derive-suggestion-issue-148207.rs b/tests/ui/derives/generated-derive-suggestion-issue-148207.rs new file mode 100644 index 0000000000000..d3ba4d7c907f2 --- /dev/null +++ b/tests/ui/derives/generated-derive-suggestion-issue-148207.rs @@ -0,0 +1,45 @@ +//@ revisions: source generated +//@ [source] run-rustfix +//@ proc-macro: generated-enum-derive.rs + +//! Regression test for https://github.com/rust-lang/rust/issues/148207. +//! Derive suggestions must target a source ADT, not its code generator. + +#![allow(dead_code)] + +extern crate generated_enum_derive; + +#[cfg(generated)] +#[generated_enum_derive::generator] +fn gen_enums_from_list() {} + +#[cfg(generated)] +gen_enums_from_list!(["X"]); + +#[cfg(generated)] +generated_enum_derive::generated_enum!(); + +#[cfg(source)] +enum Source { X } + +#[cfg(source)] +#[generated_enum_derive::passthrough] +enum Forwarded { X } + +fn main() { + #[cfg(generated)] + { + let p1 = Position1::X; + println!("{:?}", p1); + //[generated]~^ ERROR `Position1` doesn't implement `Debug` + println!("{:?}", Generated::X); + //[generated]~^ ERROR `Generated` doesn't implement `Debug` + } + #[cfg(source)] + { + println!("{:?}", Source::X); + //[source]~^ ERROR `Source` doesn't implement `Debug` + println!("{:?}", Forwarded::X); + //[source]~^ ERROR `Forwarded` doesn't implement `Debug` + } +} diff --git a/tests/ui/derives/generated-derive-suggestion-issue-148207.source.fixed b/tests/ui/derives/generated-derive-suggestion-issue-148207.source.fixed new file mode 100644 index 0000000000000..da54b5f592371 --- /dev/null +++ b/tests/ui/derives/generated-derive-suggestion-issue-148207.source.fixed @@ -0,0 +1,47 @@ +//@ revisions: source generated +//@ [source] run-rustfix +//@ proc-macro: generated-enum-derive.rs + +//! Regression test for https://github.com/rust-lang/rust/issues/148207. +//! Derive suggestions must target a source ADT, not its code generator. + +#![allow(dead_code)] + +extern crate generated_enum_derive; + +#[cfg(generated)] +#[generated_enum_derive::generator] +fn gen_enums_from_list() {} + +#[cfg(generated)] +gen_enums_from_list!(["X"]); + +#[cfg(generated)] +generated_enum_derive::generated_enum!(); + +#[cfg(source)] +#[derive(Debug)] +enum Source { X } + +#[cfg(source)] +#[generated_enum_derive::passthrough] +#[derive(Debug)] +enum Forwarded { X } + +fn main() { + #[cfg(generated)] + { + let p1 = Position1::X; + println!("{:?}", p1); + //[generated]~^ ERROR `Position1` doesn't implement `Debug` + println!("{:?}", Generated::X); + //[generated]~^ ERROR `Generated` doesn't implement `Debug` + } + #[cfg(source)] + { + println!("{:?}", Source::X); + //[source]~^ ERROR `Source` doesn't implement `Debug` + println!("{:?}", Forwarded::X); + //[source]~^ ERROR `Forwarded` doesn't implement `Debug` + } +} diff --git a/tests/ui/derives/generated-derive-suggestion-issue-148207.source.stderr b/tests/ui/derives/generated-derive-suggestion-issue-148207.source.stderr new file mode 100644 index 0000000000000..15b2dac2251fb --- /dev/null +++ b/tests/ui/derives/generated-derive-suggestion-issue-148207.source.stderr @@ -0,0 +1,33 @@ +error[E0277]: `Source` doesn't implement `Debug` + --> $DIR/generated-derive-suggestion-issue-148207.rs:40:26 + | +LL | println!("{:?}", Source::X); + | ---- ^^^^^^^^^ `Source` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter + | + = help: the trait `Debug` is not implemented for `Source` +help: consider annotating `Source` with `#[derive(Debug)]` + | +LL + #[derive(Debug)] +LL | enum Source { X } + | + +error[E0277]: `Forwarded` doesn't implement `Debug` + --> $DIR/generated-derive-suggestion-issue-148207.rs:42:26 + | +LL | println!("{:?}", Forwarded::X); + | ---- ^^^^^^^^^^^^ `Forwarded` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter + | + = help: the trait `Debug` is not implemented for `Forwarded` +help: consider annotating `Forwarded` with `#[derive(Debug)]` + | +LL + #[derive(Debug)] +LL | enum Forwarded { X } + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/field_representing_types/invariant.next.stderr b/tests/ui/field_representing_types/invariant.next.stderr index 6a622a8e5dd11..c9e0b03040d85 100644 --- a/tests/ui/field_representing_types/invariant.next.stderr +++ b/tests/ui/field_representing_types/invariant.next.stderr @@ -1,10 +1,11 @@ error: lifetime may not live long enough - --> $DIR/invariant.rs:15:5 + --> $DIR/invariant.rs:16:5 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here +LL | LL | consume(x, y); | ^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` | @@ -14,12 +15,13 @@ LL | consume(x, y); = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/invariant.rs:15:5 + --> $DIR/invariant.rs:16:5 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here +LL | LL | consume(x, y); | ^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | @@ -28,7 +30,13 @@ LL | consume(x, y); = note: the struct `FieldRepresentingType` is invariant over the parameter `T` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/invariant.rs:14:4 + | +LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { + | ^^^^^^^^^^^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/field_representing_types/invariant.old.stderr b/tests/ui/field_representing_types/invariant.old.stderr index 6a622a8e5dd11..c9e0b03040d85 100644 --- a/tests/ui/field_representing_types/invariant.old.stderr +++ b/tests/ui/field_representing_types/invariant.old.stderr @@ -1,10 +1,11 @@ error: lifetime may not live long enough - --> $DIR/invariant.rs:15:5 + --> $DIR/invariant.rs:16:5 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here +LL | LL | consume(x, y); | ^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` | @@ -14,12 +15,13 @@ LL | consume(x, y); = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/invariant.rs:15:5 + --> $DIR/invariant.rs:16:5 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here +LL | LL | consume(x, y); | ^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | @@ -28,7 +30,13 @@ LL | consume(x, y); = note: the struct `FieldRepresentingType` is invariant over the parameter `T` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/invariant.rs:14:4 + | +LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { + | ^^^^^^^^^^^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/field_representing_types/invariant.rs b/tests/ui/field_representing_types/invariant.rs index 16a45e63c79c5..b9b42b2f29105 100644 --- a/tests/ui/field_representing_types/invariant.rs +++ b/tests/ui/field_representing_types/invariant.rs @@ -12,6 +12,7 @@ pub struct Struct<'a> { fn consume<'a>(_: field_of!(Struct<'a>, field), _: field_of!(Struct<'a>, field)) {} fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { + //~^ ERROR one or more lifetime errors consume(x, y); //~^ ERROR: lifetime may not live long enough //~^^ ERROR: lifetime may not live long enough diff --git a/tests/ui/fn/fn_def_coercion.rs b/tests/ui/fn/fn_def_coercion.rs index 31c8fa41de17c..40a3d6aa9722b 100644 --- a/tests/ui/fn/fn_def_coercion.rs +++ b/tests/ui/fn/fn_def_coercion.rs @@ -6,7 +6,7 @@ fn foo(t: T) -> T { t } -fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { +fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { //~ ERROR one or more let mut x = foo::<&'a ()>; //~ ERROR: lifetime may not live long enough x = foo::<&'b ()>; //~ ERROR: lifetime may not live long enough x = foo::<&'c ()>; @@ -25,7 +25,7 @@ fn h<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { let _: &'a () = x(c); } -fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { +fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { //~ ERROR one or more let mut x = foo::<&'c ()>; x = foo::<&'b ()>; //~ ERROR lifetime may not live long enough x = foo::<&'a ()>; //~ ERROR lifetime may not live long enough @@ -34,7 +34,7 @@ fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { x(c); } -fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { +fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { //~ ERROR one or more let x = match true { true => foo::<&'b ()>, //~ ERROR lifetime may not live long enough false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough diff --git a/tests/ui/fn/fn_def_coercion.stderr b/tests/ui/fn/fn_def_coercion.stderr index 85e234c839341..3428a118b51a2 100644 --- a/tests/ui/fn/fn_def_coercion.stderr +++ b/tests/ui/fn/fn_def_coercion.stderr @@ -29,7 +29,13 @@ LL | x = foo::<&'b ()>; = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/fn_def_coercion.rs:9:4 + | +LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | ^ + | + = help: `'a` and `'b` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/fn_def_coercion.rs:20:12 @@ -76,9 +82,13 @@ LL | x = foo::<&'a ()>; = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/fn_def_coercion.rs:28:4 + | +LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | ^ | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = help: `'a` and `'b` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/fn_def_coercion.rs:39:17 @@ -112,9 +122,13 @@ LL | false => foo::<&'a ()>, = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/fn_def_coercion.rs:37:4 | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | ^ + | + = help: `'a` and `'b` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/fn_def_coercion.rs:49:17 @@ -148,10 +162,5 @@ LL | false => foo::<&'a ()>, = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance -help: the following changes may resolve your lifetime errors - | - = help: add bound `'a: 'c` - = help: add bound `'b: 'a` - -error: aborting due to 9 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs index 91c52817d8573..7d17a3a936ae5 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs @@ -9,7 +9,7 @@ trait TraitLt<'a: 'a> { fn hello() -> impl Sized + use; //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list } -fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { +fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { //~ ERROR one or more lifetime errors eq_types( //~^ ERROR lifetime may not live long enough //~| ERROR lifetime may not live long enough diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index ff461e81079b8..f294a2d34e355 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -40,7 +40,13 @@ LL | | ); | = help: consider adding the following bound: `'b: 'a` -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/rpitit.rs:12:4 + | +LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + | ^^^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.borrowck_current.stderr b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck_current.stderr index 008de7a7afc63..1401cd89f28d8 100644 --- a/tests/ui/implied-bounds/normalization-preserve-equality.borrowck_current.stderr +++ b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck_current.stderr @@ -22,7 +22,13 @@ LL | fn test_borrowck<'a, 'b>(_: ( as Trait>::Ty, Equal<'a, 'b>)) | = help: consider adding the following bound: `'b: 'a` -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/normalization-preserve-equality.rs:34:4 + | +LL | fn test_borrowck<'a, 'b>(_: ( as Trait>::Ty, Equal<'a, 'b>)) { + | ^^^^^^^^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/lub-glb/empty-binders-err.stderr b/tests/ui/lub-glb/empty-binders-err.stderr index f86f22d5e40bf..68b62c87e85b9 100644 --- a/tests/ui/lub-glb/empty-binders-err.stderr +++ b/tests/ui/lub-glb/empty-binders-err.stderr @@ -24,11 +24,6 @@ LL | let _: &'upper () = match v { | = help: consider adding the following bound: `'b: 'upper` -help: the following changes may resolve your lifetime errors - | - = help: add bound `'a: 'upper` - = help: add bound `'b: 'upper` - error: lifetime may not live long enough --> $DIR/empty-binders-err.rs:35:12 | diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.stderr index af7ea253cc52a..38c1d9c5efc9a 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.stderr @@ -70,10 +70,5 @@ LL | | ); = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance -help: the following changes may resolve your lifetime errors - | - = help: add bound `'a: 'c` - = help: add bound `'b: 'c` - error: aborting due to 2 previous errors diff --git a/tests/ui/nll/outlives-suggestion-more.rs b/tests/ui/nll/outlives-suggestion-more.rs index 2e1359fe5d496..2f49ad6b85d35 100644 --- a/tests/ui/nll/outlives-suggestion-more.rs +++ b/tests/ui/nll/outlives-suggestion-more.rs @@ -7,13 +7,13 @@ fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usize) { } // Should suggest: 'a: 'c and use 'static instead of 'b -fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) { +fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) { //~ ERROR one or (x, y) //~ERROR lifetime may not live long enough //~^ERROR lifetime may not live long enough } // Should suggest: 'a and 'b are the same and use 'static instead of 'c -fn foo3<'a, 'b, 'c, 'd, 'e>( +fn foo3<'a, 'b, 'c, 'd, 'e>( //~ ERROR one or more lifetime errors x: &'a usize, y: &'b usize, z: &'c usize, diff --git a/tests/ui/nll/outlives-suggestion-more.stderr b/tests/ui/nll/outlives-suggestion-more.stderr index c8c604b5b4c78..0b79395113bf1 100644 --- a/tests/ui/nll/outlives-suggestion-more.stderr +++ b/tests/ui/nll/outlives-suggestion-more.stderr @@ -22,11 +22,6 @@ LL | (x, y) | = help: consider adding the following bound: `'b: 'd` -help: the following changes may resolve your lifetime errors - | - = help: add bound `'a: 'c` - = help: add bound `'b: 'd` - error: lifetime may not live long enough --> $DIR/outlives-suggestion-more.rs:11:5 | @@ -47,9 +42,12 @@ LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usi LL | (x, y) | ^^^^^^ returning this value requires that `'b` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/outlives-suggestion-more.rs:10:4 + | +LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) { + | ^^^^ | - = help: add bound `'a: 'c` = help: replace `'b` with `'static` error: lifetime may not live long enough @@ -87,10 +85,14 @@ LL | fn foo3<'a, 'b, 'c, 'd, 'e>( LL | (x, y, z) | ^^^^^^^^^ returning this value requires that `'c` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/outlives-suggestion-more.rs:16:4 + | +LL | fn foo3<'a, 'b, 'c, 'd, 'e>( + | ^^^^ | = help: `'a` and `'b` must be the same: replace one with the other = help: replace `'c` with `'static` -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/nll/outlives-suggestion-simple.rs b/tests/ui/nll/outlives-suggestion-simple.rs index 2a5c31e3a6468..81d8d3dba9933 100644 --- a/tests/ui/nll/outlives-suggestion-simple.rs +++ b/tests/ui/nll/outlives-suggestion-simple.rs @@ -8,7 +8,7 @@ fn foo2<'a>(x: &'a usize) -> &'static usize { x //~ERROR lifetime may not live long enough } -fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { +fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { //~ ERROR one or more (x, y) //~ERROR lifetime may not live long enough //~^ERROR lifetime may not live long enough } diff --git a/tests/ui/nll/outlives-suggestion-simple.stderr b/tests/ui/nll/outlives-suggestion-simple.stderr index 669532005b292..36e4d8b43c6d6 100644 --- a/tests/ui/nll/outlives-suggestion-simple.stderr +++ b/tests/ui/nll/outlives-suggestion-simple.stderr @@ -42,7 +42,13 @@ LL | (x, y) | = help: consider adding the following bound: `'b: 'a` -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/outlives-suggestion-simple.rs:11:4 + | +LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { + | ^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/outlives-suggestion-simple.rs:20:5 @@ -104,5 +110,5 @@ LL | Bar2::new(&self) = note: the struct `Foo2<'a>` is invariant over the parameter `'a` = help: see for more information about variance -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr b/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr index 5756148f4eb2a..6283042e16f33 100644 --- a/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr +++ b/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr @@ -1,11 +1,11 @@ error: lifetime may not live long enough - --> $DIR/flow-sensitive-invariance.rs:20:17 + --> $DIR/flow-sensitive-invariance.rs:22:17 | LL | fn use_it<'a, 'b>(choice: bool) -> Result, Invariant<'b>> { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let returned_value = create_invariant(); +... LL | if choice { Ok(returned_value) } else { Err(returned_value) } | ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | @@ -15,13 +15,13 @@ LL | if choice { Ok(returned_value) } else { Err(returned_value) } = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/flow-sensitive-invariance.rs:20:45 + --> $DIR/flow-sensitive-invariance.rs:22:45 | LL | fn use_it<'a, 'b>(choice: bool) -> Result, Invariant<'b>> { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let returned_value = create_invariant(); +... LL | if choice { Ok(returned_value) } else { Err(returned_value) } | ^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | @@ -30,7 +30,13 @@ LL | if choice { Ok(returned_value) } else { Err(returned_value) } = note: the struct `Invariant<'l>` is invariant over the parameter `'l` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/flow-sensitive-invariance.rs:18:4 + | +LL | fn use_it<'a, 'b>(choice: bool) -> Result, Invariant<'b>> { + | ^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr b/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr index 5756148f4eb2a..6283042e16f33 100644 --- a/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr +++ b/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr @@ -1,11 +1,11 @@ error: lifetime may not live long enough - --> $DIR/flow-sensitive-invariance.rs:20:17 + --> $DIR/flow-sensitive-invariance.rs:22:17 | LL | fn use_it<'a, 'b>(choice: bool) -> Result, Invariant<'b>> { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let returned_value = create_invariant(); +... LL | if choice { Ok(returned_value) } else { Err(returned_value) } | ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | @@ -15,13 +15,13 @@ LL | if choice { Ok(returned_value) } else { Err(returned_value) } = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/flow-sensitive-invariance.rs:20:45 + --> $DIR/flow-sensitive-invariance.rs:22:45 | LL | fn use_it<'a, 'b>(choice: bool) -> Result, Invariant<'b>> { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let returned_value = create_invariant(); +... LL | if choice { Ok(returned_value) } else { Err(returned_value) } | ^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | @@ -30,7 +30,13 @@ LL | if choice { Ok(returned_value) } else { Err(returned_value) } = note: the struct `Invariant<'l>` is invariant over the parameter `'l` = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/flow-sensitive-invariance.rs:18:4 + | +LL | fn use_it<'a, 'b>(choice: bool) -> Result, Invariant<'b>> { + | ^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.rs b/tests/ui/nll/polonius/flow-sensitive-invariance.rs index c5571f131da3b..cb7cb51189d18 100644 --- a/tests/ui/nll/polonius/flow-sensitive-invariance.rs +++ b/tests/ui/nll/polonius/flow-sensitive-invariance.rs @@ -16,6 +16,8 @@ fn create_invariant<'l>() -> Invariant<'l> { } fn use_it<'a, 'b>(choice: bool) -> Result, Invariant<'b>> { + //[nll]~^ ERROR one or more lifetime errors + //[polonius]~^^ ERROR one or more lifetime errors let returned_value = create_invariant(); if choice { Ok(returned_value) } else { Err(returned_value) } //[nll]~^ ERROR lifetime may not live long enough diff --git a/tests/ui/nll/type-check-pointer-coercions.rs b/tests/ui/nll/type-check-pointer-coercions.rs index 66da57248f98f..6eceebeda39ac 100644 --- a/tests/ui/nll/type-check-pointer-coercions.rs +++ b/tests/ui/nll/type-check-pointer-coercions.rs @@ -6,7 +6,7 @@ fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 { x //~ ERROR } -fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { +fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { //~ ERROR one or more lifetime errors // Two errors because *mut is invariant x //~ ERROR //~| ERROR diff --git a/tests/ui/nll/type-check-pointer-coercions.stderr b/tests/ui/nll/type-check-pointer-coercions.stderr index ef2d928786fca..042bbb456f2ef 100644 --- a/tests/ui/nll/type-check-pointer-coercions.stderr +++ b/tests/ui/nll/type-check-pointer-coercions.stderr @@ -54,7 +54,13 @@ LL | x = note: mutable pointers are invariant over their type parameter = help: see for more information about variance -help: `'b` and `'a` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/type-check-pointer-coercions.rs:9:4 + | +LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { + | ^^^^^^^^^^^^^ + | + = help: `'b` and `'a` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/type-check-pointer-coercions.rs:16:5 @@ -107,5 +113,5 @@ LL | y | = help: consider adding the following bound: `'a: 'b` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/nll/type-check-pointer-comparisons.rs b/tests/ui/nll/type-check-pointer-comparisons.rs index 7b0ffeaef0e21..da417688baa80 100644 --- a/tests/ui/nll/type-check-pointer-comparisons.rs +++ b/tests/ui/nll/type-check-pointer-comparisons.rs @@ -1,18 +1,18 @@ // Check that we assert that pointers have a common subtype for comparisons -fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { +fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { //~ ERROR one or more x == y; //~^ ERROR lifetime may not live long enough //~| ERROR lifetime may not live long enough } -fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { +fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { //~ ERROR one or more x == y; //~^ ERROR lifetime may not live long enough //~| ERROR lifetime may not live long enough } -fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) { +fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) { //~ ERROR one or f == g; //~^ ERROR lifetime may not live long enough //~| ERROR lifetime may not live long enough diff --git a/tests/ui/nll/type-check-pointer-comparisons.stderr b/tests/ui/nll/type-check-pointer-comparisons.stderr index e362dfb3c6e7a..50ed9bc3cd3fa 100644 --- a/tests/ui/nll/type-check-pointer-comparisons.stderr +++ b/tests/ui/nll/type-check-pointer-comparisons.stderr @@ -28,7 +28,13 @@ LL | x == y; = note: mutable references are invariant over their type parameter = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/type-check-pointer-comparisons.rs:3:4 + | +LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { + | ^^^^^^^^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/type-check-pointer-comparisons.rs:10:5 @@ -60,9 +66,13 @@ LL | x == y; = note: mutable pointers are invariant over their type parameter = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/type-check-pointer-comparisons.rs:9:4 | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { + | ^^^^^^^^^^^ + | + = help: `'a` and `'b` must be the same: replace one with the other error: lifetime may not live long enough --> $DIR/type-check-pointer-comparisons.rs:16:5 @@ -94,9 +104,13 @@ LL | f == g; = note: mutable references are invariant over their type parameter = help: see for more information about variance -help: `'a` and `'b` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/type-check-pointer-comparisons.rs:15:4 + | +LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) { + | ^^^^^^^^^^^^^^ | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 6 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/nll/user-annotations/normalization-2.rs b/tests/ui/nll/user-annotations/normalization-2.rs index dddba2265c613..63ac7a7a2c02c 100644 --- a/tests/ui/nll/user-annotations/normalization-2.rs +++ b/tests/ui/nll/user-annotations/normalization-2.rs @@ -44,14 +44,14 @@ fn test_local<'a>() { //~^ ERROR lifetime may not live long enough } -fn test_closure_sig<'a, 'b>() { +fn test_closure_sig<'a, 'b>() { //~ ERROR one or more lifetime errors were found |_: Ty<'a>| {}; //~^ ERROR lifetime may not live long enough || -> Option> { None }; //~^ ERROR lifetime may not live long enough } -fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { +fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { //~ ERROR one or more lifetime errors were found >::method::>; //~^ ERROR lifetime may not live long enough >::method::>; @@ -78,14 +78,14 @@ fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { //~^ ERROR lifetime may not live long enough } -fn test_call<'a, 'b, 'c>() { +fn test_call<'a, 'b, 'c>() { //~ ERROR one or more lifetime errors were found >::method::>(); //~^ ERROR lifetime may not live long enough >::method::>(); //~^ ERROR lifetime may not live long enough } -fn test_variants<'a, 'b, 'c>() { +fn test_variants<'a, 'b, 'c>() { //~ ERROR one or more lifetime errors were found >::Struct {}; //~^ ERROR lifetime may not live long enough >::Tuple(); @@ -94,14 +94,14 @@ fn test_variants<'a, 'b, 'c>() { //~^ ERROR lifetime may not live long enough } -fn test_method_call<'a, 'b>(x: MyTy<()>) { +fn test_method_call<'a, 'b>(x: MyTy<()>) { //~ ERROR one or more lifetime errors were found x.method2::>(); //~^ ERROR lifetime may not live long enough x.trait_method::>(); //~^ ERROR lifetime may not live long enough } -fn test_struct_path<'a, 'b, 'c, 'd>() { +fn test_struct_path<'a, 'b, 'c, 'd>() { //~ ERROR one or more lifetime errors were found struct Struct { x: Option, } trait Project { @@ -126,7 +126,7 @@ fn test_struct_path<'a, 'b, 'c, 'd>() { //~^ ERROR lifetime may not live long enough } -fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { +fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { //~ ERROR one or more lifetime errors were found use MyTy::*; match MyTy::Unit { Struct::> {..} => {}, diff --git a/tests/ui/nll/user-annotations/normalization-2.stderr b/tests/ui/nll/user-annotations/normalization-2.stderr index dcf049a7a61a0..d8e679cc29137 100644 --- a/tests/ui/nll/user-annotations/normalization-2.stderr +++ b/tests/ui/nll/user-annotations/normalization-2.stderr @@ -23,7 +23,11 @@ LL | fn test_closure_sig<'a, 'b>() { LL | || -> Option> { None }; | ^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/normalization-2.rs:47:4 + | +LL | fn test_closure_sig<'a, 'b>() { + | ^^^^^^^^^^^^^^^^ | = help: replace `'a` with `'static` = help: replace `'b` with `'static` @@ -99,7 +103,11 @@ LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { LL | MyTy::>::Unit; | ^^^^^^^^^^^^^^^^^^^^ requires that `'h` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/normalization-2.rs:54:4 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | ^^^^^^^^^ | = help: replace `'a` with `'static` = help: replace `'b` with `'static` @@ -127,11 +135,14 @@ LL | fn test_call<'a, 'b, 'c>() { LL | >::method::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/normalization-2.rs:81:4 + | +LL | fn test_call<'a, 'b, 'c>() { + | ^^^^^^^^^ | = help: replace `'a` with `'static` = help: replace `'b` with `'static` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough --> $DIR/normalization-2.rs:89:5 @@ -159,7 +170,11 @@ LL | fn test_variants<'a, 'b, 'c>() { LL | >::Unit; | ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/normalization-2.rs:88:4 + | +LL | fn test_variants<'a, 'b, 'c>() { + | ^^^^^^^^^^^^^ | = help: replace `'a` with `'static` = help: replace `'b` with `'static` @@ -182,11 +197,14 @@ LL | fn test_method_call<'a, 'b>(x: MyTy<()>) { LL | x.trait_method::>(); | ^^^^^^^^^^^^ requires that `'b` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/normalization-2.rs:97:4 + | +LL | fn test_method_call<'a, 'b>(x: MyTy<()>) { + | ^^^^^^^^^^^^^^^^ | = help: replace `'a` with `'static` = help: replace `'b` with `'static` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough --> $DIR/normalization-2.rs:117:5 @@ -224,7 +242,11 @@ LL | fn test_struct_path<'a, 'b, 'c, 'd>() { LL | as Project>::Struct { x: None, }; // with SelfTy | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/normalization-2.rs:104:4 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | ^^^^^^^^^^^^^^^^ | = help: replace `'a` with `'static` = help: replace `'b` with `'static` @@ -285,7 +307,11 @@ LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { LL | >::Unit => {}, | ^^^^^^^^^^^^^^ requires that `'f` must outlive `'static` -help: the following changes may resolve your lifetime errors +error: one or more lifetime errors were found in this item + --> $DIR/normalization-2.rs:129:4 + | +LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { + | ^^^^^^^^^^^^ | = help: replace `'a` with `'static` = help: replace `'b` with `'static` @@ -294,5 +320,5 @@ help: the following changes may resolve your lifetime errors = help: replace `'e` with `'static` = help: replace `'f` with `'static` -error: aborting due to 28 previous errors +error: aborting due to 35 previous errors diff --git a/tests/ui/regions/regions-infer-not-param.rs b/tests/ui/regions/regions-infer-not-param.rs index c3766bce18a2c..381163e565040 100644 --- a/tests/ui/regions/regions-infer-not-param.rs +++ b/tests/ui/regions/regions-infer-not-param.rs @@ -17,7 +17,7 @@ fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } fn take_indirect1(p: Indirect1) -> Indirect1 { p } -fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } +fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } //~ ERROR one or more lifetime //~^ ERROR lifetime may not live long enough //~| ERROR lifetime may not live long enough diff --git a/tests/ui/regions/regions-infer-not-param.stderr b/tests/ui/regions/regions-infer-not-param.stderr index d12f07a772880..74b2638c1c681 100644 --- a/tests/ui/regions/regions-infer-not-param.stderr +++ b/tests/ui/regions/regions-infer-not-param.stderr @@ -34,7 +34,13 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } = note: the struct `Indirect2<'a>` is invariant over the parameter `'a` = help: see for more information about variance -help: `'b` and `'a` must be the same: replace one with the other +error: one or more lifetime errors were found in this item + --> $DIR/regions-infer-not-param.rs:20:4 + | +LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } + | ^^^^^^^^^^^^^^ + | + = help: `'b` and `'a` must be the same: replace one with the other -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs b/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs index 23ffabad62fe8..148711b877ad5 100644 --- a/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs +++ b/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs @@ -1,11 +1,13 @@ -// Verifies that invalid user-defined CFI encodings can't be used. -// -//@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi +//! Checks for invalid uses of the `cfi_encoding` attribute -#![feature(cfi_encoding, no_core)] -#![no_core] -#![no_main] +#![feature(cfi_encoding)] +#![crate_type = "lib"] #[cfi_encoding] //~ ERROR malformed `cfi_encoding` attribute input pub struct Type1(i32); + +#[cfi_encoding = "Foo"] //~ ERROR the `cfi_encoding` attribute cannot be used on traits +pub trait X {} + +#[cfi_encoding = "Bar"] //~ ERROR the `cfi_encoding` attribute cannot be used on type aliases +pub type Y = Type1; diff --git a/tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr b/tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr index 620957e6e95d4..b1e8908cfee31 100644 --- a/tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr +++ b/tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr @@ -1,5 +1,5 @@ error[E0539]: malformed `cfi_encoding` attribute input - --> $DIR/invalid-attr-encoding.rs:10:3 + --> $DIR/invalid-attr-encoding.rs:6:3 | LL | #[cfi_encoding] | ^^^^^^^^^^^^ expected this to be of the form `cfi_encoding = "..."` @@ -9,6 +9,22 @@ help: must be of the form LL | #[cfi_encoding = "encoding"] | ++++++++++++ -error: aborting due to 1 previous error +error: the `cfi_encoding` attribute cannot be used on traits + --> $DIR/invalid-attr-encoding.rs:9:3 + | +LL | #[cfi_encoding = "Foo"] + | ^^^^^^^^^^^^ + | + = help: the `cfi_encoding` attribute can only be applied to data types + +error: the `cfi_encoding` attribute cannot be used on type aliases + --> $DIR/invalid-attr-encoding.rs:12:3 + | +LL | #[cfi_encoding = "Bar"] + | ^^^^^^^^^^^^ + | + = help: the `cfi_encoding` attribute can only be applied to data types + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0539`.