diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5d37bbd689fe0..1a166956075c7 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2733,6 +2733,13 @@ pub enum UseTreeKind { /// `use prefix` or `use prefix as rename` Simple(Option), /// `use prefix::{...}` + /// + /// The span represents the braces of the nested group and all elements within: + /// + /// ```text + /// use foo::{bar, baz}; + /// ^^^^^^^^^^ + /// ``` Nested { items: ThinVec<(UseTree, NodeId)>, span: Span }, /// `use prefix::*` Glob, diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 5fe68085d6537..180e7f6def3a3 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -299,13 +299,13 @@ fn calc_unused_spans( let mut unused_spans = Vec::new(); let mut to_remove = Vec::new(); - let mut used_childs = 0; + let mut used_children = 0; let mut contains_self = false; let mut previous_unused = false; for (pos, (use_tree, use_tree_id)) in nested.iter().enumerate() { let remove = match calc_unused_spans(unused_import, use_tree, *use_tree_id) { UnusedSpanResult::Used => { - used_childs += 1; + used_children += 1; None } UnusedSpanResult::Unused { mut spans, remove } => { @@ -313,7 +313,7 @@ fn calc_unused_spans( Some(remove) } UnusedSpanResult::PartialUnused { mut spans, remove: mut to_remove_extra } => { - used_childs += 1; + used_children += 1; unused_spans.append(&mut spans); to_remove.append(&mut to_remove_extra); None @@ -322,7 +322,7 @@ fn calc_unused_spans( if let Some(remove) = remove { let remove_span = if nested.len() == 1 { remove - } else if pos == nested.len() - 1 || used_childs > 0 { + } else if pos == nested.len() - 1 || used_children > 0 { // Delete everything from the end of the last import, to delete the // previous comma nested[pos - 1].0.span.shrink_to_hi().to(use_tree.span) @@ -346,7 +346,7 @@ fn calc_unused_spans( } if unused_spans.is_empty() { UnusedSpanResult::Used - } else if used_childs == 0 { + } else if used_children == 0 { UnusedSpanResult::Unused { spans: unused_spans, remove: full_span } } else { // If there is only one remaining child that is used, the braces around the use @@ -360,7 +360,7 @@ fn calc_unused_spans( // `self`: `use foo::{self};` is valid Rust syntax, while `use foo::self;` errors // out. We also cannot turn `use foo::{self}` into `use foo`, as the former doesn't // import types with the same name as the module. - if used_childs == 1 && !contains_self { + if used_children == 1 && !contains_self { // Left brace, from the start of the nested group to the first item. to_remove.push( tree_span.shrink_to_lo().to(nested.first().unwrap().0.span.shrink_to_lo()), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index d693bac90dc47..20dfb5e6642df 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -422,6 +422,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { let trait_predicate = bound_predicate.rebind(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate); + let trait_predicate = self.apply_do_not_recommend(trait_predicate, &mut obligation); // Let's use the root obligation as the main message, when we care about the // most general case ("X doesn't implement Pattern<'_>") over the case that @@ -1003,6 +1004,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.emit() } + fn apply_do_not_recommend( + &self, + mut trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + obligation: &'_ mut PredicateObligation<'tcx>, + ) -> ty::Binder<'tcx, ty::TraitPredicate<'tcx>> { + let mut base_cause = obligation.cause.code().clone(); + loop { + if let ObligationCauseCode::ImplDerived(ref c) = base_cause { + if self.tcx.has_attr(c.impl_or_alias_def_id, sym::do_not_recommend) { + let code = (*c.derived.parent_code).clone(); + obligation.cause.map_code(|_| code); + obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx); + trait_predicate = c.derived.parent_trait_pred.clone(); + } + } + if let Some((parent_cause, _parent_pred)) = base_cause.parent() { + base_cause = parent_cause.clone(); + } else { + break; + } + } + + trait_predicate + } + fn emit_specialized_closure_kind_error( &self, obligation: &PredicateObligation<'tcx>, diff --git a/library/core/src/fmt/nofloat.rs b/library/core/src/fmt/nofloat.rs index a36e7efcd95c7..6b07236f1da12 100644 --- a/library/core/src/fmt/nofloat.rs +++ b/library/core/src/fmt/nofloat.rs @@ -4,6 +4,7 @@ macro_rules! floating { ($ty:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for $ty { + #[inline] fn fmt(&self, _fmt: &mut Formatter<'_>) -> Result { panic!("floating point support is turned off"); } diff --git a/library/std/src/os/hermit/mod.rs b/library/std/src/os/hermit/mod.rs index 89b1b831912df..02a4b2c3ab5e7 100644 --- a/library/std/src/os/hermit/mod.rs +++ b/library/std/src/os/hermit/mod.rs @@ -2,7 +2,7 @@ #[allow(unused_extern_crates)] #[stable(feature = "rust1", since = "1.0.0")] -pub extern crate hermit_abi as abi; +pub extern crate hermit_abi; pub mod ffi; pub mod io; diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 15ab225012238..9cca27fa5dd5b 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -199,14 +199,14 @@ pub trait CommandExt: Sealed { /// Append literal text to the command line without any quoting or escaping. /// - /// This is useful for passing arguments to applications which doesn't follow + /// This is useful for passing arguments to applications that don't follow /// the standard C run-time escaping rules, such as `cmd.exe /c`. /// - /// # Bat files + /// # Batch files /// - /// Note the `cmd /c` command line has slightly different escaping rules then bat files + /// Note the `cmd /c` command line has slightly different escaping rules than batch files /// themselves. If possible, it may be better to write complex arguments to a temporary - /// .bat file, with appropriate escaping, and simply run that using: + /// `.bat` file, with appropriate escaping, and simply run that using: /// /// ```no_run /// # use std::process::Command; @@ -217,7 +217,7 @@ pub trait CommandExt: Sealed { /// /// # Example /// - /// Run a bat script using both trusted and untrusted arguments. + /// Run a batch script using both trusted and untrusted arguments. /// /// ```no_run /// #[cfg(windows)] @@ -241,9 +241,10 @@ pub trait CommandExt: Sealed { /// if !user_name.chars().all(|c| c.is_alphanumeric()) { /// return Err(Error::new(ErrorKind::InvalidInput, "invalid user name")); /// } - /// // now we've checked the user name, let's add that too. - /// cmd_args.push(' '); - /// cmd_args.push_str(&format!("--user {user_name}")); + /// + /// // now we have validated the user name, let's add that too. + /// cmd_args.push_str(" --user "); + /// cmd_args.push_str(user_name); /// /// // call cmd.exe and return the output /// Command::new("cmd.exe") @@ -287,25 +288,37 @@ pub trait CommandExt: Sealed { #[unstable(feature = "windows_process_extensions_async_pipes", issue = "98289")] fn async_pipes(&mut self, always_async: bool) -> &mut process::Command; - /// Sets a raw attribute on the command, providing extended configuration options for Windows processes. + /// Set a raw attribute on the command, providing extended configuration options for Windows + /// processes. + /// + /// This method allows you to specify custom attributes for a child process on Windows systems + /// using raw attribute values. Raw attributes provide extended configurability for process + /// creation, but their usage can be complex and potentially unsafe. /// - /// This method allows you to specify custom attributes for a child process on Windows systems using raw attribute values. - /// Raw attributes provide extended configurability for process creation, but their usage can be complex and potentially unsafe. + /// The `attribute` parameter specifies the raw attribute to be set, while the `value` + /// parameter holds the value associated with that attribute. Please refer to the + /// [`windows-rs` documentation] or the [Win32 API documentation] for detailed information + /// about available attributes and their meanings. /// - /// The `attribute` parameter specifies the raw attribute to be set, while the `value` parameter holds the value associated with that attribute. - /// Please refer to the [`windows-rs`](https://microsoft.github.io/windows-docs-rs/doc/windows/) documentation or the [`Win32 API documentation`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute) for detailed information about available attributes and their meanings. + /// [`windows-rs` documentation]: https://microsoft.github.io/windows-docs-rs/doc/windows/ + /// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute /// /// # Note /// /// The maximum number of raw attributes is the value of [`u32::MAX`]. - /// If this limit is exceeded, the call to [`process::Command::spawn`] will return an `Error` indicating that the maximum number of attributes has been exceeded. + /// If this limit is exceeded, the call to [`process::Command::spawn`] will return an `Error` + /// indicating that the maximum number of attributes has been exceeded. + /// /// # Safety /// - /// The usage of raw attributes is potentially unsafe and should be done with caution. Incorrect attribute values or improper configuration can lead to unexpected behavior or errors. + /// The usage of raw attributes is potentially unsafe and should be done with caution. + /// Incorrect attribute values or improper configuration can lead to unexpected behavior or + /// errors. /// /// # Example /// - /// The following example demonstrates how to create a child process with a specific parent process ID using a raw attribute. + /// The following example demonstrates how to create a child process with a specific parent + /// process ID using a raw attribute. /// /// ```rust /// #![feature(windows_process_extensions_raw_attribute)] @@ -339,7 +352,9 @@ pub trait CommandExt: Sealed { /// /// # Safety Note /// - /// Remember that improper use of raw attributes can lead to undefined behavior or security vulnerabilities. Always consult the documentation and ensure proper attribute values are used. + /// Remember that improper use of raw attributes can lead to undefined behavior or security + /// vulnerabilities. Always consult the documentation and ensure proper attribute values are + /// used. #[unstable(feature = "windows_process_extensions_raw_attribute", issue = "114854")] unsafe fn raw_attribute( &mut self, diff --git a/library/std/src/process.rs b/library/std/src/process.rs index d1848224251af..c926c89f7a97f 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -90,8 +90,8 @@ //! //! # Windows argument splitting //! -//! On Unix systems arguments are passed to a new process as an array of strings -//! but on Windows arguments are passed as a single commandline string and it's +//! On Unix systems arguments are passed to a new process as an array of strings, +//! but on Windows arguments are passed as a single commandline string and it is //! up to the child process to parse it into an array. Therefore the parent and //! child processes must agree on how the commandline string is encoded. //! @@ -107,26 +107,26 @@ //! * Use [`raw_arg`] to build a custom commandline. This bypasses the escaping //! rules used by [`arg`] so should be used with due caution. //! -//! `cmd.exe` and `.bat` use non-standard argument parsing and are especially +//! `cmd.exe` and `.bat` files use non-standard argument parsing and are especially //! vulnerable to malicious input as they may be used to run arbitrary shell //! commands. Untrusted arguments should be restricted as much as possible. //! For examples on handling this see [`raw_arg`]. //! -//! ### Bat file special handling +//! ### Batch file special handling //! //! On Windows, `Command` uses the Windows API function [`CreateProcessW`] to -//! spawn new processes. An undocumented feature of this function is that, +//! spawn new processes. An undocumented feature of this function is that //! when given a `.bat` file as the application to run, it will automatically -//! convert that into running `cmd.exe /c` with the bat file as the next argument. +//! convert that into running `cmd.exe /c` with the batch file as the next argument. //! //! For historical reasons Rust currently preserves this behaviour when using //! [`Command::new`], and escapes the arguments according to `cmd.exe` rules. //! Due to the complexity of `cmd.exe` argument handling, it might not be -//! possible to safely escape some special chars, and using them will result +//! possible to safely escape some special characters, and using them will result //! in an error being returned at process spawn. The set of unescapeable -//! special chars might change between releases. +//! special characters might change between releases. //! -//! Also note that running `.bat` scripts in this way may be removed in the +//! Also note that running batch scripts in this way may be removed in the //! future and so should not be relied upon. //! //! [`spawn`]: Command::spawn @@ -659,16 +659,19 @@ impl Command { /// /// Note that the argument is not passed through a shell, but given /// literally to the program. This means that shell syntax like quotes, - /// escaped characters, word splitting, glob patterns, variable substitution, etc. - /// have no effect. + /// escaped characters, word splitting, glob patterns, variable substitution, + /// etc. have no effect. /// ///
/// - /// On Windows use caution with untrusted inputs. Most applications use the - /// standard convention for decoding arguments passed to them. These are safe to use with `arg`. - /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments - /// and are therefore vulnerable to malicious input. - /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands. + /// On Windows, use caution with untrusted inputs. Most applications use the + /// standard convention for decoding arguments passed to them. These are safe to + /// use with `arg`. However, some applications such as `cmd.exe` and `.bat` files + /// use a non-standard way of decoding arguments. They are therefore vulnerable + /// to malicious input. + /// + /// In the case of `cmd.exe` this is especially important because a malicious + /// argument can potentially run arbitrary shell commands. /// /// See [Windows argument splitting][windows-args] for more details /// or [`raw_arg`] for manually implementing non-standard argument encoding. @@ -710,11 +713,14 @@ impl Command { /// ///
/// - /// On Windows use caution with untrusted inputs. Most applications use the - /// standard convention for decoding arguments passed to them. These are safe to use with `args`. - /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments - /// and are therefore vulnerable to malicious input. - /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands. + /// On Windows, use caution with untrusted inputs. Most applications use the + /// standard convention for decoding arguments passed to them. These are safe to + /// use with `arg`. However, some applications such as `cmd.exe` and `.bat` files + /// use a non-standard way of decoding arguments. They are therefore vulnerable + /// to malicious input. + /// + /// In the case of `cmd.exe` this is especially important because a malicious + /// argument can potentially run arbitrary shell commands. /// /// See [Windows argument splitting][windows-args] for more details /// or [`raw_arg`] for manually implementing non-standard argument encoding. diff --git a/library/std/src/sys/pal/hermit/alloc.rs b/library/std/src/sys/pal/hermit/alloc.rs index de550987a4357..2cd0db909403b 100644 --- a/library/std/src/sys/pal/hermit/alloc.rs +++ b/library/std/src/sys/pal/hermit/alloc.rs @@ -1,4 +1,4 @@ -use super::abi; +use super::hermit_abi; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; @@ -6,11 +6,11 @@ use crate::ptr; unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - abi::malloc(layout.size(), layout.align()) + hermit_abi::malloc(layout.size(), layout.align()) } unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - let addr = abi::malloc(layout.size(), layout.align()); + let addr = hermit_abi::malloc(layout.size(), layout.align()); if !addr.is_null() { ptr::write_bytes(addr, 0x00, layout.size()); @@ -21,11 +21,11 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - abi::free(ptr, layout.size(), layout.align()) + hermit_abi::free(ptr, layout.size(), layout.align()) } #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - abi::realloc(ptr, layout.size(), layout.align(), new_size) + hermit_abi::realloc(ptr, layout.size(), layout.align(), new_size) } } diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs index 962577bb1ed83..d7dab08cfbd57 100644 --- a/library/std/src/sys/pal/hermit/fd.rs +++ b/library/std/src/sys/pal/hermit/fd.rs @@ -1,6 +1,6 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -use super::abi; +use super::hermit_abi; use crate::io::{self, Read}; use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd}; use crate::sys::cvt; @@ -16,7 +16,8 @@ pub struct FileDesc { impl FileDesc { pub fn read(&self, buf: &mut [u8]) -> io::Result { - let result = cvt(unsafe { abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?; + let result = + cvt(unsafe { hermit_abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?; Ok(result as usize) } @@ -26,7 +27,8 @@ impl FileDesc { } pub fn write(&self, buf: &[u8]) -> io::Result { - let result = cvt(unsafe { abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?; + let result = + cvt(unsafe { hermit_abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?; Ok(result as usize) } @@ -49,8 +51,8 @@ impl FileDesc { unsupported() } - pub fn fstat(&self, stat: *mut abi::stat) -> io::Result<()> { - cvt(unsafe { abi::fstat(self.fd.as_raw_fd(), stat) })?; + pub fn fstat(&self, stat: *mut hermit_abi::stat) -> io::Result<()> { + cvt(unsafe { hermit_abi::fstat(self.fd.as_raw_fd(), stat) })?; Ok(()) } } diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs index 6519cc22f1f6f..a4a16e6e86b0c 100644 --- a/library/std/src/sys/pal/hermit/fs.rs +++ b/library/std/src/sys/pal/hermit/fs.rs @@ -1,8 +1,8 @@ -use super::abi::{ +use super::fd::FileDesc; +use super::hermit_abi::{ self, dirent64, stat as stat_struct, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, }; -use super::fd::FileDesc; use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt; use crate::io::{self, Error, ErrorKind}; @@ -47,7 +47,7 @@ impl InnerReadDir { pub struct ReadDir { inner: Arc, - pos: i64, + pos: usize, } impl ReadDir { @@ -197,38 +197,31 @@ impl Iterator for ReadDir { fn next(&mut self) -> Option> { let mut counter: usize = 0; - let mut offset: i64 = 0; + let mut offset: usize = 0; // loop over all directory entries and search the entry for the current position loop { // leave function, if the loop reaches the of the buffer (with all entries) - if offset >= self.inner.dir.len().try_into().unwrap() { + if offset >= self.inner.dir.len() { return None; } - let dir = unsafe { - &*(self.inner.dir.as_ptr().offset(offset.try_into().unwrap()) as *const dirent64) - }; + let dir = unsafe { &*(self.inner.dir.as_ptr().add(offset) as *const dirent64) }; - if counter == self.pos.try_into().unwrap() { + if counter == self.pos { self.pos += 1; // After dirent64, the file name is stored. d_reclen represents the length of the dirent64 // plus the length of the file name. Consequently, file name has a size of d_reclen minus // the size of dirent64. The file name is always a C string and terminated by `\0`. // Consequently, we are able to ignore the last byte. - let name_bytes = unsafe { - core::slice::from_raw_parts( - &dir.d_name as *const _ as *const u8, - dir.d_reclen as usize - core::mem::size_of::() - 1, - ) - .to_vec() - }; + let name_bytes = + unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const i8).to_bytes() }; let entry = DirEntry { root: self.inner.root.clone(), ino: dir.d_ino, type_: dir.d_type as u32, - name: OsString::from_vec(name_bytes), + name: OsString::from_vec(name_bytes.to_vec()), }; return Some(Ok(entry)); @@ -237,7 +230,7 @@ impl Iterator for ReadDir { counter += 1; // move to the next dirent64, which is directly stored after the previous one - offset = offset + dir.d_off; + offset = offset + usize::from(dir.d_reclen); } } } @@ -365,7 +358,7 @@ impl File { mode = 0; } - let fd = unsafe { cvt(abi::open(path.as_ptr(), flags, mode))? }; + let fd = unsafe { cvt(hermit_abi::open(path.as_ptr(), flags, mode))? }; Ok(File(unsafe { FileDesc::from_raw_fd(fd as i32) })) } @@ -446,7 +439,7 @@ impl DirBuilder { pub fn mkdir(&self, path: &Path) -> io::Result<()> { run_path_with_cstr(path, &|path| { - cvt(unsafe { abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ()) + cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ()) }) } @@ -508,7 +501,8 @@ impl FromRawFd for File { } pub fn readdir(path: &Path) -> io::Result { - let fd_raw = run_path_with_cstr(path, &|path| cvt(unsafe { abi::opendir(path.as_ptr()) }))?; + let fd_raw = + run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::opendir(path.as_ptr()) }))?; let fd = unsafe { FileDesc::from_raw_fd(fd_raw as i32) }; let root = path.to_path_buf(); @@ -519,8 +513,9 @@ pub fn readdir(path: &Path) -> io::Result { // reserve memory to receive all directory entries vec.resize(sz, 0); - let readlen = - unsafe { abi::getdents64(fd.as_raw_fd(), vec.as_mut_ptr() as *mut dirent64, sz) }; + let readlen = unsafe { + hermit_abi::getdents64(fd.as_raw_fd(), vec.as_mut_ptr() as *mut dirent64, sz) + }; if readlen > 0 { // shrink down to the minimal size vec.resize(readlen.try_into().unwrap(), 0); @@ -529,7 +524,7 @@ pub fn readdir(path: &Path) -> io::Result { // if the buffer is too small, getdents64 returns EINVAL // otherwise, getdents64 returns an error number - if readlen != (-abi::errno::EINVAL).into() { + if readlen != (-hermit_abi::errno::EINVAL).into() { return Err(Error::from_raw_os_error(readlen.try_into().unwrap())); } @@ -547,7 +542,7 @@ pub fn readdir(path: &Path) -> io::Result { } pub fn unlink(path: &Path) -> io::Result<()> { - run_path_with_cstr(path, &|path| cvt(unsafe { abi::unlink(path.as_ptr()) }).map(|_| ())) + run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::unlink(path.as_ptr()) }).map(|_| ())) } pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { @@ -559,7 +554,7 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { } pub fn rmdir(path: &Path) -> io::Result<()> { - run_path_with_cstr(path, &|path| cvt(unsafe { abi::rmdir(path.as_ptr()) }).map(|_| ())) + run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::rmdir(path.as_ptr()) }).map(|_| ())) } pub fn remove_dir_all(_path: &Path) -> io::Result<()> { @@ -581,7 +576,7 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { pub fn stat(path: &Path) -> io::Result { run_path_with_cstr(path, &|path| { let mut stat_val: stat_struct = unsafe { mem::zeroed() }; - cvt(unsafe { abi::stat(path.as_ptr(), &mut stat_val) })?; + cvt(unsafe { hermit_abi::stat(path.as_ptr(), &mut stat_val) })?; Ok(FileAttr::from_stat(stat_val)) }) } @@ -589,7 +584,7 @@ pub fn stat(path: &Path) -> io::Result { pub fn lstat(path: &Path) -> io::Result { run_path_with_cstr(path, &|path| { let mut stat_val: stat_struct = unsafe { mem::zeroed() }; - cvt(unsafe { abi::lstat(path.as_ptr(), &mut stat_val) })?; + cvt(unsafe { hermit_abi::lstat(path.as_ptr(), &mut stat_val) })?; Ok(FileAttr::from_stat(stat_val)) }) } diff --git a/library/std/src/sys/pal/hermit/futex.rs b/library/std/src/sys/pal/hermit/futex.rs index 427d8ff6f2e4d..571b288565871 100644 --- a/library/std/src/sys/pal/hermit/futex.rs +++ b/library/std/src/sys/pal/hermit/futex.rs @@ -1,4 +1,4 @@ -use super::abi; +use super::hermit_abi; use crate::ptr::null; use crate::sync::atomic::AtomicU32; use crate::time::Duration; @@ -8,32 +8,32 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) - // // Overflows are rounded up to an infinite timeout (None). let timespec = timeout.and_then(|dur| { - Some(abi::timespec { + Some(hermit_abi::timespec { tv_sec: dur.as_secs().try_into().ok()?, tv_nsec: dur.subsec_nanos().into(), }) }); let r = unsafe { - abi::futex_wait( + hermit_abi::futex_wait( futex.as_ptr(), expected, - timespec.as_ref().map_or(null(), |t| t as *const abi::timespec), - abi::FUTEX_RELATIVE_TIMEOUT, + timespec.as_ref().map_or(null(), |t| t as *const hermit_abi::timespec), + hermit_abi::FUTEX_RELATIVE_TIMEOUT, ) }; - r != -abi::errno::ETIMEDOUT + r != -hermit_abi::errno::ETIMEDOUT } #[inline] pub fn futex_wake(futex: &AtomicU32) -> bool { - unsafe { abi::futex_wake(futex.as_ptr(), 1) > 0 } + unsafe { hermit_abi::futex_wake(futex.as_ptr(), 1) > 0 } } #[inline] pub fn futex_wake_all(futex: &AtomicU32) { unsafe { - abi::futex_wake(futex.as_ptr(), i32::MAX); + hermit_abi::futex_wake(futex.as_ptr(), i32::MAX); } } diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 910935541bd33..a64323a3a296e 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -39,7 +39,7 @@ pub mod thread_local_key; pub mod time; use crate::io::ErrorKind; -use crate::os::hermit::abi; +use crate::os::hermit::hermit_abi; pub fn unsupported() -> crate::io::Result { Err(unsupported_err()) @@ -54,7 +54,7 @@ pub fn unsupported_err() -> crate::io::Error { pub fn abort_internal() -> ! { unsafe { - abi::abort(); + hermit_abi::abort(); } } @@ -62,7 +62,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { let mut buf = [0; 16]; let mut slice = &mut buf[..]; while !slice.is_empty() { - let res = cvt(unsafe { abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) }) + let res = cvt(unsafe { hermit_abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) }) .expect("failed to generate random hashmap keys"); slice = &mut slice[res as usize..]; } @@ -109,31 +109,31 @@ pub unsafe extern "C" fn runtime_entry( let result = main(argc as isize, argv); run_dtors(); - abi::exit(result); + hermit_abi::exit(result); } #[inline] pub(crate) fn is_interrupted(errno: i32) -> bool { - errno == abi::errno::EINTR + errno == hermit_abi::errno::EINTR } pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno { - abi::errno::EACCES => ErrorKind::PermissionDenied, - abi::errno::EADDRINUSE => ErrorKind::AddrInUse, - abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, - abi::errno::EAGAIN => ErrorKind::WouldBlock, - abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted, - abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused, - abi::errno::ECONNRESET => ErrorKind::ConnectionReset, - abi::errno::EEXIST => ErrorKind::AlreadyExists, - abi::errno::EINTR => ErrorKind::Interrupted, - abi::errno::EINVAL => ErrorKind::InvalidInput, - abi::errno::ENOENT => ErrorKind::NotFound, - abi::errno::ENOTCONN => ErrorKind::NotConnected, - abi::errno::EPERM => ErrorKind::PermissionDenied, - abi::errno::EPIPE => ErrorKind::BrokenPipe, - abi::errno::ETIMEDOUT => ErrorKind::TimedOut, + hermit_abi::errno::EACCES => ErrorKind::PermissionDenied, + hermit_abi::errno::EADDRINUSE => ErrorKind::AddrInUse, + hermit_abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + hermit_abi::errno::EAGAIN => ErrorKind::WouldBlock, + hermit_abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted, + hermit_abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused, + hermit_abi::errno::ECONNRESET => ErrorKind::ConnectionReset, + hermit_abi::errno::EEXIST => ErrorKind::AlreadyExists, + hermit_abi::errno::EINTR => ErrorKind::Interrupted, + hermit_abi::errno::EINVAL => ErrorKind::InvalidInput, + hermit_abi::errno::ENOENT => ErrorKind::NotFound, + hermit_abi::errno::ENOTCONN => ErrorKind::NotConnected, + hermit_abi::errno::EPERM => ErrorKind::PermissionDenied, + hermit_abi::errno::EPIPE => ErrorKind::BrokenPipe, + hermit_abi::errno::ETIMEDOUT => ErrorKind::TimedOut, _ => ErrorKind::Uncategorized, } } diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index 1f9affbf7735d..cc6781238319b 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -1,4 +1,4 @@ -use super::abi; +use super::hermit_abi; use crate::collections::HashMap; use crate::error::Error as StdError; use crate::ffi::{CStr, OsStr, OsString}; @@ -14,11 +14,11 @@ use crate::vec; use core::slice::memchr; pub fn errno() -> i32 { - unsafe { abi::get_errno() } + unsafe { hermit_abi::get_errno() } } pub fn error_string(errno: i32) -> String { - abi::error_string(errno).to_string() + hermit_abi::error_string(errno).to_string() } pub fn getcwd() -> io::Result { @@ -197,10 +197,10 @@ pub fn home_dir() -> Option { pub fn exit(code: i32) -> ! { unsafe { - abi::exit(code); + hermit_abi::exit(code); } } pub fn getpid() -> u32 { - unsafe { abi::getpid() } + unsafe { hermit_abi::getpid() } } diff --git a/library/std/src/sys/pal/hermit/stdio.rs b/library/std/src/sys/pal/hermit/stdio.rs index ac54385e8cec5..777c57b391c89 100644 --- a/library/std/src/sys/pal/hermit/stdio.rs +++ b/library/std/src/sys/pal/hermit/stdio.rs @@ -1,4 +1,4 @@ -use super::abi; +use super::hermit_abi; use crate::io; use crate::io::{IoSlice, IoSliceMut}; @@ -37,7 +37,7 @@ impl io::Write for Stdout { fn write(&mut self, data: &[u8]) -> io::Result { let len; - unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } + unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print")) @@ -49,7 +49,7 @@ impl io::Write for Stdout { fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result { let len; - unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } + unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print")) @@ -78,7 +78,7 @@ impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { let len; - unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } + unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print")) @@ -90,7 +90,7 @@ impl io::Write for Stderr { fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result { let len; - unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } + unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print")) diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index 4fe6b12a95b09..b336dcd6860e4 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use super::abi; +use super::hermit_abi; use super::thread_local_dtor::run_dtors; use crate::ffi::CStr; use crate::io; @@ -9,7 +9,7 @@ use crate::num::NonZero; use crate::ptr; use crate::time::Duration; -pub type Tid = abi::Tid; +pub type Tid = hermit_abi::Tid; pub struct Thread { tid: Tid, @@ -27,10 +27,10 @@ impl Thread { core_id: isize, ) -> io::Result { let p = Box::into_raw(Box::new(p)); - let tid = abi::spawn2( + let tid = hermit_abi::spawn2( thread_start, p.expose_provenance(), - abi::Priority::into(abi::NORMAL_PRIO), + hermit_abi::Priority::into(hermit_abi::NORMAL_PRIO), stack, core_id, ); @@ -62,7 +62,7 @@ impl Thread { #[inline] pub fn yield_now() { unsafe { - abi::yield_now(); + hermit_abi::yield_now(); } } @@ -74,13 +74,13 @@ impl Thread { #[inline] pub fn sleep(dur: Duration) { unsafe { - abi::usleep(dur.as_micros() as u64); + hermit_abi::usleep(dur.as_micros() as u64); } } pub fn join(self) { unsafe { - let _ = abi::join(self.tid); + let _ = hermit_abi::join(self.tid); } } @@ -98,5 +98,5 @@ impl Thread { } pub fn available_parallelism() -> io::Result> { - unsafe { Ok(NonZero::new_unchecked(abi::get_processor_count())) } + unsafe { Ok(NonZero::new_unchecked(hermit_abi::get_processor_count())) } } diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index d6f9e4c1476b0..2bf24462fa825 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -1,8 +1,6 @@ #![allow(dead_code)] -use super::abi; -use super::abi::timespec; -use super::abi::{CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC}; +use super::hermit_abi::{self, timespec, CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC}; use crate::cmp::Ordering; use crate::ops::{Add, AddAssign, Sub, SubAssign}; use crate::time::Duration; @@ -106,7 +104,8 @@ pub struct Instant(Timespec); impl Instant { pub fn now() -> Instant { let mut time: Timespec = Timespec::zero(); - let _ = unsafe { abi::clock_gettime(CLOCK_MONOTONIC, core::ptr::addr_of_mut!(time.t)) }; + let _ = + unsafe { hermit_abi::clock_gettime(CLOCK_MONOTONIC, core::ptr::addr_of_mut!(time.t)) }; Instant(time) } @@ -207,7 +206,8 @@ impl SystemTime { pub fn now() -> SystemTime { let mut time: Timespec = Timespec::zero(); - let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) }; + let _ = + unsafe { hermit_abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) }; SystemTime(time) } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index d1ae24007b3d8..e08d7ff046d86 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -236,7 +236,6 @@ run-make/rustc-macro-dep-files/Makefile run-make/rustdoc-io-error/Makefile run-make/rustdoc-scrape-examples-macros/Makefile run-make/rustdoc-scrape-examples-multiple/Makefile -run-make/rustdoc-scrape-examples-test/Makefile run-make/rustdoc-scrape-examples-whitespace/Makefile run-make/rustdoc-verify-output-files/Makefile run-make/rustdoc-with-output-option/Makefile diff --git a/tests/crashes/124833.rs b/tests/crashes/124833.rs new file mode 100644 index 0000000000000..f1c4847b544a5 --- /dev/null +++ b/tests/crashes/124833.rs @@ -0,0 +1,10 @@ +//@ known-bug: rust-lang/rust#124833 +#![feature(generic_const_items)] + +trait Trait { + const C<'a>: &'a str; +} + +impl Trait for () { + const C<'a>: = "C"; +} diff --git a/tests/crashes/124857.rs b/tests/crashes/124857.rs new file mode 100644 index 0000000000000..4b952fd64ccfb --- /dev/null +++ b/tests/crashes/124857.rs @@ -0,0 +1,11 @@ +//@ known-bug: rust-lang/rust#124857 +//@ compile-flags: -Znext-solver=coherence + +#![feature(effects)] + +#[const_trait] +trait Foo {} + +impl const Foo for i32 {} + +impl const Foo for T where T: ~const Foo {} diff --git a/tests/crashes/124891.rs b/tests/crashes/124891.rs new file mode 100644 index 0000000000000..9b5892418c897 --- /dev/null +++ b/tests/crashes/124891.rs @@ -0,0 +1,22 @@ +//@ known-bug: rust-lang/rust#124891 + +type Tait = impl FnOnce() -> (); + +fn reify_as_tait() -> Thunk { + Thunk::new(|cont| cont) +} + +struct Thunk(F); + +impl Thunk { + fn new(f: F) + where + F: ContFn, + { + todo!(); + } +} + +trait ContFn {} + +impl ()> ContFn for F {} diff --git a/tests/crashes/124894.rs b/tests/crashes/124894.rs new file mode 100644 index 0000000000000..230cf4a89c151 --- /dev/null +++ b/tests/crashes/124894.rs @@ -0,0 +1,11 @@ +//@ known-bug: rust-lang/rust#124894 +//@ compile-flags: -Znext-solver=coherence + +#![feature(generic_const_exprs)] + +pub trait IsTrue {} +impl IsZST for T where (): IsTrue<{ std::mem::size_of::() == 0 }> {} + +pub trait IsZST {} + +impl IsZST for IsZST {} diff --git a/tests/crashes/125081.rs b/tests/crashes/125081.rs new file mode 100644 index 0000000000000..7139caaa00df7 --- /dev/null +++ b/tests/crashes/125081.rs @@ -0,0 +1,7 @@ +//@ known-bug: rust-lang/rust#125081 + +use std::cell::Cell; + +fn main() { + let _: Cell<&str, "a"> = Cell::new('β); +} diff --git a/tests/crashes/125099.rs b/tests/crashes/125099.rs new file mode 100644 index 0000000000000..bfc8c8fdcf683 --- /dev/null +++ b/tests/crashes/125099.rs @@ -0,0 +1,24 @@ +//@ known-bug: rust-lang/rust#125099 + +pub trait ContFn: Fn(T) -> Self::Future { + type Future; +} +impl ContFn for F +where + F: Fn(T), +{ + type Future = (); +} + +pub trait SeqHandler { + type Requires; + fn process>() -> impl Sized; +} + +pub struct ConvertToU64; +impl SeqHandler for ConvertToU64 { + type Requires = u64; + fn process>() -> impl Sized {} +} + +fn main() {} diff --git a/tests/crashes/125155.rs b/tests/crashes/125155.rs new file mode 100644 index 0000000000000..165061d4b5296 --- /dev/null +++ b/tests/crashes/125155.rs @@ -0,0 +1,17 @@ +//@ known-bug: rust-lang/rust#125155 + +enum NestedEnum { + First, + Second, + Third +} +enum Enum { + Variant2(Option<*mut &'a &'b ()>) +} + + +fn foo(x: Enum) -> isize { + match x { + Enum::Variant2(NestedEnum::Third) => 4, + } +} diff --git a/tests/crashes/125185.rs b/tests/crashes/125185.rs new file mode 100644 index 0000000000000..8693d6c7662b2 --- /dev/null +++ b/tests/crashes/125185.rs @@ -0,0 +1,16 @@ +//@ known-bug: rust-lang/rust#125185 +//@ compile-flags: -Zvalidate-mir + +type Foo = impl Send; + +struct A; + +const VALUE: Foo = value(); + +fn test(foo: Foo<'a>, f: impl for<'b> FnMut()) { + match VALUE { + 0 | 0 => {} + + _ => (), + } +} diff --git a/tests/crashes/125249.rs b/tests/crashes/125249.rs new file mode 100644 index 0000000000000..18196d7b34fe8 --- /dev/null +++ b/tests/crashes/125249.rs @@ -0,0 +1,8 @@ +//@ known-bug: rust-lang/rust#125185 +#![feature(return_position_impl_trait_in_trait, return_type_notation)] + +trait IntFactory { + fn stream(&self) -> impl IntFactory + Send>; +} + +pub fn main() {} diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs b/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs index 537d3e2d724a5..e9c54fa392237 100644 --- a/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs @@ -2,5 +2,5 @@ mod scrape; fn main() { - scrape::scrape(); + scrape::scrape(&[]); } diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs index 537d3e2d724a5..e9c54fa392237 100644 --- a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs @@ -2,5 +2,5 @@ mod scrape; fn main() { - scrape::scrape(); + scrape::scrape(&[]); } diff --git a/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs b/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs index d9deaf279ce52..4e3b895aef0c4 100644 --- a/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs @@ -1,5 +1,5 @@ mod scrape; fn main() { - scrape::scrape(); + scrape::scrape(&[]); } diff --git a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs index 709388b549214..563e3aca9aed6 100644 --- a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs +++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs @@ -2,7 +2,7 @@ use run_make_support::{htmldocck, rustc, rustdoc, source_path, tmp_dir}; use std::fs::read_dir; use std::path::Path; -pub fn scrape() { +pub fn scrape(extra_args: &[&str]) { let lib_dir = tmp_dir(); let out_dir = tmp_dir().join("rustdoc"); let crate_name = "foobar"; @@ -29,6 +29,7 @@ pub fn scrape() { .arg(&out_example) .arg("--scrape-examples-target-crate") .arg(crate_name) + .args(extra_args) .run(); out_deps.push(out_example); } diff --git a/tests/run-make/rustdoc-scrape-examples-test/Makefile b/tests/run-make/rustdoc-scrape-examples-test/Makefile deleted file mode 100644 index 1235ead675156..0000000000000 --- a/tests/run-make/rustdoc-scrape-examples-test/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -extra_flags := --scrape-tests -deps := ex - -include ../rustdoc-scrape-examples-multiple/scrape.mk - -all: scrape diff --git a/tests/run-make/rustdoc-scrape-examples-test/rmake.rs b/tests/run-make/rustdoc-scrape-examples-test/rmake.rs new file mode 100644 index 0000000000000..f96ba113ff730 --- /dev/null +++ b/tests/run-make/rustdoc-scrape-examples-test/rmake.rs @@ -0,0 +1,6 @@ +#[path = "../rustdoc-scrape-examples-remap/scrape.rs"] +mod scrape; + +fn main() { + scrape::scrape(&["--scrape-tests"]); +} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr new file mode 100644 index 0000000000000..41f222e46a77c --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `&str: AsExpression` is not satisfied + --> $DIR/as_expression.rs:57:15 + | +LL | SelectInt.check("bar"); + | ^^^^^ the trait `AsExpression` is not implemented for `&str` + | + = help: the trait `AsExpression` is implemented for `&str` + = help: for that trait implementation, expected `Text`, found `Integer` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr new file mode 100644 index 0000000000000..47acf5b968b79 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `&str: AsExpression<::SqlType>` is not satisfied + --> $DIR/as_expression.rs:57:21 + | +LL | SelectInt.check("bar"); + | ----- ^^^^^ the trait `AsExpression<::SqlType>` is not implemented for `&str` + | | + | required by a bound introduced by this call + | + = help: the trait `AsExpression` is implemented for `&str` +note: required by a bound in `Foo::check` + --> $DIR/as_expression.rs:48:12 + | +LL | fn check(&self, _: T) -> ::SqlType>>::Expression + | ----- required by a bound in this associated function +LL | where +LL | T: AsExpression, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs new file mode 100644 index 0000000000000..9cdc193d386d8 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -0,0 +1,60 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +pub trait Expression { + type SqlType; +} + +pub trait AsExpression { + type Expression: Expression; +} + +pub struct Text; +pub struct Integer; + +pub struct Bound(T); +pub struct SelectInt; + +impl Expression for SelectInt { + type SqlType = Integer; +} + +impl Expression for Bound { + type SqlType = T; +} + +#[do_not_recommend] +impl AsExpression for T +where + T: Expression, +{ + type Expression = T; +} + +impl AsExpression for i32 { + type Expression = Bound; +} + +impl AsExpression for &'_ str { + type Expression = Bound; +} + +trait Foo: Expression + Sized { + fn check(&self, _: T) -> ::SqlType>>::Expression + where + T: AsExpression, + { + todo!() + } +} + +impl Foo for T where T: Expression {} + +fn main() { + SelectInt.check("bar"); + //[next]~^ ERROR the trait bound `&str: AsExpression<::SqlType>` is not satisfied + //[current]~^^ ERROR the trait bound `&str: AsExpression` is not satisfied +} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr index a4d4b7b359ec8..729cb5694e216 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr @@ -1,16 +1,11 @@ error[E0277]: the trait bound `*mut (): Foo` is not satisfied - --> $DIR/simple.rs:19:17 + --> $DIR/simple.rs:17:17 | LL | needs_foo::<*mut ()>(); - | ^^^^^^^ the trait `Send` is not implemented for `*mut ()`, which is required by `*mut (): Foo` + | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | -note: required for `*mut ()` to implement `Foo` - --> $DIR/simple.rs:10:9 - | -LL | impl Foo for T where T: Send {} - | ^^^ ^ ---- unsatisfied trait bound introduced here note: required by a bound in `needs_foo` - --> $DIR/simple.rs:14:17 + --> $DIR/simple.rs:12:17 | LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr index 1341ca8175aff..729cb5694e216 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `*mut (): Foo` is not satisfied - --> $DIR/simple.rs:19:17 + --> $DIR/simple.rs:17:17 | LL | needs_foo::<*mut ()>(); | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | note: required by a bound in `needs_foo` - --> $DIR/simple.rs:14:17 + --> $DIR/simple.rs:12:17 | LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs index 15ff80ae4d953..6fb15b90138a4 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs @@ -8,8 +8,6 @@ trait Foo {} #[do_not_recommend] impl Foo for T where T: Send {} -//[current]~^ NOTE required for `*mut ()` to implement `Foo` -//[current]~| NOTE unsatisfied trait bound introduced here fn needs_foo() {} //~^ NOTE required by a bound in `needs_foo` @@ -18,6 +16,5 @@ fn needs_foo() {} fn main() { needs_foo::<*mut ()>(); //~^ ERROR the trait bound `*mut (): Foo` is not satisfied - //[current]~| NOTE the trait `Send` is not implemented for `*mut ()` - //[next]~| NOTE the trait `Foo` is not implemented for `*mut ()` + //~| NOTE the trait `Foo` is not implemented for `*mut ()` } diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr new file mode 100644 index 0000000000000..41a10a61e1dfd --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): Root` is not satisfied + --> $DIR/stacked.rs:19:18 + | +LL | needs_root::<()>(); + | ^^ the trait `Root` is not implemented for `()` + | +note: required by a bound in `needs_root` + --> $DIR/stacked.rs:16:18 + | +LL | fn needs_root() {} + | ^^^^ required by this bound in `needs_root` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr new file mode 100644 index 0000000000000..41a10a61e1dfd --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): Root` is not satisfied + --> $DIR/stacked.rs:19:18 + | +LL | needs_root::<()>(); + | ^^ the trait `Root` is not implemented for `()` + | +note: required by a bound in `needs_root` + --> $DIR/stacked.rs:16:18 + | +LL | fn needs_root() {} + | ^^^^ required by this bound in `needs_root` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs new file mode 100644 index 0000000000000..695660d359619 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs @@ -0,0 +1,21 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +trait Root {} +trait DontRecommend {} +trait Other {} + +#[do_not_recommend] +impl Root for T where T: DontRecommend {} + +impl DontRecommend for T where T: Other {} + +fn needs_root() {} + +fn main() { + needs_root::<()>(); + //~^ ERROR the trait bound `(): Root` is not satisfied +} diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr index 284dacf7000bd..e6f199445bf50 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr @@ -2,18 +2,8 @@ error[E0277]: the trait bound `u8: Bar` is not satisfied --> $DIR/feature-gate-do_not_recommend.rs:19:11 | LL | stuff(1u8); - | ----- ^^^ the trait `Foo` is not implemented for `u8`, which is required by `u8: Bar` - | | - | required by a bound introduced by this call + | ^^^ the trait `Bar` is not implemented for `u8` | - = help: the trait `Foo` is implemented for `i32` -note: required for `u8` to implement `Bar` - --> $DIR/feature-gate-do_not_recommend.rs:13:14 - | -LL | impl Bar for T { - | --- ^^^ ^ - | | - | unsatisfied trait bound introduced here note: required by a bound in `stuff` --> $DIR/feature-gate-do_not_recommend.rs:16:13 |