mirror of https://github.com/rust-lang/rust.git
Auto merge of #125280 - compiler-errors:rollup-401itda, r=compiler-errors
Rollup of 7 pull requests Successful merges: - #123709 (Update documentation related to the recent cmd.exe fix) - #124304 (revise the interpretation of ReadDir for HermitOS) - #124708 (Actually use the `#[do_not_recommend]` attribute if present) - #125252 (Add `#[inline]` to float `Debug` fallback used by `cfg(no_fp_fmt_parse)`) - #125261 (crashes: add more) - #125270 (Followup fixes from #123344) - #125275 (Migrate `run-make/rustdoc-scrape-examples-test` to new `rmake.rs`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
698293518d
|
@ -2733,6 +2733,13 @@ pub enum UseTreeKind {
|
|||
/// `use prefix` or `use prefix as rename`
|
||||
Simple(Option<Ident>),
|
||||
/// `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,
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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`](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.
|
||||
/// 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.
|
||||
///
|
||||
/// [`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<T: Copy + Send + Sync + 'static>(
|
||||
&mut self,
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
/// <div class="warning">
|
||||
///
|
||||
/// 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 {
|
|||
///
|
||||
/// <div class="warning">
|
||||
///
|
||||
/// 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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<usize> {
|
||||
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<usize> {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<InnerReadDir>,
|
||||
pos: i64,
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl ReadDir {
|
||||
|
@ -197,38 +197,31 @@ impl Iterator for ReadDir {
|
|||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
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::<dirent64>() - 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<ReadDir> {
|
||||
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<ReadDir> {
|
|||
// 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<ReadDir> {
|
|||
|
||||
// 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<ReadDir> {
|
|||
}
|
||||
|
||||
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<FileAttr> {
|
||||
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<FileAttr> {
|
|||
pub fn lstat(path: &Path) -> io::Result<FileAttr> {
|
||||
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))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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<Duration>) -
|
|||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<T>() -> crate::io::Result<T> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<PathBuf> {
|
||||
|
@ -197,10 +197,10 @@ pub fn home_dir() -> Option<PathBuf> {
|
|||
|
||||
pub fn exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
abi::exit(code);
|
||||
hermit_abi::exit(code);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getpid() -> u32 {
|
||||
unsafe { abi::getpid() }
|
||||
unsafe { hermit_abi::getpid() }
|
||||
}
|
||||
|
|
|
@ -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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
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"))
|
||||
|
|
|
@ -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<Thread> {
|
||||
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<NonZero<usize>> {
|
||||
unsafe { Ok(NonZero::new_unchecked(abi::get_processor_count())) }
|
||||
unsafe { Ok(NonZero::new_unchecked(hermit_abi::get_processor_count())) }
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
}
|
|
@ -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<T> const Foo for T where T: ~const Foo {}
|
|
@ -0,0 +1,22 @@
|
|||
//@ known-bug: rust-lang/rust#124891
|
||||
|
||||
type Tait = impl FnOnce() -> ();
|
||||
|
||||
fn reify_as_tait() -> Thunk<Tait> {
|
||||
Thunk::new(|cont| cont)
|
||||
}
|
||||
|
||||
struct Thunk<F>(F);
|
||||
|
||||
impl<F> Thunk<F> {
|
||||
fn new(f: F)
|
||||
where
|
||||
F: ContFn,
|
||||
{
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
trait ContFn {}
|
||||
|
||||
impl<F: FnOnce(Tait) -> ()> ContFn for F {}
|
|
@ -0,0 +1,11 @@
|
|||
//@ known-bug: rust-lang/rust#124894
|
||||
//@ compile-flags: -Znext-solver=coherence
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
pub trait IsTrue<const mem: bool> {}
|
||||
impl<T> IsZST for T where (): IsTrue<{ std::mem::size_of::<T>() == 0 }> {}
|
||||
|
||||
pub trait IsZST {}
|
||||
|
||||
impl IsZST for IsZST {}
|
|
@ -0,0 +1,7 @@
|
|||
//@ known-bug: rust-lang/rust#125081
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
fn main() {
|
||||
let _: Cell<&str, "a"> = Cell::new('β);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
//@ known-bug: rust-lang/rust#125099
|
||||
|
||||
pub trait ContFn<T>: Fn(T) -> Self::Future {
|
||||
type Future;
|
||||
}
|
||||
impl<T, F> ContFn<T> for F
|
||||
where
|
||||
F: Fn(T),
|
||||
{
|
||||
type Future = ();
|
||||
}
|
||||
|
||||
pub trait SeqHandler {
|
||||
type Requires;
|
||||
fn process<F: ContFn<Self::Requires>>() -> impl Sized;
|
||||
}
|
||||
|
||||
pub struct ConvertToU64;
|
||||
impl SeqHandler for ConvertToU64 {
|
||||
type Requires = u64;
|
||||
fn process<F: ContFn<Self::Requires>>() -> impl Sized {}
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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 => {}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
}
|
|
@ -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<stream(): IntFactory<stream(): Send> + Send>;
|
||||
}
|
||||
|
||||
pub fn main() {}
|
|
@ -2,5 +2,5 @@
|
|||
mod scrape;
|
||||
|
||||
fn main() {
|
||||
scrape::scrape();
|
||||
scrape::scrape(&[]);
|
||||
}
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
mod scrape;
|
||||
|
||||
fn main() {
|
||||
scrape::scrape();
|
||||
scrape::scrape(&[]);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
mod scrape;
|
||||
|
||||
fn main() {
|
||||
scrape::scrape();
|
||||
scrape::scrape(&[]);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
extra_flags := --scrape-tests
|
||||
deps := ex
|
||||
|
||||
include ../rustdoc-scrape-examples-multiple/scrape.mk
|
||||
|
||||
all: scrape
|
|
@ -0,0 +1,6 @@
|
|||
#[path = "../rustdoc-scrape-examples-remap/scrape.rs"]
|
||||
mod scrape;
|
||||
|
||||
fn main() {
|
||||
scrape::scrape(&["--scrape-tests"]);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
|
||||
--> $DIR/as_expression.rs:57:15
|
||||
|
|
||||
LL | SelectInt.check("bar");
|
||||
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
|
||||
|
|
||||
= help: the trait `AsExpression<Text>` 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`.
|
|
@ -0,0 +1,21 @@
|
|||
error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
|
||||
--> $DIR/as_expression.rs:57:21
|
||||
|
|
||||
LL | SelectInt.check("bar");
|
||||
| ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `AsExpression<Text>` is implemented for `&str`
|
||||
note: required by a bound in `Foo::check`
|
||||
--> $DIR/as_expression.rs:48:12
|
||||
|
|
||||
LL | fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
|
||||
| ----- required by a bound in this associated function
|
||||
LL | where
|
||||
LL | T: AsExpression<Self::SqlType>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -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<ST> {
|
||||
type Expression: Expression<SqlType = ST>;
|
||||
}
|
||||
|
||||
pub struct Text;
|
||||
pub struct Integer;
|
||||
|
||||
pub struct Bound<T>(T);
|
||||
pub struct SelectInt;
|
||||
|
||||
impl Expression for SelectInt {
|
||||
type SqlType = Integer;
|
||||
}
|
||||
|
||||
impl<T> Expression for Bound<T> {
|
||||
type SqlType = T;
|
||||
}
|
||||
|
||||
#[do_not_recommend]
|
||||
impl<T, ST> AsExpression<ST> for T
|
||||
where
|
||||
T: Expression<SqlType = ST>,
|
||||
{
|
||||
type Expression = T;
|
||||
}
|
||||
|
||||
impl AsExpression<Integer> for i32 {
|
||||
type Expression = Bound<Integer>;
|
||||
}
|
||||
|
||||
impl AsExpression<Text> for &'_ str {
|
||||
type Expression = Bound<Text>;
|
||||
}
|
||||
|
||||
trait Foo: Expression + Sized {
|
||||
fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
|
||||
where
|
||||
T: AsExpression<Self::SqlType>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Foo for T where T: Expression {}
|
||||
|
||||
fn main() {
|
||||
SelectInt.check("bar");
|
||||
//[next]~^ ERROR the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
|
||||
//[current]~^^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
|
||||
}
|
|
@ -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<T> 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<T: Foo>() {}
|
||||
| ^^^ required by this bound in `needs_foo`
|
||||
|
|
|
@ -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<T: Foo>() {}
|
||||
| ^^^ required by this bound in `needs_foo`
|
||||
|
|
|
@ -8,8 +8,6 @@ trait Foo {}
|
|||
|
||||
#[do_not_recommend]
|
||||
impl<T> Foo for T where T: Send {}
|
||||
//[current]~^ NOTE required for `*mut ()` to implement `Foo`
|
||||
//[current]~| NOTE unsatisfied trait bound introduced here
|
||||
|
||||
fn needs_foo<T: Foo>() {}
|
||||
//~^ NOTE required by a bound in `needs_foo`
|
||||
|
@ -18,6 +16,5 @@ fn needs_foo<T: 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 ()`
|
||||
}
|
||||
|
|
|
@ -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<T: 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`.
|
|
@ -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<T: 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`.
|
|
@ -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<T> Root for T where T: DontRecommend {}
|
||||
|
||||
impl<T> DontRecommend for T where T: Other {}
|
||||
|
||||
fn needs_root<T: Root>() {}
|
||||
|
||||
fn main() {
|
||||
needs_root::<()>();
|
||||
//~^ ERROR the trait bound `(): Root` is not satisfied
|
||||
}
|
|
@ -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<T: Foo> Bar for T {
|
||||
| --- ^^^ ^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
note: required by a bound in `stuff`
|
||||
--> $DIR/feature-gate-do_not_recommend.rs:16:13
|
||||
|
|
||||
|
|
Loading…
Reference in New Issue