diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 727fd59c6b306..ad942e9b494ae 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -100,7 +100,7 @@ pub struct Path {
impl PartialEq for Path {
#[inline]
fn eq(&self, symbol: &Symbol) -> bool {
- self.segments.len() == 1 && { self.segments[0].ident.name == *symbol }
+ matches!(&self.segments[..], [segment] if segment.ident.name == *symbol)
}
}
@@ -121,13 +121,13 @@ impl Path {
}
pub fn is_global(&self) -> bool {
- !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
+ self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
}
/// If this path is a single identifier with no arguments, does not ensure
/// that the path resolves to a const param, the caller should check this.
pub fn is_potential_trivial_const_arg(&self) -> bool {
- self.segments.len() == 1 && self.segments[0].args.is_none()
+ matches!(self.segments[..], [PathSegment { args: None, .. }])
}
}
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 51f1858001321..df2f4b8871249 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -302,7 +302,7 @@ impl AttrItem {
impl MetaItem {
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
pub fn ident(&self) -> Option {
- if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
+ if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None }
}
pub fn name_or_empty(&self) -> Symbol {
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index aa88e8369d5b6..3459d39131ac7 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1813,10 +1813,10 @@ pub fn walk_flat_map_stmt(
.into_iter()
.map(|kind| Stmt { id, kind, span })
.collect();
- match stmts.len() {
- 0 => {}
- 1 => vis.visit_span(&mut stmts[0].span),
- 2.. => panic!(
+ match &mut stmts[..] {
+ [] => {}
+ [stmt] => vis.visit_span(&mut stmt.span),
+ _ => panic!(
"cloning statement `NodeId`s is prohibited by default, \
the visitor should implement custom statement visiting"
),
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index f39142f08ba52..e12818623d8ec 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -39,7 +39,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
let mut i = 0;
let mut j = lines.len();
// first line of all-stars should be omitted
- if !lines.is_empty() && lines[0].chars().all(|c| c == '*') {
+ if lines.first().is_some_and(|line| line.chars().all(|c| c == '*')) {
i += 1;
}
@@ -97,7 +97,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
return None;
}
}
- if lines.is_empty() { None } else { Some(lines[0][..i].into()) }
+ Some(lines.first()?[..i].to_string())
}
let data_s = data.as_str();
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index fee7287951d0a..cc21a18af3a09 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -140,7 +140,7 @@ where
// Don't emit a new diagnostic for these errors, they are already reported elsewhere or
// should remain silent.
err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span),
- err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
+ err_inval!(Layout(LayoutError::TooGeneric(_))) | err_inval!(TooGeneric) => {
ErrorHandled::TooGeneric(span)
}
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 394719314612e..4c8f2735b9795 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -201,7 +201,7 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError
use LayoutError::*;
match layout_err {
- Unknown(ty) => {
+ TooGeneric(ty) => {
match abi {
ExternAbi::CCmseNonSecureCall => {
// prevent double reporting of this error
@@ -211,7 +211,11 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError
_ => bug!("invalid ABI: {abi}"),
}
}
- SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => {
+ Unknown(..)
+ | SizeOverflow(..)
+ | NormalizationFailure(..)
+ | ReferencesError(..)
+ | Cycle(..) => {
false // not our job to report these
}
}
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index f4929aae59901..54e9e699353fa 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -122,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("generic size {size}")
}
}
- Err(LayoutError::Unknown(bad)) => {
+ Err(LayoutError::TooGeneric(bad)) => {
if *bad == ty {
"this type does not have a fixed size".to_owned()
} else {
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 0c1bd08474fc1..55c6a122d35d5 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -76,6 +76,11 @@ lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$rea
lint_builtin_deref_nullptr = dereferencing a null pointer
.label = this code causes undefined behavior when executed
+lint_builtin_double_negations = use of a double negation
+ .note = the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
+ .note_decrement = use `-= 1` if you meant to decrement the value
+ .add_parens_suggestion = add parentheses for clarity
+
lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
.suggestion = use `..=` for an inclusive range
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 876ef944d650b..c03de687a338b 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -49,16 +49,16 @@ use rustc_trait_selection::traits::{self};
use crate::errors::BuiltinEllipsisInclusiveRangePatterns;
use crate::lints::{
BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
- BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr,
- BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
- BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
- BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
- BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes,
- BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed,
- BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller,
- BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub,
- BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
- BuiltinWhileTrue, InvalidAsmLabel,
+ BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr, BuiltinDoubleNegations,
+ BuiltinDoubleNegationsAddParens, BuiltinEllipsisInclusiveRangePatternsLint,
+ BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote,
+ BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures,
+ BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
+ BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
+ BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
+ BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub,
+ BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
+ BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
};
use crate::nonstandard_style::{MethodLateContext, method_context};
use crate::{
@@ -90,19 +90,11 @@ declare_lint! {
declare_lint_pass!(WhileTrue => [WHILE_TRUE]);
-/// Traverse through any amount of parenthesis and return the first non-parens expression.
-fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
- while let ast::ExprKind::Paren(sub) = &expr.kind {
- expr = sub;
- }
- expr
-}
-
impl EarlyLintPass for WhileTrue {
#[inline]
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
if let ast::ExprKind::While(cond, _, label) = &e.kind
- && let ast::ExprKind::Lit(token_lit) = pierce_parens(cond).kind
+ && let ast::ExprKind::Lit(token_lit) = cond.peel_parens().kind
&& let token::Lit { kind: token::Bool, symbol: kw::True, .. } = token_lit
&& !cond.span.from_expansion()
{
@@ -1576,6 +1568,58 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
}
}
+declare_lint! {
+ /// The `double_negations` lint detects expressions of the form `--x`.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// fn main() {
+ /// let x = 1;
+ /// let _b = --x;
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Negating something twice is usually the same as not negating it at all.
+ /// However, a double negation in Rust can easily be confused with the
+ /// prefix decrement operator that exists in many languages derived from C.
+ /// Use `-(-x)` if you really wanted to negate the value twice.
+ ///
+ /// To decrement a value, use `x -= 1` instead.
+ pub DOUBLE_NEGATIONS,
+ Warn,
+ "detects expressions of the form `--x`"
+}
+
+declare_lint_pass!(
+ /// Lint for expressions of the form `--x` that can be confused with C's
+ /// prefix decrement operator.
+ DoubleNegations => [DOUBLE_NEGATIONS]
+);
+
+impl EarlyLintPass for DoubleNegations {
+ #[inline]
+ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
+ // only lint on the innermost `--` in a chain of `-` operators,
+ // even if there are 3 or more negations
+ if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind
+ && let ExprKind::Unary(UnOp::Neg, ref inner2) = inner.kind
+ && !matches!(inner2.kind, ExprKind::Unary(UnOp::Neg, _))
+ {
+ cx.emit_span_lint(DOUBLE_NEGATIONS, expr.span, BuiltinDoubleNegations {
+ add_parens: BuiltinDoubleNegationsAddParens {
+ start_span: inner.span.shrink_to_lo(),
+ end_span: inner.span.shrink_to_hi(),
+ },
+ });
+ }
+ }
+}
+
declare_lint_pass!(
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
@@ -1594,7 +1638,8 @@ declare_lint_pass!(
UNSTABLE_FEATURES,
UNREACHABLE_PUB,
TYPE_ALIAS_BOUNDS,
- TRIVIAL_BOUNDS
+ TRIVIAL_BOUNDS,
+ DOUBLE_NEGATIONS
]
);
@@ -2651,7 +2696,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
}
declare_lint! {
- /// The `deref_nullptr` lint detects when an null pointer is dereferenced,
+ /// The `deref_nullptr` lint detects when a null pointer is dereferenced,
/// which causes [undefined behavior].
///
/// ### Example
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 1465c2cff7bc1..83a168c3f4462 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -181,6 +181,7 @@ early_lint_methods!(
UnusedDocComment: UnusedDocComment,
Expr2024: Expr2024,
Precedence: Precedence,
+ DoubleNegations: DoubleNegations,
]
]
);
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 3163bc8a300a1..677fc86a23519 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -331,6 +331,24 @@ pub(crate) struct BuiltinTrivialBounds<'a> {
pub predicate: Clause<'a>,
}
+#[derive(LintDiagnostic)]
+#[diag(lint_builtin_double_negations)]
+#[note(lint_note)]
+#[note(lint_note_decrement)]
+pub(crate) struct BuiltinDoubleNegations {
+ #[subdiagnostic]
+ pub add_parens: BuiltinDoubleNegationsAddParens,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(lint_add_parens_suggestion, applicability = "maybe-incorrect")]
+pub(crate) struct BuiltinDoubleNegationsAddParens {
+ #[suggestion_part(code = "(")]
+ pub start_span: Span,
+ #[suggestion_part(code = ")")]
+ pub end_span: Span,
+}
+
#[derive(LintDiagnostic)]
pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
#[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 5dd85978f007f..8dc529b4d7a21 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -100,6 +100,8 @@ middle_strict_coherence_needs_negative_coherence =
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
.label = due to this attribute
+middle_too_generic = `{$ty}` does not have a fixed size
+
middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
middle_unknown_layout =
@@ -107,4 +109,5 @@ middle_unknown_layout =
middle_values_too_big =
values of the type `{$ty}` are too big for the target architecture
+
middle_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 6300d856393c6..b0187a1848cf1 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -129,6 +129,9 @@ pub enum LayoutError<'tcx> {
#[diag(middle_unknown_layout)]
Unknown { ty: Ty<'tcx> },
+ #[diag(middle_too_generic)]
+ TooGeneric { ty: Ty<'tcx> },
+
#[diag(middle_values_too_big)]
Overflow { ty: Ty<'tcx> },
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 1e67cdfc32a9b..0d41a1d7dbfba 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -231,6 +231,7 @@ impl fmt::Display for ValidityRequirement {
pub enum LayoutError<'tcx> {
Unknown(Ty<'tcx>),
SizeOverflow(Ty<'tcx>),
+ TooGeneric(Ty<'tcx>),
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
ReferencesError(ErrorGuaranteed),
Cycle(ErrorGuaranteed),
@@ -244,6 +245,7 @@ impl<'tcx> LayoutError<'tcx> {
match self {
Unknown(_) => middle_unknown_layout,
SizeOverflow(_) => middle_values_too_big,
+ TooGeneric(_) => middle_too_generic,
NormalizationFailure(_, _) => middle_cannot_be_normalized,
Cycle(_) => middle_cycle,
ReferencesError(_) => middle_layout_references_error,
@@ -257,6 +259,7 @@ impl<'tcx> LayoutError<'tcx> {
match self {
Unknown(ty) => E::Unknown { ty },
SizeOverflow(ty) => E::Overflow { ty },
+ TooGeneric(ty) => E::TooGeneric { ty },
NormalizationFailure(ty, e) => {
E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
}
@@ -272,6 +275,9 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"),
+ LayoutError::TooGeneric(ty) => {
+ write!(f, "`{ty}` does not have a fixed size")
+ }
LayoutError::SizeOverflow(ty) => {
write!(f, "values of the type `{ty}` are too big for the target architecture")
}
@@ -350,10 +356,11 @@ impl<'tcx> SizeSkeleton<'tcx> {
return Err(tcx.arena.alloc(LayoutError::Unknown(ty)));
}
}
- Err(err @ LayoutError::Unknown(_)) => err,
+ Err(err @ LayoutError::TooGeneric(_)) => err,
// We can't extract SizeSkeleton info from other layout errors
Err(
e @ LayoutError::Cycle(_)
+ | e @ LayoutError::Unknown(_)
| e @ LayoutError::SizeOverflow(_)
| e @ LayoutError::NormalizationFailure(..)
| e @ LayoutError::ReferencesError(_),
@@ -413,10 +420,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
// Alignment is unchanged by arrays.
return Ok(SizeSkeleton::Known(Size::from_bytes(size), a));
}
- Err(tcx.arena.alloc(LayoutError::Unknown(ty)))
+ Err(err)
}
- SizeSkeleton::Pointer { .. } => Err(err),
- SizeSkeleton::Generic(_) => Err(tcx.arena.alloc(LayoutError::Unknown(ty))),
+ SizeSkeleton::Pointer { .. } | SizeSkeleton::Generic(_) => Err(err),
}
}
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 6ce9969aefe90..b00585d292212 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -197,6 +197,7 @@ pub(crate) mod rustc {
match err {
LayoutError::Unknown(..)
| LayoutError::ReferencesError(..)
+ | LayoutError::TooGeneric(..)
| LayoutError::NormalizationFailure(..) => Self::UnknownLayout,
LayoutError::SizeOverflow(..) => Self::SizeOverflow,
LayoutError::Cycle(err) => Self::TypeError(*err),
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 17be0bd0ab9e1..a04c753611831 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -104,14 +104,12 @@ fn map_error<'tcx>(
// This is sometimes not a compile error if there are trivially false where clauses.
// See `tests/ui/layout/trivial-bounds-sized.rs` for an example.
assert!(field.layout.is_unsized(), "invalid layout error {err:#?}");
- if !field.ty.is_sized(cx.tcx(), cx.typing_env) {
- let guar = cx.tcx().dcx().delayed_bug(format!(
+ if cx.typing_env.param_env.caller_bounds().is_empty() {
+ cx.tcx().dcx().delayed_bug(format!(
"encountered unexpected unsized field in layout of {ty:?}: {field:#?}"
));
- LayoutError::ReferencesError(guar)
- } else {
- LayoutError::Unknown(ty)
}
+ LayoutError::Unknown(ty)
}
LayoutCalculatorError::EmptyUnion => {
// This is always a compile error.
@@ -146,6 +144,35 @@ fn univariant_uninterned<'tcx>(
cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err))
}
+fn validate_const_with_value<'tcx>(
+ const_: ty::Const<'tcx>,
+ ty: Ty<'tcx>,
+ cx: &LayoutCx<'tcx>,
+) -> Result, &'tcx LayoutError<'tcx>> {
+ match const_.kind() {
+ ty::ConstKind::Value(..) => Ok(const_),
+ ty::ConstKind::Error(guar) => {
+ return Err(error(cx, LayoutError::ReferencesError(guar)));
+ }
+ ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
+ if !const_.has_param() {
+ bug!("no generic type found in the type: {ty:?}");
+ }
+ return Err(error(cx, LayoutError::TooGeneric(ty)));
+ }
+ ty::ConstKind::Unevaluated(_) => {
+ if !const_.has_param() {
+ return Err(error(cx, LayoutError::Unknown(ty)));
+ } else {
+ return Err(error(cx, LayoutError::TooGeneric(ty)));
+ }
+ }
+ ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
+ bug!("unexpected type: {ty:?}");
+ }
+ }
+}
+
fn layout_of_uncached<'tcx>(
cx: &LayoutCx<'tcx>,
ty: Ty<'tcx>,
@@ -182,12 +209,13 @@ fn layout_of_uncached<'tcx>(
&mut layout.backend_repr
{
if let Some(start) = start {
- scalar.valid_range_mut().start = start
- .try_to_bits(tcx, cx.typing_env)
- .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
+ scalar.valid_range_mut().start =
+ validate_const_with_value(start, ty, cx)?
+ .try_to_bits(tcx, cx.typing_env)
+ .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
}
if let Some(end) = end {
- let mut end = end
+ let mut end = validate_const_with_value(end, ty, cx)?
.try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
if !include_end {
@@ -319,17 +347,13 @@ fn layout_of_uncached<'tcx>(
}
// Arrays and slices.
- ty::Array(element, mut count) => {
- if count.has_aliases() {
- count = tcx.normalize_erasing_regions(cx.typing_env, count);
- if count.has_aliases() {
- return Err(error(cx, LayoutError::Unknown(ty)));
- }
- }
-
- let count = count
+ ty::Array(element, count) => {
+ let count = validate_const_with_value(count, ty, cx)?
+ .to_valtree()
+ .0
.try_to_target_usize(tcx)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
+
let element = cx.layout_of(element)?;
let size = element
.size
@@ -687,6 +711,9 @@ fn layout_of_uncached<'tcx>(
// Types with no meaningful known layout.
ty::Alias(..) => {
+ if ty.has_param() {
+ return Err(error(cx, LayoutError::TooGeneric(ty)));
+ }
// NOTE(eddyb) `layout_of` query should've normalized these away,
// if that was possible, so there's no reason to try again here.
return Err(error(cx, LayoutError::Unknown(ty)));
@@ -696,7 +723,11 @@ fn layout_of_uncached<'tcx>(
bug!("Layout::compute: unexpected type `{}`", ty)
}
- ty::Placeholder(..) | ty::Param(_) => {
+ ty::Param(_) => {
+ return Err(error(cx, LayoutError::TooGeneric(ty)));
+ }
+
+ ty::Placeholder(..) => {
return Err(error(cx, LayoutError::Unknown(ty)));
}
})
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index fda26a672990a..859ac1632305b 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -3727,33 +3727,33 @@ pub fn fence(order: Ordering) {
///
/// # Examples
///
-/// Without `compiler_fence`, the `assert_eq!` in following code
-/// is *not* guaranteed to succeed, despite everything happening in a single thread.
-/// To see why, remember that the compiler is free to swap the stores to
-/// `IMPORTANT_VARIABLE` and `IS_READY` since they are both
-/// `Ordering::Relaxed`. If it does, and the signal handler is invoked right
-/// after `IS_READY` is updated, then the signal handler will see
-/// `IS_READY=1`, but `IMPORTANT_VARIABLE=0`.
-/// Using a `compiler_fence` remedies this situation.
+/// Without the two `compiler_fence` calls, the read of `IMPORTANT_VARIABLE` in `signal_handler`
+/// is *undefined behavior* due to a data race, despite everything happening in a single thread.
+/// This is because the signal handler is considered to run concurrently with its associated
+/// thread, and explicit synchronization is required to pass data between a thread and its
+/// signal handler. The code below uses two `compiler_fence` calls to establish the usual
+/// release-acquire synchronization pattern (see [`fence`] for an image).
///
/// ```
-/// use std::sync::atomic::{AtomicBool, AtomicUsize};
+/// use std::sync::atomic::AtomicBool;
/// use std::sync::atomic::Ordering;
/// use std::sync::atomic::compiler_fence;
///
-/// static IMPORTANT_VARIABLE: AtomicUsize = AtomicUsize::new(0);
+/// static mut IMPORTANT_VARIABLE: usize = 0;
/// static IS_READY: AtomicBool = AtomicBool::new(false);
///
/// fn main() {
-/// IMPORTANT_VARIABLE.store(42, Ordering::Relaxed);
-/// // prevent earlier writes from being moved beyond this point
+/// unsafe { IMPORTANT_VARIABLE = 42 };
+/// // Marks earlier writes as being released with future relaxed stores.
/// compiler_fence(Ordering::Release);
/// IS_READY.store(true, Ordering::Relaxed);
/// }
///
/// fn signal_handler() {
/// if IS_READY.load(Ordering::Relaxed) {
-/// assert_eq!(IMPORTANT_VARIABLE.load(Ordering::Relaxed), 42);
+/// // Acquires writes that were released with relaxed stores that we read from.
+/// compiler_fence(Ordering::Acquire);
+/// assert_eq!(unsafe { IMPORTANT_VARIABLE }, 42);
/// }
/// }
/// ```
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 1fa13e95e6872..cfd03b8e3d6d0 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -310,6 +310,8 @@ pub use self::error::RawOsError;
pub use self::error::SimpleMessage;
#[unstable(feature = "io_const_error", issue = "133448")]
pub use self::error::const_error;
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+pub use self::pipe::{PipeReader, PipeWriter, pipe};
#[stable(feature = "is_terminal", since = "1.70.0")]
pub use self::stdio::IsTerminal;
pub(crate) use self::stdio::attempt_print_to_stderr;
@@ -330,7 +332,6 @@ pub use self::{
};
use crate::mem::take;
use crate::ops::{Deref, DerefMut};
-use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
use crate::{cmp, fmt, slice, str, sys};
mod buffered;
@@ -338,6 +339,7 @@ pub(crate) mod copy;
mod cursor;
mod error;
mod impls;
+mod pipe;
pub mod prelude;
mod stdio;
mod util;
@@ -3251,257 +3253,3 @@ impl Iterator for Lines {
}
}
}
-
-/// Create an anonymous pipe that is close-on-exec and blocking.
-///
-/// # Behavior
-///
-/// A pipe is a one-way data channel provided by the OS, which works across processes. A pipe is
-/// typically used to communicate between two or more separate processes, as there are better,
-/// faster ways to communicate within a single process.
-///
-/// In particular:
-///
-/// * A read on a [`PipeReader`] blocks until the pipe is non-empty.
-/// * A write on a [`PipeWriter`] blocks when the pipe is full.
-/// * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
-/// returns EOF.
-/// * [`PipeWriter`] can be shared, and multiple processes or threads can write to it at once, but
-/// writes (above a target-specific threshold) may have their data interleaved.
-/// * [`PipeReader`] can be shared, and multiple processes or threads can read it at once. Any
-/// given byte will only get consumed by one reader. There are no guarantees about data
-/// interleaving.
-/// * Portable applications cannot assume any atomicity of messages larger than a single byte.
-///
-/// # Capacity
-///
-/// Pipe capacity is platform dependent. To quote the Linux [man page]:
-///
-/// > Different implementations have different limits for the pipe capacity. Applications should
-/// > not rely on a particular capacity: an application should be designed so that a reading process
-/// > consumes data as soon as it is available, so that a writing process does not remain blocked.
-///
-/// # Examples
-///
-/// ```no_run
-/// #![feature(anonymous_pipe)]
-/// # #[cfg(miri)] fn main() {}
-/// # #[cfg(not(miri))]
-/// # fn main() -> std::io::Result<()> {
-/// # use std::process::Command;
-/// # use std::io::{Read, Write};
-/// let (ping_rx, mut ping_tx) = std::io::pipe()?;
-/// let (mut pong_rx, pong_tx) = std::io::pipe()?;
-///
-/// // Spawn a process that echoes its input.
-/// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
-///
-/// ping_tx.write_all(b"hello")?;
-/// // Close to unblock echo_server's reader.
-/// drop(ping_tx);
-///
-/// let mut buf = String::new();
-/// // Block until echo_server's writer is closed.
-/// pong_rx.read_to_string(&mut buf)?;
-/// assert_eq!(&buf, "hello");
-///
-/// echo_server.wait()?;
-/// # Ok(())
-/// # }
-/// ```
-/// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-#[inline]
-pub fn pipe() -> Result<(PipeReader, PipeWriter)> {
- pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
-}
-
-/// Read end of an anonymous pipe.
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-#[derive(Debug)]
-pub struct PipeReader(pub(crate) AnonPipe);
-
-/// Write end of an anonymous pipe.
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-#[derive(Debug)]
-pub struct PipeWriter(pub(crate) AnonPipe);
-
-impl PipeReader {
- /// Create a new [`PipeReader`] instance that shares the same underlying file description.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// #![feature(anonymous_pipe)]
- /// # #[cfg(miri)] fn main() {}
- /// # #[cfg(not(miri))]
- /// # fn main() -> std::io::Result<()> {
- /// # use std::fs;
- /// # use std::io::Write;
- /// # use std::process::Command;
- /// const NUM_SLOT: u8 = 2;
- /// const NUM_PROC: u8 = 5;
- /// const OUTPUT: &str = "work.txt";
- ///
- /// let mut jobs = vec![];
- /// let (reader, mut writer) = std::io::pipe()?;
- ///
- /// // Write NUM_SLOT characters the pipe.
- /// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
- ///
- /// // Spawn several processes that read a character from the pipe, do some work, then
- /// // write back to the pipe. When the pipe is empty, the processes block, so only
- /// // NUM_SLOT processes can be working at any given time.
- /// for _ in 0..NUM_PROC {
- /// jobs.push(
- /// Command::new("bash")
- /// .args(["-c",
- /// &format!(
- /// "read -n 1\n\
- /// echo -n 'x' >> '{OUTPUT}'\n\
- /// echo -n '|'",
- /// ),
- /// ])
- /// .stdin(reader.try_clone()?)
- /// .stdout(writer.try_clone()?)
- /// .spawn()?,
- /// );
- /// }
- ///
- /// // Wait for all jobs to finish.
- /// for mut job in jobs {
- /// job.wait()?;
- /// }
- ///
- /// // Check our work and clean up.
- /// let xs = fs::read_to_string(OUTPUT)?;
- /// fs::remove_file(OUTPUT)?;
- /// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
- /// # Ok(())
- /// # }
- /// ```
- #[unstable(feature = "anonymous_pipe", issue = "127154")]
- pub fn try_clone(&self) -> Result {
- self.0.try_clone().map(Self)
- }
-}
-
-impl PipeWriter {
- /// Create a new [`PipeWriter`] instance that shares the same underlying file description.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// #![feature(anonymous_pipe)]
- /// # #[cfg(miri)] fn main() {}
- /// # #[cfg(not(miri))]
- /// # fn main() -> std::io::Result<()> {
- /// # use std::process::Command;
- /// # use std::io::Read;
- /// let (mut reader, writer) = std::io::pipe()?;
- ///
- /// // Spawn a process that writes to stdout and stderr.
- /// let mut peer = Command::new("bash")
- /// .args([
- /// "-c",
- /// "echo -n foo\n\
- /// echo -n bar >&2"
- /// ])
- /// .stdout(writer.try_clone()?)
- /// .stderr(writer)
- /// .spawn()?;
- ///
- /// // Read and check the result.
- /// let mut msg = String::new();
- /// reader.read_to_string(&mut msg)?;
- /// assert_eq!(&msg, "foobar");
- ///
- /// peer.wait()?;
- /// # Ok(())
- /// # }
- /// ```
- #[unstable(feature = "anonymous_pipe", issue = "127154")]
- pub fn try_clone(&self) -> Result {
- self.0.try_clone().map(Self)
- }
-}
-
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-impl Read for &PipeReader {
- fn read(&mut self, buf: &mut [u8]) -> Result {
- self.0.read(buf)
- }
- fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result {
- self.0.read_vectored(bufs)
- }
- #[inline]
- fn is_read_vectored(&self) -> bool {
- self.0.is_read_vectored()
- }
- fn read_to_end(&mut self, buf: &mut Vec) -> Result {
- self.0.read_to_end(buf)
- }
- fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
- self.0.read_buf(buf)
- }
-}
-
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-impl Read for PipeReader {
- fn read(&mut self, buf: &mut [u8]) -> Result {
- self.0.read(buf)
- }
- fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result {
- self.0.read_vectored(bufs)
- }
- #[inline]
- fn is_read_vectored(&self) -> bool {
- self.0.is_read_vectored()
- }
- fn read_to_end(&mut self, buf: &mut Vec) -> Result {
- self.0.read_to_end(buf)
- }
- fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
- self.0.read_buf(buf)
- }
-}
-
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-impl Write for &PipeWriter {
- fn write(&mut self, buf: &[u8]) -> Result {
- self.0.write(buf)
- }
- #[inline]
- fn flush(&mut self) -> Result<()> {
- Ok(())
- }
-
- fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result {
- self.0.write_vectored(bufs)
- }
-
- #[inline]
- fn is_write_vectored(&self) -> bool {
- self.0.is_write_vectored()
- }
-}
-
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
-impl Write for PipeWriter {
- fn write(&mut self, buf: &[u8]) -> Result {
- self.0.write(buf)
- }
- #[inline]
- fn flush(&mut self) -> Result<()> {
- Ok(())
- }
-
- fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result {
- self.0.write_vectored(bufs)
- }
-
- #[inline]
- fn is_write_vectored(&self) -> bool {
- self.0.is_write_vectored()
- }
-}
diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs
new file mode 100644
index 0000000000000..266c7bc96389b
--- /dev/null
+++ b/library/std/src/io/pipe.rs
@@ -0,0 +1,260 @@
+use crate::io;
+use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
+
+/// Create an anonymous pipe.
+///
+/// # Behavior
+///
+/// A pipe is a one-way data channel provided by the OS, which works across processes. A pipe is
+/// typically used to communicate between two or more separate processes, as there are better,
+/// faster ways to communicate within a single process.
+///
+/// In particular:
+///
+/// * A read on a [`PipeReader`] blocks until the pipe is non-empty.
+/// * A write on a [`PipeWriter`] blocks when the pipe is full.
+/// * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
+/// returns EOF.
+/// * [`PipeWriter`] can be shared, and multiple processes or threads can write to it at once, but
+/// writes (above a target-specific threshold) may have their data interleaved.
+/// * [`PipeReader`] can be shared, and multiple processes or threads can read it at once. Any
+/// given byte will only get consumed by one reader. There are no guarantees about data
+/// interleaving.
+/// * Portable applications cannot assume any atomicity of messages larger than a single byte.
+///
+/// # Platform-specific behavior
+///
+/// This function currently corresponds to the `pipe` function on Unix and the
+/// `CreatePipe` function on Windows.
+///
+/// Note that this [may change in the future][changes].
+///
+/// # Capacity
+///
+/// Pipe capacity is platform dependent. To quote the Linux [man page]:
+///
+/// > Different implementations have different limits for the pipe capacity. Applications should
+/// > not rely on a particular capacity: an application should be designed so that a reading process
+/// > consumes data as soon as it is available, so that a writing process does not remain blocked.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(anonymous_pipe)]
+/// # #[cfg(miri)] fn main() {}
+/// # #[cfg(not(miri))]
+/// # fn main() -> std::io::Result<()> {
+/// use std::process::Command;
+/// use std::io::{pipe, Read, Write};
+/// let (ping_rx, mut ping_tx) = pipe()?;
+/// let (mut pong_rx, pong_tx) = pipe()?;
+///
+/// // Spawn a process that echoes its input.
+/// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
+///
+/// ping_tx.write_all(b"hello")?;
+/// // Close to unblock echo_server's reader.
+/// drop(ping_tx);
+///
+/// let mut buf = String::new();
+/// // Block until echo_server's writer is closed.
+/// pong_rx.read_to_string(&mut buf)?;
+/// assert_eq!(&buf, "hello");
+///
+/// echo_server.wait()?;
+/// # Ok(())
+/// # }
+/// ```
+/// [changes]: io#platform-specific-behavior
+/// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+#[inline]
+pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
+ pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
+}
+
+/// Read end of an anonymous pipe.
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+#[derive(Debug)]
+pub struct PipeReader(pub(crate) AnonPipe);
+
+/// Write end of an anonymous pipe.
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+#[derive(Debug)]
+pub struct PipeWriter(pub(crate) AnonPipe);
+
+impl PipeReader {
+ /// Create a new [`PipeReader`] instance that shares the same underlying file description.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(anonymous_pipe)]
+ /// # #[cfg(miri)] fn main() {}
+ /// # #[cfg(not(miri))]
+ /// # fn main() -> std::io::Result<()> {
+ /// use std::fs;
+ /// use std::io::{pipe, Write};
+ /// use std::process::Command;
+ /// const NUM_SLOT: u8 = 2;
+ /// const NUM_PROC: u8 = 5;
+ /// const OUTPUT: &str = "work.txt";
+ ///
+ /// let mut jobs = vec![];
+ /// let (reader, mut writer) = pipe()?;
+ ///
+ /// // Write NUM_SLOT characters the pipe.
+ /// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
+ ///
+ /// // Spawn several processes that read a character from the pipe, do some work, then
+ /// // write back to the pipe. When the pipe is empty, the processes block, so only
+ /// // NUM_SLOT processes can be working at any given time.
+ /// for _ in 0..NUM_PROC {
+ /// jobs.push(
+ /// Command::new("bash")
+ /// .args(["-c",
+ /// &format!(
+ /// "read -n 1\n\
+ /// echo -n 'x' >> '{OUTPUT}'\n\
+ /// echo -n '|'",
+ /// ),
+ /// ])
+ /// .stdin(reader.try_clone()?)
+ /// .stdout(writer.try_clone()?)
+ /// .spawn()?,
+ /// );
+ /// }
+ ///
+ /// // Wait for all jobs to finish.
+ /// for mut job in jobs {
+ /// job.wait()?;
+ /// }
+ ///
+ /// // Check our work and clean up.
+ /// let xs = fs::read_to_string(OUTPUT)?;
+ /// fs::remove_file(OUTPUT)?;
+ /// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
+ /// # Ok(())
+ /// # }
+ /// ```
+ #[unstable(feature = "anonymous_pipe", issue = "127154")]
+ pub fn try_clone(&self) -> io::Result {
+ self.0.try_clone().map(Self)
+ }
+}
+
+impl PipeWriter {
+ /// Create a new [`PipeWriter`] instance that shares the same underlying file description.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// #![feature(anonymous_pipe)]
+ /// # #[cfg(miri)] fn main() {}
+ /// # #[cfg(not(miri))]
+ /// # fn main() -> std::io::Result<()> {
+ /// use std::process::Command;
+ /// use std::io::{pipe, Read};
+ /// let (mut reader, writer) = pipe()?;
+ ///
+ /// // Spawn a process that writes to stdout and stderr.
+ /// let mut peer = Command::new("bash")
+ /// .args([
+ /// "-c",
+ /// "echo -n foo\n\
+ /// echo -n bar >&2"
+ /// ])
+ /// .stdout(writer.try_clone()?)
+ /// .stderr(writer)
+ /// .spawn()?;
+ ///
+ /// // Read and check the result.
+ /// let mut msg = String::new();
+ /// reader.read_to_string(&mut msg)?;
+ /// assert_eq!(&msg, "foobar");
+ ///
+ /// peer.wait()?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ #[unstable(feature = "anonymous_pipe", issue = "127154")]
+ pub fn try_clone(&self) -> io::Result {
+ self.0.try_clone().map(Self)
+ }
+}
+
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+impl io::Read for &PipeReader {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result {
+ self.0.read(buf)
+ }
+ fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result {
+ self.0.read_vectored(bufs)
+ }
+ #[inline]
+ fn is_read_vectored(&self) -> bool {
+ self.0.is_read_vectored()
+ }
+ fn read_to_end(&mut self, buf: &mut Vec) -> io::Result {
+ self.0.read_to_end(buf)
+ }
+ fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
+ self.0.read_buf(buf)
+ }
+}
+
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+impl io::Read for PipeReader {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result {
+ self.0.read(buf)
+ }
+ fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result {
+ self.0.read_vectored(bufs)
+ }
+ #[inline]
+ fn is_read_vectored(&self) -> bool {
+ self.0.is_read_vectored()
+ }
+ fn read_to_end(&mut self, buf: &mut Vec) -> io::Result {
+ self.0.read_to_end(buf)
+ }
+ fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
+ self.0.read_buf(buf)
+ }
+}
+
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+impl io::Write for &PipeWriter {
+ fn write(&mut self, buf: &[u8]) -> io::Result {
+ self.0.write(buf)
+ }
+ #[inline]
+ fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+ fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result {
+ self.0.write_vectored(bufs)
+ }
+ #[inline]
+ fn is_write_vectored(&self) -> bool {
+ self.0.is_write_vectored()
+ }
+}
+
+#[unstable(feature = "anonymous_pipe", issue = "127154")]
+impl io::Write for PipeWriter {
+ fn write(&mut self, buf: &[u8]) -> io::Result {
+ self.0.write(buf)
+ }
+ #[inline]
+ fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+ fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result {
+ self.0.write_vectored(bufs)
+ }
+ #[inline]
+ fn is_write_vectored(&self) -> bool {
+ self.0.is_write_vectored()
+ }
+}
diff --git a/library/std/src/io/pipe/tests.rs b/library/std/src/io/pipe/tests.rs
new file mode 100644
index 0000000000000..c1f3f192ca2d7
--- /dev/null
+++ b/library/std/src/io/pipe/tests.rs
@@ -0,0 +1,18 @@
+use crate::io::{Read, Write, pipe};
+
+#[test]
+#[cfg(all(windows, unix, not(miri)))]
+fn pipe_creation_clone_and_rw() {
+ let (rx, tx) = pipe().unwrap();
+
+ tx.try_clone().unwrap().write_all(b"12345").unwrap();
+ drop(tx);
+
+ let mut rx2 = rx.try_clone().unwrap();
+ drop(rx);
+
+ let mut s = String::new();
+ rx2.read_to_string(&mut s).unwrap();
+ drop(rx2);
+ assert_eq!(s, "12345");
+}
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index 226cc6011bcab..f64f034cce779 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -821,20 +821,3 @@ fn try_oom_error() {
let io_err = io::Error::from(reserve_err);
assert_eq!(io::ErrorKind::OutOfMemory, io_err.kind());
}
-
-#[test]
-#[cfg(all(windows, unix, not(miri)))]
-fn pipe_creation_clone_and_rw() {
- let (rx, tx) = std::io::pipe().unwrap();
-
- tx.try_clone().unwrap().write_all(b"12345").unwrap();
- drop(tx);
-
- let mut rx2 = rx.try_clone().unwrap();
- drop(rx);
-
- let mut s = String::new();
- rx2.read_to_string(&mut s).unwrap();
- drop(rx2);
- assert_eq!(s, "12345");
-}
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 8ebd6b8aa54cd..5fcf7eda8df79 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -16,11 +16,7 @@ use bootstrap::{
};
use build_helper::ci::CiEnv;
#[cfg(feature = "tracing")]
-use tracing::*;
-#[cfg(feature = "tracing")]
-use tracing_subscriber::EnvFilter;
-#[cfg(feature = "tracing")]
-use tracing_subscriber::prelude::*;
+use tracing::{debug, instrument};
#[cfg_attr(feature = "tracing", instrument(level = "trace", name = "main"))]
fn main() {
@@ -33,7 +29,11 @@ fn main() {
return;
}
+ #[cfg(feature = "tracing")]
+ debug!("parsing flags");
let flags = Flags::parse(&args);
+ #[cfg(feature = "tracing")]
+ debug!("parsing config based on flags");
let config = Config::parse(flags);
let mut build_lock;
@@ -95,6 +95,8 @@ fn main() {
let dump_bootstrap_shims = config.dump_bootstrap_shims;
let out_dir = config.out.clone();
+ #[cfg(feature = "tracing")]
+ debug!("creating new build based on config");
Build::new(config).build();
if suggest_setup {
@@ -211,16 +213,14 @@ fn check_version(config: &Config) -> Option {
// "tracing", instrument(..))]`.
#[cfg(feature = "tracing")]
fn setup_tracing() {
+ use tracing_subscriber::EnvFilter;
+ use tracing_subscriber::layer::SubscriberExt;
+
let filter = EnvFilter::from_env("BOOTSTRAP_TRACING");
- let layer = tracing_tree::HierarchicalLayer::default()
- .with_writer(std::io::stderr)
- .with_ansi(true)
- .with_targets(true)
- .with_bracketed_fields(true)
- .with_indent_amount(2)
- .with_indent_lines(true);
- let subscriber = tracing_subscriber::registry().with(filter).with(layer);
-
- tracing::subscriber::set_global_default(subscriber).unwrap();
- trace!("tracing subscriber setup");
+ // cf. .
+ let layer = tracing_tree::HierarchicalLayer::default().with_targets(true).with_indent_amount(2);
+
+ let registry = tracing_subscriber::registry().with(filter).with(layer);
+
+ tracing::subscriber::set_global_default(registry).unwrap();
}
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 910550b0a7d39..98490118f7d62 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -18,6 +18,8 @@ use build_helper::exit;
use build_helper::git::{GitConfig, get_closest_merge_commit, output_result};
use serde::{Deserialize, Deserializer};
use serde_derive::Deserialize;
+#[cfg(feature = "tracing")]
+use tracing::{instrument, span};
use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
use crate::core::build_steps::llvm;
@@ -1227,7 +1229,14 @@ define_config! {
}
impl Config {
+ #[cfg_attr(
+ feature = "tracing",
+ instrument(target = "CONFIG_HANDLING", level = "trace", name = "Config::default_opts")
+ )]
pub fn default_opts() -> Config {
+ #[cfg(feature = "tracing")]
+ span!(target: "CONFIG_HANDLING", tracing::Level::TRACE, "constructing default config");
+
Config {
bypass_bootstrap_lock: false,
llvm_optimize: true,
@@ -1311,10 +1320,23 @@ impl Config {
})
}
+ #[cfg_attr(
+ feature = "tracing",
+ instrument(target = "CONFIG_HANDLING", level = "trace", name = "Config::parse", skip_all)
+ )]
pub fn parse(flags: Flags) -> Config {
Self::parse_inner(flags, Self::get_toml)
}
+ #[cfg_attr(
+ feature = "tracing",
+ instrument(
+ target = "CONFIG_HANDLING",
+ level = "trace",
+ name = "Config::parse_inner",
+ skip_all
+ )
+ )]
pub(crate) fn parse_inner(
mut flags: Flags,
get_toml: impl Fn(&Path) -> Result,
@@ -1323,6 +1345,17 @@ impl Config {
// Set flags.
config.paths = std::mem::take(&mut flags.paths);
+
+ #[cfg(feature = "tracing")]
+ span!(
+ target: "CONFIG_HANDLING",
+ tracing::Level::TRACE,
+ "collecting paths and path exclusions",
+ "flags.paths" = ?flags.paths,
+ "flags.skip" = ?flags.skip,
+ "flags.exclude" = ?flags.exclude
+ );
+
config.skip = flags
.skip
.into_iter()
@@ -1339,6 +1372,14 @@ impl Config {
})
.collect();
+ #[cfg(feature = "tracing")]
+ span!(
+ target: "CONFIG_HANDLING",
+ tracing::Level::TRACE,
+ "normalizing and combining `flag.skip`/`flag.exclude` paths",
+ "config.skip" = ?config.skip,
+ );
+
config.include_default_paths = flags.include_default_paths;
config.rustc_error_format = flags.rustc_error_format;
config.json_output = flags.json_output;
@@ -1418,7 +1459,11 @@ impl Config {
config.stage0_metadata = build_helper::stage0_parser::parse_stage0_file();
- // Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, then `config.toml` in the root directory.
+ // Find configuration file, with the following cascading fallback (first match wins):
+ // - `--config `
+ // - `RUST_BOOTSTRAP_CONFIG`
+ // - `./config.toml`
+ // - `config.toml` in the root directory.
let toml_path = flags
.config
.clone()
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index f17103f97dc40..27fb00cb06e05 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -6,6 +6,8 @@
use std::path::{Path, PathBuf};
use clap::{CommandFactory, Parser, ValueEnum};
+#[cfg(feature = "tracing")]
+use tracing::instrument;
use crate::core::build_steps::setup::Profile;
use crate::core::builder::{Builder, Kind};
@@ -211,6 +213,10 @@ impl Flags {
}
}
+ #[cfg_attr(
+ feature = "tracing",
+ instrument(level = "trace", name = "Flags::parse", skip_all, fields(args = ?args))
+ )]
pub fn parse(args: &[String]) -> Self {
Flags::parse_from(normalize_args(args))
}
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 482e23cd04c31..d56f35f866cb8 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -28,6 +28,8 @@ use std::{env, fs, io, str};
use build_helper::ci::gha;
use build_helper::exit;
use termcolor::{ColorChoice, StandardStream, WriteColor};
+#[cfg(feature = "tracing")]
+use tracing::{debug, instrument, span, trace};
use utils::build_stamp::BuildStamp;
use utils::channel::GitInfo;
@@ -537,14 +539,25 @@ impl Build {
}
/// Executes the entire build, as configured by the flags and configuration.
+ #[cfg_attr(feature = "tracing", instrument(level = "debug", name = "Build::build", skip_all))]
pub fn build(&mut self) {
+ #[cfg(feature = "tracing")]
+ trace!("setting up job management");
unsafe {
crate::utils::job::setup(self);
}
+ #[cfg(feature = "tracing")]
+ trace!("downloading rustfmt early");
+
// Download rustfmt early so that it can be used in rust-analyzer configs.
let _ = &builder::Builder::new(self).initial_rustfmt();
+ #[cfg(feature = "tracing")]
+ let hardcoded_span =
+ span!(tracing::Level::DEBUG, "handling hardcoded subcommands (Format, Suggest, Perf)")
+ .entered();
+
// hardcoded subcommands
match &self.config.cmd {
Subcommand::Format { check, all } => {
@@ -561,25 +574,50 @@ impl Build {
Subcommand::Perf { .. } => {
return core::build_steps::perf::perf(&builder::Builder::new(self));
}
- _ => (),
+ _cmd => {
+ #[cfg(feature = "tracing")]
+ debug!(cmd = ?_cmd, "not a hardcoded subcommand; returning to normal handling");
+ }
}
+ #[cfg(feature = "tracing")]
+ drop(hardcoded_span);
+ #[cfg(feature = "tracing")]
+ debug!("handling subcommand normally");
+
if !self.config.dry_run() {
+ #[cfg(feature = "tracing")]
+ let _real_run_span = span!(tracing::Level::DEBUG, "executing real run").entered();
+
{
+ #[cfg(feature = "tracing")]
+ let _sanity_check_span =
+ span!(tracing::Level::DEBUG, "(1) executing dry-run sanity-check").entered();
+
// We first do a dry-run. This is a sanity-check to ensure that
// steps don't do anything expensive in the dry-run.
self.config.dry_run = DryRun::SelfCheck;
let builder = builder::Builder::new(self);
builder.execute_cli();
}
+
+ #[cfg(feature = "tracing")]
+ let _actual_run_span =
+ span!(tracing::Level::DEBUG, "(2) executing actual run").entered();
self.config.dry_run = DryRun::Disabled;
let builder = builder::Builder::new(self);
builder.execute_cli();
} else {
+ #[cfg(feature = "tracing")]
+ let _dry_run_span = span!(tracing::Level::DEBUG, "executing dry run").entered();
+
let builder = builder::Builder::new(self);
builder.execute_cli();
}
+ #[cfg(feature = "tracing")]
+ debug!("checking for postponed test failures from `test --no-fail-fast`");
+
// Check for postponed failures from `test --no-fail-fast`.
let failures = self.delayed_failures.borrow();
if failures.len() > 0 {
diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md
index 972b4a8fb0e62..3f907e85dd6cc 100644
--- a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md
+++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md
@@ -1,6 +1,6 @@
# Debugging bootstrap
-> FIXME: this page could be expanded
+> FIXME: this section should be expanded
## `tracing` in bootstrap
@@ -10,21 +10,69 @@ Bootstrap has conditional [`tracing`][tracing] setup to provide structured loggi
### Enabling `tracing` output
-Bootstrap will conditionally enable `tracing` output if the `BOOTSTRAP_TRACING` env var is set.
+Bootstrap will conditionally build `tracing` support and enable `tracing` output if the `BOOTSTRAP_TRACING` env var is set.
-Example usage:
+#### Basic usage
+
+Example basic usage[^just-trace]:
+
+[^just-trace]: It is not recommend to use *just* `BOOTSTRAP_TRACING=TRACE` because that will dump *everything* at `TRACE` level, including logs intentionally gated behind custom targets as they are too verbose even for `TRACE` level by default.
```bash
-$ BOOTSTRAP_TRACING=TRACE ./x build library --stage 1
+$ BOOTSTRAP_TRACING=bootstrap=TRACE ./x build library --stage 1
+```
+
+Example output[^unstable]:
+
+```
+$ BOOTSTRAP_TRACING=bootstrap=TRACE ./x check src/bootstrap/
+Building bootstrap
+ Compiling bootstrap v0.0.0 (/home/joe/repos/rust/src/bootstrap)
+ Finished `dev` profile [unoptimized] target(s) in 2.74s
+ DEBUG bootstrap parsing flags
+ bootstrap::core::config::flags::Flags::parse args=["check", "src/bootstrap/"]
+ DEBUG bootstrap parsing config based on flags
+ DEBUG bootstrap creating new build based on config
+ bootstrap::Build::build
+ TRACE bootstrap setting up job management
+ TRACE bootstrap downloading rustfmt early
+ bootstrap::handling hardcoded subcommands (Format, Suggest, Perf)
+ DEBUG bootstrap not a hardcoded subcommand; returning to normal handling, cmd=Check { all_targets: false }
+ DEBUG bootstrap handling subcommand normally
+ bootstrap::executing real run
+ bootstrap::(1) executing dry-run sanity-check
+ bootstrap::(2) executing actual run
+Checking stage0 library artifacts (x86_64-unknown-linux-gnu)
+ Finished `release` profile [optimized + debuginfo] target(s) in 0.04s
+Checking stage0 compiler artifacts {rustc-main, rustc_abi, rustc_arena, rustc_ast, rustc_ast_ir, rustc_ast_lowering, rustc_ast_passes, rustc_ast_pretty, rustc_attr_data_structures, rustc_attr_parsing, rustc_baked_icu_data, rustc_borrowck, rustc_builtin_macros, rustc_codegen_llvm, rustc_codegen_ssa, rustc_const_eval, rustc_data_structures, rustc_driver, rustc_driver_impl, rustc_error_codes, rustc_error_messages, rustc_errors, rustc_expand, rustc_feature, rustc_fluent_macro, rustc_fs_util, rustc_graphviz, rustc_hir, rustc_hir_analysis, rustc_hir_pretty, rustc_hir_typeck, rustc_incremental, rustc_index, rustc_index_macros, rustc_infer, rustc_interface, rustc_lexer, rustc_lint, rustc_lint_defs, rustc_llvm, rustc_log, rustc_macros, rustc_metadata, rustc_middle, rustc_mir_build, rustc_mir_dataflow, rustc_mir_transform, rustc_monomorphize, rustc_next_trait_solver, rustc_parse, rustc_parse_format, rustc_passes, rustc_pattern_analysis, rustc_privacy, rustc_query_impl, rustc_query_system, rustc_resolve, rustc_sanitizers, rustc_serialize, rustc_session, rustc_smir, rustc_span, rustc_symbol_mangling, rustc_target, rustc_trait_selection, rustc_traits, rustc_transmute, rustc_ty_utils, rustc_type_ir, rustc_type_ir_macros, stable_mir} (x86_64-unknown-linux-gnu)
+ Finished `release` profile [optimized + debuginfo] target(s) in 0.23s
+Checking stage0 bootstrap artifacts (x86_64-unknown-linux-gnu)
+ Checking bootstrap v0.0.0 (/home/joe/repos/rust/src/bootstrap)
+ Finished `release` profile [optimized + debuginfo] target(s) in 0.64s
+ DEBUG bootstrap checking for postponed test failures from `test --no-fail-fast`
+Build completed successfully in 0:00:08
```
-Example output[^experimental]:
+#### Controlling log output
+
+The env var `BOOTSTRAP_TRACING` accepts a [`tracing` env-filter][tracing-env-filter].
+
+There are two orthogonal ways to control which kind of logs you want:
-
+1. You can specify the log **level**, e.g. `DEBUG` or `TRACE`.
+2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` vs custom targets like `CONFIG_HANDLING`.
+ - Custom targets are used to limit what is output when `BOOTSTRAP_TRACING=bootstrap=TRACE` is used, as they can be too verbose even for `TRACE` level by default. Currently used custom targets:
+ - `CONFIG_HANDLING`
-[^experimental]: This shows what's *possible* with the infra in an experimental implementation.
+The `TRACE` filter will enable *all* `trace` level or less verbose level tracing output.
-The env var `BOOTSTRAP_TRACING` accepts a [`tracing` env-filter][tracing-env-filter]. The `TRACE` filter will enable *all* `trace` level or less verbose level tracing output.
+You can of course combine them (custom target logs are typically gated behind `TRACE` log level additionally):
+
+```bash
+$ BOOTSTRAP_TRACING=CONFIG_HANDLING=TRACE ./x build library --stage 1
+```
+
+[^unstable]: This output is always subject to further changes.
[tracing-env-filter]: https://docs.rs/tracing-subscriber/0.3.19/tracing_subscriber/filter/struct.EnvFilter.html
@@ -73,28 +121,6 @@ For `#[instrument]`, it's recommended to:
- Explicitly pick an instrumentation name via `name = ".."` to distinguish between e.g. `run` of different steps.
- Take care to not cause diverging behavior via tracing, e.g. building extra things only when tracing infra is enabled.
-### Enabling `tracing` bootstrap feature in rust-analyzer
+### rust-analyzer integration?
-You can adjust your `settings.json`'s `rust-analyzer.check.overrideCommand` and `rust-analyzer.cargo.buildScripts.overrideCommand` if you want to also enable `logging` cargo feature by default in your editor. This is mostly useful if you want proper r-a completions and such when working on bootstrap itself.
-
-```json
-"rust-analyzer.check.overrideCommand": [
- "BOOTSTRAP_TRACING=1", // <- BOOTSTRAP_TRACING=1 won't enable tracing filter, but it will activate bootstrap's `tracing` feature
- "python3",
- "x.py",
- "check",
- "--json-output",
- "--build-dir=build-rust-analyzer"
-],
-```
-
-```json
-"rust-analyzer.cargo.buildScripts.overrideCommand": [
- "BOOTSTRAP_TRACING=1", // <- note this
- "python3",
- "x.py",
- "check",
- "--json-output",
- "--build-dir=build-rust-analyzer"
-],
-```
+Unfortunately, because bootstrap is a `rust-analyzer.linkedProjects`, you can't ask r-a to check/build bootstrap itself with `tracing` feature enabled to get relevant completions, due to lack of support as described in .
diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap/tracing-output-example.png b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap/tracing-output-example.png
deleted file mode 100644
index 745aec50d4a36..0000000000000
Binary files a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap/tracing-output-example.png and /dev/null differ
diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html
index aee96fb8c417e..9c62826ccc2e3 100644
--- a/src/librustdoc/html/templates/type_layout.html
+++ b/src/librustdoc/html/templates/type_layout.html
@@ -28,13 +28,11 @@
{# #}
{% endfor %}
{% endif %}
- {# This kind of layout error can occur with valid code, e.g. if you try to
- get the layout of a generic type such as `Vec`. #}
+ {# This kind of layout error can occur with valid code, for example
+ if there are trivial bounds: `struct Foo(str, str) where str: Sized;`. #}
{% when Err(LayoutError::Unknown(_)) %}
{# #}
- Note: Unable to compute type layout, {#+ #}
- possibly due to this type having generic parameters. {#+ #}
- Layout can only be computed for concrete, fully-instantiated types. {# #}
+ Note: Unable to compute type layout. {# #}
{# This kind of error probably can't happen with valid code, but we don't
want to panic and prevent the docs from building, so we just let the
@@ -44,6 +42,14 @@
{# #}
Note: Encountered an error during type layout; {#+ #}
the type was too big. {# #}
+ {# This kind of layout error can occur with valid code, e.g. if you try to
+ get the layout of a generic type such as `Vec`. #}
+ {% when Err(LayoutError::TooGeneric(_)) %}
+
{# #}
+ Note: Unable to compute type layout, {#+ #}
+ possibly due to this type having generic parameters. {#+ #}
+ Layout can only be computed for concrete, fully-instantiated types. {# #}
+
{% when Err(LayoutError::ReferencesError(_)) %}
{# #}
Note: Encountered an error during type layout; {#+ #}
diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh
index 09202b1878b23..701be6bd76d34 100755
--- a/src/tools/clippy/.github/driver.sh
+++ b/src/tools/clippy/.github/driver.sh
@@ -47,9 +47,9 @@ unset CARGO_MANIFEST_DIR
# Run a lint and make sure it produces the expected output. It's also expected to exit with code 1
# FIXME: How to match the clippy invocation in compile-test.rs?
-./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1
-sed -e "/= help: for/d" double_neg.stderr > normalized.stderr
-diff -u normalized.stderr tests/ui/double_neg.stderr
+./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/box_default.rs 2>box_default.stderr && exit 1
+sed -e "/= help: for/d" box_default.stderr > normalized.stderr
+diff -u normalized.stderr tests/ui/box_default.stderr
# make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
SYSROOT=$(rustc --print sysroot)
diff --git a/src/tools/clippy/book/src/usage.md b/src/tools/clippy/book/src/usage.md
index 7a0be6994fe1b..23edf6c2abaaf 100644
--- a/src/tools/clippy/book/src/usage.md
+++ b/src/tools/clippy/book/src/usage.md
@@ -33,7 +33,7 @@ You can configure lint levels on the command line by adding
`-A/W/D clippy::lint_name` like this:
```bash
-cargo clippy -- -Aclippy::style -Wclippy::double_neg -Dclippy::perf
+cargo clippy -- -Aclippy::style -Wclippy::box_default -Dclippy::perf
```
For [CI] all warnings can be elevated to errors which will in turn fail
@@ -101,11 +101,10 @@ You can configure lint levels in source code the same way you can configure
```rust,ignore
#![allow(clippy::style)]
-#[warn(clippy::double_neg)]
+#[warn(clippy::box_default)]
fn main() {
- let x = 1;
- let y = --x;
- // ^^ warning: double negation
+ let _ = Box::::new(Default::default());
+ // ^ warning: `Box::new(_)` of default value
}
```
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 24d1a53266a07..35dd986ff614f 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -455,7 +455,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
});
// Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl
- while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token == TokenKind::Ident) {
+ while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token_kind == TokenKind::Ident) {
let mut iter = iter
.by_ref()
.filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. }));
@@ -465,7 +465,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
// matches `!{`
match_tokens!(iter, Bang OpenBrace);
if let Some(LintDeclSearchResult { range, .. }) =
- iter.find(|result| result.token == TokenKind::CloseBrace)
+ iter.find(|result| result.token_kind == TokenKind::CloseBrace)
{
last_decl_curly_offset = Some(range.end);
}
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 3ff10d850f82b..87e546fbf0144 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -507,7 +507,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::misc::USED_UNDERSCORE_BINDING_INFO,
crate::misc::USED_UNDERSCORE_ITEMS_INFO,
crate::misc_early::BUILTIN_TYPE_SHADOW_INFO,
- crate::misc_early::DOUBLE_NEG_INFO,
crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
crate::misc_early::MIXED_CASE_HEX_LITERALS_INFO,
crate::misc_early::REDUNDANT_AT_REST_PATTERN_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index 3ea792d8b835c..5604172d6f309 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -129,6 +129,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
("clippy::clone_double_ref", "suspicious_double_ref_op"),
#[clippy::version = ""]
("clippy::cmp_nan", "invalid_nan_comparisons"),
+ #[clippy::version = "1.86.0"]
+ ("clippy::double_neg", "double_negations"),
#[clippy::version = ""]
("clippy::drop_bounds", "drop_bounds"),
#[clippy::version = ""]
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs b/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs
deleted file mode 100644
index 06ba968fa4ed3..0000000000000
--- a/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use rustc_ast::ast::{Expr, ExprKind, UnOp};
-use rustc_lint::EarlyContext;
-
-use super::DOUBLE_NEG;
-
-pub(super) fn check(cx: &EarlyContext<'_>, expr: &Expr) {
- if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind {
- if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
- span_lint(
- cx,
- DOUBLE_NEG,
- expr.span,
- "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
- );
- }
- }
-}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
index 37d7427f9a5d2..637d6ed3ad2c6 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
@@ -1,5 +1,4 @@
mod builtin_type_shadow;
-mod double_neg;
mod literal_suffix;
mod mixed_case_hex_literals;
mod redundant_at_rest_pattern;
@@ -85,25 +84,6 @@ declare_clippy_lint! {
"function arguments having names which only differ by an underscore"
}
-declare_clippy_lint! {
- /// ### What it does
- /// Detects expressions of the form `--x`.
- ///
- /// ### Why is this bad?
- /// It can mislead C/C++ programmers to think `x` was
- /// decremented.
- ///
- /// ### Example
- /// ```no_run
- /// let mut x = 3;
- /// --x;
- /// ```
- #[clippy::version = "pre 1.29.0"]
- pub DOUBLE_NEG,
- style,
- "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++"
-}
-
declare_clippy_lint! {
/// ### What it does
/// Warns on hexadecimal literals with mixed-case letter
@@ -352,7 +332,6 @@ declare_clippy_lint! {
declare_lint_pass!(MiscEarlyLints => [
UNNEEDED_FIELD_PATTERN,
DUPLICATE_UNDERSCORE_ARGUMENT,
- DOUBLE_NEG,
MIXED_CASE_HEX_LITERALS,
UNSEPARATED_LITERAL_SUFFIX,
SEPARATED_LITERAL_SUFFIX,
@@ -415,7 +394,6 @@ impl EarlyLintPass for MiscEarlyLints {
if let ExprKind::Lit(lit) = expr.kind {
MiscEarlyLints::check_lit(cx, lit, expr.span);
}
- double_neg::check(cx, expr);
}
}
diff --git a/src/tools/clippy/tests/ui/double_neg.rs b/src/tools/clippy/tests/ui/double_neg.rs
deleted file mode 100644
index 3be8c62887381..0000000000000
--- a/src/tools/clippy/tests/ui/double_neg.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#[warn(clippy::double_neg)]
-#[allow(clippy::no_effect)]
-fn main() {
- let x = 1;
- -x;
- -(-x);
- --x;
- //~^ ERROR: `--x` could be misinterpreted as pre-decrement by C programmers, is usually
- //~| NOTE: `-D clippy::double-neg` implied by `-D warnings`
-}
diff --git a/src/tools/clippy/tests/ui/double_neg.stderr b/src/tools/clippy/tests/ui/double_neg.stderr
deleted file mode 100644
index 9a902d1323ccd..0000000000000
--- a/src/tools/clippy/tests/ui/double_neg.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op
- --> tests/ui/double_neg.rs:7:5
- |
-LL | --x;
- | ^^^
- |
- = note: `-D clippy::double-neg` implied by `-D warnings`
- = help: to override `-D warnings` add `#[allow(clippy::double_neg)]`
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 47d6e119543d1..501811fa491b3 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -13,9 +13,8 @@
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
#![allow(clippy::mixed_read_write_in_expression)]
-#![allow(clippy::manual_find_map)]
#![allow(clippy::manual_filter_map)]
-#![allow(unpredictable_function_pointer_comparisons)]
+#![allow(clippy::manual_find_map)]
#![allow(clippy::useless_conversion)]
#![allow(clippy::redundant_pattern_matching)]
#![allow(clippy::match_result_ok)]
@@ -30,6 +29,7 @@
#![allow(clippy::unwrap_used)]
#![allow(clippy::panicking_overflow_checks)]
#![allow(clippy::needless_borrow)]
+#![allow(clippy::reversed_empty_ranges)]
#![allow(clippy::single_char_add_str)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_const_for_thread_local)]
@@ -39,9 +39,11 @@
#![allow(invalid_reference_casting)]
#![allow(suspicious_double_ref_op)]
#![allow(invalid_nan_comparisons)]
+#![allow(double_negations)]
#![allow(drop_bounds)]
#![allow(dropping_copy_types)]
#![allow(dropping_references)]
+#![allow(unpredictable_function_pointer_comparisons)]
#![allow(useless_ptr_null_checks)]
#![allow(for_loops_over_fallibles)]
#![allow(forgetting_copy_types)]
@@ -60,8 +62,6 @@
#![allow(unknown_lints)]
#![allow(unused_labels)]
#![allow(ambiguous_wide_pointer_comparisons)]
-#![allow(unpredictable_function_pointer_comparisons)]
-#![allow(clippy::reversed_empty_ranges)]
#![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
#![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name`
#![warn(clippy::blocks_in_conditions)] //~ ERROR: lint `clippy::block_in_if_condition_expr`
@@ -74,9 +74,8 @@
#![warn(clippy::disallowed_methods)] //~ ERROR: lint `clippy::disallowed_method`
#![warn(clippy::disallowed_types)] //~ ERROR: lint `clippy::disallowed_type`
#![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence`
-#![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map`
#![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map`
-#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
+#![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map`
#![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion`
#![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
#![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result`
@@ -95,6 +94,7 @@
#![warn(clippy::expect_used)] //~ ERROR: lint `clippy::result_expect_used`
#![warn(clippy::map_unwrap_or)] //~ ERROR: lint `clippy::result_map_unwrap_or_else`
#![warn(clippy::unwrap_used)] //~ ERROR: lint `clippy::result_unwrap_used`
+#![warn(clippy::reversed_empty_ranges)] //~ ERROR: lint `clippy::reverse_range_loop`
#![warn(clippy::single_char_add_str)] //~ ERROR: lint `clippy::single_char_push_str`
#![warn(clippy::module_name_repetitions)] //~ ERROR: lint `clippy::stutter`
#![warn(clippy::missing_const_for_thread_local)] //~ ERROR: lint `clippy::thread_local_initializer_can_be_made_const`
@@ -104,9 +104,11 @@
#![warn(invalid_reference_casting)] //~ ERROR: lint `clippy::cast_ref_to_mut`
#![warn(suspicious_double_ref_op)] //~ ERROR: lint `clippy::clone_double_ref`
#![warn(invalid_nan_comparisons)] //~ ERROR: lint `clippy::cmp_nan`
+#![warn(double_negations)] //~ ERROR: lint `clippy::double_neg`
#![warn(drop_bounds)] //~ ERROR: lint `clippy::drop_bounds`
#![warn(dropping_copy_types)] //~ ERROR: lint `clippy::drop_copy`
#![warn(dropping_references)] //~ ERROR: lint `clippy::drop_ref`
+#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
#![warn(useless_ptr_null_checks)] //~ ERROR: lint `clippy::fn_null_check`
#![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loop_over_option`
#![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loop_over_result`
@@ -128,6 +130,5 @@
#![warn(unknown_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints`
#![warn(unused_labels)] //~ ERROR: lint `clippy::unused_label`
#![warn(ambiguous_wide_pointer_comparisons)] //~ ERROR: lint `clippy::vtable_address_comparisons`
-#![warn(clippy::reversed_empty_ranges)] //~ ERROR: lint `clippy::reverse_range_loop`
fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 12c7db69be2e4..7f4b8062e1b4b 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -13,9 +13,8 @@
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
#![allow(clippy::mixed_read_write_in_expression)]
-#![allow(clippy::manual_find_map)]
#![allow(clippy::manual_filter_map)]
-#![allow(unpredictable_function_pointer_comparisons)]
+#![allow(clippy::manual_find_map)]
#![allow(clippy::useless_conversion)]
#![allow(clippy::redundant_pattern_matching)]
#![allow(clippy::match_result_ok)]
@@ -30,6 +29,7 @@
#![allow(clippy::unwrap_used)]
#![allow(clippy::panicking_overflow_checks)]
#![allow(clippy::needless_borrow)]
+#![allow(clippy::reversed_empty_ranges)]
#![allow(clippy::single_char_add_str)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::missing_const_for_thread_local)]
@@ -39,9 +39,11 @@
#![allow(invalid_reference_casting)]
#![allow(suspicious_double_ref_op)]
#![allow(invalid_nan_comparisons)]
+#![allow(double_negations)]
#![allow(drop_bounds)]
#![allow(dropping_copy_types)]
#![allow(dropping_references)]
+#![allow(unpredictable_function_pointer_comparisons)]
#![allow(useless_ptr_null_checks)]
#![allow(for_loops_over_fallibles)]
#![allow(forgetting_copy_types)]
@@ -60,8 +62,6 @@
#![allow(unknown_lints)]
#![allow(unused_labels)]
#![allow(ambiguous_wide_pointer_comparisons)]
-#![allow(unpredictable_function_pointer_comparisons)]
-#![allow(clippy::reversed_empty_ranges)]
#![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
#![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name`
#![warn(clippy::block_in_if_condition_expr)] //~ ERROR: lint `clippy::block_in_if_condition_expr`
@@ -74,9 +74,8 @@
#![warn(clippy::disallowed_method)] //~ ERROR: lint `clippy::disallowed_method`
#![warn(clippy::disallowed_type)] //~ ERROR: lint `clippy::disallowed_type`
#![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence`
-#![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map`
#![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map`
-#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
+#![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map`
#![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion`
#![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
#![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result`
@@ -95,6 +94,7 @@
#![warn(clippy::result_expect_used)] //~ ERROR: lint `clippy::result_expect_used`
#![warn(clippy::result_map_unwrap_or_else)] //~ ERROR: lint `clippy::result_map_unwrap_or_else`
#![warn(clippy::result_unwrap_used)] //~ ERROR: lint `clippy::result_unwrap_used`
+#![warn(clippy::reverse_range_loop)] //~ ERROR: lint `clippy::reverse_range_loop`
#![warn(clippy::single_char_push_str)] //~ ERROR: lint `clippy::single_char_push_str`
#![warn(clippy::stutter)] //~ ERROR: lint `clippy::stutter`
#![warn(clippy::thread_local_initializer_can_be_made_const)] //~ ERROR: lint `clippy::thread_local_initializer_can_be_made_const`
@@ -104,9 +104,11 @@
#![warn(clippy::cast_ref_to_mut)] //~ ERROR: lint `clippy::cast_ref_to_mut`
#![warn(clippy::clone_double_ref)] //~ ERROR: lint `clippy::clone_double_ref`
#![warn(clippy::cmp_nan)] //~ ERROR: lint `clippy::cmp_nan`
+#![warn(clippy::double_neg)] //~ ERROR: lint `clippy::double_neg`
#![warn(clippy::drop_bounds)] //~ ERROR: lint `clippy::drop_bounds`
#![warn(clippy::drop_copy)] //~ ERROR: lint `clippy::drop_copy`
#![warn(clippy::drop_ref)] //~ ERROR: lint `clippy::drop_ref`
+#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
#![warn(clippy::fn_null_check)] //~ ERROR: lint `clippy::fn_null_check`
#![warn(clippy::for_loop_over_option)] //~ ERROR: lint `clippy::for_loop_over_option`
#![warn(clippy::for_loop_over_result)] //~ ERROR: lint `clippy::for_loop_over_result`
@@ -128,6 +130,5 @@
#![warn(clippy::unknown_clippy_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints`
#![warn(clippy::unused_label)] //~ ERROR: lint `clippy::unused_label`
#![warn(clippy::vtable_address_comparisons)] //~ ERROR: lint `clippy::vtable_address_comparisons`
-#![warn(clippy::reverse_range_loop)] //~ ERROR: lint `clippy::reverse_range_loop`
fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 1ec45c4f1f7ba..f24eaec3917ad 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -73,132 +73,132 @@ error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_r
LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
-error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
- --> tests/ui/rename.rs:77:9
- |
-LL | #![warn(clippy::find_map)]
- | ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
-
error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map`
- --> tests/ui/rename.rs:78:9
+ --> tests/ui/rename.rs:77:9
|
LL | #![warn(clippy::filter_map)]
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map`
-error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons`
- --> tests/ui/rename.rs:79:9
+error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
+ --> tests/ui/rename.rs:78:9
|
-LL | #![warn(clippy::fn_address_comparisons)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons`
+LL | #![warn(clippy::find_map)]
+ | ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
- --> tests/ui/rename.rs:80:9
+ --> tests/ui/rename.rs:79:9
|
LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching`
- --> tests/ui/rename.rs:81:9
+ --> tests/ui/rename.rs:80:9
|
LL | #![warn(clippy::if_let_redundant_pattern_matching)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching`
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
- --> tests/ui/rename.rs:82:9
+ --> tests/ui/rename.rs:81:9
|
LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
- --> tests/ui/rename.rs:83:9
+ --> tests/ui/rename.rs:82:9
|
LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
- --> tests/ui/rename.rs:84:9
+ --> tests/ui/rename.rs:83:9
|
LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
- --> tests/ui/rename.rs:85:9
+ --> tests/ui/rename.rs:84:9
|
LL | #![warn(clippy::integer_arithmetic)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
- --> tests/ui/rename.rs:86:9
+ --> tests/ui/rename.rs:85:9
|
LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
- --> tests/ui/rename.rs:87:9
+ --> tests/ui/rename.rs:86:9
|
LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
- --> tests/ui/rename.rs:88:9
+ --> tests/ui/rename.rs:87:9
|
LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
- --> tests/ui/rename.rs:89:9
+ --> tests/ui/rename.rs:88:9
|
LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
- --> tests/ui/rename.rs:90:9
+ --> tests/ui/rename.rs:89:9
|
LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> tests/ui/rename.rs:91:9
+ --> tests/ui/rename.rs:90:9
|
LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> tests/ui/rename.rs:92:9
+ --> tests/ui/rename.rs:91:9
|
LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks`
- --> tests/ui/rename.rs:93:9
+ --> tests/ui/rename.rs:92:9
|
LL | #![warn(clippy::overflow_check_conditional)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
- --> tests/ui/rename.rs:94:9
+ --> tests/ui/rename.rs:93:9
|
LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
- --> tests/ui/rename.rs:95:9
+ --> tests/ui/rename.rs:94:9
|
LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> tests/ui/rename.rs:96:9
+ --> tests/ui/rename.rs:95:9
|
LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> tests/ui/rename.rs:97:9
+ --> tests/ui/rename.rs:96:9
|
LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
+error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
+ --> tests/ui/rename.rs:97:9
+ |
+LL | #![warn(clippy::reverse_range_loop)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
+
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
--> tests/ui/rename.rs:98:9
|
@@ -253,155 +253,161 @@ error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
LL | #![warn(clippy::cmp_nan)]
| ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
-error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
+error: lint `clippy::double_neg` has been renamed to `double_negations`
--> tests/ui/rename.rs:107:9
|
+LL | #![warn(clippy::double_neg)]
+ | ^^^^^^^^^^^^^^^^^^ help: use the new name: `double_negations`
+
+error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
+ --> tests/ui/rename.rs:108:9
+ |
LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
- --> tests/ui/rename.rs:108:9
+ --> tests/ui/rename.rs:109:9
|
LL | #![warn(clippy::drop_copy)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
error: lint `clippy::drop_ref` has been renamed to `dropping_references`
- --> tests/ui/rename.rs:109:9
+ --> tests/ui/rename.rs:110:9
|
LL | #![warn(clippy::drop_ref)]
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
+error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons`
+ --> tests/ui/rename.rs:111:9
+ |
+LL | #![warn(clippy::fn_address_comparisons)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons`
+
error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
- --> tests/ui/rename.rs:110:9
+ --> tests/ui/rename.rs:112:9
|
LL | #![warn(clippy::fn_null_check)]
| ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
- --> tests/ui/rename.rs:111:9
+ --> tests/ui/rename.rs:113:9
|
LL | #![warn(clippy::for_loop_over_option)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
- --> tests/ui/rename.rs:112:9
+ --> tests/ui/rename.rs:114:9
|
LL | #![warn(clippy::for_loop_over_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
- --> tests/ui/rename.rs:113:9
+ --> tests/ui/rename.rs:115:9
|
LL | #![warn(clippy::for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
- --> tests/ui/rename.rs:114:9
+ --> tests/ui/rename.rs:116:9
|
LL | #![warn(clippy::forget_copy)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
- --> tests/ui/rename.rs:115:9
+ --> tests/ui/rename.rs:117:9
|
LL | #![warn(clippy::forget_ref)]
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
- --> tests/ui/rename.rs:116:9
+ --> tests/ui/rename.rs:118:9
|
LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
- --> tests/ui/rename.rs:117:9
+ --> tests/ui/rename.rs:119:9
|
LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
- --> tests/ui/rename.rs:118:9
+ --> tests/ui/rename.rs:120:9
|
LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
- --> tests/ui/rename.rs:119:9
+ --> tests/ui/rename.rs:121:9
|
LL | #![warn(clippy::invalid_utf8_in_unchecked)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
- --> tests/ui/rename.rs:120:9
+ --> tests/ui/rename.rs:122:9
|
LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs`
- --> tests/ui/rename.rs:121:9
+ --> tests/ui/rename.rs:123:9
|
LL | #![warn(clippy::maybe_misused_cfg)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
- --> tests/ui/rename.rs:122:9
+ --> tests/ui/rename.rs:124:9
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs`
- --> tests/ui/rename.rs:123:9
+ --> tests/ui/rename.rs:125:9
|
LL | #![warn(clippy::mismatched_target_os)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
- --> tests/ui/rename.rs:124:9
+ --> tests/ui/rename.rs:126:9
|
LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
- --> tests/ui/rename.rs:125:9
+ --> tests/ui/rename.rs:127:9
|
LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
- --> tests/ui/rename.rs:126:9
+ --> tests/ui/rename.rs:128:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
- --> tests/ui/rename.rs:127:9
+ --> tests/ui/rename.rs:129:9
|
LL | #![warn(clippy::undropped_manually_drops)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
- --> tests/ui/rename.rs:128:9
+ --> tests/ui/rename.rs:130:9
|
LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels`
- --> tests/ui/rename.rs:129:9
+ --> tests/ui/rename.rs:131:9
|
LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
- --> tests/ui/rename.rs:130:9
+ --> tests/ui/rename.rs:132:9
|
LL | #![warn(clippy::vtable_address_comparisons)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
-error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
- --> tests/ui/rename.rs:131:9
- |
-LL | #![warn(clippy::reverse_range_loop)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
-
-error: aborting due to 67 previous errors
+error: aborting due to 68 previous errors
diff --git a/tests/crashes/108428.rs b/tests/crashes/108428.rs
new file mode 100644
index 0000000000000..b18123b6a7c40
--- /dev/null
+++ b/tests/crashes/108428.rs
@@ -0,0 +1,6 @@
+//@ known-bug: #108428
+//@ needs-rustc-debug-assertions
+//@ compile-flags: -Wunused-lifetimes
+fn main() {
+ let _: extern fn<'a: 'static>();
+}
diff --git a/tests/crashes/132826.rs b/tests/crashes/132826.rs
new file mode 100644
index 0000000000000..9889cecdac541
--- /dev/null
+++ b/tests/crashes/132826.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #132826
+pub trait MyTrait {
+ type Item;
+}
+
+impl MyTrait for Vec {
+ type Item = Vec;
+}
+
+impl From> for as MyTrait>::Item {}
diff --git a/tests/crashes/135020.rs b/tests/crashes/135020.rs
deleted file mode 100644
index b44056eb3af30..0000000000000
--- a/tests/crashes/135020.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #135020
-
-pub fn problem_thingy(items: &mut impl Iterator) {
- let mut peeker = items.peekable();
- match peeker.peek() {
- Some(_) => (),
- None => return (),
- }
-}
-
-pub fn main() {}
diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs
index 1e462210cba21..5f34c8b99e0ff 100644
--- a/tests/rustdoc/type-layout.rs
+++ b/tests/rustdoc/type-layout.rs
@@ -37,7 +37,8 @@ pub struct Y(u8);
pub struct Z;
// We can't compute layout for generic types.
-//@ hasraw type_layout/struct.Generic.html 'Unable to compute type layout, possibly due to this type having generic parameters'
+//@ hasraw type_layout/struct.Generic.html 'Unable to compute type layout, possibly due to this type having generic parameters.'
+//@ hasraw type_layout/struct.Generic.html 'Layout can only be computed for concrete, fully-instantiated types.'
//@ !hasraw - 'Size: '
pub struct Generic(T);
@@ -91,3 +92,9 @@ pub enum Uninhabited {}
//@ hasraw type_layout/struct.Uninhabited2.html 'Size: '
//@ hasraw - '8 bytes (uninhabited)'
pub struct Uninhabited2(std::convert::Infallible, u64);
+
+pub trait Project { type Assoc; }
+// We can't compute layout. A `LayoutError::Unknown` is returned.
+//@ hasraw type_layout/struct.Unknown.html 'Unable to compute type layout.'
+//@ !hasraw - 'Size: '
+pub struct Unknown(<() as Project>::Assoc) where for<'a> (): Project;
diff --git a/tests/ui/enum-discriminant/eval-error.rs b/tests/ui/enum-discriminant/eval-error.rs
index f2c3b58162765..08b71d52a8b03 100644
--- a/tests/ui/enum-discriminant/eval-error.rs
+++ b/tests/ui/enum-discriminant/eval-error.rs
@@ -6,7 +6,7 @@ union Foo {
enum Bar {
Boo = {
- let _: Option = None;
+ let _: Option = None; //~ ERROR evaluation of constant value failed
0
},
}
diff --git a/tests/ui/enum-discriminant/eval-error.stderr b/tests/ui/enum-discriminant/eval-error.stderr
index 0f12308de3c1c..6bec2c8b420f7 100644
--- a/tests/ui/enum-discriminant/eval-error.stderr
+++ b/tests/ui/enum-discriminant/eval-error.stderr
@@ -45,7 +45,13 @@ help: wrap the field type in `ManuallyDrop<...>`
LL | a: std::mem::ManuallyDrop,
| +++++++++++++++++++++++ +
-error: aborting due to 4 previous errors
+error[E0080]: evaluation of constant value failed
+ --> $DIR/eval-error.rs:9:30
+ |
+LL | let _: Option = None;
+ | ^^^^ the type `Foo` has an unknown layout
+
+error: aborting due to 5 previous errors
-Some errors have detailed explanations: E0277, E0517, E0740.
-For more information about an error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0080, E0277, E0517, E0740.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
index 410862c532624..e28b8f373dabb 100644
--- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
+++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs
@@ -24,7 +24,7 @@ impl VirtualWrapper {
impl MyTrait for VirtualWrapper {
fn virtualize(&self) -> &dyn MyTrait {
unsafe { virtualize_my_trait(L, self) }
- // unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem
+ // unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem
}
}
diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.rs b/tests/ui/layout/base-layout-is-sized-ice-123078.rs
index 15f11145f845e..b1c33e1507551 100644
--- a/tests/ui/layout/base-layout-is-sized-ice-123078.rs
+++ b/tests/ui/layout/base-layout-is-sized-ice-123078.rs
@@ -8,6 +8,7 @@ struct S {
}
const C: S = unsafe { std::mem::transmute(()) };
+//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
const _: [(); {
C;
0
diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr
index 9181368533a46..d8743d4e6d63b 100644
--- a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr
+++ b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr
@@ -16,6 +16,16 @@ help: the `Box` type always has a statically known size and allocates its conten
LL | a: Box<[u8]>,
| ++++ +
-error: aborting due to 1 previous error
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+ --> $DIR/base-layout-is-sized-ice-123078.rs:10:23
+ |
+LL | const C: S = unsafe { std::mem::transmute(()) };
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: source type: `()` (0 bits)
+ = note: target type: `S` (the type `S` has an unknown layout)
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0512.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/layout/invalid-unsized-const-eval.rs b/tests/ui/layout/invalid-unsized-const-eval.rs
index 2dec0b0faacf2..1f664d30055d6 100644
--- a/tests/ui/layout/invalid-unsized-const-eval.rs
+++ b/tests/ui/layout/invalid-unsized-const-eval.rs
@@ -10,5 +10,6 @@ struct LazyLock {
}
static EMPTY_SET: LazyLock = todo!();
+//~^ ERROR could not evaluate static initializer
fn main() {}
diff --git a/tests/ui/layout/invalid-unsized-const-eval.stderr b/tests/ui/layout/invalid-unsized-const-eval.stderr
index bf65782b7a805..a434ca9b2c7cf 100644
--- a/tests/ui/layout/invalid-unsized-const-eval.stderr
+++ b/tests/ui/layout/invalid-unsized-const-eval.stderr
@@ -7,6 +7,13 @@ LL | data: (dyn Sync, ()),
= help: the trait `Sized` is not implemented for `(dyn Sync + 'static)`
= note: only the last element of a tuple may have a dynamically sized type
-error: aborting due to 1 previous error
+error[E0080]: could not evaluate static initializer
+ --> $DIR/invalid-unsized-const-eval.rs:12:1
+ |
+LL | static EMPTY_SET: LazyLock = todo!();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `(dyn Sync, ())` has an unknown layout
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0080, E0277.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr b/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr
index 3f565d6ee5ba8..f54e97e2a5c76 100644
--- a/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr
+++ b/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr
@@ -18,6 +18,20 @@ LL | struct MySlice(T);
| |
| this could be changed to `T: ?Sized`...
-error: aborting due to 1 previous error
+error[E0080]: could not evaluate static initializer
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+ |
+ = note: the type `MySlice<[bool]>` has an unknown layout
+ |
+note: inside `align_of::`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `CHECK`
+ --> $DIR/invalid-unsized-in-always-sized-tail.rs:15:28
+ |
+LL | static CHECK: () = assert!(align_of::() == 1);
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0080, E0277.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs b/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs
index 96c993035ef18..f84c10d8e5c03 100644
--- a/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs
+++ b/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs
@@ -6,5 +6,6 @@ struct ArenaSet::Target>(V, U);
//~^ ERROR the size for values of type `V` cannot be known at compilation time
const DATA: *const ArenaSet> = std::ptr::null_mut();
+//~^ ERROR evaluation of constant value failed
pub fn main() {}
diff --git a/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr b/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr
index f39cb29868af5..220951fab86f8 100644
--- a/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr
+++ b/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr
@@ -22,6 +22,13 @@ help: the `Box` type always has a statically known size and allocates its conten
LL | struct ArenaSet::Target>(Box, U);
| ++++ +
-error: aborting due to 1 previous error
+error[E0080]: evaluation of constant value failed
+ --> $DIR/issue-unsized-tail-restatic-ice-122488.rs:8:1
+ |
+LL | const DATA: *const ArenaSet> = std::ptr::null_mut();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `ArenaSet, [u8]>` has an unknown layout
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0080, E0277.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.rs b/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.rs
new file mode 100644
index 0000000000000..91280e49dcd7e
--- /dev/null
+++ b/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.rs
@@ -0,0 +1,11 @@
+#![feature(trivial_bounds)]
+
+fn return_str()
+where
+ str: Sized,
+{
+ [(); { let _a: Option = None; 0 }];
+ //~^ ERROR evaluation of constant value failed
+}
+
+fn main() {}
diff --git a/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.stderr b/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.stderr
new file mode 100644
index 0000000000000..6c7c51db8df7f
--- /dev/null
+++ b/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/uncomputable-due-to-trivial-bounds-ice-135138.rs:7:16
+ |
+LL | [(); { let _a: Option = None; 0 }];
+ | ^^ the type `Option` has an unknown layout
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/layout/unexpected-unsized-field-issue-135020.rs b/tests/ui/layout/unexpected-unsized-field-issue-135020.rs
new file mode 100644
index 0000000000000..c81d037e510f2
--- /dev/null
+++ b/tests/ui/layout/unexpected-unsized-field-issue-135020.rs
@@ -0,0 +1,7 @@
+//@ check-pass
+
+fn problem_thingy(items: &mut impl Iterator) {
+ items.peekable();
+}
+
+fn main() {}
diff --git a/tests/ui/layout/unknown-when-no-type-parameter.rs b/tests/ui/layout/unknown-when-no-type-parameter.rs
new file mode 100644
index 0000000000000..94c32cf262f2a
--- /dev/null
+++ b/tests/ui/layout/unknown-when-no-type-parameter.rs
@@ -0,0 +1,14 @@
+#![feature(trivial_bounds)]
+
+//@ error-pattern: error[E0080]: evaluation of constant value failed
+//@ error-pattern: the type `<() as Project>::Assoc` has an unknown layout
+
+trait Project {
+ type Assoc;
+}
+
+fn foo() where (): Project {
+ [(); size_of::<<() as Project>::Assoc>()];
+}
+
+fn main() {}
diff --git a/tests/ui/layout/unknown-when-no-type-parameter.stderr b/tests/ui/layout/unknown-when-no-type-parameter.stderr
new file mode 100644
index 0000000000000..d0456e2b3293b
--- /dev/null
+++ b/tests/ui/layout/unknown-when-no-type-parameter.stderr
@@ -0,0 +1,16 @@
+error[E0080]: evaluation of constant value failed
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+ |
+ = note: the type `<() as Project>::Assoc` has an unknown layout
+ |
+note: inside `std::mem::size_of::<<() as Project>::Assoc>`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `foo::{constant#0}`
+ --> $DIR/unknown-when-no-type-parameter.rs:11:10
+ |
+LL | [(); size_of::<<() as Project>::Assoc>()];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs
new file mode 100644
index 0000000000000..973235fe65afc
--- /dev/null
+++ b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs
@@ -0,0 +1,12 @@
+#![feature(ptr_metadata)]
+#![feature(trivial_bounds)]
+
+fn return_str()
+where
+ str: std::ptr::Pointee,
+{
+ [(); { let _a: Option<&str> = None; 0 }];
+ //~^ ERROR evaluation of constant value failed
+}
+
+fn main() {}
diff --git a/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr
new file mode 100644
index 0000000000000..68bba2e967826
--- /dev/null
+++ b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/unknown-when-ptr-metadata-is-DST.rs:8:16
+ |
+LL | [(); { let _a: Option<&str> = None; 0 }];
+ | ^^ the type `str` has an unknown layout
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/lint/lint-double-negations.rs b/tests/ui/lint/lint-double-negations.rs
new file mode 100644
index 0000000000000..43e61dd7c1327
--- /dev/null
+++ b/tests/ui/lint/lint-double-negations.rs
@@ -0,0 +1,9 @@
+//@ check-pass
+fn main() {
+ let x = 1;
+ -x;
+ -(-x);
+ --x; //~ WARN use of a double negation
+ ---x; //~ WARN use of a double negation
+ let _y = --(-x); //~ WARN use of a double negation
+}
diff --git a/tests/ui/lint/lint-double-negations.stderr b/tests/ui/lint/lint-double-negations.stderr
new file mode 100644
index 0000000000000..9367f74be546d
--- /dev/null
+++ b/tests/ui/lint/lint-double-negations.stderr
@@ -0,0 +1,42 @@
+warning: use of a double negation
+ --> $DIR/lint-double-negations.rs:6:5
+ |
+LL | --x;
+ | ^^^
+ |
+ = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
+ = note: use `-= 1` if you meant to decrement the value
+ = note: `#[warn(double_negations)]` on by default
+help: add parentheses for clarity
+ |
+LL | -(-x);
+ | + +
+
+warning: use of a double negation
+ --> $DIR/lint-double-negations.rs:7:6
+ |
+LL | ---x;
+ | ^^^
+ |
+ = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
+ = note: use `-= 1` if you meant to decrement the value
+help: add parentheses for clarity
+ |
+LL | --(-x);
+ | + +
+
+warning: use of a double negation
+ --> $DIR/lint-double-negations.rs:8:14
+ |
+LL | let _y = --(-x);
+ | ^^^^^^
+ |
+ = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
+ = note: use `-= 1` if you meant to decrement the value
+help: add parentheses for clarity
+ |
+LL | let _y = -(-(-x));
+ | + +
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/lint/lint-type-overflow2.rs b/tests/ui/lint/lint-type-overflow2.rs
index f007b45b8479d..ac7420326c893 100644
--- a/tests/ui/lint/lint-type-overflow2.rs
+++ b/tests/ui/lint/lint-type-overflow2.rs
@@ -4,6 +4,7 @@
fn main() {
let x2: i8 = --128; //~ ERROR literal out of range for `i8`
+ //~| WARN use of a double negation
let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
diff --git a/tests/ui/lint/lint-type-overflow2.stderr b/tests/ui/lint/lint-type-overflow2.stderr
index eb593d062f218..2cfb18e9fe924 100644
--- a/tests/ui/lint/lint-type-overflow2.stderr
+++ b/tests/ui/lint/lint-type-overflow2.stderr
@@ -1,3 +1,17 @@
+warning: use of a double negation
+ --> $DIR/lint-type-overflow2.rs:6:18
+ |
+LL | let x2: i8 = --128;
+ | ^^^^^
+ |
+ = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
+ = note: use `-= 1` if you meant to decrement the value
+ = note: `#[warn(double_negations)]` on by default
+help: add parentheses for clarity
+ |
+LL | let x2: i8 = -(-128);
+ | + +
+
error: literal out of range for `i8`
--> $DIR/lint-type-overflow2.rs:6:20
|
@@ -13,7 +27,7 @@ LL | #![deny(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
error: literal out of range for `f32`
- --> $DIR/lint-type-overflow2.rs:8:14
+ --> $DIR/lint-type-overflow2.rs:9:14
|
LL | let x = -3.40282357e+38_f32;
| ^^^^^^^^^^^^^^^^^^
@@ -21,7 +35,7 @@ LL | let x = -3.40282357e+38_f32;
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
error: literal out of range for `f32`
- --> $DIR/lint-type-overflow2.rs:9:14
+ --> $DIR/lint-type-overflow2.rs:10:14
|
LL | let x = 3.40282357e+38_f32;
| ^^^^^^^^^^^^^^^^^^
@@ -29,7 +43,7 @@ LL | let x = 3.40282357e+38_f32;
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
error: literal out of range for `f64`
- --> $DIR/lint-type-overflow2.rs:10:14
+ --> $DIR/lint-type-overflow2.rs:11:14
|
LL | let x = -1.7976931348623159e+308_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -37,12 +51,12 @@ LL | let x = -1.7976931348623159e+308_f64;
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
error: literal out of range for `f64`
- --> $DIR/lint-type-overflow2.rs:11:14
+ --> $DIR/lint-type-overflow2.rs:12:14
|
LL | let x = 1.7976931348623159e+308_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
diff --git a/tests/ui/structs/ice-struct-tail-normalization-113272.rs b/tests/ui/structs/ice-struct-tail-normalization-113272.rs
index 0ae24a7b71b49..ce2871fabb8c5 100644
--- a/tests/ui/structs/ice-struct-tail-normalization-113272.rs
+++ b/tests/ui/structs/ice-struct-tail-normalization-113272.rs
@@ -13,6 +13,6 @@ struct Other {
fn main() {
unsafe {
std::mem::transmute::