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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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 }
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
///
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = &[
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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!(
|
||||
|
||||
@@ -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 { .. }
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 },
|
||||
..
|
||||
|
||||
@@ -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! {
|
||||
{
|
||||
|
||||
13
tests/ui/allocator/weak-uninhabited-type.rs
Normal file
13
tests/ui/allocator/weak-uninhabited-type.rs
Normal 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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
15
tests/ui/binding/underscore-prefixed-function-argument.rs
Normal file
15
tests/ui/binding/underscore-prefixed-function-argument.rs
Normal 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);
|
||||
}
|
||||
19
tests/ui/borrowck/ownership-struct-update-moved-error.rs
Normal file
19
tests/ui/borrowck/ownership-struct-update-moved-error.rs
Normal 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`
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Sanity check for no capture closures
|
||||
|
||||
//@ run-pass
|
||||
|
||||
pub fn main() {
|
||||
@@ -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
|
||||
|
||||
|
||||
15
tests/ui/consts/const-eval-array-len-in-impl.rs
Normal file
15
tests/ui/consts/const-eval-array-len-in-impl.rs
Normal 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
|
||||
}
|
||||
@@ -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]`
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Checks basic multiple variable declaration using tuple destructuring in a `let` binding.
|
||||
|
||||
//@ run-pass
|
||||
|
||||
pub fn main() {
|
||||
@@ -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
|
||||
|
||||
|
||||
12
tests/ui/drop/box-drop-unused-value-statement-regression.rs
Normal file
12
tests/ui/drop/box-drop-unused-value-statement-regression.rs
Normal 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);
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
12
tests/ui/lang-items/lang-item-unknown-definition-error.rs
Normal file
12
tests/ui/lang-items/lang-item-unknown-definition-error.rs
Normal 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() {}
|
||||
@@ -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`
|
||||
@@ -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> {
|
||||
@@ -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);
|
||||
@@ -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`
|
||||
|
|
||||
@@ -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
|
||||
|
||||
"
|
||||
}
|
||||
|
||||
12
tests/ui/macros/macro-fragment-ident-underscore-error.rs
Normal file
12
tests/ui/macros/macro-fragment-ident-underscore-error.rs
Normal 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 `_`
|
||||
}
|
||||
@@ -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
|
||||
20
tests/ui/modules/module-qualified-paths-basic.rs
Normal file
20
tests/ui/modules/module-qualified-paths-basic.rs
Normal 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();
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Checks complex `use` syntax and availability of types across nested modules.
|
||||
|
||||
//@ run-pass
|
||||
|
||||
mod a {
|
||||
13
tests/ui/modules/primitive-type-module-deprecated-paths.rs
Normal file
13
tests/ui/modules/primitive-type-module-deprecated-paths.rs
Normal 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;
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 `-`
|
||||
@@ -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 `-`
|
||||
@@ -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);
|
||||
}
|
||||
15
tests/ui/parser/integer-literal-method-call-underscore.rs
Normal file
15
tests/ui/parser/integer-literal-method-call-underscore.rs
Normal 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();
|
||||
}
|
||||
@@ -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 {};
|
||||
|
||||
@@ -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
|
||||
26
tests/ui/process/windows-exit-code-still-active.rs
Normal file
26
tests/ui/process/windows-exit-code-still-active.rs
Normal 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() {}
|
||||
18
tests/ui/ptr_ops/ptr-write-bool-representation.rs
Normal file
18
tests/ui/ptr_ops/ptr-write-bool-representation.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
18
tests/ui/ptr_ops/raw-pointer-type-basic.rs
Normal file
18
tests/ui/ptr_ops/raw-pointer-type-basic.rs
Normal 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;
|
||||
}
|
||||
19
tests/ui/reachable/diverging-expressions-unreachable-code.rs
Normal file
19
tests/ui/reachable/diverging-expressions-unreachable-code.rs
Normal 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() {}
|
||||
@@ -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;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
130
tests/ui/suggestions/multi-suggestion.ascii.stderr
Normal file
130
tests/ui/suggestions/multi-suggestion.ascii.stderr
Normal 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`.
|
||||
22
tests/ui/suggestions/multi-suggestion.rs
Normal file
22
tests/ui/suggestions/multi-suggestion.rs
Normal 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
|
||||
}
|
||||
130
tests/ui/suggestions/multi-suggestion.unicode.stderr
Normal file
130
tests/ui/suggestions/multi-suggestion.unicode.stderr
Normal 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`.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>()?)
|
||||
}
|
||||
24
tests/ui/try-trait/try-operator-expansion-hygiene.rs
Normal file
24
tests/ui/try-trait/try-operator-expansion-hygiene.rs
Normal 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>()?)
|
||||
}
|
||||
@@ -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?)
|
||||
@@ -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>");
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
@@ -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`
|
||||
@@ -0,0 +1,5 @@
|
||||
//! Regression test for <https://github.com/rust-lang/rust/issues/5062>.
|
||||
|
||||
fn main() {
|
||||
None; //~ ERROR type annotations needed [E0282]
|
||||
}
|
||||
@@ -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`
|
||||
@@ -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); }
|
||||
@@ -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; }
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
17
tests/ui/type/type-name-basic.rs
Normal file
17
tests/ui/type/type-name-basic.rs
Normal 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>");
|
||||
}
|
||||
@@ -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>()
|
||||
14
tests/ui/type/unit-type-basic-usages.rs
Normal file
14
tests/ui/type/unit-type-basic-usages.rs
Normal 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 = ();
|
||||
()
|
||||
}
|
||||
@@ -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`
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
// Issue #5062
|
||||
|
||||
fn main() {
|
||||
None; //~ ERROR type annotations needed [E0282]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
struct S<'a, T:'a> {
|
||||
o: &'a Option<T>
|
||||
}
|
||||
|
||||
fn main() {
|
||||
S { o: &None }; //~ ERROR type annotations needed [E0282]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
macro_rules! identity {
|
||||
($i: ident) => (
|
||||
$i
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let identity!(_) = 10; //~ ERROR no rules expected reserved identifier `_`
|
||||
}
|
||||
@@ -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 });
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
//@ run-pass
|
||||
|
||||
trait Tr : Sized {
|
||||
fn _method_on_numbers(self) {}
|
||||
}
|
||||
|
||||
impl Tr for i32 {}
|
||||
|
||||
fn main() {
|
||||
42._method_on_numbers();
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user