Auto merge of #120121 - matthiaskrgr:rollup-razammh, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #118665 (Consolidate all associated items on the NonZero integer types into a single impl block per type) - #118798 (Use AtomicU8 instead of AtomicUsize in backtrace.rs) - #119062 (Deny braced macro invocations in let-else) - #119138 (Docs: Use non-SeqCst in module example of atomics) - #119907 (Update `fn()` trait implementation docs) - #120083 (Warn when not having a profiler runtime means that coverage tests won't be run/blessed) - #120107 (dead_code treats #[repr(transparent)] the same as #[repr(C)]) - #120110 (Update documentation for Vec::into_boxed_slice to be more clear about excess capacity) - #120113 (Remove myself from review rotation) - #120118 (Fix typo in documentation in base.rs) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
32ec40c685
23 changed files with 1397 additions and 1347 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// Predicates on exprs and stmts that the pretty-printer and parser use
|
// Predicates on exprs and stmts that the pretty-printer and parser use
|
||||||
|
|
||||||
use crate::ast;
|
use crate::{ast, token::Delimiter};
|
||||||
|
|
||||||
/// Does this expression require a semicolon to be treated
|
/// Does this expression require a semicolon to be treated
|
||||||
/// as a statement? The negation of this: 'can this expression
|
/// as a statement? The negation of this: 'can this expression
|
||||||
|
@ -59,8 +59,12 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
||||||
| While(..)
|
| While(..)
|
||||||
| ConstBlock(_) => break Some(expr),
|
| ConstBlock(_) => break Some(expr),
|
||||||
|
|
||||||
// FIXME: These can end in `}`, but changing these would break stable code.
|
MacCall(mac) => {
|
||||||
InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
|
break (mac.args.delim == Delimiter::Brace).then_some(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
|
||||||
|
// These should have been denied pre-expansion.
|
||||||
break None;
|
break None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -666,8 +666,8 @@ pub enum SyntaxExtensionKind {
|
||||||
/// A token-based attribute macro.
|
/// A token-based attribute macro.
|
||||||
Attr(
|
Attr(
|
||||||
/// An expander with signature (TokenStream, TokenStream) -> TokenStream.
|
/// An expander with signature (TokenStream, TokenStream) -> TokenStream.
|
||||||
/// The first TokenSteam is the attribute itself, the second is the annotated item.
|
/// The first TokenStream is the attribute itself, the second is the annotated item.
|
||||||
/// The produced TokenSteam replaces the input TokenSteam.
|
/// The produced TokenStream replaces the input TokenStream.
|
||||||
Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
|
Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -687,7 +687,7 @@ pub enum SyntaxExtensionKind {
|
||||||
/// A token-based derive macro.
|
/// A token-based derive macro.
|
||||||
Derive(
|
Derive(
|
||||||
/// An expander with signature TokenStream -> TokenStream.
|
/// An expander with signature TokenStream -> TokenStream.
|
||||||
/// The produced TokenSteam is appended to the input TokenSteam.
|
/// The produced TokenStream is appended to the input TokenStream.
|
||||||
///
|
///
|
||||||
/// FIXME: The text above describes how this should work. Currently it
|
/// FIXME: The text above describes how this should work. Currently it
|
||||||
/// is handled identically to `LegacyDerive`. It should be migrated to
|
/// is handled identically to `LegacyDerive`. It should be migrated to
|
||||||
|
|
|
@ -724,6 +724,8 @@ parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifeti
|
||||||
|
|
||||||
parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
|
parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
|
||||||
|
|
||||||
|
parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro
|
||||||
|
|
||||||
parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
|
parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
|
||||||
|
|
||||||
parse_switch_mut_let_order =
|
parse_switch_mut_let_order =
|
||||||
|
|
|
@ -722,19 +722,32 @@ pub(crate) struct LabeledLoopInBreak {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub sub: WrapExpressionInParentheses,
|
pub sub: WrapInParentheses,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
#[multipart_suggestion(
|
|
||||||
|
pub(crate) enum WrapInParentheses {
|
||||||
|
#[multipart_suggestion(
|
||||||
parse_sugg_wrap_expression_in_parentheses,
|
parse_sugg_wrap_expression_in_parentheses,
|
||||||
applicability = "machine-applicable"
|
applicability = "machine-applicable"
|
||||||
)]
|
)]
|
||||||
pub(crate) struct WrapExpressionInParentheses {
|
Expression {
|
||||||
#[suggestion_part(code = "(")]
|
#[suggestion_part(code = "(")]
|
||||||
pub left: Span,
|
left: Span,
|
||||||
#[suggestion_part(code = ")")]
|
#[suggestion_part(code = ")")]
|
||||||
pub right: Span,
|
right: Span,
|
||||||
|
},
|
||||||
|
#[multipart_suggestion(
|
||||||
|
parse_sugg_wrap_macro_in_parentheses,
|
||||||
|
applicability = "machine-applicable"
|
||||||
|
)]
|
||||||
|
MacroArgs {
|
||||||
|
#[suggestion_part(code = "(")]
|
||||||
|
left: Span,
|
||||||
|
#[suggestion_part(code = ")")]
|
||||||
|
right: Span,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -936,7 +949,7 @@ pub(crate) struct InvalidExpressionInLetElse {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub operator: &'static str,
|
pub operator: &'static str,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub sugg: WrapExpressionInParentheses,
|
pub sugg: WrapInParentheses,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -945,7 +958,7 @@ pub(crate) struct InvalidCurlyInLetElse {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub sugg: WrapExpressionInParentheses,
|
pub sugg: WrapInParentheses,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -1844,7 +1844,7 @@ impl<'a> Parser<'a> {
|
||||||
let lexpr = self.parse_expr_labeled(label, true)?;
|
let lexpr = self.parse_expr_labeled(label, true)?;
|
||||||
self.dcx().emit_err(errors::LabeledLoopInBreak {
|
self.dcx().emit_err(errors::LabeledLoopInBreak {
|
||||||
span: lexpr.span,
|
span: lexpr.span,
|
||||||
sub: errors::WrapExpressionInParentheses {
|
sub: errors::WrapInParentheses::Expression {
|
||||||
left: lexpr.span.shrink_to_lo(),
|
left: lexpr.span.shrink_to_lo(),
|
||||||
right: lexpr.span.shrink_to_hi(),
|
right: lexpr.span.shrink_to_hi(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -389,7 +389,7 @@ impl<'a> Parser<'a> {
|
||||||
self.dcx().emit_err(errors::InvalidExpressionInLetElse {
|
self.dcx().emit_err(errors::InvalidExpressionInLetElse {
|
||||||
span: init.span,
|
span: init.span,
|
||||||
operator: op.node.as_str(),
|
operator: op.node.as_str(),
|
||||||
sugg: errors::WrapExpressionInParentheses {
|
sugg: errors::WrapInParentheses::Expression {
|
||||||
left: init.span.shrink_to_lo(),
|
left: init.span.shrink_to_lo(),
|
||||||
right: init.span.shrink_to_hi(),
|
right: init.span.shrink_to_hi(),
|
||||||
},
|
},
|
||||||
|
@ -400,12 +400,19 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
|
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
|
||||||
if let Some(trailing) = classify::expr_trailing_brace(init) {
|
if let Some(trailing) = classify::expr_trailing_brace(init) {
|
||||||
self.dcx().emit_err(errors::InvalidCurlyInLetElse {
|
let sugg = match &trailing.kind {
|
||||||
span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
|
ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs {
|
||||||
sugg: errors::WrapExpressionInParentheses {
|
left: mac.args.dspan.open,
|
||||||
|
right: mac.args.dspan.close,
|
||||||
|
},
|
||||||
|
_ => errors::WrapInParentheses::Expression {
|
||||||
left: trailing.span.shrink_to_lo(),
|
left: trailing.span.shrink_to_lo(),
|
||||||
right: trailing.span.shrink_to_hi(),
|
right: trailing.span.shrink_to_hi(),
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
self.dcx().emit_err(errors::InvalidCurlyInLetElse {
|
||||||
|
span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
|
||||||
|
sugg,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct MarkSymbolVisitor<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
|
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
|
||||||
live_symbols: LocalDefIdSet,
|
live_symbols: LocalDefIdSet,
|
||||||
repr_has_repr_c: bool,
|
repr_unconditionally_treats_fields_as_live: bool,
|
||||||
repr_has_repr_simd: bool,
|
repr_has_repr_simd: bool,
|
||||||
in_pat: bool,
|
in_pat: bool,
|
||||||
ignore_variant_stack: Vec<DefId>,
|
ignore_variant_stack: Vec<DefId>,
|
||||||
|
@ -365,15 +365,17 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let had_repr_c = self.repr_has_repr_c;
|
let unconditionally_treated_fields_as_live =
|
||||||
|
self.repr_unconditionally_treats_fields_as_live;
|
||||||
let had_repr_simd = self.repr_has_repr_simd;
|
let had_repr_simd = self.repr_has_repr_simd;
|
||||||
self.repr_has_repr_c = false;
|
self.repr_unconditionally_treats_fields_as_live = false;
|
||||||
self.repr_has_repr_simd = false;
|
self.repr_has_repr_simd = false;
|
||||||
match node {
|
match node {
|
||||||
Node::Item(item) => match item.kind {
|
Node::Item(item) => match item.kind {
|
||||||
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
|
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
|
||||||
let def = self.tcx.adt_def(item.owner_id);
|
let def = self.tcx.adt_def(item.owner_id);
|
||||||
self.repr_has_repr_c = def.repr().c();
|
self.repr_unconditionally_treats_fields_as_live =
|
||||||
|
def.repr().c() || def.repr().transparent();
|
||||||
self.repr_has_repr_simd = def.repr().simd();
|
self.repr_has_repr_simd = def.repr().simd();
|
||||||
|
|
||||||
intravisit::walk_item(self, item)
|
intravisit::walk_item(self, item)
|
||||||
|
@ -411,7 +413,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.repr_has_repr_simd = had_repr_simd;
|
self.repr_has_repr_simd = had_repr_simd;
|
||||||
self.repr_has_repr_c = had_repr_c;
|
self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
|
fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
|
||||||
|
@ -435,11 +437,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
|
||||||
|
|
||||||
fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) {
|
fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let has_repr_c = self.repr_has_repr_c;
|
let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live;
|
||||||
let has_repr_simd = self.repr_has_repr_simd;
|
let has_repr_simd = self.repr_has_repr_simd;
|
||||||
let live_fields = def.fields().iter().filter_map(|f| {
|
let live_fields = def.fields().iter().filter_map(|f| {
|
||||||
let def_id = f.def_id;
|
let def_id = f.def_id;
|
||||||
if has_repr_c || (f.is_positional() && has_repr_simd) {
|
if unconditionally_treat_fields_as_live || (f.is_positional() && has_repr_simd) {
|
||||||
return Some(def_id);
|
return Some(def_id);
|
||||||
}
|
}
|
||||||
if !tcx.visibility(f.hir_id.owner.def_id).is_public() {
|
if !tcx.visibility(f.hir_id.owner.def_id).is_public() {
|
||||||
|
@ -741,7 +743,7 @@ fn live_symbols_and_ignored_derived_traits(
|
||||||
tcx,
|
tcx,
|
||||||
maybe_typeck_results: None,
|
maybe_typeck_results: None,
|
||||||
live_symbols: Default::default(),
|
live_symbols: Default::default(),
|
||||||
repr_has_repr_c: false,
|
repr_unconditionally_treats_fields_as_live: false,
|
||||||
repr_has_repr_simd: false,
|
repr_has_repr_simd: false,
|
||||||
in_pat: false,
|
in_pat: false,
|
||||||
ignore_variant_stack: vec![],
|
ignore_variant_stack: vec![],
|
||||||
|
|
|
@ -171,7 +171,6 @@ struct WithHeader<H>(NonNull<u8>, PhantomData<H>);
|
||||||
/// An opaque representation of `WithHeader<H>` to avoid the
|
/// An opaque representation of `WithHeader<H>` to avoid the
|
||||||
/// projection invariance of `<T as Pointee>::Metadata`.
|
/// projection invariance of `<T as Pointee>::Metadata`.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[allow(dead_code)] // Field only used through `WithHeader` type above.
|
|
||||||
struct WithOpaqueHeader(NonNull<u8>);
|
struct WithOpaqueHeader(NonNull<u8>);
|
||||||
|
|
||||||
impl WithOpaqueHeader {
|
impl WithOpaqueHeader {
|
||||||
|
|
|
@ -358,7 +358,7 @@ mod spec_extend;
|
||||||
///
|
///
|
||||||
/// `vec![x; n]`, `vec![a, b, c, d]`, and
|
/// `vec![x; n]`, `vec![a, b, c, d]`, and
|
||||||
/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec`
|
/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec`
|
||||||
/// with exactly the requested capacity. If <code>[len] == [capacity]</code>,
|
/// with at least the requested capacity. If <code>[len] == [capacity]</code>,
|
||||||
/// (as is the case for the [`vec!`] macro), then a `Vec<T>` can be converted to
|
/// (as is the case for the [`vec!`] macro), then a `Vec<T>` can be converted to
|
||||||
/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements.
|
/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements.
|
||||||
///
|
///
|
||||||
|
@ -1023,8 +1023,11 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
|
|
||||||
/// Shrinks the capacity of the vector as much as possible.
|
/// Shrinks the capacity of the vector as much as possible.
|
||||||
///
|
///
|
||||||
/// It will drop down as close as possible to the length but the allocator
|
/// The behavior of this method depends on the allocator, which may either shrink the vector
|
||||||
/// may still inform the vector that there is space for a few more elements.
|
/// in-place or reallocate. The resulting vector might still have some excess capacity, just as
|
||||||
|
/// is the case for [`with_capacity`]. See [`Allocator::shrink`] for more details.
|
||||||
|
///
|
||||||
|
/// [`with_capacity`]: Vec::with_capacity
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1074,10 +1077,10 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
|
|
||||||
/// Converts the vector into [`Box<[T]>`][owned slice].
|
/// Converts the vector into [`Box<[T]>`][owned slice].
|
||||||
///
|
///
|
||||||
/// If the vector has excess capacity, its items will be moved into a
|
/// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`].
|
||||||
/// newly-allocated buffer with exactly the right capacity.
|
|
||||||
///
|
///
|
||||||
/// [owned slice]: Box
|
/// [owned slice]: Box
|
||||||
|
/// [`shrink_to_fit`]: Vec::shrink_to_fit
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -3290,8 +3293,10 @@ impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> {
|
||||||
impl<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> {
|
impl<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> {
|
||||||
/// Convert a vector into a boxed slice.
|
/// Convert a vector into a boxed slice.
|
||||||
///
|
///
|
||||||
/// If `v` has excess capacity, its items will be moved into a
|
/// Before doing the conversion, this method discards excess capacity like [`Vec::shrink_to_fit`].
|
||||||
/// newly-allocated buffer with exactly the right capacity.
|
///
|
||||||
|
/// [owned slice]: Box
|
||||||
|
/// [`Vec::shrink_to_fit`]: Vec::shrink_to_fit
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1634,9 +1634,8 @@ mod prim_ref {}
|
||||||
/// function pointers of varying length. Note that this is a convenience notation to avoid
|
/// function pointers of varying length. Note that this is a convenience notation to avoid
|
||||||
/// repetitive documentation, not valid Rust syntax.
|
/// repetitive documentation, not valid Rust syntax.
|
||||||
///
|
///
|
||||||
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
|
/// The following traits are implemented for function pointers with any number of arguments and
|
||||||
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
|
/// any ABI.
|
||||||
/// may change:
|
|
||||||
///
|
///
|
||||||
/// * [`PartialEq`]
|
/// * [`PartialEq`]
|
||||||
/// * [`Eq`]
|
/// * [`Eq`]
|
||||||
|
@ -1645,11 +1644,6 @@ mod prim_ref {}
|
||||||
/// * [`Hash`]
|
/// * [`Hash`]
|
||||||
/// * [`Pointer`]
|
/// * [`Pointer`]
|
||||||
/// * [`Debug`]
|
/// * [`Debug`]
|
||||||
///
|
|
||||||
/// The following traits are implemented for function pointers with any number of arguments and
|
|
||||||
/// any ABI. These traits have implementations that are automatically generated by the compiler,
|
|
||||||
/// so are not limited by missing language features:
|
|
||||||
///
|
|
||||||
/// * [`Clone`]
|
/// * [`Clone`]
|
||||||
/// * [`Copy`]
|
/// * [`Copy`]
|
||||||
/// * [`Send`]
|
/// * [`Send`]
|
||||||
|
|
|
@ -138,7 +138,7 @@
|
||||||
//!
|
//!
|
||||||
//! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting
|
//! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting
|
||||||
//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only
|
//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only
|
||||||
//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since
|
//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since
|
||||||
//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault
|
//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault
|
||||||
//! on read-only memory.
|
//! on read-only memory.
|
||||||
//!
|
//!
|
||||||
|
@ -181,12 +181,13 @@
|
||||||
//! let spinlock = Arc::new(AtomicUsize::new(1));
|
//! let spinlock = Arc::new(AtomicUsize::new(1));
|
||||||
//!
|
//!
|
||||||
//! let spinlock_clone = Arc::clone(&spinlock);
|
//! let spinlock_clone = Arc::clone(&spinlock);
|
||||||
|
//!
|
||||||
//! let thread = thread::spawn(move|| {
|
//! let thread = thread::spawn(move|| {
|
||||||
//! spinlock_clone.store(0, Ordering::SeqCst);
|
//! spinlock_clone.store(0, Ordering::Release);
|
||||||
//! });
|
//! });
|
||||||
//!
|
//!
|
||||||
//! // Wait for the other thread to release the lock
|
//! // Wait for the other thread to release the lock
|
||||||
//! while spinlock.load(Ordering::SeqCst) != 0 {
|
//! while spinlock.load(Ordering::Acquire) != 0 {
|
||||||
//! hint::spin_loop();
|
//! hint::spin_loop();
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
@ -203,7 +204,11 @@
|
||||||
//!
|
//!
|
||||||
//! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0);
|
//! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
//!
|
//!
|
||||||
//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
|
//! // Note that Relaxed ordering doesn't synchronize anything
|
||||||
|
//! // except the global thread counter itself.
|
||||||
|
//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::Relaxed);
|
||||||
|
//! // Note that this number may not be true at the moment of printing
|
||||||
|
//! // because some other thread may have changed static value already.
|
||||||
//! println!("live threads: {}", old_thread_count + 1);
|
//! println!("live threads: {}", old_thread_count + 1);
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ use crate::env;
|
||||||
use crate::ffi::c_void;
|
use crate::ffi::c_void;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::panic::UnwindSafe;
|
use crate::panic::UnwindSafe;
|
||||||
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
|
use crate::sync::atomic::{AtomicU8, Ordering::Relaxed};
|
||||||
use crate::sync::LazyLock;
|
use crate::sync::LazyLock;
|
||||||
use crate::sys_common::backtrace::{lock, output_filename, set_image_base};
|
use crate::sys_common::backtrace::{lock, output_filename, set_image_base};
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ impl Backtrace {
|
||||||
// Cache the result of reading the environment variables to make
|
// Cache the result of reading the environment variables to make
|
||||||
// backtrace captures speedy, because otherwise reading environment
|
// backtrace captures speedy, because otherwise reading environment
|
||||||
// variables every time can be somewhat slow.
|
// variables every time can be somewhat slow.
|
||||||
static ENABLED: AtomicUsize = AtomicUsize::new(0);
|
static ENABLED: AtomicU8 = AtomicU8::new(0);
|
||||||
match ENABLED.load(Relaxed) {
|
match ENABLED.load(Relaxed) {
|
||||||
0 => {}
|
0 => {}
|
||||||
1 => return false,
|
1 => return false,
|
||||||
|
@ -267,7 +267,7 @@ impl Backtrace {
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
ENABLED.store(enabled as usize + 1, Relaxed);
|
ENABLED.store(enabled as u8 + 1, Relaxed);
|
||||||
enabled
|
enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,15 @@ fn main() {
|
||||||
eprintln!("warning: `tidy` is not installed; diffs will not be generated");
|
eprintln!("warning: `tidy` is not installed; diffs will not be generated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !config.profiler_support && config.mode == Mode::CoverageRun {
|
||||||
|
let actioned = if config.bless { "blessed" } else { "checked" };
|
||||||
|
eprintln!(
|
||||||
|
r#"
|
||||||
|
WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned}
|
||||||
|
help: try setting `profiler = true` in the `[build]` section of `config.toml`"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
log_config(&config);
|
log_config(&config);
|
||||||
run_tests(config);
|
run_tests(config);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
trait Empty {}
|
trait Empty {}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct FunnyPointer(#[allow(dead_code)] dyn Empty);
|
pub struct FunnyPointer(dyn Empty);
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Meta {
|
pub struct Meta {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//@compile-flags: -Cdebug-assertions=no
|
//@compile-flags: -Cdebug-assertions=no
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct HasDrop(#[allow(dead_code)] u8);
|
struct HasDrop(u8);
|
||||||
|
|
||||||
impl Drop for HasDrop {
|
impl Drop for HasDrop {
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct Foo(#[allow(dead_code)] u32);
|
struct Foo(u32);
|
||||||
|
|
||||||
const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
|
const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ use std::sync::{Mutex, RwLock};
|
||||||
struct Wrapper<T>(#[allow(dead_code)] T);
|
struct Wrapper<T>(#[allow(dead_code)] T);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct Transparent<T>(#[allow(dead_code)] T);
|
struct Transparent<T>(T);
|
||||||
|
|
||||||
struct NoNiche<T>(UnsafeCell<T>);
|
struct NoNiche<T>(UnsafeCell<T>);
|
||||||
|
|
||||||
|
|
14
tests/ui/lint/dead-code/type-in-transparent.rs
Normal file
14
tests/ui/lint/dead-code/type-in-transparent.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Verify that we do not warn on fields that are part of transparent types.
|
||||||
|
// check-pass
|
||||||
|
#![deny(dead_code)]
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct NamedStruct { field: u8 }
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct TupleStruct(u8);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = NamedStruct { field: 1 };
|
||||||
|
let _ = TupleStruct(1);
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ impl<'a> Drop for Aligned<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct NotCopy(#[allow(dead_code)] u8);
|
struct NotCopy(u8);
|
||||||
|
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
struct Packed<'a>(NotCopy, Aligned<'a>);
|
struct Packed<'a>(NotCopy, Aligned<'a>);
|
||||||
|
|
|
@ -161,4 +161,29 @@ fn q() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn r() {
|
||||||
|
let ok = format_args!("") else { return; };
|
||||||
|
|
||||||
|
let bad = format_args! {""} else { return; };
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
fn s() {
|
||||||
|
macro_rules! a {
|
||||||
|
() => { {} }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! b {
|
||||||
|
(1) => {
|
||||||
|
let x = a!() else { return; };
|
||||||
|
};
|
||||||
|
(2) => {
|
||||||
|
let x = a! {} else { return; };
|
||||||
|
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
b!(1); b!(2);
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -228,5 +228,31 @@ LL | x
|
||||||
LL ~ }) else {
|
LL ~ }) else {
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 17 previous errors
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:167:31
|
||||||
|
|
|
||||||
|
LL | let bad = format_args! {""} else { return; };
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: use parentheses instead of braces for this macro
|
||||||
|
|
|
||||||
|
LL | let bad = format_args! ("") else { return; };
|
||||||
|
| ~ ~
|
||||||
|
|
||||||
|
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||||
|
--> $DIR/bad-let-else-statement.rs:181:25
|
||||||
|
|
|
||||||
|
LL | let x = a! {} else { return; };
|
||||||
|
| ^
|
||||||
|
...
|
||||||
|
LL | b!(1); b!(2);
|
||||||
|
| ----- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: use parentheses instead of braces for this macro
|
||||||
|
|
|
||||||
|
LL | let x = a! () else { return; };
|
||||||
|
| ~~
|
||||||
|
|
||||||
|
error: aborting due to 19 previous errors
|
||||||
|
|
||||||
|
|
|
@ -644,7 +644,6 @@ compiler-team = [
|
||||||
]
|
]
|
||||||
compiler-team-contributors = [
|
compiler-team-contributors = [
|
||||||
"@TaKO8Ki",
|
"@TaKO8Ki",
|
||||||
"@WaffleLapkin",
|
|
||||||
"@b-naber",
|
"@b-naber",
|
||||||
]
|
]
|
||||||
compiler = [
|
compiler = [
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue