Auto merge of #143766 - matthiaskrgr:rollup-0x7t69s, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#142391 (rust: library: Add `setsid` method to `CommandExt` trait)
 - rust-lang/rust#143302 (`tests/ui`: A New Order [27/N])
 - rust-lang/rust#143303 (`tests/ui`: A New Order [28/28] FINAL PART)
 - rust-lang/rust#143568 (std: sys: net: uefi: tcp4: Add timeout support)
 - rust-lang/rust#143611 (Mention more APIs in `ParseIntError` docs)
 - rust-lang/rust#143661 (chore: Improve how the other suggestions message gets rendered)
 - rust-lang/rust#143708 (fix: Include frontmatter in -Zunpretty output )
 - rust-lang/rust#143718 (Make UB transmutes really UB in LLVM)

r? `@ghost`
`@rustbot` modify labels: rollup

try-job: i686-gnu-nopt-1
try-job: test-various
This commit is contained in:
bors
2025-07-12 07:44:04 +00:00
111 changed files with 1165 additions and 478 deletions

View File

@@ -120,7 +120,7 @@ fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment>
pos += shebang_len;
}
for token in rustc_lexer::tokenize(&text[pos..]) {
for token in rustc_lexer::tokenize(&text[pos..], rustc_lexer::FrontmatterAllowed::Yes) {
let token_text = &text[pos..pos + token.len as usize];
match token.kind {
rustc_lexer::TokenKind::Whitespace => {
@@ -171,6 +171,14 @@ fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment>
})
}
}
rustc_lexer::TokenKind::Frontmatter { .. } => {
code_to_the_left = false;
comments.push(Comment {
style: CommentStyle::Isolated,
lines: vec![token_text.to_string()],
pos: start_bpos + BytePos(pos as u32),
});
}
_ => {
code_to_the_left = true;
}

View File

@@ -207,9 +207,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
{
// These cases are all UB to actually hit, so don't emit code for them.
// (The size mismatches are reachable via `transmute_unchecked`.)
// We can't use unreachable because that's a terminator, and we
// need something that can be in the middle of a basic block.
bx.assume(bx.cx().const_bool(false))
bx.unreachable_nonterminator();
} else {
// Since in this path we have a place anyway, we can store or copy to it,
// making sure we use the destination place's alignment even if the
@@ -236,14 +234,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|| operand.layout.is_uninhabited()
|| cast.is_uninhabited()
{
if !operand.layout.is_uninhabited() {
// Since this is known statically and the input could have existed
// without already having hit UB, might as well trap for it.
bx.abort();
}
bx.unreachable_nonterminator();
// Because this transmute is UB, return something easy to generate,
// since it's fine that later uses of the value are probably UB.
// We still need to return a value of the appropriate type, but
// it's already UB so do the easiest thing available.
return OperandValue::poison(bx, cast);
}

View File

@@ -136,6 +136,16 @@ pub trait BuilderMethods<'a, 'tcx>:
) -> Self::Value;
fn unreachable(&mut self);
/// Like [`Self::unreachable`], but for use in the middle of a basic block.
fn unreachable_nonterminator(&mut self) {
// This is the preferred LLVM incantation for this per
// https://llvm.org/docs/Frontend/PerformanceTips.html#other-things-to-consider
// Other backends may override if they have a better way.
let const_true = self.cx().const_bool(true);
let poison_ptr = self.const_poison(self.cx().type_ptr());
self.store(const_true, poison_ptr, Align::ONE);
}
fn add(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
fn fadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
fn fadd_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;

View File

@@ -2446,17 +2446,22 @@ impl HumanEmitter {
| DisplaySuggestion::Underline => row_num - 1,
DisplaySuggestion::None => row_num,
};
if other_suggestions > 0 {
self.draw_col_separator_no_space(&mut buffer, row, max_line_num_len + 1);
} else {
self.draw_col_separator_end(&mut buffer, row, max_line_num_len + 1);
}
row_num = row + 1;
}
}
if other_suggestions > 0 {
self.draw_note_separator(&mut buffer, row_num, max_line_num_len + 1, false);
let msg = format!(
"and {} other candidate{}",
other_suggestions,
pluralize!(other_suggestions)
);
buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
buffer.append(row_num, &msg, Style::NoStyle);
}
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;

View File

@@ -273,7 +273,8 @@ pub fn strip_shebang(input: &str) -> Option<usize> {
if let Some(input_tail) = input.strip_prefix("#!") {
// Ok, this is a shebang but if the next non-whitespace token is `[`,
// then it may be valid Rust code, so consider it Rust code.
let next_non_whitespace_token = tokenize(input_tail).map(|tok| tok.kind).find(|tok| {
let next_non_whitespace_token =
tokenize(input_tail, FrontmatterAllowed::No).map(|tok| tok.kind).find(|tok| {
!matches!(
tok,
TokenKind::Whitespace
@@ -303,8 +304,16 @@ pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError>
}
/// Creates an iterator that produces tokens from the input string.
pub fn tokenize(input: &str) -> impl Iterator<Item = Token> {
let mut cursor = Cursor::new(input, FrontmatterAllowed::No);
///
/// When parsing a full Rust document,
/// first [`strip_shebang`] and then allow frontmatters with [`FrontmatterAllowed::Yes`].
///
/// When tokenizing a slice of a document, be sure to disallow frontmatters with [`FrontmatterAllowed::No`]
pub fn tokenize(
input: &str,
frontmatter_allowed: FrontmatterAllowed,
) -> impl Iterator<Item = Token> {
let mut cursor = Cursor::new(input, frontmatter_allowed);
std::iter::from_fn(move || {
let token = cursor.advance_token();
if token.kind != TokenKind::Eof { Some(token) } else { None }

View File

@@ -124,8 +124,9 @@ fn test_valid_shebang() {
assert_eq!(strip_shebang(input), None);
}
fn check_lexing(src: &str, expect: Expect) {
let actual: String = tokenize(src).map(|token| format!("{:?}\n", token)).collect();
fn check_lexing(src: &str, frontmatter_allowed: FrontmatterAllowed, expect: Expect) {
let actual: String =
tokenize(src, frontmatter_allowed).map(|token| format!("{:?}\n", token)).collect();
expect.assert_eq(&actual)
}
@@ -133,6 +134,7 @@ fn check_lexing(src: &str, expect: Expect) {
fn smoke_test() {
check_lexing(
"/* my source file */ fn main() { println!(\"zebra\"); }\n",
FrontmatterAllowed::No,
expect![[r#"
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 20 }
Token { kind: Whitespace, len: 1 }
@@ -171,6 +173,7 @@ fn comment_flavors() {
/** outer doc block */
/*! inner doc block */
",
FrontmatterAllowed::No,
expect![[r#"
Token { kind: Whitespace, len: 1 }
Token { kind: LineComment { doc_style: None }, len: 7 }
@@ -199,6 +202,7 @@ fn comment_flavors() {
fn nested_block_comments() {
check_lexing(
"/* /* */ */'a'",
FrontmatterAllowed::No,
expect![[r#"
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
@@ -210,6 +214,7 @@ fn nested_block_comments() {
fn characters() {
check_lexing(
"'a' ' ' '\\n'",
FrontmatterAllowed::No,
expect![[r#"
Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
Token { kind: Whitespace, len: 1 }
@@ -224,6 +229,7 @@ fn characters() {
fn lifetime() {
check_lexing(
"'abc",
FrontmatterAllowed::No,
expect![[r#"
Token { kind: Lifetime { starts_with_number: false }, len: 4 }
"#]],
@@ -234,6 +240,7 @@ fn lifetime() {
fn raw_string() {
check_lexing(
"r###\"\"#a\\b\x00c\"\"###",
FrontmatterAllowed::No,
expect![[r#"
Token { kind: Literal { kind: RawStr { n_hashes: Some(3) }, suffix_start: 17 }, len: 17 }
"#]],
@@ -257,6 +264,7 @@ b"a"
r###"raw"###suffix
br###"raw"###suffix
"####,
FrontmatterAllowed::No,
expect![[r#"
Token { kind: Whitespace, len: 1 }
Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
@@ -286,3 +294,78 @@ br###"raw"###suffix
"#]],
)
}
#[test]
fn frontmatter_allowed() {
check_lexing(
r#"
---cargo
[dependencies]
clap = "4"
---
fn main() {}
"#,
FrontmatterAllowed::Yes,
expect![[r#"
Token { kind: Whitespace, len: 1 }
Token { kind: Frontmatter { has_invalid_preceding_whitespace: false, invalid_infostring: false }, len: 38 }
Token { kind: Whitespace, len: 2 }
Token { kind: Ident, len: 2 }
Token { kind: Whitespace, len: 1 }
Token { kind: Ident, len: 4 }
Token { kind: OpenParen, len: 1 }
Token { kind: CloseParen, len: 1 }
Token { kind: Whitespace, len: 1 }
Token { kind: OpenBrace, len: 1 }
Token { kind: CloseBrace, len: 1 }
Token { kind: Whitespace, len: 1 }
"#]],
)
}
#[test]
fn frontmatter_disallowed() {
check_lexing(
r#"
---cargo
[dependencies]
clap = "4"
---
fn main() {}
"#,
FrontmatterAllowed::No,
expect![[r#"
Token { kind: Whitespace, len: 1 }
Token { kind: Minus, len: 1 }
Token { kind: Minus, len: 1 }
Token { kind: Minus, len: 1 }
Token { kind: Ident, len: 5 }
Token { kind: Whitespace, len: 1 }
Token { kind: OpenBracket, len: 1 }
Token { kind: Ident, len: 12 }
Token { kind: CloseBracket, len: 1 }
Token { kind: Whitespace, len: 1 }
Token { kind: Ident, len: 4 }
Token { kind: Whitespace, len: 1 }
Token { kind: Eq, len: 1 }
Token { kind: Whitespace, len: 1 }
Token { kind: Literal { kind: Str { terminated: true }, suffix_start: 3 }, len: 3 }
Token { kind: Whitespace, len: 1 }
Token { kind: Minus, len: 1 }
Token { kind: Minus, len: 1 }
Token { kind: Minus, len: 1 }
Token { kind: Whitespace, len: 2 }
Token { kind: Ident, len: 2 }
Token { kind: Whitespace, len: 1 }
Token { kind: Ident, len: 4 }
Token { kind: OpenParen, len: 1 }
Token { kind: CloseParen, len: 1 }
Token { kind: Whitespace, len: 1 }
Token { kind: OpenBrace, len: 1 }
Token { kind: CloseBrace, len: 1 }
Token { kind: Whitespace, len: 1 }
"#]],
)
}

View File

@@ -45,8 +45,11 @@ impl From<!> for TryFromIntError {
/// An error which can be returned when parsing an integer.
///
/// This error is used as the error type for the `from_str_radix()` functions
/// on the primitive integer types, such as [`i8::from_str_radix`].
/// For example, this error is returned by the `from_str_radix()` functions
/// on the primitive integer types (such as [`i8::from_str_radix`])
/// and is used as the error type in their [`FromStr`] implementations.
///
/// [`FromStr`]: crate::str::FromStr
///
/// # Potential causes
///

View File

@@ -210,6 +210,9 @@ pub trait CommandExt: Sealed {
/// intentional difference from the underlying `chroot` system call.)
#[unstable(feature = "process_chroot", issue = "141298")]
fn chroot<P: AsRef<Path>>(&mut self, dir: P) -> &mut process::Command;
#[unstable(feature = "process_setsid", issue = "105376")]
fn setsid(&mut self, setsid: bool) -> &mut process::Command;
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -260,6 +263,11 @@ impl CommandExt for process::Command {
self.as_inner_mut().chroot(dir.as_ref());
self
}
fn setsid(&mut self, setsid: bool) -> &mut process::Command {
self.as_inner_mut().setsid(setsid);
self
}
}
/// Unix-specific extensions to [`process::ExitStatus`] and

View File

@@ -1,37 +1,54 @@
use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::sync::{Arc, Mutex};
use crate::sys::unsupported;
use crate::time::Duration;
mod tcp;
pub(crate) mod tcp4;
pub struct TcpStream(tcp::Tcp);
pub struct TcpStream {
inner: tcp::Tcp,
read_timeout: Arc<Mutex<Option<Duration>>>,
write_timeout: Arc<Mutex<Option<Duration>>>,
}
impl TcpStream {
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
tcp::Tcp::connect(addr?).map(Self)
let inner = tcp::Tcp::connect(addr?, None)?;
Ok(Self {
inner,
read_timeout: Arc::new(Mutex::new(None)),
write_timeout: Arc::new(Mutex::new(None)),
})
}
pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
unsupported()
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
let inner = tcp::Tcp::connect(addr, Some(timeout))?;
Ok(Self {
inner,
read_timeout: Arc::new(Mutex::new(None)),
write_timeout: Arc::new(Mutex::new(None)),
})
}
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
unsupported()
pub fn set_read_timeout(&self, t: Option<Duration>) -> io::Result<()> {
self.read_timeout.set(t).unwrap();
Ok(())
}
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
unsupported()
pub fn set_write_timeout(&self, t: Option<Duration>) -> io::Result<()> {
self.write_timeout.set(t).unwrap();
Ok(())
}
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
unsupported()
Ok(self.read_timeout.get_cloned().unwrap())
}
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
unsupported()
Ok(self.write_timeout.get_cloned().unwrap())
}
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
@@ -39,7 +56,7 @@ impl TcpStream {
}
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
self.inner.read(buf, self.read_timeout()?)
}
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
@@ -56,7 +73,7 @@ impl TcpStream {
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
self.inner.write(buf, self.write_timeout()?)
}
pub fn write_vectored(&self, buf: &[IoSlice<'_>]) -> io::Result<usize> {

View File

@@ -1,33 +1,34 @@
use super::tcp4;
use crate::io;
use crate::net::SocketAddr;
use crate::time::Duration;
pub(crate) enum Tcp {
V4(tcp4::Tcp4),
}
impl Tcp {
pub(crate) fn connect(addr: &SocketAddr) -> io::Result<Self> {
pub(crate) fn connect(addr: &SocketAddr, timeout: Option<Duration>) -> io::Result<Self> {
match addr {
SocketAddr::V4(x) => {
let temp = tcp4::Tcp4::new()?;
temp.configure(true, Some(x), None)?;
temp.connect()?;
temp.connect(timeout)?;
Ok(Tcp::V4(temp))
}
SocketAddr::V6(_) => todo!(),
}
}
pub(crate) fn write(&self, buf: &[u8]) -> io::Result<usize> {
pub(crate) fn write(&self, buf: &[u8], timeout: Option<Duration>) -> io::Result<usize> {
match self {
Self::V4(client) => client.write(buf),
Self::V4(client) => client.write(buf, timeout),
}
}
pub(crate) fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
pub(crate) fn read(&self, buf: &mut [u8], timeout: Option<Duration>) -> io::Result<usize> {
match self {
Self::V4(client) => client.read(buf),
Self::V4(client) => client.read(buf, timeout),
}
}
}

View File

@@ -6,6 +6,7 @@ use crate::net::SocketAddrV4;
use crate::ptr::NonNull;
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sys::pal::helpers;
use crate::time::{Duration, Instant};
const TYPE_OF_SERVICE: u8 = 8;
const TIME_TO_LIVE: u8 = 255;
@@ -66,7 +67,7 @@ impl Tcp4 {
if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}
pub(crate) fn connect(&self) -> io::Result<()> {
pub(crate) fn connect(&self, timeout: Option<Duration>) -> io::Result<()> {
let evt = unsafe { self.create_evt() }?;
let completion_token =
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
@@ -79,7 +80,7 @@ impl Tcp4 {
return Err(io::Error::from_raw_os_error(r.as_usize()));
}
self.wait_for_flag();
unsafe { self.wait_or_cancel(timeout, &mut conn_token.completion_token) }?;
if completion_token.status.is_error() {
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
@@ -88,7 +89,7 @@ impl Tcp4 {
}
}
pub(crate) fn write(&self, buf: &[u8]) -> io::Result<usize> {
pub(crate) fn write(&self, buf: &[u8], timeout: Option<Duration>) -> io::Result<usize> {
let evt = unsafe { self.create_evt() }?;
let completion_token =
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
@@ -119,7 +120,7 @@ impl Tcp4 {
return Err(io::Error::from_raw_os_error(r.as_usize()));
}
self.wait_for_flag();
unsafe { self.wait_or_cancel(timeout, &mut token.completion_token) }?;
if completion_token.status.is_error() {
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
@@ -128,7 +129,7 @@ impl Tcp4 {
}
}
pub(crate) fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
pub(crate) fn read(&self, buf: &mut [u8], timeout: Option<Duration>) -> io::Result<usize> {
let evt = unsafe { self.create_evt() }?;
let completion_token =
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
@@ -158,7 +159,7 @@ impl Tcp4 {
return Err(io::Error::from_raw_os_error(r.as_usize()));
}
self.wait_for_flag();
unsafe { self.wait_or_cancel(timeout, &mut token.completion_token) }?;
if completion_token.status.is_error() {
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
@@ -167,6 +168,50 @@ impl Tcp4 {
}
}
/// Wait for an event to finish. This is checked by an atomic boolean that is supposed to be set
/// to true in the event callback.
///
/// Optionally, allow specifying a timeout.
///
/// If a timeout is provided, the operation (specified by its `EFI_TCP4_COMPLETION_TOKEN`) is
/// canceled and Error of kind TimedOut is returned.
///
/// # SAFETY
///
/// Pointer to a valid `EFI_TCP4_COMPLETION_TOKEN`
unsafe fn wait_or_cancel(
&self,
timeout: Option<Duration>,
token: *mut tcp4::CompletionToken,
) -> io::Result<()> {
if !self.wait_for_flag(timeout) {
let _ = unsafe { self.cancel(token) };
return Err(io::Error::new(io::ErrorKind::TimedOut, "Operation Timed out"));
}
Ok(())
}
/// Abort an asynchronous connection, listen, transmission or receive request.
///
/// If token is NULL, then all pending tokens issued by EFI_TCP4_PROTOCOL.Connect(),
/// EFI_TCP4_PROTOCOL.Accept(), EFI_TCP4_PROTOCOL.Transmit() or EFI_TCP4_PROTOCOL.Receive() are
/// aborted.
///
/// # SAFETY
///
/// Pointer to a valid `EFI_TCP4_COMPLETION_TOKEN` or NULL
unsafe fn cancel(&self, token: *mut tcp4::CompletionToken) -> io::Result<()> {
let protocol = self.protocol.as_ptr();
let r = unsafe { ((*protocol).cancel)(protocol, token) };
if r.is_error() {
return Err(io::Error::from_raw_os_error(r.as_usize()));
} else {
Ok(())
}
}
unsafe fn create_evt(&self) -> io::Result<helpers::OwnedEvent> {
self.flag.store(false, Ordering::Relaxed);
helpers::OwnedEvent::new(
@@ -177,11 +222,20 @@ impl Tcp4 {
)
}
fn wait_for_flag(&self) {
fn wait_for_flag(&self, timeout: Option<Duration>) -> bool {
let start = Instant::now();
while !self.flag.load(Ordering::Relaxed) {
let _ = self.poll();
if let Some(t) = timeout {
if Instant::now().duration_since(start) >= t {
return false;
}
}
}
true
}
fn poll(&self) -> io::Result<()> {
let protocol = self.protocol.as_ptr();

View File

@@ -98,6 +98,7 @@ pub struct Command {
#[cfg(target_os = "linux")]
create_pidfd: bool,
pgroup: Option<pid_t>,
setsid: bool,
}
// passed back to std::process with the pipes connected to the child, if any
@@ -185,6 +186,7 @@ impl Command {
#[cfg(target_os = "linux")]
create_pidfd: false,
pgroup: None,
setsid: false,
}
}
@@ -220,6 +222,9 @@ impl Command {
self.cwd(&OsStr::new("/"));
}
}
pub fn setsid(&mut self, setsid: bool) {
self.setsid = setsid;
}
#[cfg(target_os = "linux")]
pub fn create_pidfd(&mut self, val: bool) {
@@ -298,6 +303,10 @@ impl Command {
pub fn get_chroot(&self) -> Option<&CStr> {
self.chroot.as_deref()
}
#[allow(dead_code)]
pub fn get_setsid(&self) -> bool {
self.setsid
}
pub fn get_closures(&mut self) -> &mut Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>> {
&mut self.closures

View File

@@ -134,6 +134,64 @@ fn test_process_group_no_posix_spawn() {
}
}
#[test]
#[cfg_attr(
any(
// See test_process_mask
target_os = "macos",
target_arch = "arm",
target_arch = "aarch64",
target_arch = "riscv64",
),
ignore
)]
fn test_setsid_posix_spawn() {
// Spawn a cat subprocess that's just going to hang since there is no I/O.
let mut cmd = Command::new(OsStr::new("cat"));
cmd.setsid(true);
cmd.stdin(Stdio::MakePipe);
cmd.stdout(Stdio::MakePipe);
let (mut cat, _pipes) = t!(cmd.spawn(Stdio::Null, true));
unsafe {
// Setsid will create a new session and process group, so check that
// we can kill the process group, which means there *is* one.
t!(cvt(libc::kill(-(cat.id() as libc::pid_t), libc::SIGINT)));
t!(cat.wait());
}
}
#[test]
#[cfg_attr(
any(
// See test_process_mask
target_os = "macos",
target_arch = "arm",
target_arch = "aarch64",
target_arch = "riscv64",
),
ignore
)]
fn test_setsid_no_posix_spawn() {
let mut cmd = Command::new(OsStr::new("cat"));
cmd.setsid(true);
cmd.stdin(Stdio::MakePipe);
cmd.stdout(Stdio::MakePipe);
unsafe {
// Same as above, create hang-y cat. This time, force using the non-posix_spawn path.
cmd.pre_exec(Box::new(|| Ok(()))); // pre_exec forces fork + exec rather than posix spawn.
let (mut cat, _pipes) = t!(cmd.spawn(Stdio::Null, true));
// Setsid will create a new session and process group, so check that
// we can kill the process group, which means there *is* one.
t!(cvt(libc::kill(-(cat.id() as libc::pid_t), libc::SIGINT)));
t!(cat.wait());
}
}
#[test]
fn test_program_kind() {
let vectors = &[

View File

@@ -340,6 +340,10 @@ impl Command {
cvt(libc::setpgid(0, pgroup))?;
}
if self.get_setsid() {
cvt(libc::setsid())?;
}
// emscripten has no signal support.
#[cfg(not(target_os = "emscripten"))]
{
@@ -741,6 +745,16 @@ impl Command {
flags |= libc::POSIX_SPAWN_SETSIGDEF;
}
if self.get_setsid() {
cfg_if::cfg_if! {
if #[cfg(all(target_os = "linux", target_env = "gnu"))] {
flags |= libc::POSIX_SPAWN_SETSID;
} else {
return Ok(None);
}
}
}
cvt_nz(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
// Make sure we synchronize access to the global `environ` resource

View File

@@ -9,7 +9,7 @@ use clippy_utils::visitors::{Descend, for_each_expr};
use hir::HirId;
use rustc_hir as hir;
use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
use rustc_lexer::{TokenKind, tokenize};
use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass;
use rustc_span::{BytePos, Pos, RelativeBytePos, Span, SyntaxContext};
@@ -746,7 +746,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos
loop {
if line.starts_with("/*") {
let src = &src[line_start..line_starts.last().unwrap().to_usize()];
let mut tokens = tokenize(src);
let mut tokens = tokenize(src, FrontmatterAllowed::No);
return (src[..tokens.next().unwrap().len as usize]
.to_ascii_uppercase()
.contains("SAFETY:")

View File

@@ -3,7 +3,7 @@ use clippy_utils::source::SpanRangeExt;
use itertools::Itertools;
use rustc_ast::{Crate, Expr, ExprKind, FormatArgs};
use rustc_data_structures::fx::FxHashMap;
use rustc_lexer::{TokenKind, tokenize};
use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::impl_lint_pass;
use rustc_span::{Span, hygiene};
@@ -82,7 +82,7 @@ fn has_span_from_proc_macro(cx: &EarlyContext<'_>, args: &FormatArgs) -> bool {
.all(|sp| {
sp.check_source_text(cx, |src| {
// text should be either `, name` or `, name =`
let mut iter = tokenize(src).filter(|t| {
let mut iter = tokenize(src, FrontmatterAllowed::No).filter(|t| {
!matches!(
t.kind,
TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace

View File

@@ -15,7 +15,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::{
BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExpr, PatExprKind, QPath, UnOp,
};
use rustc_lexer::tokenize;
use rustc_lexer::{FrontmatterAllowed, tokenize};
use rustc_lint::LateContext;
use rustc_middle::mir::ConstValue;
use rustc_middle::mir::interpret::{Scalar, alloc_range};
@@ -304,9 +304,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option<Ty<'tcx>>) -> Constan
match *lit {
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
LitKind::Byte(b) => Constant::Int(u128::from(b)),
LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => {
Constant::Binary(s.as_byte_str().to_vec())
}
LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(s.as_byte_str().to_vec()),
LitKind::Char(c) => Constant::Char(c),
LitKind::Int(n, _) => Constant::Int(n.get()),
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
@@ -568,9 +566,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
} else {
match &lit.node {
LitKind::Str(is, _) => Some(is.is_empty()),
LitKind::ByteStr(s, _) | LitKind::CStr(s, _) => {
Some(s.as_byte_str().is_empty())
}
LitKind::ByteStr(s, _) | LitKind::CStr(s, _) => Some(s.as_byte_str().is_empty()),
_ => None,
}
}
@@ -715,7 +711,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
&& let Some(src) = src.as_str()
{
use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace};
if !tokenize(src)
if !tokenize(src, FrontmatterAllowed::No)
.map(|t| t.kind)
.filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi))
.eq([OpenBrace])

View File

@@ -12,7 +12,7 @@ use rustc_hir::{
Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr,
TraitBoundModifiers, Ty, TyKind, TyPat, TyPatKind,
};
use rustc_lexer::{TokenKind, tokenize};
use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
use rustc_lint::LateContext;
use rustc_middle::ty::TypeckResults;
use rustc_span::{BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext, sym};
@@ -686,7 +686,7 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &'
// `{}` => `()`
([], None)
if block.span.check_source_text(cx, |src| {
tokenize(src)
tokenize(src, FrontmatterAllowed::No)
.map(|t| t.kind)
.filter(|t| {
!matches!(

View File

@@ -106,7 +106,7 @@ use rustc_hir::{
Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, TraitFn, TraitItem,
TraitItemKind, TraitRef, TyKind, UnOp, def,
};
use rustc_lexer::{TokenKind, tokenize};
use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
use rustc_lint::{LateContext, Level, Lint, LintContext};
use rustc_middle::hir::nested_filter;
use rustc_middle::hir::place::PlaceBase;
@@ -2764,7 +2764,7 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'tcx>) -> ExprUseCtx
/// Tokenizes the input while keeping the text associated with each token.
pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str, InnerSpan)> {
let mut pos = 0;
tokenize(s).map(move |t| {
tokenize(s, FrontmatterAllowed::No).map(move |t| {
let end = pos + t.len;
let range = pos as usize..end as usize;
let inner = InnerSpan::new(range.start, range.end);
@@ -2779,7 +2779,7 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
let Ok(snippet) = sm.span_to_snippet(span) else {
return false;
};
return tokenize(&snippet).any(|token| {
return tokenize(&snippet, FrontmatterAllowed::No).any(|token| {
matches!(
token.kind,
TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }

View File

@@ -7,7 +7,7 @@ use std::sync::Arc;
use rustc_ast::{LitKind, StrStyle};
use rustc_errors::Applicability;
use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
use rustc_lexer::{LiteralKind, TokenKind, tokenize};
use rustc_lexer::{FrontmatterAllowed, LiteralKind, TokenKind, tokenize};
use rustc_lint::{EarlyContext, LateContext};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
@@ -277,7 +277,7 @@ fn map_range(
}
fn ends_with_line_comment_or_broken(text: &str) -> bool {
let Some(last) = tokenize(text).last() else {
let Some(last) = tokenize(text, FrontmatterAllowed::No).last() else {
return false;
};
match last.kind {
@@ -310,7 +310,8 @@ fn with_leading_whitespace_inner(lines: &[RelativeBytePos], src: &str, range: Ra
&& ends_with_line_comment_or_broken(&start[prev_start..])
&& let next_line = lines.partition_point(|&pos| pos.to_usize() < range.end)
&& let next_start = lines.get(next_line).map_or(src.len(), |&x| x.to_usize())
&& tokenize(src.get(range.end..next_start)?).any(|t| !matches!(t.kind, TokenKind::Whitespace))
&& tokenize(src.get(range.end..next_start)?, FrontmatterAllowed::No)
.any(|t| !matches!(t.kind, TokenKind::Whitespace))
{
Some(range.start)
} else {

View File

@@ -11,8 +11,8 @@
use std::ops;
use rustc_literal_escaper::{
EscapeError, Mode, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char,
unescape_str,
unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str, EscapeError,
Mode,
};
use crate::{
@@ -44,7 +44,9 @@ impl<'a> LexedStr<'a> {
// Re-create the tokenizer from scratch every token because `GuardedStrPrefix` is one token in the lexer
// but we want to split it to two in edition <2024.
while let Some(token) = rustc_lexer::tokenize(&text[conv.offset..]).next() {
while let Some(token) =
rustc_lexer::tokenize(&text[conv.offset..], rustc_lexer::FrontmatterAllowed::No).next()
{
let token_text = &text[conv.offset..][..token.len as usize];
conv.extend_token(&token.kind, token_text);
@@ -58,7 +60,7 @@ impl<'a> LexedStr<'a> {
return None;
}
let token = rustc_lexer::tokenize(text).next()?;
let token = rustc_lexer::tokenize(text, rustc_lexer::FrontmatterAllowed::No).next()?;
if token.len as usize != text.len() {
return None;
}

View File

@@ -121,7 +121,7 @@ pub(super) fn literal_from_str<Span: Copy>(
use proc_macro::bridge::LitKind;
use rustc_lexer::{LiteralKind, Token, TokenKind};
let mut tokens = rustc_lexer::tokenize(s);
let mut tokens = rustc_lexer::tokenize(s, rustc_lexer::FrontmatterAllowed::No);
let minus_or_lit = tokens.next().unwrap_or(Token { kind: TokenKind::Eof, len: 0 });
let lit = if minus_or_lit.kind == TokenKind::Minus {

View File

@@ -579,7 +579,7 @@ where
{
use rustc_lexer::LiteralKind;
let token = rustc_lexer::tokenize(text).next_tuple();
let token = rustc_lexer::tokenize(text, rustc_lexer::FrontmatterAllowed::No).next_tuple();
let Some((rustc_lexer::Token {
kind: rustc_lexer::TokenKind::Literal { kind, suffix_start },
..

View File

@@ -29,28 +29,28 @@ pub struct Aggregate8(u8);
// CHECK-LABEL: @check_bigger_size(
#[no_mangle]
pub unsafe fn check_bigger_size(x: u16) -> u32 {
// CHECK: call void @llvm.assume(i1 false)
// CHECK: store i1 true, ptr poison, align 1
transmute_unchecked(x)
}
// CHECK-LABEL: @check_smaller_size(
#[no_mangle]
pub unsafe fn check_smaller_size(x: u32) -> u16 {
// CHECK: call void @llvm.assume(i1 false)
// CHECK: store i1 true, ptr poison, align 1
transmute_unchecked(x)
}
// CHECK-LABEL: @check_smaller_array(
#[no_mangle]
pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
// CHECK: call void @llvm.assume(i1 false)
// CHECK: store i1 true, ptr poison, align 1
transmute_unchecked(x)
}
// CHECK-LABEL: @check_bigger_array(
#[no_mangle]
pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
// CHECK: call void @llvm.assume(i1 false)
// CHECK: store i1 true, ptr poison, align 1
transmute_unchecked(x)
}
@@ -58,9 +58,9 @@ pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
// CHECK-NOT: trap
// CHECK: call void @llvm.trap
// CHECK-NOT: trap
// CHECK: start
// CHECK-NEXT: store i1 true, ptr poison, align 1
// CHECK-NEXT: ret void
mir! {
{
RET = CastTransmute(x);
@@ -73,9 +73,9 @@ pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
// CHECK-NOT: call
// CHECK: call void @llvm.assume(i1 false)
// CHECK-NOT: call
// CHECK: start
// CHECK-NEXT: store i1 true, ptr poison, align 1
// CHECK-NEXT: ret void
mir! {
{
RET = CastTransmute(x);
@@ -88,9 +88,9 @@ pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_to_uninhabited(x: u16) {
// CHECK-NOT: trap
// CHECK: call void @llvm.trap
// CHECK-NOT: trap
// CHECK: start
// CHECK-NEXT: store i1 true, ptr poison, align 1
// CHECK-NEXT: ret void
mir! {
let temp: BigNever;
{
@@ -104,7 +104,9 @@ pub unsafe fn check_to_uninhabited(x: u16) {
#[no_mangle]
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
// CHECK: ret i16 poison
// CHECK: start
// CHECK-NEXT: store i1 true, ptr poison, align 1
// CHECK-NEXT: ret i16 poison
mir! {
{
RET = CastTransmute(x);
@@ -401,9 +403,9 @@ pub unsafe fn check_issue_109992(x: ()) -> [(); 1] {
pub unsafe fn check_unit_to_never(x: ()) {
// This uses custom MIR to avoid MIR optimizations having removed ZST ops.
// CHECK-NOT: trap
// CHECK: call void @llvm.trap
// CHECK-NOT: trap
// CHECK: start
// CHECK-NEXT: store i1 true, ptr poison, align 1
// CHECK-NEXT: ret void
mir! {
let temp: ZstNever;
{
@@ -420,6 +422,7 @@ pub unsafe fn check_unit_from_never(x: ZstNever) -> () {
// This uses custom MIR to avoid MIR optimizations having removed ZST ops.
// CHECK: start
// CHECK-NEXT: store i1 true, ptr poison, align 1
// CHECK-NEXT: ret void
mir! {
{

View File

@@ -0,0 +1,13 @@
//! Checks that `Weak` pointers can be created with an empty enum type parameter.
//! And generic `Weak` handles zero-variant enums without error.
//!
//! Regression test for <https://github.com/rust-lang/rust/issues/48493>
//@ run-pass
enum Void {}
fn main() {
let _ = std::rc::Weak::<Void>::new();
let _ = std::sync::Weak::<Void>::new();
}

View File

@@ -42,7 +42,7 @@ LL + type X = <CString as Deref>::Target;
LL - type X = std::ops::Deref::Target;
LL + type X = <IoSlice<'_> as Deref>::Target;
|
and N other candidates
= and N other candidates
error[E0223]: ambiguous associated type
--> $DIR/associated-types-in-ambiguous-context.rs:13:23

View File

@@ -1,11 +1,14 @@
//! Checks how type parameters interact with auto-traits like `Send` and `Sync` with implicit
//! bounds
//@ run-pass
#![allow(non_camel_case_types)]
#![allow(dead_code)]
fn p_foo<T>(_pinned: T) { }
fn s_foo<T>(_shared: T) { }
fn u_foo<T:Send>(_unique: T) { }
fn p_foo<T>(_pinned: T) {}
fn s_foo<T>(_shared: T) {}
fn u_foo<T: Send>(_unique: T) {}
struct r {
i: isize,
@@ -15,10 +18,8 @@ impl Drop for r {
fn drop(&mut self) {}
}
fn r(i:isize) -> r {
r {
i: i
}
fn r(i: isize) -> r {
r { i }
}
pub fn main() {

View File

@@ -0,0 +1,15 @@
//! Test that argument names starting with `_` are usable.
//@ run-pass
fn good(_a: &isize) {}
fn called<F>(_f: F)
where
F: FnOnce(&isize),
{
}
pub fn main() {
called(good);
}

View File

@@ -0,0 +1,19 @@
//! Checks borrow after move error when using `self` consuming method with struct update syntax.
struct Mine {
test: String,
other_val: isize,
}
impl Mine {
fn make_string_bar(mut self) -> Mine {
self.test = "Bar".to_string();
self
}
}
fn main() {
let start = Mine { test: "Foo".to_string(), other_val: 0 };
let end = Mine { other_val: 1, ..start.make_string_bar() };
println!("{}", start.test); //~ ERROR borrow of moved value: `start`
}

View File

@@ -1,17 +1,17 @@
error[E0382]: borrow of moved value: `start`
--> $DIR/walk-struct-literal-with.rs:16:20
--> $DIR/ownership-struct-update-moved-error.rs:18:20
|
LL | let start = Mine{test:"Foo".to_string(), other_val:0};
LL | let start = Mine { test: "Foo".to_string(), other_val: 0 };
| ----- move occurs because `start` has type `Mine`, which does not implement the `Copy` trait
LL | let end = Mine{other_val:1, ..start.make_string_bar()};
LL | let end = Mine { other_val: 1, ..start.make_string_bar() };
| ----------------- `start` moved due to this method call
LL | println!("{}", start.test);
| ^^^^^^^^^^ value borrowed here after move
|
note: `Mine::make_string_bar` takes ownership of the receiver `self`, which moves `start`
--> $DIR/walk-struct-literal-with.rs:7:28
--> $DIR/ownership-struct-update-moved-error.rs:9:28
|
LL | fn make_string_bar(mut self) -> Mine{
LL | fn make_string_bar(mut self) -> Mine {
| ^^^^
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@@ -1,3 +1,5 @@
//! Sanity check for no capture closures
//@ run-pass
pub fn main() {

View File

@@ -14,7 +14,7 @@ LL + use std::collections::btree_map::IntoIter;
|
LL + use std::collections::btree_set::IntoIter;
|
and 9 other candidates
= and 9 other candidates
error: aborting due to 1 previous error

View File

@@ -0,0 +1,15 @@
//! This checks that compiler correctly evaluate constant array lengths within trait `impl` headers.
//!
//! Regression test for <https://github.com/rust-lang/rust/issues/49208>.
trait Foo {
fn foo();
}
impl Foo for [(); 1] {
fn foo() {}
}
fn main() {
<[(); 0] as Foo>::foo() //~ ERROR E0277
}

View File

@@ -1,5 +1,5 @@
error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied
--> $DIR/unevaluated_fixed_size_array_len.rs:12:6
--> $DIR/const-eval-array-len-in-impl.rs:14:6
|
LL | <[(); 0] as Foo>::foo()
| ^^^^^^^ the trait `Foo` is not implemented for `[(); 0]`

View File

@@ -1,3 +1,5 @@
//! Checks basic multiple variable declaration using tuple destructuring in a `let` binding.
//@ run-pass
pub fn main() {

View File

@@ -18,7 +18,7 @@ LL + fn setup() -> Determine { Set }
LL - fn setup() -> Set { Set }
LL + fn setup() -> PutDown { Set }
|
and 3 other candidates
= and 3 other candidates
error[E0425]: cannot find value `Set` in this scope
--> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21
@@ -36,7 +36,7 @@ LL + use Determine::Set;
|
LL + use PutDown::Set;
|
and 3 other candidates
= and 3 other candidates
error: aborting due to 2 previous errors

View File

@@ -0,0 +1,12 @@
//! Regression test for a crash caused by an "unsused move"
//! (specifically, a variable bound to a `Box` used as a statement)
//! leading to incorrect memory zero-filling after drop.
//!
//! Regression test for <https://github.com/rust-lang/rust/issues/3878>.
//@ run-pass
pub fn main() {
let y: Box<_> = Box::new(1);
drop(y);
}

View File

@@ -1,26 +1,27 @@
//! Check for correct initialization of `HashSet` with enums. This is a regression test for a
//! codegen bug that caused the `HashSet` to appear as if it contained one of each enum variant.
//!
//! Regression test for <https://github.com/rust-lang/rust/issues/42918>
//@ run-pass
//
#![allow(dead_code)]
//@ compile-flags: -O
#![allow(dead_code)]
use std::collections::HashSet;
#[derive(PartialEq, Debug, Hash, Eq, Clone, PartialOrd, Ord)]
enum MyEnum {
E0,
E1,
E2,
E3,
E4,
E5,
E6,
E7,
}
fn main() {
use MyEnum::*;
let s: HashSet<_> = [E4, E1].iter().cloned().collect();

View File

@@ -30,7 +30,7 @@ LL + use std::fmt::Display;
|
LL + use std::fmt::LowerExp;
|
and 5 other candidates
= and 5 other candidates
error: aborting due to 2 previous errors

View File

@@ -18,7 +18,7 @@ LL + use ::issue_56125::issue_56125;
LL - use empty::issue_56125;
LL + use ::issue_56125::last_segment::issue_56125;
|
and 1 other candidate
= and 1 other candidate
error[E0659]: `issue_56125` is ambiguous
--> $DIR/issue-56125.rs:6:9

View File

@@ -1,3 +1,6 @@
//! Tests that errors from both the writer (`Write::write`) and formatter (`Display::fmt`)
//! are correctly propagated: writer errors return `Err`, formatter errors cause panics.
//@ run-pass
//@ needs-unwind
@@ -24,7 +27,9 @@ impl Write for ErrorWriter {
Err(Error::new(WRITER_ERROR, "not connected"))
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
fn main() {
@@ -37,7 +42,8 @@ fn main() {
let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap();
assert!(
err.contains("formatting trait implementation returned an error"),
"unexpected panic: {}", err
"unexpected panic: {}",
err
);
// Writer error when there's some string before the first `{}`
@@ -50,6 +56,7 @@ fn main() {
let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap();
assert!(
err.contains("formatting trait implementation returned an error"),
"unexpected panic: {}", err
"unexpected panic: {}",
err
);
}

View File

@@ -0,0 +1,12 @@
//! Checks that compiler prevernt attempting to define an unrecognized or unknown lang item
#![allow(unused)]
#![feature(lang_items)]
#[lang = "foo"]
fn bar() -> ! {
//~^^ ERROR definition of an unknown lang item: `foo`
loop {}
}
fn main() {}

View File

@@ -1,5 +1,5 @@
error[E0522]: definition of an unknown lang item: `foo`
--> $DIR/unknown-language-item.rs:4:1
--> $DIR/lang-item-unknown-definition-error.rs:6:1
|
LL | #[lang = "foo"]
| ^^^^^^^^^^^^^^^ definition of unknown lang item `foo`

View File

@@ -1,11 +1,15 @@
//! Checks that `std::any::Any` cannot be used to circumvent lifetime rules
//! with higher-rank types.
//@ run-pass
// Test that we can't ignore lifetimes by going through Any.
use std::any::Any;
struct Foo<'a>(&'a str);
fn good(s: &String) -> Foo<'_> { Foo(s) }
fn good(s: &String) -> Foo<'_> {
Foo(s)
}
fn bad1(s: String) -> Option<&'static str> {
let a: Box<dyn Any> = Box::new(good as fn(&String) -> Foo);
@@ -17,7 +21,9 @@ trait AsStr<'a, 'b> {
}
impl<'a> AsStr<'a, 'a> for String {
fn get(&'a self) -> &'a str { self }
fn get(&'a self) -> &'a str {
self
}
}
fn bad2(s: String) -> Option<&'static str> {

View File

@@ -1,17 +1,19 @@
//@ build-fail
//@ compile-flags: -Copt-level=0 -Zenforce-type-length-limit
//~^^ ERROR reached the type-length limit
//~ ERROR reached the type-length limit
// Test that the type length limit can be changed.
// The exact type depends on optimizations, so disable them.
//! Checks the enforcement of the type-length limit
//! and its configurability via `#![type_length_limit]`.
//@ compile-flags: -Copt-level=0 -Zenforce-type-length-limit
//@ build-fail
#![allow(dead_code)]
#![type_length_limit="8"]
#![type_length_limit = "8"]
macro_rules! link {
($id:ident, $t:ty) => {
pub type $id = ($t, $t, $t);
}
};
}
link! { A1, B1 }
@@ -26,7 +28,7 @@ link! { D, E }
link! { E, F }
link! { F, G<Option<i32>, Option<i32>> }
pub struct G<T, K>(std::marker::PhantomData::<(T, K)>);
pub struct G<T, K>(std::marker::PhantomData<(T, K)>);
fn main() {
drop::<Option<A>>(None);

View File

@@ -1,11 +1,11 @@
error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
--> $DIR/type_length_limit.rs:32:5
--> $DIR/type-length-limit-enforcement.rs:34:5
|
LL | drop::<Option<A>>(None);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#![type_length_limit="4010"]` attribute to your crate
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit.long-type.txt'
= note: the full type name has been written to '$TEST_BUILD_DIR/type-length-limit-enforcement.long-type.txt'
error: reached the type-length limit while instantiating `<{closure@rt::lang_start<()>::{closure#0}} as FnMut<()>>::call_mut`
|

View File

@@ -419,7 +419,7 @@ mod foo {
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::hash_map::Iter;\u001b[0m
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
\u001b[0m and 9 other candidates\u001b[0m
\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0mand 9 other candidates\u001b[0m
"
}

View File

@@ -0,0 +1,12 @@
//! Verifies that the reserved underscore `_` cannot be used as an `ident` fragment specifier
//! within a macro pattern, as it leads to a compilation error.
macro_rules! identity {
($i: ident) => {
$i
};
}
fn main() {
let identity!(_) = 10; //~ ERROR no rules expected reserved identifier `_`
}

View File

@@ -1,5 +1,5 @@
error: no rules expected reserved identifier `_`
--> $DIR/underscore-ident-matcher.rs:8:19
--> $DIR/macro-fragment-ident-underscore-error.rs:11:19
|
LL | macro_rules! identity {
| --------------------- when calling this macro
@@ -8,9 +8,9 @@ LL | let identity!(_) = 10;
| ^ no rules expected this token in macro call
|
note: while trying to match meta-variable `$i:ident`
--> $DIR/underscore-ident-matcher.rs:2:6
--> $DIR/macro-fragment-ident-underscore-error.rs:5:6
|
LL | ($i: ident) => (
LL | ($i: ident) => {
| ^^^^^^^^^
error: aborting due to 1 previous error

View File

@@ -0,0 +1,20 @@
//! Checks that functions from different modules are accessible via their fully-qualified paths.
//@ run-pass
mod foo {
pub fn x() -> isize {
return 1;
}
}
mod bar {
pub fn y() -> isize {
return 1;
}
}
pub fn main() {
foo::x();
bar::y();
}

View File

@@ -1,3 +1,5 @@
//! Checks complex `use` syntax and availability of types across nested modules.
//@ run-pass
mod a {

View File

@@ -0,0 +1,13 @@
//! Make sure the module level constants are still there and accessible even after
//! the corresponding associated constants have been added, and later stabilized.
//@ run-pass
#![allow(deprecated, deprecated_in_future)]
use std::{f32, u16};
fn main() {
let _ = u16::MAX;
let _ = f32::EPSILON;
let _ = std::f64::MANTISSA_DIGITS;
}

View File

@@ -1,18 +1,20 @@
//! Checks module re-exports, aliasing with `pub use`,
//! and calling private methods via `Self` in an impl block.
//@ run-pass
#![allow(unused_variables)]
pub struct A;
mod test {
pub use super :: A;
pub use self :: A as B;
pub use self::A as B;
pub use super::A;
}
impl A {
fn f() {}
fn g() {
Self :: f()
Self::f()
}
}

View File

@@ -0,0 +1,14 @@
//@ run-pass
struct A {
a: isize,
}
fn a(a: A) -> isize {
return a.a;
}
pub fn main() {
let x: A = A { a: 1 };
assert_eq!(a(x), 1);
}

View File

@@ -1,3 +1,5 @@
//! This test ensures that the unary negation operator (`-`) cannot be applied to unsigned ints
fn main() {
let x = -1 as usize; //~ ERROR: cannot apply unary operator `-`
let x = (-1) as usize; //~ ERROR: cannot apply unary operator `-`

View File

@@ -1,5 +1,5 @@
error[E0600]: cannot apply unary operator `-` to type `usize`
--> $DIR/unsigned-literal-negation.rs:2:13
--> $DIR/unary-negation-unsigned-integer-error.rs:4:13
|
LL | let x = -1 as usize;
| ^^ cannot apply unary operator `-`
@@ -12,7 +12,7 @@ LL + let x = usize::MAX;
|
error[E0600]: cannot apply unary operator `-` to type `usize`
--> $DIR/unsigned-literal-negation.rs:3:13
--> $DIR/unary-negation-unsigned-integer-error.rs:5:13
|
LL | let x = (-1) as usize;
| ^^^^ cannot apply unary operator `-`
@@ -25,7 +25,7 @@ LL + let x = usize::MAX;
|
error[E0600]: cannot apply unary operator `-` to type `u32`
--> $DIR/unsigned-literal-negation.rs:4:18
--> $DIR/unary-negation-unsigned-integer-error.rs:6:18
|
LL | let x: u32 = -1;
| ^^ cannot apply unary operator `-`

View File

@@ -1,3 +1,7 @@
//! This test checks that Rust's unwinding mechanism correctly executes `Drop`
//! implementations during stack unwinding, even when unwind tables (`uwtable`)
//! are explicitly disabled via `-C force-unwind-tables=n`.
//@ run-pass
//@ needs-unwind
//@ ignore-windows target requires uwtable
@@ -26,9 +30,12 @@ fn increase(count: &mut u8) {
fn main() {
let mut count = 0;
assert!(panic::catch_unwind(AssertUnwindSafe(
assert!(
panic::catch_unwind(AssertUnwindSafe(
#[inline(never)]
|| increase(&mut count)
)).is_err());
))
.is_err()
);
assert_eq!(count, 1);
}

View File

@@ -0,0 +1,15 @@
//! Checks that methods with names starting with an underscore (`_`) can be
//! successfully called directly on integer literals, confirming the correct
//! parsing of such expressions where the underscore is part of the method identifier.
//@ run-pass
trait Tr: Sized {
fn _method_on_numbers(self) {}
}
impl Tr for i32 {}
fn main() {
42._method_on_numbers();
}

View File

@@ -63,7 +63,7 @@ LL - x: (),
LL - })),
LL + wtf: Some(Box::new_in(_, _)),
|
and 12 other candidates
= and 12 other candidates
help: consider using the `Default` trait
|
LL - wtf: Some(Box(U {
@@ -118,7 +118,7 @@ LL + let _ = Box::new_zeroed();
LL - let _ = Box {};
LL + let _ = Box::new_in(_, _);
|
and 12 other candidates
= and 12 other candidates
help: consider using the `Default` trait
|
LL - let _ = Box {};

View File

@@ -1,3 +1,9 @@
//! Tests that repeatedly spawning a failing command does not create zombie processes.
//! Spawns a deliberately invalid command multiple times, verifies each spawn fails,
//! then uses `ps` (on Unix) to detect any leftover zombie (defunct) child processes.
//! Checks Rust's process spawning cleans up resources properly.
//! Skipped on platforms without `ps` utility.
//@ run-pass
//@ needs-subprocess
//@ ignore-vxworks no 'ps'
@@ -36,35 +42,42 @@ fn find_zombies() {
// the PPID column contains a "-" for the respective process.
// Filter out any lines that have a "-" as the PPID as the PPID is
// expected to be an integer.
let filtered_ps: Vec<_> = ps_output
.lines()
.filter(|line| line.split_whitespace().nth(1) != Some("-"))
.collect();
let filtered_ps: Vec<_> =
ps_output.lines().filter(|line| line.split_whitespace().nth(1) != Some("-")).collect();
for (line_no, line) in filtered_ps.into_iter().enumerate() {
if 0 < line_no && 0 < line.len() &&
my_pid == line.split(' ').filter(|w| 0 < w.len()).nth(1)
if 0 < line_no
&& 0 < line.len()
&& my_pid
== line
.split(' ')
.filter(|w| 0 < w.len())
.nth(1)
.expect("1st column should be PPID")
.parse().ok()
.expect("PPID string into integer") &&
line.contains("defunct") {
.parse()
.ok()
.expect("PPID string into integer")
&& line.contains("defunct")
{
panic!("Zombie child {}", line);
}
}
}
#[cfg(windows)]
fn find_zombies() { }
fn find_zombies() {}
fn main() {
let too_long = format!("/NoSuchCommand{:0300}", 0u8);
let _failures = (0..100).map(|_| {
let _failures = (0..100)
.map(|_| {
let mut cmd = Command::new(&too_long);
let failed = cmd.spawn();
assert!(failed.is_err(), "Make sure the command fails to spawn(): {:?}", cmd);
failed
}).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
find_zombies();
// then _failures goes out of scope

View File

@@ -0,0 +1,26 @@
//! On Windows the GetExitCodeProcess API is used to get the exit code of a
//! process, but it's easy to mistake a process exiting with the code 259 as
//! "still running" because this is the value of the STILL_ACTIVE constant. Make
//! sure we handle this case in the standard library and correctly report the
//! status.
//!
//! Note that this is disabled on unix as processes exiting with 259 will have
//! their exit status truncated to 3 (only the lower 8 bits are used).
//@ run-pass
#[cfg(windows)]
fn main() {
use std::env;
use std::process::{self, Command};
if env::args().len() == 1 {
let status = Command::new(env::current_exe().unwrap()).arg("foo").status().unwrap();
assert_eq!(status.code(), Some(259));
} else {
process::exit(259);
}
}
#[cfg(not(windows))]
fn main() {}

View File

@@ -0,0 +1,18 @@
//! Validates the correct behavior of writing a `bool` value using `std::ptr::write`.
//!
//! This test addresses historical concerns regarding the internal representation of `bool`
//! (e.g., as `i1` in LLVM versus its byte-aligned memory layout) and checks that
//! `ptr::write` correctly handles this type without issues, confirming its memory
//! behavior is as expected.
//@ run-pass
use std::ptr;
pub fn main() {
unsafe {
let mut x: bool = false;
// this line breaks it
ptr::write(&mut x, false);
}
}

View File

@@ -0,0 +1,18 @@
//! Checks the basic usage of raw pointers (`*const isize`) as function argument and return types.
//@ run-pass
#![allow(dead_code)]
fn f(a: *const isize) -> *const isize {
return a;
}
fn g(a: *const isize) -> *const isize {
let b = f(a);
return b;
}
pub fn main() {
return;
}

View File

@@ -0,0 +1,19 @@
//@ run-pass
#![allow(unused_must_use)]
#![allow(unreachable_code)]
fn _id(x: bool) -> bool {
x
}
fn _call_id() {
let _c = panic!();
_id(_c);
}
fn _call_id_3() {
_id(return) && _id(return);
}
pub fn main() {}

View File

@@ -26,8 +26,12 @@ fn call_id_3() {
fn ret_guard() {
match 2 {
x if (return) => { x; }
x if let true = return => { x; }
x if (return) => {
x;
}
x if let true = return => {
x;
}
_ => {}
}
}

View File

@@ -14,7 +14,7 @@ LL + use std::collections::hash_map::Drain;
|
LL + use std::collections::hash_set::Drain;
|
and 3 other candidates
= and 3 other candidates
error: aborting due to 1 previous error

View File

@@ -0,0 +1,130 @@
error[E0423]: expected function, tuple struct or tuple variant, found struct `std::collections::HashMap`
--> $DIR/multi-suggestion.rs:17:13
|
LL | let _ = std::collections::HashMap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
= note: `std::collections::HashMap` defined here
|
help: you might have meant to use an associated function to build this type
|
LL | let _ = std::collections::HashMap::new();
| +++++
LL - let _ = std::collections::HashMap();
LL + let _ = std::collections::HashMap::with_capacity(_);
|
LL - let _ = std::collections::HashMap();
LL + let _ = std::collections::HashMap::with_hasher(_);
|
LL - let _ = std::collections::HashMap();
LL + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _);
|
help: consider using the `Default` trait
|
LL | let _ = <std::collections::HashMap as std::default::Default>::default();
| + ++++++++++++++++++++++++++++++++++
error[E0423]: cannot initialize a tuple struct which contains private fields
--> $DIR/multi-suggestion.rs:11:19
|
LL | wtf: Some(Box(U {
| ^^^
|
note: constructor is not visible here due to private fields
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
= note: private field
|
= note: private field
help: you might have meant to use an associated function to build this type
|
LL - wtf: Some(Box(U {
LL - wtf: None,
LL - x: (),
LL - })),
LL + wtf: Some(Box::new(_)),
|
LL - wtf: Some(Box(U {
LL - wtf: None,
LL - x: (),
LL - })),
LL + wtf: Some(Box::new_uninit()),
|
LL - wtf: Some(Box(U {
LL - wtf: None,
LL - x: (),
LL - })),
LL + wtf: Some(Box::new_zeroed()),
|
LL - wtf: Some(Box(U {
LL - wtf: None,
LL - x: (),
LL - })),
LL + wtf: Some(Box::new_in(_, _)),
|
= and 12 other candidates
help: consider using the `Default` trait
|
LL - wtf: Some(Box(U {
LL + wtf: Some(<Box as std::default::Default>::default()),
|
error: cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields
--> $DIR/multi-suggestion.rs:19:13
|
LL | let _ = std::collections::HashMap {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: private field `base` that was not provided
help: you might have meant to use an associated function to build this type
|
LL - let _ = std::collections::HashMap {};
LL + let _ = std::collections::HashMap::new();
|
LL - let _ = std::collections::HashMap {};
LL + let _ = std::collections::HashMap::with_capacity(_);
|
LL - let _ = std::collections::HashMap {};
LL + let _ = std::collections::HashMap::with_hasher(_);
|
LL - let _ = std::collections::HashMap {};
LL + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _);
|
help: consider using the `Default` trait
|
LL - let _ = std::collections::HashMap {};
LL + let _ = <std::collections::HashMap as std::default::Default>::default();
|
error: cannot construct `Box<_, _>` with struct literal syntax due to private fields
--> $DIR/multi-suggestion.rs:21:13
|
LL | let _ = Box {};
| ^^^
|
= note: private fields `0` and `1` that were not provided
help: you might have meant to use an associated function to build this type
|
LL - let _ = Box {};
LL + let _ = Box::new(_);
|
LL - let _ = Box {};
LL + let _ = Box::new_uninit();
|
LL - let _ = Box {};
LL + let _ = Box::new_zeroed();
|
LL - let _ = Box {};
LL + let _ = Box::new_in(_, _);
|
= and 12 other candidates
help: consider using the `Default` trait
|
LL - let _ = Box {};
LL + let _ = <Box as std::default::Default>::default();
|
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0423`.

View File

@@ -0,0 +1,22 @@
//@ revisions: ascii unicode
//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode
#![allow(dead_code)]
struct U <T> {
wtf: Option<Box<U<T>>>,
x: T,
}
fn main() {
U {
wtf: Some(Box(U { //[ascii]~ ERROR cannot initialize a tuple struct which contains private fields
wtf: None,
x: (),
})),
x: ()
};
let _ = std::collections::HashMap();
//[ascii]~^ ERROR expected function, tuple struct or tuple variant, found struct `std::collections::HashMap`
let _ = std::collections::HashMap {};
//[ascii]~^ ERROR cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields
let _ = Box {}; //[ascii]~ ERROR cannot construct `Box<_, _>` with struct literal syntax due to private fields
}

View File

@@ -0,0 +1,130 @@
error[E0423]: expected function, tuple struct or tuple variant, found struct `std::collections::HashMap`
╭▸ $DIR/multi-suggestion.rs:17:13
LL │ let _ = std::collections::HashMap();
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━
╭▸ $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
╰ note: `std::collections::HashMap` defined here
╰╴
help: you might have meant to use an associated function to build this type
╭╴
LL │ let _ = std::collections::HashMap::new();
├╴ +++++
LL - let _ = std::collections::HashMap();
LL + let _ = std::collections::HashMap::with_capacity(_);
├╴
LL - let _ = std::collections::HashMap();
LL + let _ = std::collections::HashMap::with_hasher(_);
├╴
LL - let _ = std::collections::HashMap();
LL + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _);
╰╴
help: consider using the `Default` trait
╭╴
LL │ let _ = <std::collections::HashMap as std::default::Default>::default();
╰╴ + ++++++++++++++++++++++++++++++++++
error[E0423]: cannot initialize a tuple struct which contains private fields
╭▸ $DIR/multi-suggestion.rs:11:19
LL │ wtf: Some(Box(U {
│ ━━━
╰╴
note: constructor is not visible here due to private fields
╭▸ $SRC_DIR/alloc/src/boxed.rs:LL:COL
╰ note: private field
╰ note: private field
help: you might have meant to use an associated function to build this type
╭╴
LL - wtf: Some(Box(U {
LL - wtf: None,
LL - x: (),
LL - })),
LL + wtf: Some(Box::new(_)),
├╴
LL - wtf: Some(Box(U {
LL - wtf: None,
LL - x: (),
LL - })),
LL + wtf: Some(Box::new_uninit()),
├╴
LL - wtf: Some(Box(U {
LL - wtf: None,
LL - x: (),
LL - })),
LL + wtf: Some(Box::new_zeroed()),
├╴
LL - wtf: Some(Box(U {
LL - wtf: None,
LL - x: (),
LL - })),
LL + wtf: Some(Box::new_in(_, _)),
╰ and 12 other candidates
help: consider using the `Default` trait
╭╴
LL - wtf: Some(Box(U {
LL + wtf: Some(<Box as std::default::Default>::default()),
╰╴
error: cannot construct `HashMap<_, _, _>` with struct literal syntax due to private fields
╭▸ $DIR/multi-suggestion.rs:19:13
LL │ let _ = std::collections::HashMap {};
│ ━━━━━━━━━━━━━━━━━━━━━━━━━
╰ note: private field `base` that was not provided
help: you might have meant to use an associated function to build this type
╭╴
LL - let _ = std::collections::HashMap {};
LL + let _ = std::collections::HashMap::new();
├╴
LL - let _ = std::collections::HashMap {};
LL + let _ = std::collections::HashMap::with_capacity(_);
├╴
LL - let _ = std::collections::HashMap {};
LL + let _ = std::collections::HashMap::with_hasher(_);
├╴
LL - let _ = std::collections::HashMap {};
LL + let _ = std::collections::HashMap::with_capacity_and_hasher(_, _);
╰╴
help: consider using the `Default` trait
╭╴
LL - let _ = std::collections::HashMap {};
LL + let _ = <std::collections::HashMap as std::default::Default>::default();
╰╴
error: cannot construct `Box<_, _>` with struct literal syntax due to private fields
╭▸ $DIR/multi-suggestion.rs:21:13
LL │ let _ = Box {};
│ ━━━
╰ note: private fields `0` and `1` that were not provided
help: you might have meant to use an associated function to build this type
╭╴
LL - let _ = Box {};
LL + let _ = Box::new(_);
├╴
LL - let _ = Box {};
LL + let _ = Box::new_uninit();
├╴
LL - let _ = Box {};
LL + let _ = Box::new_zeroed();
├╴
LL - let _ = Box {};
LL + let _ = Box::new_in(_, _);
╰ and 12 other candidates
help: consider using the `Default` trait
╭╴
LL - let _ = Box {};
LL + let _ = <Box as std::default::Default>::default();
╰╴
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0423`.

View File

@@ -17,7 +17,7 @@ LL | t.a2.bar();
| +++
LL | t.a3.bar();
| +++
and 6 other candidates
= and 6 other candidates
error[E0609]: no field `field` on type `Thing`
--> $DIR/too-many-field-suggestions.rs:26:7
@@ -35,7 +35,7 @@ LL | t.a2.field;
| +++
LL | t.a3.field;
| +++
and 6 other candidates
= and 6 other candidates
error: aborting due to 2 previous errors

View File

@@ -1,5 +1,7 @@
//! Regression test for https://github.com/rust-lang/rust/issues/137646.
//! The parameter value at all calls to `check` should be `(1, 1, 1)`.
//! This test checks the correct parameter handling during virtual method calls
//! through a `dyn Trait` object.
//!
//! Regression test for: <https://github.com/rust-lang/rust/issues/137646>
//@ run-pass

View File

@@ -1,26 +0,0 @@
//@ run-pass
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
// `expr?` expands to:
//
// match expr {
// Ok(val) => val,
// Err(err) => return Err(From::from(err)),
// }
//
// This test verifies that the expansion is hygienic, i.e., it's not affected by other `val` and
// `err` bindings that may be in scope.
use std::num::ParseIntError;
fn main() {
assert_eq!(parse(), Ok(1));
}
fn parse() -> Result<i32, ParseIntError> {
const val: char = 'a';
const err: char = 'b';
Ok("1".parse::<i32>()?)
}

View File

@@ -0,0 +1,24 @@
//! This test verifies that the `?` operator expansion is hygienic,
//! i.e., it's not affected by other `val` and `err` bindings that may be in scope.
//!
//! Note: Prior to the Try trait stabilization, `expr?` expanded to a match
//! with `val` and `err` bindings. The current implementation uses Try::branch()
//! but this test remains relevant for hygiene verification.
//@ run-pass
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
use std::num::ParseIntError;
fn main() {
assert_eq!(parse(), Ok(1));
}
fn parse() -> Result<i32, ParseIntError> {
const val: char = 'a';
const err: char = 'b';
Ok("1".parse::<i32>()?)
}

View File

@@ -1,9 +1,11 @@
//! Checks the functionality of the `?` operator in various syntactic contexts.
//@ run-pass
#![allow(dead_code)]
use std::fs::File;
use std::io::{Read, self};
use std::io::{self, Read};
use std::num::ParseIntError;
use std::str::FromStr;
@@ -35,7 +37,9 @@ fn on_path() -> Result<i32, ParseIntError> {
fn on_macro() -> Result<i32, ParseIntError> {
macro_rules! id {
($e:expr) => { $e }
($e:expr) => {
$e
};
}
Ok(id!("7".parse::<i32>())?)
@@ -50,11 +54,14 @@ fn on_parens() -> Result<i32, ParseIntError> {
fn on_block() -> Result<i32, ParseIntError> {
let x = "9".parse::<i32>();
Ok({x}?)
Ok({ x }?)
}
fn on_field() -> Result<i32, ParseIntError> {
struct Pair<A, B> { a: A, b: B }
struct Pair<A, B> {
a: A,
b: B,
}
let x = Pair { a: "10".parse::<i32>(), b: 0 };
@@ -89,7 +96,9 @@ fn on_index() -> Result<i32, ParseIntError> {
}
fn on_args() -> Result<i32, ParseIntError> {
fn sub(x: i32, y: i32) -> i32 { x - y }
fn sub(x: i32, y: i32) -> i32 {
x - y
}
let x = "20".parse();
let y = "21".parse();
@@ -98,19 +107,11 @@ fn on_args() -> Result<i32, ParseIntError> {
}
fn on_if() -> Result<i32, ParseIntError> {
Ok(if true {
"22".parse::<i32>()
} else {
"23".parse::<i32>()
}?)
Ok(if true { "22".parse::<i32>() } else { "23".parse::<i32>() }?)
}
fn on_if_let() -> Result<i32, ParseIntError> {
Ok(if let Ok(..) = "24".parse::<i32>() {
"25".parse::<i32>()
} else {
"26".parse::<i32>()
}?)
Ok(if let Ok(..) = "24".parse::<i32>() { "25".parse::<i32>() } else { "26".parse::<i32>() }?)
}
fn on_match() -> Result<i32, ParseIntError> {
@@ -121,7 +122,9 @@ fn on_match() -> Result<i32, ParseIntError> {
}
fn tight_binding() -> Result<bool, ()> {
fn ok<T>(x: T) -> Result<T, ()> { Ok(x) }
fn ok<T>(x: T) -> Result<T, ()> {
Ok(x)
}
let x = ok(true);
Ok(!x?)

View File

@@ -1,14 +0,0 @@
//@ run-pass
#![allow(dead_code)]
use std::any::type_name;
struct Foo<T> {
x: T
}
pub fn main() {
assert_eq!(type_name::<isize>(), "isize");
assert_eq!(type_name::<Foo<usize>>(), "tydesc_name::Foo<usize>");
}

View File

@@ -0,0 +1,9 @@
//! Checks that unconstrained `None` is rejected through references and generics
struct S<'a, T: 'a> {
o: &'a Option<T>,
}
fn main() {
S { o: &None }; //~ ERROR type annotations needed [E0282]
}

View File

@@ -1,5 +1,5 @@
error[E0282]: type annotations needed
--> $DIR/unconstrained-ref.rs:6:5
--> $DIR/type-inference-none-in-generic-ref.rs:8:5
|
LL | S { o: &None };
| ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `S`

View File

@@ -0,0 +1,5 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/5062>.
fn main() {
None; //~ ERROR type annotations needed [E0282]
}

View File

@@ -1,5 +1,5 @@
error[E0282]: type annotations needed
--> $DIR/unconstrained-none.rs:4:5
--> $DIR/type-inference-unconstrained-none.rs:4:5
|
LL | None;
| ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`

View File

@@ -1,7 +0,0 @@
//@ run-pass
struct A { a: isize }
fn a(a: A) -> isize { return a.a; }
pub fn main() { let x: A = A {a: 1}; assert_eq!(a(x), 1); }

View File

@@ -1,9 +0,0 @@
//@ run-pass
#![allow(dead_code)]
fn f(a: *const isize) -> *const isize { return a; }
fn g(a: *const isize) -> *const isize { let b = f(a); return b; }
pub fn main() { return; }

View File

@@ -1,11 +0,0 @@
//@ run-pass
use std::ptr;
pub fn main() {
unsafe {
let mut x: bool = false;
// this line breaks it
ptr::write(&mut x, false);
}
}

View File

@@ -0,0 +1,17 @@
//! Checks the basic functionality of `std::any::type_name` for primitive types
//! and simple generic structs.
//@ run-pass
#![allow(dead_code)]
use std::any::type_name;
struct Foo<T> {
x: T,
}
pub fn main() {
assert_eq!(type_name::<isize>(), "isize");
assert_eq!(type_name::<Foo<usize>>(), "type_name_basic::Foo<usize>");
}

View File

@@ -1,16 +1,18 @@
//! Checks the correctness and consistency of `std::any::TypeId::of`.
//@ run-pass
#![allow(deprecated)]
//@ aux-build:typeid-intrinsic-aux1.rs
//@ aux-build:typeid-intrinsic-aux2.rs
#![feature(core_intrinsics)]
extern crate typeid_intrinsic_aux1 as other1;
extern crate typeid_intrinsic_aux2 as other2;
//@ aux-build:typeid-consistency-aux1.rs
//@ aux-build:typeid-consistency-aux2.rs
extern crate typeid_consistency_aux1 as other1;
extern crate typeid_consistency_aux2 as other2;
use std::hash::{SipHasher, Hasher, Hash};
use std::any::TypeId;
use std::hash::{Hash, Hasher, SipHasher};
struct A;
struct Test;
@@ -34,7 +36,7 @@ pub fn main() {
assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
assert_eq!(TypeId::of::<other2::H>(), other2::id_H());
assert_eq!(TypeId::of::<other1::I>(), other2::id_I());
assert_eq!(TypeId::of::<other2::I>(), other2::id_I());
assert_eq!(other1::id_F(), other2::id_F());
assert_eq!(other1::id_G(), other2::id_G());
@@ -49,10 +51,8 @@ pub fn main() {
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
// sanity test of TypeId
let (a, b, c) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
TypeId::of::<Test>());
let (d, e, f) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
TypeId::of::<Test>());
let (a, b, c) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(), TypeId::of::<Test>());
let (d, e, f) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(), TypeId::of::<Test>());
assert!(a != b);
assert!(a != c);
@@ -82,10 +82,7 @@ pub fn main() {
assert_ne!(TypeId::of::<other1::I32Iterator>(), TypeId::of::<other1::U32Iterator>());
// Check fn pointer against collisions
assert_ne!(
TypeId::of::<fn(fn(A) -> A) -> A>(),
TypeId::of::<fn(fn() -> A, A) -> A>()
);
assert_ne!(TypeId::of::<fn(fn(A) -> A) -> A>(), TypeId::of::<fn(fn() -> A, A) -> A>());
assert_ne!(
TypeId::of::<for<'a> fn(&'a i32) -> &'a i32>(),
TypeId::of::<for<'a> fn(&'a i32) -> &'static i32>()

View File

@@ -0,0 +1,14 @@
//! Checks the basic usage of unit type
//@ run-pass
fn f(u: ()) {
u
}
pub fn main() {
let u1: () = ();
let mut _u2: () = f(u1);
_u2 = ();
()
}

View File

@@ -1,3 +1,5 @@
//! Sanity test that primitives cannot have const generics.
fn foo() {
let x: usize<foo>; //~ ERROR const arguments are not allowed on builtin type `usize`
}

View File

@@ -1,5 +1,5 @@
error[E0109]: const arguments are not allowed on builtin type `usize`
--> $DIR/usize-generic-argument-parent.rs:2:18
--> $DIR/usize-no-generic-arguments.rs:4:18
|
LL | let x: usize<foo>;
| ----- ^^^ const argument not allowed

View File

@@ -1,5 +0,0 @@
// Issue #5062
fn main() {
None; //~ ERROR type annotations needed [E0282]
}

View File

@@ -1,7 +0,0 @@
struct S<'a, T:'a> {
o: &'a Option<T>
}
fn main() {
S { o: &None }; //~ ERROR type annotations needed [E0282]
}

View File

@@ -1,9 +0,0 @@
macro_rules! identity {
($i: ident) => (
$i
)
}
fn main() {
let identity!(_) = 10; //~ ERROR no rules expected reserved identifier `_`
}

View File

@@ -1,6 +1,9 @@
//! Checks the correct usage and behavior of the anonymous lifetime `'_` (underscore lifetime)
//@ run-pass
#![allow(dead_code, mismatched_lifetime_syntaxes)]
struct Foo<'a>(&'a u8);
fn foo(x: &u8) -> Foo<'_> {
@@ -31,8 +34,5 @@ fn main() {
let _ = foo2(x);
let _ = foo3(x);
foo4(Foo(x));
let _ = foo5(Foo2 {
a: x,
b: &6,
});
let _ = foo5(Foo2 { a: x, b: &6 });
}

View File

@@ -1,11 +0,0 @@
//@ run-pass
trait Tr : Sized {
fn _method_on_numbers(self) {}
}
impl Tr for i32 {}
fn main() {
42._method_on_numbers();
}

View File

@@ -1,13 +0,0 @@
// https://github.com/rust-lang/rust/issues/49208
trait Foo {
fn foo();
}
impl Foo for [(); 1] {
fn foo() {}
}
fn main() {
<[(); 0] as Foo>::foo() //~ ERROR E0277
}

View File

@@ -1,16 +0,0 @@
//@ run-pass
#![allow(unused_assignments)]
#![allow(unknown_lints)]
#![allow(unused_variables)]
#![allow(dead_assignment)]
fn f(u: ()) { return u; }
pub fn main() {
let u1: () = ();
let mut u2: () = f(u1);
u2 = ();
return ();
}

View File

@@ -1,10 +0,0 @@
#![allow(unused)]
#![feature(lang_items)]
#[lang = "foo"]
fn bar() -> ! {
//~^^ ERROR definition of an unknown lang item: `foo`
loop {}
}
fn main() {}

Some files were not shown because too many files have changed in this diff Show More