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;
|
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];
|
let token_text = &text[pos..pos + token.len as usize];
|
||||||
match token.kind {
|
match token.kind {
|
||||||
rustc_lexer::TokenKind::Whitespace => {
|
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;
|
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.
|
// These cases are all UB to actually hit, so don't emit code for them.
|
||||||
// (The size mismatches are reachable via `transmute_unchecked`.)
|
// (The size mismatches are reachable via `transmute_unchecked`.)
|
||||||
// We can't use unreachable because that's a terminator, and we
|
bx.unreachable_nonterminator();
|
||||||
// need something that can be in the middle of a basic block.
|
|
||||||
bx.assume(bx.cx().const_bool(false))
|
|
||||||
} else {
|
} else {
|
||||||
// Since in this path we have a place anyway, we can store or copy to it,
|
// 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
|
// 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()
|
|| operand.layout.is_uninhabited()
|
||||||
|| cast.is_uninhabited()
|
|| cast.is_uninhabited()
|
||||||
{
|
{
|
||||||
if !operand.layout.is_uninhabited() {
|
bx.unreachable_nonterminator();
|
||||||
// Since this is known statically and the input could have existed
|
|
||||||
// without already having hit UB, might as well trap for it.
|
|
||||||
bx.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Because this transmute is UB, return something easy to generate,
|
// We still need to return a value of the appropriate type, but
|
||||||
// since it's fine that later uses of the value are probably UB.
|
// it's already UB so do the easiest thing available.
|
||||||
return OperandValue::poison(bx, cast);
|
return OperandValue::poison(bx, cast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,16 @@ pub trait BuilderMethods<'a, 'tcx>:
|
|||||||
) -> Self::Value;
|
) -> Self::Value;
|
||||||
fn unreachable(&mut self);
|
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 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(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
|
||||||
fn fadd_fast(&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::Underline => row_num - 1,
|
||||||
DisplaySuggestion::None => row_num,
|
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);
|
self.draw_col_separator_end(&mut buffer, row, max_line_num_len + 1);
|
||||||
|
}
|
||||||
row_num = row + 1;
|
row_num = row + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if other_suggestions > 0 {
|
if other_suggestions > 0 {
|
||||||
|
self.draw_note_separator(&mut buffer, row_num, max_line_num_len + 1, false);
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"and {} other candidate{}",
|
"and {} other candidate{}",
|
||||||
other_suggestions,
|
other_suggestions,
|
||||||
pluralize!(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)?;
|
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("#!") {
|
if let Some(input_tail) = input.strip_prefix("#!") {
|
||||||
// Ok, this is a shebang but if the next non-whitespace token is `[`,
|
// 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.
|
// 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!(
|
!matches!(
|
||||||
tok,
|
tok,
|
||||||
TokenKind::Whitespace
|
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.
|
/// 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 || {
|
std::iter::from_fn(move || {
|
||||||
let token = cursor.advance_token();
|
let token = cursor.advance_token();
|
||||||
if token.kind != TokenKind::Eof { Some(token) } else { None }
|
if token.kind != TokenKind::Eof { Some(token) } else { None }
|
||||||
|
|||||||
@@ -124,8 +124,9 @@ fn test_valid_shebang() {
|
|||||||
assert_eq!(strip_shebang(input), None);
|
assert_eq!(strip_shebang(input), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_lexing(src: &str, expect: Expect) {
|
fn check_lexing(src: &str, frontmatter_allowed: FrontmatterAllowed, expect: Expect) {
|
||||||
let actual: String = tokenize(src).map(|token| format!("{:?}\n", token)).collect();
|
let actual: String =
|
||||||
|
tokenize(src, frontmatter_allowed).map(|token| format!("{:?}\n", token)).collect();
|
||||||
expect.assert_eq(&actual)
|
expect.assert_eq(&actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +134,7 @@ fn check_lexing(src: &str, expect: Expect) {
|
|||||||
fn smoke_test() {
|
fn smoke_test() {
|
||||||
check_lexing(
|
check_lexing(
|
||||||
"/* my source file */ fn main() { println!(\"zebra\"); }\n",
|
"/* my source file */ fn main() { println!(\"zebra\"); }\n",
|
||||||
|
FrontmatterAllowed::No,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 20 }
|
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 20 }
|
||||||
Token { kind: Whitespace, len: 1 }
|
Token { kind: Whitespace, len: 1 }
|
||||||
@@ -171,6 +173,7 @@ fn comment_flavors() {
|
|||||||
/** outer doc block */
|
/** outer doc block */
|
||||||
/*! inner doc block */
|
/*! inner doc block */
|
||||||
",
|
",
|
||||||
|
FrontmatterAllowed::No,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Token { kind: Whitespace, len: 1 }
|
Token { kind: Whitespace, len: 1 }
|
||||||
Token { kind: LineComment { doc_style: None }, len: 7 }
|
Token { kind: LineComment { doc_style: None }, len: 7 }
|
||||||
@@ -199,6 +202,7 @@ fn comment_flavors() {
|
|||||||
fn nested_block_comments() {
|
fn nested_block_comments() {
|
||||||
check_lexing(
|
check_lexing(
|
||||||
"/* /* */ */'a'",
|
"/* /* */ */'a'",
|
||||||
|
FrontmatterAllowed::No,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
|
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
|
||||||
Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
|
Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
|
||||||
@@ -210,6 +214,7 @@ fn nested_block_comments() {
|
|||||||
fn characters() {
|
fn characters() {
|
||||||
check_lexing(
|
check_lexing(
|
||||||
"'a' ' ' '\\n'",
|
"'a' ' ' '\\n'",
|
||||||
|
FrontmatterAllowed::No,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
|
Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
|
||||||
Token { kind: Whitespace, len: 1 }
|
Token { kind: Whitespace, len: 1 }
|
||||||
@@ -224,6 +229,7 @@ fn characters() {
|
|||||||
fn lifetime() {
|
fn lifetime() {
|
||||||
check_lexing(
|
check_lexing(
|
||||||
"'abc",
|
"'abc",
|
||||||
|
FrontmatterAllowed::No,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Token { kind: Lifetime { starts_with_number: false }, len: 4 }
|
Token { kind: Lifetime { starts_with_number: false }, len: 4 }
|
||||||
"#]],
|
"#]],
|
||||||
@@ -234,6 +240,7 @@ fn lifetime() {
|
|||||||
fn raw_string() {
|
fn raw_string() {
|
||||||
check_lexing(
|
check_lexing(
|
||||||
"r###\"\"#a\\b\x00c\"\"###",
|
"r###\"\"#a\\b\x00c\"\"###",
|
||||||
|
FrontmatterAllowed::No,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Token { kind: Literal { kind: RawStr { n_hashes: Some(3) }, suffix_start: 17 }, len: 17 }
|
Token { kind: Literal { kind: RawStr { n_hashes: Some(3) }, suffix_start: 17 }, len: 17 }
|
||||||
"#]],
|
"#]],
|
||||||
@@ -257,6 +264,7 @@ b"a"
|
|||||||
r###"raw"###suffix
|
r###"raw"###suffix
|
||||||
br###"raw"###suffix
|
br###"raw"###suffix
|
||||||
"####,
|
"####,
|
||||||
|
FrontmatterAllowed::No,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Token { kind: Whitespace, len: 1 }
|
Token { kind: Whitespace, len: 1 }
|
||||||
Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
|
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.
|
/// An error which can be returned when parsing an integer.
|
||||||
///
|
///
|
||||||
/// This error is used as the error type for the `from_str_radix()` functions
|
/// For example, this error is returned by the `from_str_radix()` functions
|
||||||
/// on the primitive integer types, such as [`i8::from_str_radix`].
|
/// 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
|
/// # Potential causes
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -210,6 +210,9 @@ pub trait CommandExt: Sealed {
|
|||||||
/// intentional difference from the underlying `chroot` system call.)
|
/// intentional difference from the underlying `chroot` system call.)
|
||||||
#[unstable(feature = "process_chroot", issue = "141298")]
|
#[unstable(feature = "process_chroot", issue = "141298")]
|
||||||
fn chroot<P: AsRef<Path>>(&mut self, dir: P) -> &mut process::Command;
|
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")]
|
#[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.as_inner_mut().chroot(dir.as_ref());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn setsid(&mut self, setsid: bool) -> &mut process::Command {
|
||||||
|
self.as_inner_mut().setsid(setsid);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unix-specific extensions to [`process::ExitStatus`] and
|
/// Unix-specific extensions to [`process::ExitStatus`] and
|
||||||
|
|||||||
@@ -1,37 +1,54 @@
|
|||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
||||||
|
use crate::sync::{Arc, Mutex};
|
||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
|
|
||||||
mod tcp;
|
mod tcp;
|
||||||
pub(crate) mod tcp4;
|
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 {
|
impl TcpStream {
|
||||||
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<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> {
|
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
|
||||||
unsupported()
|
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<()> {
|
pub fn set_read_timeout(&self, t: Option<Duration>) -> io::Result<()> {
|
||||||
unsupported()
|
self.read_timeout.set(t).unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
pub fn set_write_timeout(&self, t: Option<Duration>) -> io::Result<()> {
|
||||||
unsupported()
|
self.write_timeout.set(t).unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
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>> {
|
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> {
|
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> {
|
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<()> {
|
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||||
@@ -56,7 +73,7 @@ impl TcpStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
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> {
|
pub fn write_vectored(&self, buf: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||||
|
|||||||
@@ -1,33 +1,34 @@
|
|||||||
use super::tcp4;
|
use super::tcp4;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::net::SocketAddr;
|
use crate::net::SocketAddr;
|
||||||
|
use crate::time::Duration;
|
||||||
|
|
||||||
pub(crate) enum Tcp {
|
pub(crate) enum Tcp {
|
||||||
V4(tcp4::Tcp4),
|
V4(tcp4::Tcp4),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tcp {
|
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 {
|
match addr {
|
||||||
SocketAddr::V4(x) => {
|
SocketAddr::V4(x) => {
|
||||||
let temp = tcp4::Tcp4::new()?;
|
let temp = tcp4::Tcp4::new()?;
|
||||||
temp.configure(true, Some(x), None)?;
|
temp.configure(true, Some(x), None)?;
|
||||||
temp.connect()?;
|
temp.connect(timeout)?;
|
||||||
Ok(Tcp::V4(temp))
|
Ok(Tcp::V4(temp))
|
||||||
}
|
}
|
||||||
SocketAddr::V6(_) => todo!(),
|
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 {
|
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 {
|
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::ptr::NonNull;
|
||||||
use crate::sync::atomic::{AtomicBool, Ordering};
|
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||||
use crate::sys::pal::helpers;
|
use crate::sys::pal::helpers;
|
||||||
|
use crate::time::{Duration, Instant};
|
||||||
|
|
||||||
const TYPE_OF_SERVICE: u8 = 8;
|
const TYPE_OF_SERVICE: u8 = 8;
|
||||||
const TIME_TO_LIVE: u8 = 255;
|
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(()) }
|
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 evt = unsafe { self.create_evt() }?;
|
||||||
let completion_token =
|
let completion_token =
|
||||||
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
|
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()));
|
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() {
|
if completion_token.status.is_error() {
|
||||||
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
|
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 evt = unsafe { self.create_evt() }?;
|
||||||
let completion_token =
|
let completion_token =
|
||||||
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
|
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()));
|
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() {
|
if completion_token.status.is_error() {
|
||||||
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
|
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 evt = unsafe { self.create_evt() }?;
|
||||||
let completion_token =
|
let completion_token =
|
||||||
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
|
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()));
|
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() {
|
if completion_token.status.is_error() {
|
||||||
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
|
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> {
|
unsafe fn create_evt(&self) -> io::Result<helpers::OwnedEvent> {
|
||||||
self.flag.store(false, Ordering::Relaxed);
|
self.flag.store(false, Ordering::Relaxed);
|
||||||
helpers::OwnedEvent::new(
|
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) {
|
while !self.flag.load(Ordering::Relaxed) {
|
||||||
let _ = self.poll();
|
let _ = self.poll();
|
||||||
|
if let Some(t) = timeout {
|
||||||
|
if Instant::now().duration_since(start) >= t {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn poll(&self) -> io::Result<()> {
|
fn poll(&self) -> io::Result<()> {
|
||||||
let protocol = self.protocol.as_ptr();
|
let protocol = self.protocol.as_ptr();
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ pub struct Command {
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
create_pidfd: bool,
|
create_pidfd: bool,
|
||||||
pgroup: Option<pid_t>,
|
pgroup: Option<pid_t>,
|
||||||
|
setsid: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// passed back to std::process with the pipes connected to the child, if any
|
// passed back to std::process with the pipes connected to the child, if any
|
||||||
@@ -185,6 +186,7 @@ impl Command {
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
create_pidfd: false,
|
create_pidfd: false,
|
||||||
pgroup: None,
|
pgroup: None,
|
||||||
|
setsid: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,6 +222,9 @@ impl Command {
|
|||||||
self.cwd(&OsStr::new("/"));
|
self.cwd(&OsStr::new("/"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn setsid(&mut self, setsid: bool) {
|
||||||
|
self.setsid = setsid;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub fn create_pidfd(&mut self, val: bool) {
|
pub fn create_pidfd(&mut self, val: bool) {
|
||||||
@@ -298,6 +303,10 @@ impl Command {
|
|||||||
pub fn get_chroot(&self) -> Option<&CStr> {
|
pub fn get_chroot(&self) -> Option<&CStr> {
|
||||||
self.chroot.as_deref()
|
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>> {
|
pub fn get_closures(&mut self) -> &mut Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>> {
|
||||||
&mut self.closures
|
&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]
|
#[test]
|
||||||
fn test_program_kind() {
|
fn test_program_kind() {
|
||||||
let vectors = &[
|
let vectors = &[
|
||||||
|
|||||||
@@ -340,6 +340,10 @@ impl Command {
|
|||||||
cvt(libc::setpgid(0, pgroup))?;
|
cvt(libc::setpgid(0, pgroup))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.get_setsid() {
|
||||||
|
cvt(libc::setsid())?;
|
||||||
|
}
|
||||||
|
|
||||||
// emscripten has no signal support.
|
// emscripten has no signal support.
|
||||||
#[cfg(not(target_os = "emscripten"))]
|
#[cfg(not(target_os = "emscripten"))]
|
||||||
{
|
{
|
||||||
@@ -741,6 +745,16 @@ impl Command {
|
|||||||
flags |= libc::POSIX_SPAWN_SETSIGDEF;
|
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 _))?;
|
cvt_nz(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
|
||||||
|
|
||||||
// Make sure we synchronize access to the global `environ` resource
|
// 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 hir::HirId;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
|
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_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::{BytePos, Pos, RelativeBytePos, Span, SyntaxContext};
|
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 {
|
loop {
|
||||||
if line.starts_with("/*") {
|
if line.starts_with("/*") {
|
||||||
let src = &src[line_start..line_starts.last().unwrap().to_usize()];
|
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]
|
return (src[..tokens.next().unwrap().len as usize]
|
||||||
.to_ascii_uppercase()
|
.to_ascii_uppercase()
|
||||||
.contains("SAFETY:")
|
.contains("SAFETY:")
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use clippy_utils::source::SpanRangeExt;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_ast::{Crate, Expr, ExprKind, FormatArgs};
|
use rustc_ast::{Crate, Expr, ExprKind, FormatArgs};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_lexer::{TokenKind, tokenize};
|
use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::{Span, hygiene};
|
use rustc_span::{Span, hygiene};
|
||||||
@@ -82,7 +82,7 @@ fn has_span_from_proc_macro(cx: &EarlyContext<'_>, args: &FormatArgs) -> bool {
|
|||||||
.all(|sp| {
|
.all(|sp| {
|
||||||
sp.check_source_text(cx, |src| {
|
sp.check_source_text(cx, |src| {
|
||||||
// text should be either `, name` or `, name =`
|
// text should be either `, name` or `, name =`
|
||||||
let mut iter = tokenize(src).filter(|t| {
|
let mut iter = tokenize(src, FrontmatterAllowed::No).filter(|t| {
|
||||||
!matches!(
|
!matches!(
|
||||||
t.kind,
|
t.kind,
|
||||||
TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
|
TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use rustc_hir::def::{DefKind, Res};
|
|||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, PatExpr, PatExprKind, QPath, UnOp,
|
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_lint::LateContext;
|
||||||
use rustc_middle::mir::ConstValue;
|
use rustc_middle::mir::ConstValue;
|
||||||
use rustc_middle::mir::interpret::{Scalar, alloc_range};
|
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 {
|
match *lit {
|
||||||
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
|
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
|
||||||
LitKind::Byte(b) => Constant::Int(u128::from(b)),
|
LitKind::Byte(b) => Constant::Int(u128::from(b)),
|
||||||
LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => {
|
LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(s.as_byte_str().to_vec()),
|
||||||
Constant::Binary(s.as_byte_str().to_vec())
|
|
||||||
}
|
|
||||||
LitKind::Char(c) => Constant::Char(c),
|
LitKind::Char(c) => Constant::Char(c),
|
||||||
LitKind::Int(n, _) => Constant::Int(n.get()),
|
LitKind::Int(n, _) => Constant::Int(n.get()),
|
||||||
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
|
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
|
||||||
@@ -568,9 +566,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
match &lit.node {
|
match &lit.node {
|
||||||
LitKind::Str(is, _) => Some(is.is_empty()),
|
LitKind::Str(is, _) => Some(is.is_empty()),
|
||||||
LitKind::ByteStr(s, _) | LitKind::CStr(s, _) => {
|
LitKind::ByteStr(s, _) | LitKind::CStr(s, _) => Some(s.as_byte_str().is_empty()),
|
||||||
Some(s.as_byte_str().is_empty())
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -715,7 +711,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
|
|||||||
&& let Some(src) = src.as_str()
|
&& let Some(src) = src.as_str()
|
||||||
{
|
{
|
||||||
use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace};
|
use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace};
|
||||||
if !tokenize(src)
|
if !tokenize(src, FrontmatterAllowed::No)
|
||||||
.map(|t| t.kind)
|
.map(|t| t.kind)
|
||||||
.filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi))
|
.filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi))
|
||||||
.eq([OpenBrace])
|
.eq([OpenBrace])
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use rustc_hir::{
|
|||||||
Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr,
|
Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr,
|
||||||
TraitBoundModifiers, Ty, TyKind, TyPat, TyPatKind,
|
TraitBoundModifiers, Ty, TyKind, TyPat, TyPatKind,
|
||||||
};
|
};
|
||||||
use rustc_lexer::{TokenKind, tokenize};
|
use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::TypeckResults;
|
use rustc_middle::ty::TypeckResults;
|
||||||
use rustc_span::{BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext, sym};
|
use rustc_span::{BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext, sym};
|
||||||
@@ -686,7 +686,7 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &'
|
|||||||
// `{}` => `()`
|
// `{}` => `()`
|
||||||
([], None)
|
([], None)
|
||||||
if block.span.check_source_text(cx, |src| {
|
if block.span.check_source_text(cx, |src| {
|
||||||
tokenize(src)
|
tokenize(src, FrontmatterAllowed::No)
|
||||||
.map(|t| t.kind)
|
.map(|t| t.kind)
|
||||||
.filter(|t| {
|
.filter(|t| {
|
||||||
!matches!(
|
!matches!(
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ use rustc_hir::{
|
|||||||
Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, TraitFn, TraitItem,
|
Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, TraitFn, TraitItem,
|
||||||
TraitItemKind, TraitRef, TyKind, UnOp, def,
|
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_lint::{LateContext, Level, Lint, LintContext};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::hir::place::PlaceBase;
|
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.
|
/// Tokenizes the input while keeping the text associated with each token.
|
||||||
pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str, InnerSpan)> {
|
pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str, InnerSpan)> {
|
||||||
let mut pos = 0;
|
let mut pos = 0;
|
||||||
tokenize(s).map(move |t| {
|
tokenize(s, FrontmatterAllowed::No).map(move |t| {
|
||||||
let end = pos + t.len;
|
let end = pos + t.len;
|
||||||
let range = pos as usize..end as usize;
|
let range = pos as usize..end as usize;
|
||||||
let inner = InnerSpan::new(range.start, range.end);
|
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 {
|
let Ok(snippet) = sm.span_to_snippet(span) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
return tokenize(&snippet).any(|token| {
|
return tokenize(&snippet, FrontmatterAllowed::No).any(|token| {
|
||||||
matches!(
|
matches!(
|
||||||
token.kind,
|
token.kind,
|
||||||
TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }
|
TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::sync::Arc;
|
|||||||
use rustc_ast::{LitKind, StrStyle};
|
use rustc_ast::{LitKind, StrStyle};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
|
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_lint::{EarlyContext, LateContext};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
@@ -277,7 +277,7 @@ fn map_range(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ends_with_line_comment_or_broken(text: &str) -> bool {
|
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;
|
return false;
|
||||||
};
|
};
|
||||||
match last.kind {
|
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..])
|
&& ends_with_line_comment_or_broken(&start[prev_start..])
|
||||||
&& let next_line = lines.partition_point(|&pos| pos.to_usize() < range.end)
|
&& 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())
|
&& 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)
|
Some(range.start)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
use std::ops;
|
use std::ops;
|
||||||
|
|
||||||
use rustc_literal_escaper::{
|
use rustc_literal_escaper::{
|
||||||
EscapeError, Mode, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char,
|
unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str, EscapeError,
|
||||||
unescape_str,
|
Mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
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
|
// 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.
|
// 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];
|
let token_text = &text[conv.offset..][..token.len as usize];
|
||||||
|
|
||||||
conv.extend_token(&token.kind, token_text);
|
conv.extend_token(&token.kind, token_text);
|
||||||
@@ -58,7 +60,7 @@ impl<'a> LexedStr<'a> {
|
|||||||
return None;
|
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() {
|
if token.len as usize != text.len() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ pub(super) fn literal_from_str<Span: Copy>(
|
|||||||
use proc_macro::bridge::LitKind;
|
use proc_macro::bridge::LitKind;
|
||||||
use rustc_lexer::{LiteralKind, Token, TokenKind};
|
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 minus_or_lit = tokens.next().unwrap_or(Token { kind: TokenKind::Eof, len: 0 });
|
||||||
|
|
||||||
let lit = if minus_or_lit.kind == TokenKind::Minus {
|
let lit = if minus_or_lit.kind == TokenKind::Minus {
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ where
|
|||||||
{
|
{
|
||||||
use rustc_lexer::LiteralKind;
|
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 {
|
let Some((rustc_lexer::Token {
|
||||||
kind: rustc_lexer::TokenKind::Literal { kind, suffix_start },
|
kind: rustc_lexer::TokenKind::Literal { kind, suffix_start },
|
||||||
..
|
..
|
||||||
|
|||||||
@@ -29,28 +29,28 @@ pub struct Aggregate8(u8);
|
|||||||
// CHECK-LABEL: @check_bigger_size(
|
// CHECK-LABEL: @check_bigger_size(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn check_bigger_size(x: u16) -> u32 {
|
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)
|
transmute_unchecked(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @check_smaller_size(
|
// CHECK-LABEL: @check_smaller_size(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn check_smaller_size(x: u32) -> u16 {
|
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)
|
transmute_unchecked(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @check_smaller_array(
|
// CHECK-LABEL: @check_smaller_array(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] {
|
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)
|
transmute_unchecked(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @check_bigger_array(
|
// CHECK-LABEL: @check_bigger_array(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
|
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)
|
transmute_unchecked(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,9 +58,9 @@ pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
|
pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
|
||||||
// CHECK-NOT: trap
|
// CHECK: start
|
||||||
// CHECK: call void @llvm.trap
|
// CHECK-NEXT: store i1 true, ptr poison, align 1
|
||||||
// CHECK-NOT: trap
|
// CHECK-NEXT: ret void
|
||||||
mir! {
|
mir! {
|
||||||
{
|
{
|
||||||
RET = CastTransmute(x);
|
RET = CastTransmute(x);
|
||||||
@@ -73,9 +73,9 @@ pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
|
pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
|
||||||
// CHECK-NOT: call
|
// CHECK: start
|
||||||
// CHECK: call void @llvm.assume(i1 false)
|
// CHECK-NEXT: store i1 true, ptr poison, align 1
|
||||||
// CHECK-NOT: call
|
// CHECK-NEXT: ret void
|
||||||
mir! {
|
mir! {
|
||||||
{
|
{
|
||||||
RET = CastTransmute(x);
|
RET = CastTransmute(x);
|
||||||
@@ -88,9 +88,9 @@ pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
pub unsafe fn check_to_uninhabited(x: u16) {
|
pub unsafe fn check_to_uninhabited(x: u16) {
|
||||||
// CHECK-NOT: trap
|
// CHECK: start
|
||||||
// CHECK: call void @llvm.trap
|
// CHECK-NEXT: store i1 true, ptr poison, align 1
|
||||||
// CHECK-NOT: trap
|
// CHECK-NEXT: ret void
|
||||||
mir! {
|
mir! {
|
||||||
let temp: BigNever;
|
let temp: BigNever;
|
||||||
{
|
{
|
||||||
@@ -104,7 +104,9 @@ pub unsafe fn check_to_uninhabited(x: u16) {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 {
|
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! {
|
mir! {
|
||||||
{
|
{
|
||||||
RET = CastTransmute(x);
|
RET = CastTransmute(x);
|
||||||
@@ -401,9 +403,9 @@ pub unsafe fn check_issue_109992(x: ()) -> [(); 1] {
|
|||||||
pub unsafe fn check_unit_to_never(x: ()) {
|
pub unsafe fn check_unit_to_never(x: ()) {
|
||||||
// This uses custom MIR to avoid MIR optimizations having removed ZST ops.
|
// This uses custom MIR to avoid MIR optimizations having removed ZST ops.
|
||||||
|
|
||||||
// CHECK-NOT: trap
|
// CHECK: start
|
||||||
// CHECK: call void @llvm.trap
|
// CHECK-NEXT: store i1 true, ptr poison, align 1
|
||||||
// CHECK-NOT: trap
|
// CHECK-NEXT: ret void
|
||||||
mir! {
|
mir! {
|
||||||
let temp: ZstNever;
|
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.
|
// This uses custom MIR to avoid MIR optimizations having removed ZST ops.
|
||||||
|
|
||||||
// CHECK: start
|
// CHECK: start
|
||||||
|
// CHECK-NEXT: store i1 true, ptr poison, align 1
|
||||||
// CHECK-NEXT: ret void
|
// CHECK-NEXT: ret void
|
||||||
mir! {
|
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 = std::ops::Deref::Target;
|
||||||
LL + type X = <IoSlice<'_> as Deref>::Target;
|
LL + type X = <IoSlice<'_> as Deref>::Target;
|
||||||
|
|
|
|
||||||
and N other candidates
|
= and N other candidates
|
||||||
|
|
||||||
error[E0223]: ambiguous associated type
|
error[E0223]: ambiguous associated type
|
||||||
--> $DIR/associated-types-in-ambiguous-context.rs:13:23
|
--> $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
|
//@ run-pass
|
||||||
|
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
fn p_foo<T>(_pinned: T) { }
|
fn p_foo<T>(_pinned: T) {}
|
||||||
fn s_foo<T>(_shared: T) { }
|
fn s_foo<T>(_shared: T) {}
|
||||||
fn u_foo<T:Send>(_unique: T) { }
|
fn u_foo<T: Send>(_unique: T) {}
|
||||||
|
|
||||||
struct r {
|
struct r {
|
||||||
i: isize,
|
i: isize,
|
||||||
@@ -15,10 +18,8 @@ impl Drop for r {
|
|||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r(i:isize) -> r {
|
fn r(i: isize) -> r {
|
||||||
r {
|
r { i }
|
||||||
i: i
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
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`
|
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
|
| ----- 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
|
| ----------------- `start` moved due to this method call
|
||||||
LL | println!("{}", start.test);
|
LL | println!("{}", start.test);
|
||||||
| ^^^^^^^^^^ value borrowed here after move
|
| ^^^^^^^^^^ value borrowed here after move
|
||||||
|
|
|
|
||||||
note: `Mine::make_string_bar` takes ownership of the receiver `self`, which moves `start`
|
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)
|
= 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
|
//@ run-pass
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
@@ -14,7 +14,7 @@ LL + use std::collections::btree_map::IntoIter;
|
|||||||
|
|
|
|
||||||
LL + use std::collections::btree_set::IntoIter;
|
LL + use std::collections::btree_set::IntoIter;
|
||||||
|
|
|
|
||||||
and 9 other candidates
|
= and 9 other candidates
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
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
|
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()
|
LL | <[(); 0] as Foo>::foo()
|
||||||
| ^^^^^^^ the trait `Foo` is not implemented for `[(); 0]`
|
| ^^^^^^^ 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
|
//@ run-pass
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
@@ -18,7 +18,7 @@ LL + fn setup() -> Determine { Set }
|
|||||||
LL - fn setup() -> Set { Set }
|
LL - fn setup() -> Set { Set }
|
||||||
LL + fn setup() -> PutDown { Set }
|
LL + fn setup() -> PutDown { Set }
|
||||||
|
|
|
|
||||||
and 3 other candidates
|
= and 3 other candidates
|
||||||
|
|
||||||
error[E0425]: cannot find value `Set` in this scope
|
error[E0425]: cannot find value `Set` in this scope
|
||||||
--> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21
|
--> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21
|
||||||
@@ -36,7 +36,7 @@ LL + use Determine::Set;
|
|||||||
|
|
|
|
||||||
LL + use PutDown::Set;
|
LL + use PutDown::Set;
|
||||||
|
|
|
|
||||||
and 3 other candidates
|
= and 3 other candidates
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
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
|
//@ run-pass
|
||||||
//
|
|
||||||
#![allow(dead_code)]
|
|
||||||
//@ compile-flags: -O
|
//@ compile-flags: -O
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Hash, Eq, Clone, PartialOrd, Ord)]
|
#[derive(PartialEq, Debug, Hash, Eq, Clone, PartialOrd, Ord)]
|
||||||
enum MyEnum {
|
enum MyEnum {
|
||||||
E0,
|
E0,
|
||||||
|
|
||||||
E1,
|
E1,
|
||||||
|
|
||||||
E2,
|
E2,
|
||||||
E3,
|
E3,
|
||||||
E4,
|
E4,
|
||||||
|
|
||||||
E5,
|
E5,
|
||||||
E6,
|
E6,
|
||||||
E7,
|
E7,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
use MyEnum::*;
|
use MyEnum::*;
|
||||||
let s: HashSet<_> = [E4, E1].iter().cloned().collect();
|
let s: HashSet<_> = [E4, E1].iter().cloned().collect();
|
||||||
@@ -30,7 +30,7 @@ LL + use std::fmt::Display;
|
|||||||
|
|
|
|
||||||
LL + use std::fmt::LowerExp;
|
LL + use std::fmt::LowerExp;
|
||||||
|
|
|
|
||||||
and 5 other candidates
|
= and 5 other candidates
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ LL + use ::issue_56125::issue_56125;
|
|||||||
LL - use empty::issue_56125;
|
LL - use empty::issue_56125;
|
||||||
LL + use ::issue_56125::last_segment::issue_56125;
|
LL + use ::issue_56125::last_segment::issue_56125;
|
||||||
|
|
|
|
||||||
and 1 other candidate
|
= and 1 other candidate
|
||||||
|
|
||||||
error[E0659]: `issue_56125` is ambiguous
|
error[E0659]: `issue_56125` is ambiguous
|
||||||
--> $DIR/issue-56125.rs:6:9
|
--> $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
|
//@ run-pass
|
||||||
//@ needs-unwind
|
//@ needs-unwind
|
||||||
|
|
||||||
@@ -24,7 +27,9 @@ impl Write for ErrorWriter {
|
|||||||
Err(Error::new(WRITER_ERROR, "not connected"))
|
Err(Error::new(WRITER_ERROR, "not connected"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -37,7 +42,8 @@ fn main() {
|
|||||||
let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap();
|
let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap();
|
||||||
assert!(
|
assert!(
|
||||||
err.contains("formatting trait implementation returned an error"),
|
err.contains("formatting trait implementation returned an error"),
|
||||||
"unexpected panic: {}", err
|
"unexpected panic: {}",
|
||||||
|
err
|
||||||
);
|
);
|
||||||
|
|
||||||
// Writer error when there's some string before the first `{}`
|
// 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();
|
let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap();
|
||||||
assert!(
|
assert!(
|
||||||
err.contains("formatting trait implementation returned an error"),
|
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`
|
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"]
|
LL | #[lang = "foo"]
|
||||||
| ^^^^^^^^^^^^^^^ definition of unknown lang item `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
|
//@ run-pass
|
||||||
// Test that we can't ignore lifetimes by going through Any.
|
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
struct Foo<'a>(&'a str);
|
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> {
|
fn bad1(s: String) -> Option<&'static str> {
|
||||||
let a: Box<dyn Any> = Box::new(good as fn(&String) -> Foo);
|
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 {
|
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> {
|
fn bad2(s: String) -> Option<&'static str> {
|
||||||
@@ -1,17 +1,19 @@
|
|||||||
//@ build-fail
|
//~ ERROR reached the type-length limit
|
||||||
//@ compile-flags: -Copt-level=0 -Zenforce-type-length-limit
|
|
||||||
//~^^ ERROR reached the type-length limit
|
|
||||||
|
|
||||||
// Test that the type length limit can be changed.
|
//! Checks the enforcement of the type-length limit
|
||||||
// The exact type depends on optimizations, so disable them.
|
//! and its configurability via `#![type_length_limit]`.
|
||||||
|
|
||||||
|
//@ compile-flags: -Copt-level=0 -Zenforce-type-length-limit
|
||||||
|
|
||||||
|
//@ build-fail
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![type_length_limit="8"]
|
#![type_length_limit = "8"]
|
||||||
|
|
||||||
macro_rules! link {
|
macro_rules! link {
|
||||||
($id:ident, $t:ty) => {
|
($id:ident, $t:ty) => {
|
||||||
pub type $id = ($t, $t, $t);
|
pub type $id = ($t, $t, $t);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
link! { A1, B1 }
|
link! { A1, B1 }
|
||||||
@@ -26,7 +28,7 @@ link! { D, E }
|
|||||||
link! { E, F }
|
link! { E, F }
|
||||||
link! { F, G<Option<i32>, Option<i32>> }
|
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() {
|
fn main() {
|
||||||
drop::<Option<A>>(None);
|
drop::<Option<A>>(None);
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
|
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);
|
LL | drop::<Option<A>>(None);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: consider adding a `#![type_length_limit="4010"]` attribute to your crate
|
= 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`
|
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[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[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 \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 `_`
|
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 {
|
LL | macro_rules! identity {
|
||||||
| --------------------- when calling this macro
|
| --------------------- when calling this macro
|
||||||
@@ -8,9 +8,9 @@ LL | let identity!(_) = 10;
|
|||||||
| ^ no rules expected this token in macro call
|
| ^ no rules expected this token in macro call
|
||||||
|
|
|
|
||||||
note: while trying to match meta-variable `$i:ident`
|
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
|
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
|
//@ run-pass
|
||||||
|
|
||||||
mod a {
|
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
|
//@ run-pass
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
pub struct A;
|
pub struct A;
|
||||||
|
|
||||||
mod test {
|
mod test {
|
||||||
pub use super :: A;
|
pub use self::A as B;
|
||||||
|
pub use super::A;
|
||||||
pub use self :: A as B;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl A {
|
impl A {
|
||||||
fn f() {}
|
fn f() {}
|
||||||
fn g() {
|
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() {
|
fn main() {
|
||||||
let x = -1 as usize; //~ ERROR: cannot apply unary operator `-`
|
let x = -1 as usize; //~ ERROR: cannot apply unary operator `-`
|
||||||
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`
|
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;
|
LL | let x = -1 as usize;
|
||||||
| ^^ cannot apply unary operator `-`
|
| ^^ cannot apply unary operator `-`
|
||||||
@@ -12,7 +12,7 @@ LL + let x = usize::MAX;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0600]: cannot apply unary operator `-` to type `usize`
|
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;
|
LL | let x = (-1) as usize;
|
||||||
| ^^^^ cannot apply unary operator `-`
|
| ^^^^ cannot apply unary operator `-`
|
||||||
@@ -25,7 +25,7 @@ LL + let x = usize::MAX;
|
|||||||
|
|
|
|
||||||
|
|
||||||
error[E0600]: cannot apply unary operator `-` to type `u32`
|
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;
|
LL | let x: u32 = -1;
|
||||||
| ^^ cannot apply unary operator `-`
|
| ^^ 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
|
//@ run-pass
|
||||||
//@ needs-unwind
|
//@ needs-unwind
|
||||||
//@ ignore-windows target requires uwtable
|
//@ ignore-windows target requires uwtable
|
||||||
@@ -26,9 +30,12 @@ fn increase(count: &mut u8) {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
assert!(panic::catch_unwind(AssertUnwindSafe(
|
assert!(
|
||||||
|
panic::catch_unwind(AssertUnwindSafe(
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
|| increase(&mut count)
|
|| increase(&mut count)
|
||||||
)).is_err());
|
))
|
||||||
|
.is_err()
|
||||||
|
);
|
||||||
assert_eq!(count, 1);
|
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 - })),
|
||||||
LL + wtf: Some(Box::new_in(_, _)),
|
LL + wtf: Some(Box::new_in(_, _)),
|
||||||
|
|
|
|
||||||
and 12 other candidates
|
= and 12 other candidates
|
||||||
help: consider using the `Default` trait
|
help: consider using the `Default` trait
|
||||||
|
|
|
|
||||||
LL - wtf: Some(Box(U {
|
LL - wtf: Some(Box(U {
|
||||||
@@ -118,7 +118,7 @@ LL + let _ = Box::new_zeroed();
|
|||||||
LL - let _ = Box {};
|
LL - let _ = Box {};
|
||||||
LL + let _ = Box::new_in(_, _);
|
LL + let _ = Box::new_in(_, _);
|
||||||
|
|
|
|
||||||
and 12 other candidates
|
= and 12 other candidates
|
||||||
help: consider using the `Default` trait
|
help: consider using the `Default` trait
|
||||||
|
|
|
|
||||||
LL - let _ = Box {};
|
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
|
//@ run-pass
|
||||||
//@ needs-subprocess
|
//@ needs-subprocess
|
||||||
//@ ignore-vxworks no 'ps'
|
//@ ignore-vxworks no 'ps'
|
||||||
@@ -36,35 +42,42 @@ fn find_zombies() {
|
|||||||
// the PPID column contains a "-" for the respective process.
|
// the PPID column contains a "-" for the respective process.
|
||||||
// Filter out any lines that have a "-" as the PPID as the PPID is
|
// Filter out any lines that have a "-" as the PPID as the PPID is
|
||||||
// expected to be an integer.
|
// expected to be an integer.
|
||||||
let filtered_ps: Vec<_> = ps_output
|
let filtered_ps: Vec<_> =
|
||||||
.lines()
|
ps_output.lines().filter(|line| line.split_whitespace().nth(1) != Some("-")).collect();
|
||||||
.filter(|line| line.split_whitespace().nth(1) != Some("-"))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for (line_no, line) in filtered_ps.into_iter().enumerate() {
|
for (line_no, line) in filtered_ps.into_iter().enumerate() {
|
||||||
if 0 < line_no && 0 < line.len() &&
|
if 0 < line_no
|
||||||
my_pid == line.split(' ').filter(|w| 0 < w.len()).nth(1)
|
&& 0 < line.len()
|
||||||
|
&& my_pid
|
||||||
|
== line
|
||||||
|
.split(' ')
|
||||||
|
.filter(|w| 0 < w.len())
|
||||||
|
.nth(1)
|
||||||
.expect("1st column should be PPID")
|
.expect("1st column should be PPID")
|
||||||
.parse().ok()
|
.parse()
|
||||||
.expect("PPID string into integer") &&
|
.ok()
|
||||||
line.contains("defunct") {
|
.expect("PPID string into integer")
|
||||||
|
&& line.contains("defunct")
|
||||||
|
{
|
||||||
panic!("Zombie child {}", line);
|
panic!("Zombie child {}", line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn find_zombies() { }
|
fn find_zombies() {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let too_long = format!("/NoSuchCommand{:0300}", 0u8);
|
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 mut cmd = Command::new(&too_long);
|
||||||
let failed = cmd.spawn();
|
let failed = cmd.spawn();
|
||||||
assert!(failed.is_err(), "Make sure the command fails to spawn(): {:?}", cmd);
|
assert!(failed.is_err(), "Make sure the command fails to spawn(): {:?}", cmd);
|
||||||
failed
|
failed
|
||||||
}).collect::<Vec<_>>();
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
find_zombies();
|
find_zombies();
|
||||||
// then _failures goes out of scope
|
// 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() {
|
fn ret_guard() {
|
||||||
match 2 {
|
match 2 {
|
||||||
x if (return) => { x; }
|
x if (return) => {
|
||||||
x if let true = return => { x; }
|
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;
|
LL + use std::collections::hash_set::Drain;
|
||||||
|
|
|
|
||||||
and 3 other candidates
|
= and 3 other candidates
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
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();
|
LL | t.a3.bar();
|
||||||
| +++
|
| +++
|
||||||
and 6 other candidates
|
= and 6 other candidates
|
||||||
|
|
||||||
error[E0609]: no field `field` on type `Thing`
|
error[E0609]: no field `field` on type `Thing`
|
||||||
--> $DIR/too-many-field-suggestions.rs:26:7
|
--> $DIR/too-many-field-suggestions.rs:26:7
|
||||||
@@ -35,7 +35,7 @@ LL | t.a2.field;
|
|||||||
| +++
|
| +++
|
||||||
LL | t.a3.field;
|
LL | t.a3.field;
|
||||||
| +++
|
| +++
|
||||||
and 6 other candidates
|
= and 6 other candidates
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
//! Regression test for https://github.com/rust-lang/rust/issues/137646.
|
//! This test checks the correct parameter handling during virtual method calls
|
||||||
//! The parameter value at all calls to `check` should be `(1, 1, 1)`.
|
//! through a `dyn Trait` object.
|
||||||
|
//!
|
||||||
|
//! Regression test for: <https://github.com/rust-lang/rust/issues/137646>
|
||||||
|
|
||||||
//@ run-pass
|
//@ 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
|
//@ run-pass
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, self};
|
use std::io::{self, Read};
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
@@ -35,7 +37,9 @@ fn on_path() -> Result<i32, ParseIntError> {
|
|||||||
|
|
||||||
fn on_macro() -> Result<i32, ParseIntError> {
|
fn on_macro() -> Result<i32, ParseIntError> {
|
||||||
macro_rules! id {
|
macro_rules! id {
|
||||||
($e:expr) => { $e }
|
($e:expr) => {
|
||||||
|
$e
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(id!("7".parse::<i32>())?)
|
Ok(id!("7".parse::<i32>())?)
|
||||||
@@ -50,11 +54,14 @@ fn on_parens() -> Result<i32, ParseIntError> {
|
|||||||
fn on_block() -> Result<i32, ParseIntError> {
|
fn on_block() -> Result<i32, ParseIntError> {
|
||||||
let x = "9".parse::<i32>();
|
let x = "9".parse::<i32>();
|
||||||
|
|
||||||
Ok({x}?)
|
Ok({ x }?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_field() -> Result<i32, ParseIntError> {
|
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 };
|
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 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 x = "20".parse();
|
||||||
let y = "21".parse();
|
let y = "21".parse();
|
||||||
@@ -98,19 +107,11 @@ fn on_args() -> Result<i32, ParseIntError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_if() -> Result<i32, ParseIntError> {
|
fn on_if() -> Result<i32, ParseIntError> {
|
||||||
Ok(if true {
|
Ok(if true { "22".parse::<i32>() } else { "23".parse::<i32>() }?)
|
||||||
"22".parse::<i32>()
|
|
||||||
} else {
|
|
||||||
"23".parse::<i32>()
|
|
||||||
}?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_if_let() -> Result<i32, ParseIntError> {
|
fn on_if_let() -> Result<i32, ParseIntError> {
|
||||||
Ok(if let Ok(..) = "24".parse::<i32>() {
|
Ok(if let Ok(..) = "24".parse::<i32>() { "25".parse::<i32>() } else { "26".parse::<i32>() }?)
|
||||||
"25".parse::<i32>()
|
|
||||||
} else {
|
|
||||||
"26".parse::<i32>()
|
|
||||||
}?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_match() -> Result<i32, ParseIntError> {
|
fn on_match() -> Result<i32, ParseIntError> {
|
||||||
@@ -121,7 +122,9 @@ fn on_match() -> Result<i32, ParseIntError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn tight_binding() -> Result<bool, ()> {
|
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);
|
let x = ok(true);
|
||||||
Ok(!x?)
|
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
|
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 };
|
LL | S { o: &None };
|
||||||
| ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `S`
|
| ^^^^^^^^^^^^^^ 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
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/unconstrained-none.rs:4:5
|
--> $DIR/type-inference-unconstrained-none.rs:4:5
|
||||||
|
|
|
|
||||||
LL | None;
|
LL | None;
|
||||||
| ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
|
| ^^^^ 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
|
//@ run-pass
|
||||||
|
|
||||||
#![allow(deprecated)]
|
#![allow(deprecated)]
|
||||||
//@ aux-build:typeid-intrinsic-aux1.rs
|
|
||||||
//@ aux-build:typeid-intrinsic-aux2.rs
|
|
||||||
|
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
|
||||||
extern crate typeid_intrinsic_aux1 as other1;
|
//@ aux-build:typeid-consistency-aux1.rs
|
||||||
extern crate typeid_intrinsic_aux2 as other2;
|
//@ 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::any::TypeId;
|
||||||
|
use std::hash::{Hash, Hasher, SipHasher};
|
||||||
|
|
||||||
struct A;
|
struct A;
|
||||||
struct Test;
|
struct Test;
|
||||||
@@ -34,7 +36,7 @@ pub fn main() {
|
|||||||
assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
|
assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
|
||||||
assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
|
assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
|
||||||
assert_eq!(TypeId::of::<other2::H>(), other2::id_H());
|
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_F(), other2::id_F());
|
||||||
assert_eq!(other1::id_G(), other2::id_G());
|
assert_eq!(other1::id_G(), other2::id_G());
|
||||||
@@ -49,10 +51,8 @@ pub fn main() {
|
|||||||
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
|
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
|
||||||
|
|
||||||
// sanity test of TypeId
|
// sanity test of TypeId
|
||||||
let (a, b, c) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
|
let (a, b, c) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(), TypeId::of::<Test>());
|
||||||
TypeId::of::<Test>());
|
let (d, e, f) = (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 != b);
|
||||||
assert!(a != c);
|
assert!(a != c);
|
||||||
@@ -82,10 +82,7 @@ pub fn main() {
|
|||||||
assert_ne!(TypeId::of::<other1::I32Iterator>(), TypeId::of::<other1::U32Iterator>());
|
assert_ne!(TypeId::of::<other1::I32Iterator>(), TypeId::of::<other1::U32Iterator>());
|
||||||
|
|
||||||
// Check fn pointer against collisions
|
// Check fn pointer against collisions
|
||||||
assert_ne!(
|
assert_ne!(TypeId::of::<fn(fn(A) -> A) -> A>(), TypeId::of::<fn(fn() -> A, A) -> A>());
|
||||||
TypeId::of::<fn(fn(A) -> A) -> A>(),
|
|
||||||
TypeId::of::<fn(fn() -> A, A) -> A>()
|
|
||||||
);
|
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
TypeId::of::<for<'a> fn(&'a i32) -> &'a i32>(),
|
TypeId::of::<for<'a> fn(&'a i32) -> &'a i32>(),
|
||||||
TypeId::of::<for<'a> fn(&'a i32) -> &'static 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() {
|
fn foo() {
|
||||||
let x: usize<foo>; //~ ERROR const arguments are not allowed on builtin type `usize`
|
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`
|
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>;
|
LL | let x: usize<foo>;
|
||||||
| ----- ^^^ const argument not allowed
|
| ----- ^^^ 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
|
//@ run-pass
|
||||||
|
|
||||||
#![allow(dead_code, mismatched_lifetime_syntaxes)]
|
#![allow(dead_code, mismatched_lifetime_syntaxes)]
|
||||||
|
|
||||||
struct Foo<'a>(&'a u8);
|
struct Foo<'a>(&'a u8);
|
||||||
|
|
||||||
fn foo(x: &u8) -> Foo<'_> {
|
fn foo(x: &u8) -> Foo<'_> {
|
||||||
@@ -31,8 +34,5 @@ fn main() {
|
|||||||
let _ = foo2(x);
|
let _ = foo2(x);
|
||||||
let _ = foo3(x);
|
let _ = foo3(x);
|
||||||
foo4(Foo(x));
|
foo4(Foo(x));
|
||||||
let _ = foo5(Foo2 {
|
let _ = foo5(Foo2 { a: x, b: &6 });
|
||||||
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