>,
}
-/// A static item in `extern` block.
-// This struct is identical to StaticItem for now but it's going to have a safety attribute.
-#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct StaticForeignItem {
- pub ty: P,
- pub safety: Safety,
- pub mutability: Mutability,
- pub expr: Option
>,
-}
-
-impl From for StaticForeignItem {
- fn from(static_item: StaticItem) -> StaticForeignItem {
- StaticForeignItem {
- ty: static_item.ty,
- safety: static_item.safety,
- mutability: static_item.mutability,
- expr: static_item.expr,
- }
- }
-}
-
-impl From for StaticItem {
- fn from(static_item: StaticForeignItem) -> StaticItem {
- StaticItem {
- ty: static_item.ty,
- safety: static_item.safety,
- mutability: static_item.mutability,
- expr: static_item.expr,
- }
- }
-}
-
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ConstItem {
pub defaultness: Defaultness,
@@ -3430,7 +3398,7 @@ impl TryFrom for AssocItemKind {
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ForeignItemKind {
/// A foreign static item (`static FOO: u8`).
- Static(Box),
+ Static(Box),
/// An foreign function.
Fn(Box),
/// An foreign type.
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 35aa53e978c15..c9d2f5c779bb6 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1310,12 +1310,7 @@ pub fn noop_flat_map_item(
impl NoopVisitItemKind for ForeignItemKind {
fn noop_visit(&mut self, visitor: &mut impl MutVisitor) {
match self {
- ForeignItemKind::Static(box StaticForeignItem {
- ty,
- mutability: _,
- expr,
- safety: _,
- }) => {
+ ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));
}
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 4dc41a02cb853..cc66cc87652d0 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -900,7 +900,11 @@ pub enum NonterminalKind {
PatWithOr,
Expr,
/// Matches an expression using the rules from edition 2021 and earlier.
- Expr2021,
+ Expr2021 {
+ /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the
+ /// edition of the span. This is used for diagnostics AND feature gating.
+ inferred: bool,
+ },
Ty,
Ident,
Lifetime,
@@ -929,8 +933,13 @@ impl NonterminalKind {
Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr,
},
sym::pat_param => NonterminalKind::PatParam { inferred: false },
- sym::expr => NonterminalKind::Expr,
- sym::expr_2021 if edition().at_least_rust_2021() => NonterminalKind::Expr2021,
+ sym::expr => match edition() {
+ Edition::Edition2015 | Edition::Edition2018 | Edition::Edition2021 => {
+ NonterminalKind::Expr2021 { inferred: true }
+ }
+ Edition::Edition2024 => NonterminalKind::Expr,
+ },
+ sym::expr_2021 => NonterminalKind::Expr2021 { inferred: false },
sym::ty => NonterminalKind::Ty,
sym::ident => NonterminalKind::Ident,
sym::lifetime => NonterminalKind::Lifetime,
@@ -949,8 +958,8 @@ impl NonterminalKind {
NonterminalKind::Stmt => sym::stmt,
NonterminalKind::PatParam { inferred: false } => sym::pat_param,
NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat,
- NonterminalKind::Expr => sym::expr,
- NonterminalKind::Expr2021 => sym::expr_2021,
+ NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: true } => sym::expr,
+ NonterminalKind::Expr2021 { inferred: false } => sym::expr_2021,
NonterminalKind::Ty => sym::ty,
NonterminalKind::Ident => sym::ident,
NonterminalKind::Lifetime => sym::lifetime,
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index ed34a44db677f..ce38a67ea69ab 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -672,12 +672,7 @@ impl WalkItemKind for ForeignItemKind {
) -> V::Result {
let &Item { id, span, ident, ref vis, .. } = item;
match self {
- ForeignItemKind::Static(box StaticForeignItem {
- ty,
- mutability: _,
- expr,
- safety: _,
- }) => {
+ ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => {
try_visit!(visitor.visit_ty(ty));
visit_opt!(visitor, visit_expr, expr);
}
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index c6c0d9a2e608e..4c7e8c24d32a9 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -664,12 +664,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety)
}
- ForeignItemKind::Static(box StaticForeignItem {
- ty,
- mutability,
- expr: _,
- safety,
- }) => {
+ ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
let ty = self
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index b274a9b9114ac..cad1fc79d7f4f 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1232,7 +1232,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_foreign_ty_genericless(generics, where_clauses);
self.check_foreign_item_ascii_only(fi.ident);
}
- ForeignItemKind::Static(box StaticForeignItem { expr, safety, .. }) => {
+ ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => {
self.check_foreign_item_safety(fi.span, *safety);
self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span));
self.check_foreign_item_ascii_only(fi.ident);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 49ac5ece337f0..d8382057d3f64 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -37,12 +37,7 @@ impl<'a> State<'a> {
ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
}
- ast::ForeignItemKind::Static(box ast::StaticForeignItem {
- ty,
- mutability,
- expr,
- safety,
- }) => {
+ ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => {
self.print_safety(*safety);
self.print_item_const(
ident,
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 49b1f5ce0e3ea..0050ff10539a8 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -1292,7 +1292,9 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
// maintain
IsInFollow::Yes
}
- NonterminalKind::Stmt | NonterminalKind::Expr | NonterminalKind::Expr2021 => {
+ NonterminalKind::Stmt
+ | NonterminalKind::Expr
+ | NonterminalKind::Expr2021 { inferred: _ } => {
const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
match tok {
TokenTree::Token(token) => match token.kind {
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 74f78c0ef7857..fdf187438d3d7 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -113,7 +113,8 @@ pub(super) fn parse(
);
token::NonterminalKind::Ident
});
- if kind == token::NonterminalKind::Expr2021
+ if kind
+ == (token::NonterminalKind::Expr2021 { inferred: false })
&& !features.expr_fragment_specifier_2024
{
rustc_session::parse::feature_err(
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index c2b91488a117a..81d5f0fca0ec9 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -2965,9 +2965,10 @@ impl<'a> Parser<'a> {
/// This checks if this is a conflict marker, depending of the parameter passed.
///
- /// * `>>>>>`
- /// * `=====`
- /// * `<<<<<`
+ /// * `<<<<<<<`
+ /// * `|||||||`
+ /// * `=======`
+ /// * `>>>>>>>`
///
pub(super) fn is_vcs_conflict_marker(
&mut self,
@@ -2997,14 +2998,18 @@ impl<'a> Parser<'a> {
}
pub(crate) fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> {
+ // <<<<<<<
let Some(start) = self.conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt)
else {
return Ok(());
};
let mut spans = Vec::with_capacity(3);
spans.push(start);
+ // |||||||
let mut middlediff3 = None;
+ // =======
let mut middle = None;
+ // >>>>>>>
let mut end = None;
loop {
if self.token.kind == TokenKind::Eof {
@@ -3025,29 +3030,50 @@ impl<'a> Parser<'a> {
}
self.bump();
}
+
let mut err = self.dcx().struct_span_err(spans, "encountered diff marker");
- err.span_label(start, "after this is the code before the merge");
- if let Some(middle) = middlediff3 {
- err.span_label(middle, "");
- }
+ match middlediff3 {
+ // We're using diff3
+ Some(middlediff3) => {
+ err.span_label(
+ start,
+ "between this marker and `|||||||` is the code that we're merging into",
+ );
+ err.span_label(middlediff3, "between this marker and `=======` is the base code (what the two refs diverged from)");
+ }
+ None => {
+ err.span_label(
+ start,
+ "between this marker and `=======` is the code that we're merging into",
+ );
+ }
+ };
+
if let Some(middle) = middle {
- err.span_label(middle, "");
+ err.span_label(middle, "between this marker and `>>>>>>>` is the incoming code");
}
if let Some(end) = end {
- err.span_label(end, "above this are the incoming code changes");
+ err.span_label(end, "this marker concludes the conflict region");
}
- err.help(
- "if you're having merge conflicts after pulling new code, the top section is the code \
- you already had and the bottom section is the remote code",
+ err.note(
+ "conflict markers indicate that a merge was started but could not be completed due \
+ to merge conflicts\n\
+ to resolve a conflict, keep only the code you want and then delete the lines \
+ containing conflict markers",
);
err.help(
- "if you're in the middle of a rebase, the top section is the code being rebased onto \
- and the bottom section is the code coming from the current commit being rebased",
+ "if you're having merge conflicts after pulling new code:\n\
+ the top section is the code you already had and the bottom section is the remote code\n\
+ if you're in the middle of a rebase:\n\
+ the top section is the code being rebased onto and the bottom section is the code \
+ coming from the current commit being rebased",
);
+
err.note(
- "for an explanation on these markers from the `git` documentation, visit \
- ",
+ "for an explanation on these markers from the `git` documentation:\n\
+ visit ",
);
+
Err(err)
}
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 3e1ea7b129de0..abb6b51cebd68 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1228,7 +1228,7 @@ impl<'a> Parser<'a> {
ident_span: ident.span,
const_span,
});
- ForeignItemKind::Static(Box::new(StaticForeignItem {
+ ForeignItemKind::Static(Box::new(StaticItem {
ty,
mutability: Mutability::Not,
expr,
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index a0b704aeea5fb..59f6eff07b320 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -36,7 +36,7 @@ impl<'a> Parser<'a> {
}
match kind {
- NonterminalKind::Expr2021 => {
+ NonterminalKind::Expr2021 { inferred: _ } => {
token.can_begin_expr()
// This exception is here for backwards compatibility.
&& !token.is_keyword(kw::Let)
@@ -47,7 +47,6 @@ impl<'a> Parser<'a> {
token.can_begin_expr()
// This exception is here for backwards compatibility.
&& !token.is_keyword(kw::Let)
- && (!token.is_keyword(kw::Const) || token.span.edition().at_least_rust_2024())
}
NonterminalKind::Ty => token.can_begin_type(),
NonterminalKind::Ident => get_macro_ident(token).is_some(),
@@ -149,7 +148,7 @@ impl<'a> Parser<'a> {
})?)
}
- NonterminalKind::Expr | NonterminalKind::Expr2021 => {
+ NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: _ } => {
NtExpr(self.parse_expr_force_collect()?)
}
NonterminalKind::Literal => {
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 60789c083133f..1bca5602a4eaa 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -217,12 +217,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
let def_kind = match fi.kind {
- ForeignItemKind::Static(box StaticForeignItem {
- ty: _,
- mutability,
- expr: _,
- safety,
- }) => {
+ ForeignItemKind::Static(box StaticItem { ty: _, mutability, expr: _, safety }) => {
let safety = match safety {
ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
ast::Safety::Safe(_) => hir::Safety::Safe,
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index d9812540e497d..017fd3072fdb7 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -208,6 +208,11 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[
("avx512vnni", Unstable(sym::avx512_target_feature)),
("avx512vp2intersect", Unstable(sym::avx512_target_feature)),
("avx512vpopcntdq", Unstable(sym::avx512_target_feature)),
+ ("avxifma", Unstable(sym::avx512_target_feature)),
+ ("avxneconvert", Unstable(sym::avx512_target_feature)),
+ ("avxvnni", Unstable(sym::avx512_target_feature)),
+ ("avxvnniint16", Unstable(sym::avx512_target_feature)),
+ ("avxvnniint8", Unstable(sym::avx512_target_feature)),
("bmi1", Stable),
("bmi2", Stable),
("cmpxchg16b", Stable),
diff --git a/library/core/tests/num/int_log.rs b/library/core/tests/num/int_log.rs
index a1edb1a518632..2320a7acc35ac 100644
--- a/library/core/tests/num/int_log.rs
+++ b/library/core/tests/num/int_log.rs
@@ -24,15 +24,15 @@ fn checked_ilog() {
#[cfg(not(miri))] // Miri is too slow
for i in i16::MIN..=0 {
- assert_eq!(i.checked_ilog(4), None);
+ assert_eq!(i.checked_ilog(4), None, "checking {i}");
}
#[cfg(not(miri))] // Miri is too slow
for i in 1..=i16::MAX {
- assert_eq!(i.checked_ilog(13), Some((i as f32).log(13.0) as u32));
+ assert_eq!(i.checked_ilog(13), Some((i as f32).log(13.0) as u32), "checking {i}");
}
#[cfg(not(miri))] // Miri is too slow
for i in 1..=u16::MAX {
- assert_eq!(i.checked_ilog(13), Some((i as f32).log(13.0) as u32));
+ assert_eq!(i.checked_ilog(13), Some((i as f32).log(13.0) as u32), "checking {i}");
}
}
@@ -49,30 +49,30 @@ fn checked_ilog2() {
assert_eq!(0i16.checked_ilog2(), None);
for i in 1..=u8::MAX {
- assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32));
+ assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}");
}
#[cfg(not(miri))] // Miri is too slow
for i in 1..=u16::MAX {
// Guard against Android's imprecise f32::ilog2 implementation.
if i != 8192 && i != 32768 {
- assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32));
+ assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}");
}
}
for i in i8::MIN..=0 {
- assert_eq!(i.checked_ilog2(), None);
+ assert_eq!(i.checked_ilog2(), None, "checking {i}");
}
for i in 1..=i8::MAX {
- assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32));
+ assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}");
}
#[cfg(not(miri))] // Miri is too slow
for i in i16::MIN..=0 {
- assert_eq!(i.checked_ilog2(), None);
+ assert_eq!(i.checked_ilog2(), None, "checking {i}");
}
#[cfg(not(miri))] // Miri is too slow
for i in 1..=i16::MAX {
// Guard against Android's imprecise f32::ilog2 implementation.
if i != 8192 {
- assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32));
+ assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}");
}
}
}
@@ -95,19 +95,19 @@ fn checked_ilog10() {
#[cfg(not(miri))] // Miri is too slow
for i in i16::MIN..=0 {
- assert_eq!(i.checked_ilog10(), None);
+ assert_eq!(i.checked_ilog10(), None, "checking {i}");
}
#[cfg(not(miri))] // Miri is too slow
for i in 1..=i16::MAX {
- assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32));
+ assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32), "checking {i}");
}
#[cfg(not(miri))] // Miri is too slow
for i in 1..=u16::MAX {
- assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32));
+ assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32), "checking {i}");
}
#[cfg(not(miri))] // Miri is too slow
for i in 1..=100_000u32 {
- assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32));
+ assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32), "checking {i}");
}
}
diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs
index 2ba67a6dd1aa9..e9d436bc355cd 100644
--- a/library/std/src/os/linux/process.rs
+++ b/library/std/src/os/linux/process.rs
@@ -6,20 +6,21 @@
use crate::io::Result;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
-use crate::process;
+use crate::process::{self, ExitStatus};
use crate::sealed::Sealed;
-#[cfg(not(doc))]
use crate::sys::fd::FileDesc;
+#[cfg(not(doc))]
+use crate::sys::linux::pidfd::PidFd as InnerPidFd;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
#[cfg(doc)]
-struct FileDesc;
+struct InnerPidFd;
/// This type represents a file descriptor that refers to a process.
///
/// A `PidFd` can be obtained by setting the corresponding option on [`Command`]
/// with [`create_pidfd`]. Subsequently, the created pidfd can be retrieved
-/// from the [`Child`] by calling [`pidfd`] or [`take_pidfd`].
+/// from the [`Child`] by calling [`pidfd`] or [`into_pidfd`].
///
/// Example:
/// ```no_run
@@ -33,7 +34,7 @@ struct FileDesc;
/// .expect("Failed to spawn child");
///
/// let pidfd = child
-/// .take_pidfd()
+/// .into_pidfd()
/// .expect("Failed to retrieve pidfd");
///
/// // The file descriptor will be closed when `pidfd` is dropped.
@@ -44,28 +45,63 @@ struct FileDesc;
/// [`create_pidfd`]: CommandExt::create_pidfd
/// [`Child`]: process::Child
/// [`pidfd`]: fn@ChildExt::pidfd
-/// [`take_pidfd`]: ChildExt::take_pidfd
+/// [`into_pidfd`]: ChildExt::into_pidfd
/// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html
#[derive(Debug)]
+#[repr(transparent)]
pub struct PidFd {
- inner: FileDesc,
+ inner: InnerPidFd,
+}
+
+impl PidFd {
+ /// Forces the child process to exit.
+ ///
+ /// Unlike [`Child::kill`] it is possible to attempt to kill
+ /// reaped children since PidFd does not suffer from pid recycling
+ /// races. But doing so will return an Error.
+ ///
+ /// [`Child::kill`]: process::Child::kill
+ pub fn kill(&self) -> Result<()> {
+ self.inner.kill()
+ }
+
+ /// Waits for the child to exit completely, returning the status that it exited with.
+ ///
+ /// Unlike [`Child::wait`] it does not ensure that the stdin handle is closed.
+ /// Additionally it will not return an `ExitStatus` if the child
+ /// has already been reaped. Instead an error will be returned.
+ ///
+ /// [`Child::wait`]: process::Child::wait
+ pub fn wait(&self) -> Result {
+ self.inner.wait().map(FromInner::from_inner)
+ }
+
+ /// Attempts to collect the exit status of the child if it has already exited.
+ ///
+ /// Unlike [`Child::try_wait`] this method will return an Error
+ /// if the child has already been reaped.
+ ///
+ /// [`Child::try_wait`]: process::Child::try_wait
+ pub fn try_wait(&self) -> Result