1
Fork 0

Auto merge of #133893 - fmease:rollup-11pi6fg, r=fmease

Rollup of 10 pull requests

Successful merges:

 - #118833 (Add lint against function pointer comparisons)
 - #122161 (Fix suggestion when shorthand `self` has erroneous type)
 - #133233 (Add context to "const in pattern" errors)
 - #133761 (Update books)
 - #133843 (Do not emit empty suggestion)
 - #133863 (Rename `core_pattern_type` and `core_pattern_types` lib feature  gates to `pattern_type_macro`)
 - #133872 (No need to create placeholders for GAT args in confirm_object_candidate)
 - #133874 (`fn_sig_for_fn_abi` should return a `ty::FnSig`, no need for a binder)
 - #133890 (Add a new test ui/incoherent-inherent-impls/no-other-unrelated-errors to check E0116 does not cause unrelated errors)
 - #133892 (Revert #133817)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-12-05 07:08:49 +00:00
commit 0e98766a54
201 changed files with 2299 additions and 1115 deletions

View file

@ -2566,6 +2566,18 @@ pub enum SelfKind {
Explicit(P<Ty>, Mutability), Explicit(P<Ty>, Mutability),
} }
impl SelfKind {
pub fn to_ref_suggestion(&self) -> String {
match self {
SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(),
SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()),
SelfKind::Value(_) | SelfKind::Explicit(_, _) => {
unreachable!("if we had an explicit self, we wouldn't be here")
}
}
}
}
pub type ExplicitSelf = Spanned<SelfKind>; pub type ExplicitSelf = Spanned<SelfKind>;
impl Param { impl Param {

View file

@ -3394,7 +3394,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else {
return; return;
}; };
if self.can_eq(self.param_env, expected_ty, ty) { if self.can_eq(self.param_env, expected_ty, ty)
// FIXME: this happens with macro calls. Need to figure out why the stmt
// `println!();` doesn't include the `;` in its `Span`. (#133845)
// We filter these out to avoid ICEs with debug assertions on caused by
// empty suggestions.
&& stmt.span.hi() != tail_expr.span.hi()
{
err.span_suggestion_short( err.span_suggestion_short(
stmt.span.with_lo(tail_expr.span.hi()), stmt.span.with_lo(tail_expr.span.hi()),
"remove this semicolon", "remove this semicolon",

View file

@ -885,6 +885,12 @@ lint_unnameable_test_items = cannot test inner items
lint_unnecessary_qualification = unnecessary qualification lint_unnecessary_qualification = unnecessary qualification
.suggestion = remove the unnecessary path segments .suggestion = remove the unnecessary path segments
lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
.note_duplicated_fn = the address of the same function can vary between different codegen units
.note_deduplicated_fn = furthermore, different functions could have the same address after being merged together
.note_visit_fn_addr_eq = for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
.fn_addr_eq_suggestion = refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::` lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::`
lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe

View file

@ -1815,6 +1815,42 @@ pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
}, },
} }
#[derive(LintDiagnostic)]
pub(crate) enum UnpredictableFunctionPointerComparisons<'a> {
#[diag(lint_unpredictable_fn_pointer_comparisons)]
#[note(lint_note_duplicated_fn)]
#[note(lint_note_deduplicated_fn)]
#[note(lint_note_visit_fn_addr_eq)]
Suggestion {
#[subdiagnostic]
sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a>,
},
#[diag(lint_unpredictable_fn_pointer_comparisons)]
#[note(lint_note_duplicated_fn)]
#[note(lint_note_deduplicated_fn)]
#[note(lint_note_visit_fn_addr_eq)]
Warn,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(
lint_fn_addr_eq_suggestion,
style = "verbose",
applicability = "maybe-incorrect"
)]
pub(crate) struct UnpredictableFunctionPointerComparisonsSuggestion<'a> {
pub ne: &'a str,
pub cast_right: String,
pub deref_left: &'a str,
pub deref_right: &'a str,
#[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
pub left: Span,
#[suggestion_part(code = ", {deref_right}")]
pub middle: Span,
#[suggestion_part(code = "{cast_right})")]
pub right: Span,
}
pub(crate) struct ImproperCTypes<'a> { pub(crate) struct ImproperCTypes<'a> {
pub ty: Ty<'a>, pub ty: Ty<'a>,
pub desc: &'a str, pub desc: &'a str,

View file

@ -23,7 +23,9 @@ use crate::lints::{
AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion, AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad, AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
InvalidNanComparisonsSuggestion, UnusedComparisons, VariantSizeDifferencesDiag, InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons,
UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons,
VariantSizeDifferencesDiag,
}; };
use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
@ -166,6 +168,35 @@ declare_lint! {
"detects ambiguous wide pointer comparisons" "detects ambiguous wide pointer comparisons"
} }
declare_lint! {
/// The `unpredictable_function_pointer_comparisons` lint checks comparison
/// of function pointer as the operands.
///
/// ### Example
///
/// ```rust
/// fn a() {}
/// fn b() {}
///
/// let f: fn() = a;
/// let g: fn() = b;
///
/// let _ = f == g;
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Function pointers comparisons do not produce meaningful result since
/// they are never guaranteed to be unique and could vary between different
/// code generation units. Furthermore, different functions could have the
/// same address after being merged together.
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
Warn,
"detects unpredictable function pointer comparisons"
}
#[derive(Copy, Clone, Default)] #[derive(Copy, Clone, Default)]
pub(crate) struct TypeLimits { pub(crate) struct TypeLimits {
/// Id of the last visited negated expression /// Id of the last visited negated expression
@ -178,7 +209,8 @@ impl_lint_pass!(TypeLimits => [
UNUSED_COMPARISONS, UNUSED_COMPARISONS,
OVERFLOWING_LITERALS, OVERFLOWING_LITERALS,
INVALID_NAN_COMPARISONS, INVALID_NAN_COMPARISONS,
AMBIGUOUS_WIDE_POINTER_COMPARISONS AMBIGUOUS_WIDE_POINTER_COMPARISONS,
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS
]); ]);
impl TypeLimits { impl TypeLimits {
@ -255,7 +287,7 @@ fn lint_nan<'tcx>(
cx.emit_span_lint(INVALID_NAN_COMPARISONS, e.span, lint); cx.emit_span_lint(INVALID_NAN_COMPARISONS, e.span, lint);
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Copy, Clone)]
enum ComparisonOp { enum ComparisonOp {
BinOp(hir::BinOpKind), BinOp(hir::BinOpKind),
Other, Other,
@ -383,6 +415,100 @@ fn lint_wide_pointer<'tcx>(
); );
} }
fn lint_fn_pointer<'tcx>(
cx: &LateContext<'tcx>,
e: &'tcx hir::Expr<'tcx>,
cmpop: ComparisonOp,
l: &'tcx hir::Expr<'tcx>,
r: &'tcx hir::Expr<'tcx>,
) {
let peel_refs = |mut ty: Ty<'tcx>| -> (Ty<'tcx>, usize) {
let mut refs = 0;
while let ty::Ref(_, inner_ty, _) = ty.kind() {
ty = *inner_ty;
refs += 1;
}
(ty, refs)
};
// Left and right operands can have borrows, remove them
let l = l.peel_borrows();
let r = r.peel_borrows();
let Some(l_ty) = cx.typeck_results().expr_ty_opt(l) else { return };
let Some(r_ty) = cx.typeck_results().expr_ty_opt(r) else { return };
// Remove any references as `==` will deref through them (and count the
// number of references removed, for latter).
let (l_ty, l_ty_refs) = peel_refs(l_ty);
let (r_ty, r_ty_refs) = peel_refs(r_ty);
if !l_ty.is_fn() || !r_ty.is_fn() {
return;
}
// Let's try to suggest `ptr::fn_addr_eq` if/when possible.
let is_eq_ne = matches!(cmpop, ComparisonOp::BinOp(hir::BinOpKind::Eq | hir::BinOpKind::Ne));
if !is_eq_ne {
// Neither `==` nor `!=`, we can't suggest `ptr::fn_addr_eq`, just show the warning.
return cx.emit_span_lint(
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
e.span,
UnpredictableFunctionPointerComparisons::Warn,
);
}
let (Some(l_span), Some(r_span)) =
(l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span))
else {
// No appropriate spans for the left and right operands, just show the warning.
return cx.emit_span_lint(
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
e.span,
UnpredictableFunctionPointerComparisons::Warn,
);
};
let ne = if cmpop == ComparisonOp::BinOp(hir::BinOpKind::Ne) { "!" } else { "" };
// `ptr::fn_addr_eq` only works with raw pointer, deref any references.
let deref_left = &*"*".repeat(l_ty_refs);
let deref_right = &*"*".repeat(r_ty_refs);
let left = e.span.shrink_to_lo().until(l_span.shrink_to_lo());
let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo());
let right = r_span.shrink_to_hi().until(e.span.shrink_to_hi());
// We only check for a right cast as `FnDef` == `FnPtr` is not possible,
// only `FnPtr == FnDef` is possible.
let cast_right = if !r_ty.is_fn_ptr() {
let fn_sig = r_ty.fn_sig(cx.tcx);
format!(" as {fn_sig}")
} else {
String::new()
};
cx.emit_span_lint(
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
e.span,
UnpredictableFunctionPointerComparisons::Suggestion {
sugg: UnpredictableFunctionPointerComparisonsSuggestion {
ne,
deref_left,
deref_right,
left,
middle,
right,
cast_right,
},
},
);
}
impl<'tcx> LateLintPass<'tcx> for TypeLimits { impl<'tcx> LateLintPass<'tcx> for TypeLimits {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
match e.kind { match e.kind {
@ -399,7 +525,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons); cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
} else { } else {
lint_nan(cx, e, binop, l, r); lint_nan(cx, e, binop, l, r);
lint_wide_pointer(cx, e, ComparisonOp::BinOp(binop.node), l, r); let cmpop = ComparisonOp::BinOp(binop.node);
lint_wide_pointer(cx, e, cmpop, l, r);
lint_fn_pointer(cx, e, cmpop, l, r);
} }
} }
} }
@ -411,6 +539,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
&& let Some(cmpop) = diag_item_cmpop(diag_item) => && let Some(cmpop) = diag_item_cmpop(diag_item) =>
{ {
lint_wide_pointer(cx, e, cmpop, l, r); lint_wide_pointer(cx, e, cmpop, l, r);
lint_fn_pointer(cx, e, cmpop, l, r);
} }
hir::ExprKind::MethodCall(_, l, [r], _) hir::ExprKind::MethodCall(_, l, [r], _)
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
@ -418,6 +547,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
&& let Some(cmpop) = diag_item_cmpop(diag_item) => && let Some(cmpop) = diag_item_cmpop(diag_item) =>
{ {
lint_wide_pointer(cx, e, cmpop, l, r); lint_wide_pointer(cx, e, cmpop, l, r);
lint_fn_pointer(cx, e, cmpop, l, r);
} }
_ => {} _ => {}
}; };

View file

@ -84,12 +84,17 @@ mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns mir_build_const_defined_here = constant defined here
mir_build_const_pattern_depends_on_generic_parameter = mir_build_const_param_in_pattern = constant parameters cannot be referenced in patterns
constant pattern depends on a generic parameter .label = can't be used in patterns
mir_build_const_param_in_pattern_def = constant defined here
mir_build_const_pattern_depends_on_generic_parameter = constant pattern cannot depend on generic parameters
.label = `const` depends on a generic parameter
mir_build_could_not_eval_const_pattern = could not evaluate constant pattern mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
.label = could not evaluate constant
mir_build_deref_raw_pointer_requires_unsafe = mir_build_deref_raw_pointer_requires_unsafe =
dereference of raw pointer is unsafe and requires unsafe block dereference of raw pointer is unsafe and requires unsafe block
@ -147,7 +152,8 @@ mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
mir_build_interpreted_as_const = introduce a variable instead mir_build_interpreted_as_const = introduce a variable instead
mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns mir_build_invalid_pattern = {$prefix} `{$non_sm_ty}` cannot be used in patterns
.label = {$prefix} can't be used in patterns
mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count -> mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count ->
[one] pattern [one] pattern
@ -244,10 +250,12 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa
.label = mutation of layout constrained field .label = mutation of layout constrained field
mir_build_nan_pattern = cannot use NaN in patterns mir_build_nan_pattern = cannot use NaN in patterns
.label = evaluates to `NaN`, which is not allowed in patterns
.note = NaNs compare inequal to everything, even themselves, so this pattern would never match .note = NaNs compare inequal to everything, even themselves, so this pattern would never match
.help = try using the `is_nan` method instead .help = try using the `is_nan` method instead
mir_build_non_const_path = runtime values cannot be referenced in patterns mir_build_non_const_path = runtime values cannot be referenced in patterns
.label = references a runtime value
mir_build_non_empty_never_pattern = mir_build_non_empty_never_pattern =
mismatched types mismatched types
@ -265,13 +273,15 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type
.suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
.help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
mir_build_non_partial_eq_match = mir_build_non_partial_eq_match = constant of non-structural type `{$ty}` in a pattern
to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq` .label = constant of non-structural type
mir_build_pattern_not_covered = refutable pattern in {$origin} mir_build_pattern_not_covered = refutable pattern in {$origin}
.pattern_ty = the matched value is of type `{$pattern_ty}` .pattern_ty = the matched value is of type `{$pattern_ty}`
mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
.label = can't be used in patterns
.note = see https://github.com/rust-lang/rust/issues/70861 for details
mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
@ -283,6 +293,8 @@ mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
.missing_box = `#[rustc_box]` requires the `owned_box` lang item .missing_box = `#[rustc_box]` requires the `owned_box` lang item
mir_build_static_in_pattern = statics cannot be referenced in patterns mir_build_static_in_pattern = statics cannot be referenced in patterns
.label = can't be used in patterns
mir_build_static_in_pattern_def = `static` defined here
mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
@ -310,12 +322,12 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
*[other] them *[other] them
} into the body } into the body
mir_build_type_not_structural = mir_build_type_not_structural = constant of non-structural type `{$ty}` in a pattern
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]` .label = constant of non-structural type
mir_build_type_not_structural_def = `{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
mir_build_type_not_structural_tip =
mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
mir_build_unconditional_recursion = function cannot return without recursing mir_build_unconditional_recursion = function cannot return without recursing
.label = cannot return without recursing .label = cannot return without recursing
@ -334,6 +346,7 @@ mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
.label = access to union field .label = access to union field
mir_build_union_pattern = cannot use unions in constant patterns mir_build_union_pattern = cannot use unions in constant patterns
.label = can't use a `union` here
mir_build_unreachable_making_this_unreachable = collectively making this unreachable mir_build_unreachable_making_this_unreachable = collectively making this unreachable

View file

@ -631,20 +631,27 @@ pub(crate) struct NonExhaustiveMatchAllArmsGuarded;
#[diag(mir_build_static_in_pattern, code = E0158)] #[diag(mir_build_static_in_pattern, code = E0158)]
pub(crate) struct StaticInPattern { pub(crate) struct StaticInPattern {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
#[label(mir_build_static_in_pattern_def)]
pub(crate) static_span: Span,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(mir_build_const_param_in_pattern, code = E0158)] #[diag(mir_build_const_param_in_pattern, code = E0158)]
pub(crate) struct ConstParamInPattern { pub(crate) struct ConstParamInPattern {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
#[label(mir_build_const_param_in_pattern_def)]
pub(crate) const_span: Span,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(mir_build_non_const_path, code = E0080)] #[diag(mir_build_non_const_path, code = E0080)]
pub(crate) struct NonConstPath { pub(crate) struct NonConstPath {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
} }
@ -695,6 +702,7 @@ pub(crate) struct WantedConstant {
#[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)] #[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)]
pub(crate) struct ConstPatternDependsOnGenericParameter { pub(crate) struct ConstPatternDependsOnGenericParameter {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
} }
@ -702,6 +710,7 @@ pub(crate) struct ConstPatternDependsOnGenericParameter {
#[diag(mir_build_could_not_eval_const_pattern)] #[diag(mir_build_could_not_eval_const_pattern)]
pub(crate) struct CouldNotEvalConstPattern { pub(crate) struct CouldNotEvalConstPattern {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
} }
@ -867,33 +876,43 @@ pub(crate) enum Conflict {
#[diag(mir_build_union_pattern)] #[diag(mir_build_union_pattern)]
pub(crate) struct UnionPattern { pub(crate) struct UnionPattern {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(mir_build_type_not_structural)] #[diag(mir_build_type_not_structural)]
#[note(mir_build_type_not_structural_tip)]
#[note(mir_build_type_not_structural_more_info)]
pub(crate) struct TypeNotStructural<'tcx> { pub(crate) struct TypeNotStructural<'tcx> {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
pub(crate) non_sm_ty: Ty<'tcx>, #[label(mir_build_type_not_structural_def)]
pub(crate) ty_def_span: Span,
pub(crate) ty: Ty<'tcx>,
#[note(mir_build_type_not_structural_tip)]
pub(crate) manual_partialeq_impl_span: Option<Span>,
#[note(mir_build_type_not_structural_more_info)]
pub(crate) manual_partialeq_impl_note: bool,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(mir_build_non_partial_eq_match)] #[diag(mir_build_non_partial_eq_match)]
#[note(mir_build_type_not_structural_more_info)]
pub(crate) struct TypeNotPartialEq<'tcx> { pub(crate) struct TypeNotPartialEq<'tcx> {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
pub(crate) non_peq_ty: Ty<'tcx>, pub(crate) ty: Ty<'tcx>,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(mir_build_invalid_pattern)] #[diag(mir_build_invalid_pattern)]
pub(crate) struct InvalidPattern<'tcx> { pub(crate) struct InvalidPattern<'tcx> {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
pub(crate) non_sm_ty: Ty<'tcx>, pub(crate) non_sm_ty: Ty<'tcx>,
pub(crate) prefix: String,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
@ -910,13 +929,16 @@ pub(crate) struct UnsizedPattern<'tcx> {
#[help] #[help]
pub(crate) struct NaNPattern { pub(crate) struct NaNPattern {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(mir_build_pointer_pattern)] #[diag(mir_build_pointer_pattern)]
#[note]
pub(crate) struct PointerPattern { pub(crate) struct PointerPattern {
#[primary_span] #[primary_span]
#[label]
pub(crate) span: Span, pub(crate) span: Span,
} }

View file

@ -1,14 +1,17 @@
use rustc_abi::{FieldIdx, VariantIdx}; use rustc_abi::{FieldIdx, VariantIdx};
use rustc_apfloat::Float; use rustc_apfloat::Float;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Diag;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_index::Idx; use rustc_index::Idx;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::Obligation; use rustc_infer::traits::Obligation;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir::{FieldPat, Pat, PatKind}; use rustc_middle::thir::{FieldPat, Pat, PatKind};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeVisitor, ValTree};
use rustc_middle::{mir, span_bug}; use rustc_middle::{mir, span_bug};
use rustc_span::Span; use rustc_span::def_id::DefId;
use rustc_span::{Span, sym};
use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::ObligationCause;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
@ -35,7 +38,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
id: hir::HirId, id: hir::HirId,
span: Span, span: Span,
) -> Box<Pat<'tcx>> { ) -> Box<Pat<'tcx>> {
let mut convert = ConstToPat::new(self, id, span); let mut convert = ConstToPat::new(self, id, span, c);
match c.kind() { match c.kind() {
ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty), ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty),
@ -49,21 +52,26 @@ struct ConstToPat<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
span: Span, span: Span,
id: hir::HirId,
treat_byte_string_as_slice: bool, treat_byte_string_as_slice: bool,
c: ty::Const<'tcx>,
} }
impl<'tcx> ConstToPat<'tcx> { impl<'tcx> ConstToPat<'tcx> {
fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span) -> Self { fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
trace!(?pat_ctxt.typeck_results.hir_owner); trace!(?pat_ctxt.typeck_results.hir_owner);
ConstToPat { ConstToPat {
tcx: pat_ctxt.tcx, tcx: pat_ctxt.tcx,
typing_env: pat_ctxt.typing_env, typing_env: pat_ctxt.typing_env,
span, span,
id,
treat_byte_string_as_slice: pat_ctxt treat_byte_string_as_slice: pat_ctxt
.typeck_results .typeck_results
.treat_byte_string_as_slice .treat_byte_string_as_slice
.contains(&id.local_id), .contains(&id.local_id),
c,
} }
} }
@ -71,13 +79,32 @@ impl<'tcx> ConstToPat<'tcx> {
ty.is_structural_eq_shallow(self.tcx) ty.is_structural_eq_shallow(self.tcx)
} }
/// We errored. Signal that in the pattern, so that follow up errors can be silenced.
fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
if let ty::ConstKind::Unevaluated(uv) = self.c.kind() {
let def_kind = self.tcx.def_kind(uv.def);
if let hir::def::DefKind::AssocConst = def_kind
&& let Some(def_id) = uv.def.as_local()
{
// Include the container item in the output.
err.span_label(self.tcx.def_span(self.tcx.local_parent(def_id)), "");
}
if let hir::def::DefKind::Const | hir::def::DefKind::AssocConst = def_kind {
err.span_label(
self.tcx.def_span(uv.def),
crate::fluent_generated::mir_build_const_defined_here,
);
}
}
Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()) })
}
fn unevaluated_to_pat( fn unevaluated_to_pat(
&mut self, &mut self,
uv: ty::UnevaluatedConst<'tcx>, uv: ty::UnevaluatedConst<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Box<Pat<'tcx>> { ) -> Box<Pat<'tcx>> {
trace!(self.treat_byte_string_as_slice); trace!(self.treat_byte_string_as_slice);
let pat_from_kind = |kind| Box::new(Pat { span: self.span, ty, kind });
// It's not *technically* correct to be revealing opaque types here as borrowcheck has // It's not *technically* correct to be revealing opaque types here as borrowcheck has
// not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even
@ -96,32 +123,60 @@ impl<'tcx> ConstToPat<'tcx> {
Ok(Ok(c)) => c, Ok(Ok(c)) => c,
Err(ErrorHandled::Reported(_, _)) => { Err(ErrorHandled::Reported(_, _)) => {
// Let's tell the use where this failing const occurs. // Let's tell the use where this failing const occurs.
let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span: self.span }); let mut err =
return pat_from_kind(PatKind::Error(e)); self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span });
// We've emitted an error on the original const, it would be redundant to complain
// on its use as well.
if let ty::ConstKind::Unevaluated(uv) = self.c.kind()
&& let hir::def::DefKind::Const | hir::def::DefKind::AssocConst =
self.tcx.def_kind(uv.def)
{
err.downgrade_to_delayed_bug();
}
return self.mk_err(err, ty);
} }
Err(ErrorHandled::TooGeneric(_)) => { Err(ErrorHandled::TooGeneric(_)) => {
let e = self let mut e = self
.tcx .tcx
.dcx() .dcx()
.emit_err(ConstPatternDependsOnGenericParameter { span: self.span }); .create_err(ConstPatternDependsOnGenericParameter { span: self.span });
return pat_from_kind(PatKind::Error(e)); for arg in uv.args {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Param(param_ty) = ty.kind()
{
let def_id = self.tcx.hir().enclosing_body_owner(self.id);
let generics = self.tcx.generics_of(def_id);
let param = generics.type_param(*param_ty, self.tcx);
let span = self.tcx.def_span(param.def_id);
e.span_label(span, "constant depends on this generic parameter");
if let Some(ident) = self.tcx.def_ident_span(def_id)
&& self.tcx.sess.source_map().is_multiline(ident.between(span))
{
// Display the `fn` name as well in the diagnostic, as the generic isn't
// in the same line and it could be confusing otherwise.
e.span_label(ident, "");
}
}
}
return self.mk_err(e, ty);
} }
Ok(Err(bad_ty)) => { Ok(Err(bad_ty)) => {
// The pattern cannot be turned into a valtree. // The pattern cannot be turned into a valtree.
let e = match bad_ty.kind() { let e = match bad_ty.kind() {
ty::Adt(def, ..) => { ty::Adt(def, ..) => {
assert!(def.is_union()); assert!(def.is_union());
self.tcx.dcx().emit_err(UnionPattern { span: self.span }) self.tcx.dcx().create_err(UnionPattern { span: self.span })
} }
ty::FnPtr(..) | ty::RawPtr(..) => { ty::FnPtr(..) | ty::RawPtr(..) => {
self.tcx.dcx().emit_err(PointerPattern { span: self.span }) self.tcx.dcx().create_err(PointerPattern { span: self.span })
} }
_ => self _ => self.tcx.dcx().create_err(InvalidPattern {
.tcx span: self.span,
.dcx() non_sm_ty: bad_ty,
.emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }), prefix: bad_ty.prefix_string(self.tcx).to_string(),
}),
}; };
return pat_from_kind(PatKind::Error(e)); return self.mk_err(e, ty);
} }
}; };
@ -130,42 +185,16 @@ impl<'tcx> ConstToPat<'tcx> {
if !inlined_const_as_pat.references_error() { if !inlined_const_as_pat.references_error() {
// Always check for `PartialEq` if we had no other errors yet. // Always check for `PartialEq` if we had no other errors yet.
if !self.type_has_partial_eq_impl(ty) { if !type_has_partial_eq_impl(self.tcx, typing_env, ty).0 {
let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty }; let mut err = self.tcx.dcx().create_err(TypeNotPartialEq { span: self.span, ty });
let e = self.tcx.dcx().emit_err(err); extend_type_not_partial_eq(self.tcx, typing_env, ty, &mut err);
return pat_from_kind(PatKind::Error(e)); return self.mk_err(err, ty);
} }
} }
inlined_const_as_pat inlined_const_as_pat
} }
#[instrument(level = "trace", skip(self), ret)]
fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
// double-check there even *is* a semantic `PartialEq` to dispatch to.
//
// (If there isn't, then we can safely issue a hard
// error, because that's never worked, due to compiler
// using `PartialEq::eq` in this scenario in the past.)
let partial_eq_trait_id =
self.tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
let partial_eq_obligation = Obligation::new(
self.tcx,
ObligationCause::dummy(),
param_env,
ty::TraitRef::new(self.tcx, partial_eq_trait_id, [ty, ty]),
);
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
// ignored. However that should be pretty much impossible since consts that do not depend on
// generics can only mention the `'static` lifetime, and how would one have a type that's
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
// can ensure that the type really implements `PartialEq`.
infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation)
}
fn field_pats( fn field_pats(
&self, &self,
vals: impl Iterator<Item = (ValTree<'tcx>, Ty<'tcx>)>, vals: impl Iterator<Item = (ValTree<'tcx>, Ty<'tcx>)>,
@ -190,10 +219,25 @@ impl<'tcx> ConstToPat<'tcx> {
// Extremely important check for all ADTs! Make sure they opted-in to be used in // Extremely important check for all ADTs! Make sure they opted-in to be used in
// patterns. // patterns.
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty); debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty);
let err = TypeNotStructural { span, non_sm_ty: ty }; let (_impls_partial_eq, derived, structural, impl_def_id) =
let e = tcx.dcx().emit_err(err); type_has_partial_eq_impl(self.tcx, self.typing_env, ty);
// We errored. Signal that in the pattern, so that follow up errors can be silenced. let (manual_partialeq_impl_span, manual_partialeq_impl_note) =
PatKind::Error(e) match (structural, impl_def_id) {
(true, _) => (None, false),
(_, Some(def_id)) if def_id.is_local() && !derived => {
(Some(tcx.def_span(def_id)), false)
}
_ => (None, true),
};
let ty_def_span = tcx.def_span(adt_def.did());
let err = TypeNotStructural {
span,
ty,
ty_def_span,
manual_partialeq_impl_span,
manual_partialeq_impl_note,
};
return self.mk_err(tcx.dcx().create_err(err), ty);
} }
ty::Adt(adt_def, args) if adt_def.is_enum() => { ty::Adt(adt_def, args) if adt_def.is_enum() => {
let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap(); let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap();
@ -207,7 +251,7 @@ impl<'tcx> ConstToPat<'tcx> {
adt_def.variants()[variant_index] adt_def.variants()[variant_index]
.fields .fields
.iter() .iter()
.map(|field| field.ty(self.tcx, args)), .map(|field| field.ty(tcx, args)),
), ),
), ),
} }
@ -216,7 +260,7 @@ impl<'tcx> ConstToPat<'tcx> {
assert!(!def.is_union()); // Valtree construction would never succeed for unions. assert!(!def.is_union()); // Valtree construction would never succeed for unions.
PatKind::Leaf { PatKind::Leaf {
subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip( subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx, args)), def.non_enum_variant().fields.iter().map(|field| field.ty(tcx, args)),
)), )),
} }
} }
@ -252,10 +296,10 @@ impl<'tcx> ConstToPat<'tcx> {
// deref pattern. // deref pattern.
_ => { _ => {
if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() { if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() {
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; return self.mk_err(
let e = tcx.dcx().emit_err(err); tcx.dcx().create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty }),
// We errored. Signal that in the pattern, so that follow up errors can be silenced. ty,
PatKind::Error(e) );
} else { } else {
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
// matching against references, you can only use byte string literals. // matching against references, you can only use byte string literals.
@ -286,8 +330,7 @@ impl<'tcx> ConstToPat<'tcx> {
if is_nan { if is_nan {
// NaNs are not ever equal to anything so they make no sense as patterns. // NaNs are not ever equal to anything so they make no sense as patterns.
// Also see <https://github.com/rust-lang/rfcs/pull/3535>. // Also see <https://github.com/rust-lang/rfcs/pull/3535>.
let e = tcx.dcx().emit_err(NaNPattern { span }); return self.mk_err(tcx.dcx().create_err(NaNPattern { span }), ty);
PatKind::Error(e)
} else { } else {
PatKind::Constant { PatKind::Constant {
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)), value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
@ -305,13 +348,153 @@ impl<'tcx> ConstToPat<'tcx> {
) )
} }
_ => { _ => {
let err = InvalidPattern { span, non_sm_ty: ty }; let err = InvalidPattern {
let e = tcx.dcx().emit_err(err); span,
// We errored. Signal that in the pattern, so that follow up errors can be silenced. non_sm_ty: ty,
PatKind::Error(e) prefix: ty.prefix_string(tcx).to_string(),
};
return self.mk_err(tcx.dcx().create_err(err), ty);
} }
}; };
Box::new(Pat { span, ty, kind }) Box::new(Pat { span, ty, kind })
} }
} }
/// Given a type with type parameters, visit every ADT looking for types that need to
/// `#[derive(PartialEq)]` for it to be a structural type.
fn extend_type_not_partial_eq<'tcx>(
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
err: &mut Diag<'_>,
) {
/// Collect all types that need to be `StructuralPartialEq`.
struct UsedParamsNeedInstantiationVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
/// The user has written `impl PartialEq for Ty` which means it's non-structual.
adts_with_manual_partialeq: FxHashSet<Span>,
/// The type has no `PartialEq` implementation, neither manual or derived.
adts_without_partialeq: FxHashSet<Span>,
/// The user has written `impl PartialEq for Ty` which means it's non-structual,
/// but we don't have a span to point at, so we'll just add them as a `note`.
manual: Vec<Ty<'tcx>>,
/// The type has no `PartialEq` implementation, neither manual or derived, but
/// we don't have a span to point at, so we'll just add them as a `note`.
without: Vec<Ty<'tcx>>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if let ty::Adt(def, _args) = ty.kind() {
let ty_def_id = def.did();
let ty_def_span = self.tcx.def_span(ty_def_id);
let (impls_partial_eq, derived, structural, impl_def_id) =
type_has_partial_eq_impl(self.tcx, self.typing_env, ty);
match (impls_partial_eq, derived, structural, impl_def_id) {
(_, _, true, _) => {}
(true, false, _, Some(def_id)) if def_id.is_local() => {
self.adts_with_manual_partialeq.insert(self.tcx.def_span(def_id));
}
(true, false, _, _) if ty_def_id.is_local() => {
self.adts_with_manual_partialeq.insert(ty_def_span);
}
(false, _, _, _) if ty_def_id.is_local() => {
self.adts_without_partialeq.insert(ty_def_span);
}
(true, false, _, _) => {
self.manual.push(ty);
}
(false, _, _, _) => {
self.without.push(ty);
}
_ => {}
};
}
use rustc_middle::ty::TypeSuperVisitable;
ty.super_visit_with(self)
}
}
let mut v = UsedParamsNeedInstantiationVisitor {
tcx,
typing_env,
adts_with_manual_partialeq: FxHashSet::default(),
adts_without_partialeq: FxHashSet::default(),
manual: vec![],
without: vec![],
};
v.visit_ty(ty);
#[allow(rustc::potential_query_instability)] // Span labels will be sorted by the rendering
for span in v.adts_with_manual_partialeq {
err.span_note(span, "the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details");
}
#[allow(rustc::potential_query_instability)] // Span labels will be sorted by the rendering
for span in v.adts_without_partialeq {
err.span_label(
span,
"must be annotated with `#[derive(PartialEq)]` to be usable in patterns",
);
}
for ty in v.manual {
err.note(format!(
"`{ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details"
));
}
for ty in v.without {
err.note(format!(
"`{ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns"
));
}
}
#[instrument(level = "trace", skip(tcx), ret)]
fn type_has_partial_eq_impl<'tcx>(
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
) -> (
/* has impl */ bool,
/* is derived */ bool,
/* structural partial eq */ bool,
/* non-blanket impl */ Option<DefId>,
) {
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
// double-check there even *is* a semantic `PartialEq` to dispatch to.
//
// (If there isn't, then we can safely issue a hard
// error, because that's never worked, due to compiler
// using `PartialEq::eq` in this scenario in the past.)
let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, None);
let structural_partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::StructuralPeq, None);
let partial_eq_obligation = Obligation::new(
tcx,
ObligationCause::dummy(),
param_env,
ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]),
);
let mut automatically_derived = false;
let mut structural_peq = false;
let mut impl_def_id = None;
for def_id in tcx.non_blanket_impls_for_ty(partial_eq_trait_id, ty) {
automatically_derived = tcx.has_attr(def_id, sym::automatically_derived);
impl_def_id = Some(def_id);
}
for _ in tcx.non_blanket_impls_for_ty(structural_partial_eq_trait_id, ty) {
structural_peq = true;
}
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get
// ignored. However that should be pretty much impossible since consts that do not depend on
// generics can only mention the `'static` lifetime, and how would one have a type that's
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
// can ensure that the type really implements `PartialEq`.
(
infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation),
automatically_derived,
structural_peq,
impl_def_id,
)
}

View file

@ -528,11 +528,17 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
| Res::SelfCtor(..) => PatKind::Leaf { subpatterns }, | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
_ => { _ => {
let e = match res { let e = match res {
Res::Def(DefKind::ConstParam, _) => { Res::Def(DefKind::ConstParam, def_id) => {
self.tcx.dcx().emit_err(ConstParamInPattern { span }) self.tcx.dcx().emit_err(ConstParamInPattern {
span,
const_span: self.tcx().def_span(def_id),
})
} }
Res::Def(DefKind::Static { .. }, _) => { Res::Def(DefKind::Static { .. }, def_id) => {
self.tcx.dcx().emit_err(StaticInPattern { span }) self.tcx.dcx().emit_err(StaticInPattern {
span,
static_span: self.tcx().def_span(def_id),
})
} }
_ => self.tcx.dcx().emit_err(NonConstPath { span }), _ => self.tcx.dcx().emit_err(NonConstPath { span }),
}; };

View file

@ -747,8 +747,8 @@ fn build_call_shim<'tcx>(
sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
} }
// FIXME(eddyb) avoid having this snippet both here and in // FIXME: Avoid having to adjust the signature both here and in
// `Instance::fn_sig` (introduce `InstanceKind::fn_sig`?). // `fn_sig_for_fn_abi`.
if let ty::InstanceKind::VTableShim(..) = instance { if let ty::InstanceKind::VTableShim(..) = instance {
// Modify fn(self, ...) to fn(self: *mut Self, ...) // Modify fn(self, ...) to fn(self: *mut Self, ...)
let mut inputs_and_output = sig.inputs_and_output.to_vec(); let mut inputs_and_output = sig.inputs_and_output.to_vec();

View file

@ -343,6 +343,9 @@ parse_incorrect_semicolon =
.suggestion = remove this semicolon .suggestion = remove this semicolon
.help = {$name} declarations are not followed by a semicolon .help = {$name} declarations are not followed by a semicolon
parse_incorrect_type_on_self = type not allowed for shorthand `self` parameter
.suggestion = move the modifiers on `self` to the type
parse_incorrect_use_of_await = incorrect use of `await` parse_incorrect_use_of_await = incorrect use of `await`
.parentheses_suggestion = `await` is not a method call, remove the parentheses .parentheses_suggestion = `await` is not a method call, remove the parentheses

View file

@ -3409,3 +3409,22 @@ pub(crate) struct PolarityAndModifiers {
pub polarity: &'static str, pub polarity: &'static str,
pub modifiers_concatenated: String, pub modifiers_concatenated: String,
} }
#[derive(Diagnostic)]
#[diag(parse_incorrect_type_on_self)]
pub(crate) struct IncorrectTypeOnSelf {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub move_self_modifier: MoveSelfModifier,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct MoveSelfModifier {
#[suggestion_part(code = "")]
pub removal_span: Span,
#[suggestion_part(code = "{modifier}")]
pub insertion_span: Span,
pub modifier: String,
}

View file

@ -2941,6 +2941,32 @@ impl<'a> Parser<'a> {
}; };
Ok((eself, eself_ident, eself_hi)) Ok((eself, eself_ident, eself_hi))
}; };
let expect_self_ident_not_typed =
|this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
let eself_ident = expect_self_ident(this);
// Recover `: Type` after a qualified self
if this.may_recover() && this.eat_noexpect(&token::Colon) {
let snap = this.create_snapshot_for_diagnostic();
match this.parse_ty() {
Ok(ty) => {
this.dcx().emit_err(errors::IncorrectTypeOnSelf {
span: ty.span,
move_self_modifier: errors::MoveSelfModifier {
removal_span: modifier_span,
insertion_span: ty.span.shrink_to_lo(),
modifier: modifier.to_ref_suggestion(),
},
});
}
Err(diag) => {
diag.cancel();
this.restore_snapshot(snap);
}
}
}
eself_ident
};
// Recover for the grammar `*self`, `*const self`, and `*mut self`. // Recover for the grammar `*self`, `*const self`, and `*mut self`.
let recover_self_ptr = |this: &mut Self| { let recover_self_ptr = |this: &mut Self| {
this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span }); this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
@ -2978,7 +3004,9 @@ impl<'a> Parser<'a> {
// `&not_self` // `&not_self`
return Ok(None); return Ok(None);
}; };
(eself, expect_self_ident(self), self.prev_token.span) let hi = self.token.span;
let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
(eself, self_ident, hi)
} }
// `*self` // `*self`
token::BinOp(token::Star) if is_isolated_self(self, 1) => { token::BinOp(token::Star) if is_isolated_self(self, 1) => {

View file

@ -3838,6 +3838,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
&& self.predicate_must_hold_modulo_regions(&Obligation::misc( && self.predicate_must_hold_modulo_regions(&Obligation::misc(
tcx, expr.span, body_id, param_env, pred, tcx, expr.span, body_id, param_env, pred,
)) ))
&& expr.span.hi() != rcvr.span.hi()
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(
expr.span.with_lo(rcvr.span.hi()), expr.span.with_lo(rcvr.span.hi()),
@ -4115,6 +4116,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// the expected is a projection that we need to resolve. // the expected is a projection that we need to resolve.
// && let Some(tail_ty) = typeck_results.expr_ty_opt(expr) // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr)
&& expected_found.found.is_unit() && expected_found.found.is_unit()
// FIXME: this happens with macro calls. Need to figure out why the stmt
// `println!();` doesn't include the `;` in its `Span`. (#133845)
// We filter these out to avoid ICEs with debug assertions on caused by
// empty suggestions.
&& expr.span.hi() != stmt.span.hi()
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(
expr.span.shrink_to_hi().with_hi(stmt.span.hi()), expr.span.shrink_to_hi().with_hi(stmt.span.hi()),

View file

@ -16,9 +16,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk}; use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk};
use rustc_infer::traits::ObligationCauseCode; use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
use rustc_middle::ty::{ use rustc_middle::ty::{self, GenericArgsRef, ToPolyTraitRef, Ty, TyCtxt, Upcast};
self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, Ty, TyCtxt, Upcast,
};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
@ -638,60 +636,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// higher-ranked things. // higher-ranked things.
// Prevent, e.g., `dyn Iterator<Item = str>`. // Prevent, e.g., `dyn Iterator<Item = str>`.
for bound in self.tcx().item_bounds(assoc_type).transpose_iter() { for bound in self.tcx().item_bounds(assoc_type).transpose_iter() {
let arg_bound = if defs.is_empty() {
bound.instantiate(tcx, trait_predicate.trait_ref.args)
} else {
let mut args = smallvec::SmallVec::with_capacity(defs.count());
args.extend(trait_predicate.trait_ref.args.iter());
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
smallvec::SmallVec::with_capacity(
bound.skip_binder().kind().bound_vars().len() + defs.count(),
);
bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter());
GenericArgs::fill_single(&mut args, defs, &mut |param, _| match param.kind {
GenericParamDefKind::Type { .. } => {
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
Ty::new_bound(tcx, ty::INNERMOST, ty::BoundTy {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind,
})
.into()
}
GenericParamDefKind::Lifetime => {
let kind = ty::BoundRegionKind::Named(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Region(kind);
bound_vars.push(bound_var);
ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind,
})
.into()
}
GenericParamDefKind::Const { .. } => {
let bound_var = ty::BoundVariableKind::Const;
bound_vars.push(bound_var);
ty::Const::new_bound(
tcx,
ty::INNERMOST,
ty::BoundVar::from_usize(bound_vars.len() - 1),
)
.into()
}
});
let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
let assoc_ty_args = tcx.mk_args(&args);
let bound =
bound.map_bound(|b| b.kind().skip_binder()).instantiate(tcx, assoc_ty_args);
ty::Binder::bind_with_vars(bound, bound_vars).upcast(tcx)
};
let normalized_bound = normalize_with_depth_to( let normalized_bound = normalize_with_depth_to(
self, self,
obligation.param_env, obligation.param_env,
obligation.cause.clone(), obligation.cause.clone(),
obligation.recursion_depth + 1, obligation.recursion_depth + 1,
arg_bound, bound.instantiate(tcx, trait_predicate.trait_ref.args),
&mut nested, &mut nested,
); );
nested.push(obligation.with(tcx, normalized_bound)); nested.push(obligation.with(tcx, normalized_bound));

View file

@ -31,20 +31,20 @@ fn fn_sig_for_fn_abi<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
typing_env: ty::TypingEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
) -> ty::PolyFnSig<'tcx> { ) -> ty::FnSig<'tcx> {
if let InstanceKind::ThreadLocalShim(..) = instance.def { if let InstanceKind::ThreadLocalShim(..) = instance.def {
return ty::Binder::dummy(tcx.mk_fn_sig( return tcx.mk_fn_sig(
[], [],
tcx.thread_local_ptr_ty(instance.def_id()), tcx.thread_local_ptr_ty(instance.def_id()),
false, false,
hir::Safety::Safe, hir::Safety::Safe,
rustc_abi::ExternAbi::Unadjusted, rustc_abi::ExternAbi::Unadjusted,
)); );
} }
let ty = instance.ty(tcx, typing_env); let ty = instance.ty(tcx, typing_env);
match *ty.kind() { match *ty.kind() {
ty::FnDef(..) => { ty::FnDef(def_id, args) => {
// HACK(davidtwco,eddyb): This is a workaround for polymorphization considering // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering
// parameters unused if they show up in the signature, but not in the `mir::Body` // parameters unused if they show up in the signature, but not in the `mir::Body`
// (i.e. due to being inside a projection that got normalized, see // (i.e. due to being inside a projection that got normalized, see
@ -52,9 +52,8 @@ fn fn_sig_for_fn_abi<'tcx>(
// track of a polymorphization `ParamEnv` to allow normalizing later. // track of a polymorphization `ParamEnv` to allow normalizing later.
// //
// We normalize the `fn_sig` again after instantiating at a later point. // We normalize the `fn_sig` again after instantiating at a later point.
let mut sig = match *ty.kind() { let mut sig = tcx.instantiate_bound_regions_with_erased(
ty::FnDef(def_id, args) => tcx tcx.fn_sig(def_id)
.fn_sig(def_id)
.map_bound(|fn_sig| { .map_bound(|fn_sig| {
tcx.normalize_erasing_regions( tcx.normalize_erasing_regions(
ty::TypingEnv::non_body_analysis(tcx, def_id), ty::TypingEnv::non_body_analysis(tcx, def_id),
@ -62,62 +61,36 @@ fn fn_sig_for_fn_abi<'tcx>(
) )
}) })
.instantiate(tcx, args), .instantiate(tcx, args),
_ => unreachable!(), );
};
if let ty::InstanceKind::VTableShim(..) = instance.def { if let ty::InstanceKind::VTableShim(..) = instance.def {
// Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. let mut inputs_and_output = sig.inputs_and_output.to_vec();
sig = sig.map_bound(|mut sig| { inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]);
let mut inputs_and_output = sig.inputs_and_output.to_vec(); sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]);
sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
sig
});
} }
sig sig
} }
ty::Closure(def_id, args) => { ty::Closure(def_id, args) => {
let sig = args.as_closure().sig(); let sig = tcx.instantiate_bound_regions_with_erased(args.as_closure().sig());
let bound_vars =
tcx.mk_bound_variable_kinds_from_iter(sig.bound_vars().iter().chain(iter::once(
ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
)));
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::ClosureEnv,
};
let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
let env_ty = tcx.closure_env_ty( let env_ty = tcx.closure_env_ty(
Ty::new_closure(tcx, def_id, args), Ty::new_closure(tcx, def_id, args),
args.as_closure().kind(), args.as_closure().kind(),
env_region, tcx.lifetimes.re_erased,
); );
let sig = sig.skip_binder(); tcx.mk_fn_sig(
ty::Binder::bind_with_vars( iter::once(env_ty).chain(sig.inputs().iter().cloned()),
tcx.mk_fn_sig( sig.output(),
iter::once(env_ty).chain(sig.inputs().iter().cloned()), sig.c_variadic,
sig.output(), sig.safety,
sig.c_variadic, sig.abi,
sig.safety,
sig.abi,
),
bound_vars,
) )
} }
ty::CoroutineClosure(def_id, args) => { ty::CoroutineClosure(def_id, args) => {
let coroutine_ty = Ty::new_coroutine_closure(tcx, def_id, args); let coroutine_ty = Ty::new_coroutine_closure(tcx, def_id, args);
let sig = args.as_coroutine_closure().coroutine_closure_sig(); let sig = args.as_coroutine_closure().coroutine_closure_sig();
let bound_vars =
tcx.mk_bound_variable_kinds_from_iter(sig.bound_vars().iter().chain(iter::once(
ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
)));
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::ClosureEnv,
};
let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
// When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`, // When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`,
// make sure we respect the `target_kind` in that shim. // make sure we respect the `target_kind` in that shim.
// FIXME(async_closures): This shouldn't be needed, and we should be populating // FIXME(async_closures): This shouldn't be needed, and we should be populating
@ -138,42 +111,32 @@ fn fn_sig_for_fn_abi<'tcx>(
coroutine_ty coroutine_ty
} }
} else { } else {
tcx.closure_env_ty(coroutine_ty, coroutine_kind, env_region) tcx.closure_env_ty(coroutine_ty, coroutine_kind, tcx.lifetimes.re_erased)
}; };
let sig = sig.skip_binder(); let sig = tcx.instantiate_bound_regions_with_erased(sig);
ty::Binder::bind_with_vars(
tcx.mk_fn_sig( tcx.mk_fn_sig(
iter::once(env_ty).chain([sig.tupled_inputs_ty]), iter::once(env_ty).chain([sig.tupled_inputs_ty]),
sig.to_coroutine_given_kind_and_upvars( sig.to_coroutine_given_kind_and_upvars(
tcx, tcx,
args.as_coroutine_closure().parent_args(), args.as_coroutine_closure().parent_args(),
tcx.coroutine_for_closure(def_id), tcx.coroutine_for_closure(def_id),
coroutine_kind, coroutine_kind,
env_region, tcx.lifetimes.re_erased,
args.as_coroutine_closure().tupled_upvars_ty(), args.as_coroutine_closure().tupled_upvars_ty(),
args.as_coroutine_closure().coroutine_captures_by_ref_ty(), args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
),
sig.c_variadic,
sig.safety,
sig.abi,
), ),
bound_vars, sig.c_variadic,
sig.safety,
sig.abi,
) )
} }
ty::Coroutine(did, args) => { ty::Coroutine(did, args) => {
let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let coroutine_kind = tcx.coroutine_kind(did).unwrap();
let sig = args.as_coroutine().sig(); let sig = args.as_coroutine().sig();
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(iter::once( let env_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
));
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::ClosureEnv,
};
let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty);
let pin_did = tcx.require_lang_item(LangItem::Pin, None); let pin_did = tcx.require_lang_item(LangItem::Pin, None);
let pin_adt_ref = tcx.adt_def(pin_did); let pin_adt_ref = tcx.adt_def(pin_did);
@ -268,7 +231,7 @@ fn fn_sig_for_fn_abi<'tcx>(
} }
}; };
let fn_sig = if let Some(resume_ty) = resume_ty { if let Some(resume_ty) = resume_ty {
tcx.mk_fn_sig( tcx.mk_fn_sig(
[env_ty, resume_ty], [env_ty, resume_ty],
ret_ty, ret_ty,
@ -285,8 +248,7 @@ fn fn_sig_for_fn_abi<'tcx>(
hir::Safety::Safe, hir::Safety::Safe,
rustc_abi::ExternAbi::Rust, rustc_abi::ExternAbi::Rust,
) )
}; }
ty::Binder::bind_with_vars(fn_sig, bound_vars)
} }
_ => bug!("unexpected type {:?} in Instance::fn_sig", ty), _ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
} }
@ -335,8 +297,16 @@ fn fn_abi_of_fn_ptr<'tcx>(
query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>, query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query; let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query;
let cx = LayoutCx::new(tcx, typing_env); let cx = LayoutCx::new(tcx, typing_env);
fn_abi_new_uncached(&cx, sig, extra_args, None, None, false) fn_abi_new_uncached(
&cx,
tcx.instantiate_bound_regions_with_erased(sig),
extra_args,
None,
None,
false,
)
} }
fn fn_abi_of_instance<'tcx>( fn fn_abi_of_instance<'tcx>(
@ -567,7 +537,7 @@ fn fn_abi_sanity_check<'tcx>(
#[tracing::instrument(level = "debug", skip(cx, caller_location, fn_def_id, force_thin_self_ptr))] #[tracing::instrument(level = "debug", skip(cx, caller_location, fn_def_id, force_thin_self_ptr))]
fn fn_abi_new_uncached<'tcx>( fn fn_abi_new_uncached<'tcx>(
cx: &LayoutCx<'tcx>, cx: &LayoutCx<'tcx>,
sig: ty::PolyFnSig<'tcx>, sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>], extra_args: &[Ty<'tcx>],
caller_location: Option<Ty<'tcx>>, caller_location: Option<Ty<'tcx>>,
fn_def_id: Option<DefId>, fn_def_id: Option<DefId>,
@ -575,7 +545,7 @@ fn fn_abi_new_uncached<'tcx>(
force_thin_self_ptr: bool, force_thin_self_ptr: bool,
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> { ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
let tcx = cx.tcx(); let tcx = cx.tcx();
let sig = tcx.normalize_erasing_late_bound_regions(cx.typing_env, sig); let sig = tcx.normalize_erasing_regions(cx.typing_env, sig);
let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);

View file

@ -345,7 +345,7 @@ pub mod net;
pub mod option; pub mod option;
pub mod panic; pub mod panic;
pub mod panicking; pub mod panicking;
#[unstable(feature = "core_pattern_types", issue = "123646")] #[unstable(feature = "pattern_type_macro", issue = "123646")]
pub mod pat; pub mod pat;
pub mod pin; pub mod pin;
#[unstable(feature = "random", issue = "130703")] #[unstable(feature = "random", issue = "130703")]

View file

@ -6,7 +6,7 @@
/// ``` /// ```
#[macro_export] #[macro_export]
#[rustc_builtin_macro(pattern_type)] #[rustc_builtin_macro(pattern_type)]
#[unstable(feature = "core_pattern_type", issue = "123646")] #[unstable(feature = "pattern_type_macro", issue = "123646")]
macro_rules! pattern_type { macro_rules! pattern_type {
($($arg:tt)*) => { ($($arg:tt)*) => {
/* compiler built-in */ /* compiler built-in */

View file

@ -304,6 +304,7 @@ fn test_const_nonnull_new() {
#[test] #[test]
#[cfg(unix)] // printf may not be available on other platforms #[cfg(unix)] // printf may not be available on other platforms
#[allow(deprecated)] // For SipHasher #[allow(deprecated)] // For SipHasher
#[cfg_attr(not(bootstrap), allow(unpredictable_function_pointer_comparisons))]
pub fn test_variadic_fnptr() { pub fn test_variadic_fnptr() {
use core::ffi; use core::ffi;
use core::hash::{Hash, SipHasher}; use core::hash::{Hash, SipHasher};

View file

@ -589,7 +589,7 @@ pub mod net;
pub mod num; pub mod num;
pub mod os; pub mod os;
pub mod panic; pub mod panic;
#[unstable(feature = "core_pattern_types", issue = "123646")] #[unstable(feature = "pattern_type_macro", issue = "123646")]
pub mod pat; pub mod pat;
pub mod path; pub mod path;
#[unstable(feature = "anonymous_pipe", issue = "127154")] #[unstable(feature = "anonymous_pipe", issue = "127154")]

View file

@ -48,9 +48,9 @@ fn main() {
err => { err => {
drop(err); drop(err);
if let Ok(pid) = pid { if let Ok(pid) = pid {
eprintln!("WARNING: build directory locked by process {pid}, waiting for lock"); println!("WARNING: build directory locked by process {pid}, waiting for lock");
} else { } else {
eprintln!("WARNING: build directory locked, waiting for lock"); println!("WARNING: build directory locked, waiting for lock");
} }
let mut lock = t!(build_lock.write()); let mut lock = t!(build_lock.write());
t!(lock.write(process::id().to_string().as_ref())); t!(lock.write(process::id().to_string().as_ref()));
@ -70,13 +70,13 @@ fn main() {
// changelog warning, not the `x.py setup` message. // changelog warning, not the `x.py setup` message.
let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. }); let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. });
if suggest_setup { if suggest_setup {
eprintln!("WARNING: you have not made a `config.toml`"); println!("WARNING: you have not made a `config.toml`");
eprintln!( println!(
"HELP: consider running `./x.py setup` or copying `config.example.toml` by running \ "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
`cp config.example.toml config.toml`" `cp config.example.toml config.toml`"
); );
} else if let Some(suggestion) = &changelog_suggestion { } else if let Some(suggestion) = &changelog_suggestion {
eprintln!("{suggestion}"); println!("{suggestion}");
} }
let pre_commit = config.src.join(".git").join("hooks").join("pre-commit"); let pre_commit = config.src.join(".git").join("hooks").join("pre-commit");
@ -86,13 +86,13 @@ fn main() {
Build::new(config).build(); Build::new(config).build();
if suggest_setup { if suggest_setup {
eprintln!("WARNING: you have not made a `config.toml`"); println!("WARNING: you have not made a `config.toml`");
eprintln!( println!(
"HELP: consider running `./x.py setup` or copying `config.example.toml` by running \ "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
`cp config.example.toml config.toml`" `cp config.example.toml config.toml`"
); );
} else if let Some(suggestion) = &changelog_suggestion { } else if let Some(suggestion) = &changelog_suggestion {
eprintln!("{suggestion}"); println!("{suggestion}");
} }
// Give a warning if the pre-commit script is in pre-commit and not pre-push. // Give a warning if the pre-commit script is in pre-commit and not pre-push.
@ -102,14 +102,14 @@ fn main() {
if fs::read_to_string(pre_commit).is_ok_and(|contents| { if fs::read_to_string(pre_commit).is_ok_and(|contents| {
contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570") contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
}) { }) {
eprintln!( println!(
"WARNING: You have the pre-push script installed to .git/hooks/pre-commit. \ "WARNING: You have the pre-push script installed to .git/hooks/pre-commit. \
Consider moving it to .git/hooks/pre-push instead, which runs less often." Consider moving it to .git/hooks/pre-push instead, which runs less often."
); );
} }
if suggest_setup || changelog_suggestion.is_some() { if suggest_setup || changelog_suggestion.is_some() {
eprintln!("NOTE: this message was printed twice to make it more likely to be seen"); println!("NOTE: this message was printed twice to make it more likely to be seen");
} }
if dump_bootstrap_shims { if dump_bootstrap_shims {

View file

@ -306,7 +306,7 @@ fn main() {
// should run on success, after this block. // should run on success, after this block.
} }
if verbose > 0 { if verbose > 0 {
eprintln!("\nDid not run successfully: {status}\n{cmd:?}\n-------------"); println!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
} }
if let Some(mut on_fail) = on_fail { if let Some(mut on_fail) = on_fail {

View file

@ -287,7 +287,7 @@ impl Step for CodegenBackend {
fn run(self, builder: &Builder<'_>) { fn run(self, builder: &Builder<'_>) {
// FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved // FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved
if builder.build.config.vendor && self.backend == "gcc" { if builder.build.config.vendor && self.backend == "gcc" {
eprintln!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled."); println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
return; return;
} }

View file

@ -1611,7 +1611,7 @@ impl Step for Sysroot {
let sysroot = sysroot_dir(compiler.stage); let sysroot = sysroot_dir(compiler.stage);
builder builder
.verbose(|| eprintln!("Removing sysroot {} to avoid caching bugs", sysroot.display())); .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
let _ = fs::remove_dir_all(&sysroot); let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot)); t!(fs::create_dir_all(&sysroot));
@ -1681,7 +1681,7 @@ impl Step for Sysroot {
return true; return true;
} }
if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) { if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
builder.verbose_than(1, || eprintln!("ignoring {}", path.display())); builder.verbose_than(1, || println!("ignoring {}", path.display()));
false false
} else { } else {
true true
@ -2240,7 +2240,7 @@ pub fn stream_cargo(
cargo.arg(arg); cargo.arg(arg);
} }
builder.verbose(|| eprintln!("running: {cargo:?}")); builder.verbose(|| println!("running: {cargo:?}"));
if builder.config.dry_run() { if builder.config.dry_run() {
return true; return true;
@ -2261,12 +2261,12 @@ pub fn stream_cargo(
Ok(msg) => { Ok(msg) => {
if builder.config.json_output { if builder.config.json_output {
// Forward JSON to stdout. // Forward JSON to stdout.
eprintln!("{line}"); println!("{line}");
} }
cb(msg) cb(msg)
} }
// If this was informational, just print it out and continue // If this was informational, just print it out and continue
Err(_) => eprintln!("{line}"), Err(_) => println!("{line}"),
} }
} }

View file

@ -2080,7 +2080,7 @@ fn maybe_install_llvm(
{ {
let mut cmd = command(llvm_config); let mut cmd = command(llvm_config);
cmd.arg("--libfiles"); cmd.arg("--libfiles");
builder.verbose(|| eprintln!("running {cmd:?}")); builder.verbose(|| println!("running {cmd:?}"));
let files = cmd.run_capture_stdout(builder).stdout(); let files = cmd.run_capture_stdout(builder).stdout();
let build_llvm_out = &builder.llvm_out(builder.config.build); let build_llvm_out = &builder.llvm_out(builder.config.build);
let target_llvm_out = &builder.llvm_out(target); let target_llvm_out = &builder.llvm_out(target);

View file

@ -107,10 +107,10 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() }; if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() };
if len <= 10 { if len <= 10 {
for path in paths { for path in paths {
eprintln!("fmt: {verb} {adjective}file {path}"); println!("fmt: {verb} {adjective}file {path}");
} }
} else { } else {
eprintln!("fmt: {verb} {len} {adjective}files"); println!("fmt: {verb} {len} {adjective}files");
} }
} }
@ -199,7 +199,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
match get_modified_rs_files(build) { match get_modified_rs_files(build) {
Ok(Some(files)) => { Ok(Some(files)) => {
if files.is_empty() { if files.is_empty() {
eprintln!("fmt info: No modified files detected for formatting."); println!("fmt info: No modified files detected for formatting.");
return; return;
} }

View file

@ -134,7 +134,7 @@ impl Step for Profile {
t!(fs::remove_file(path)); t!(fs::remove_file(path));
} }
_ => { _ => {
eprintln!("Exiting."); println!("Exiting.");
crate::exit!(1); crate::exit!(1);
} }
} }
@ -184,15 +184,15 @@ pub fn setup(config: &Config, profile: Profile) {
Profile::Dist => &["dist", "build"], Profile::Dist => &["dist", "build"],
}; };
eprintln!(); println!();
eprintln!("To get started, try one of the following commands:"); println!("To get started, try one of the following commands:");
for cmd in suggestions { for cmd in suggestions {
eprintln!("- `x.py {cmd}`"); println!("- `x.py {cmd}`");
} }
if profile != Profile::Dist { if profile != Profile::Dist {
eprintln!( println!(
"For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html" "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
); );
} }
@ -224,7 +224,7 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
t!(fs::write(path, settings)); t!(fs::write(path, settings));
let include_path = profile.include_path(&config.src); let include_path = profile.include_path(&config.src);
eprintln!("`x.py` will now use the configuration at {}", include_path.display()); println!("`x.py` will now use the configuration at {}", include_path.display());
} }
/// Creates a toolchain link for stage1 using `rustup` /// Creates a toolchain link for stage1 using `rustup`
@ -256,7 +256,7 @@ impl Step for Link {
} }
if !rustup_installed(builder) { if !rustup_installed(builder) {
eprintln!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking."); println!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
return; return;
} }
@ -296,7 +296,7 @@ fn attempt_toolchain_link(builder: &Builder<'_>, stage_path: &str) {
} }
if try_link_toolchain(builder, stage_path) { if try_link_toolchain(builder, stage_path) {
eprintln!( println!(
"Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain" "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
); );
} else { } else {
@ -321,14 +321,14 @@ fn toolchain_is_linked(builder: &Builder<'_>) -> bool {
return false; return false;
} }
// The toolchain has already been linked. // The toolchain has already been linked.
eprintln!( println!(
"`stage1` toolchain already linked; not attempting to link `stage1` toolchain" "`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
); );
} }
None => { None => {
// In this case, we don't know if the `stage1` toolchain has been linked; // In this case, we don't know if the `stage1` toolchain has been linked;
// but `rustup` failed, so let's not go any further. // but `rustup` failed, so let's not go any further.
eprintln!( println!(
"`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain" "`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain"
); );
} }
@ -389,9 +389,9 @@ pub fn interactive_path() -> io::Result<Profile> {
input.parse() input.parse()
} }
eprintln!("Welcome to the Rust project! What do you want to do with x.py?"); println!("Welcome to the Rust project! What do you want to do with x.py?");
for ((letter, _), profile) in abbrev_all() { for ((letter, _), profile) in abbrev_all() {
eprintln!("{}) {}: {}", letter, profile, profile.purpose()); println!("{}) {}: {}", letter, profile, profile.purpose());
} }
let template = loop { let template = loop {
print!( print!(
@ -488,7 +488,7 @@ fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<
return Ok(()); return Ok(());
} }
eprintln!( println!(
"\nRust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality. "\nRust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
pushing your code to ensure your code is up to par. If you decide later that this behavior is pushing your code to ensure your code is up to par. If you decide later that this behavior is
@ -496,7 +496,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
); );
if prompt_user("Would you like to install the git hook?: [y/N]")? != Some(PromptResult::Yes) { if prompt_user("Would you like to install the git hook?: [y/N]")? != Some(PromptResult::Yes) {
eprintln!("Ok, skipping installation!"); println!("Ok, skipping installation!");
return Ok(()); return Ok(());
} }
if !hooks_dir.exists() { if !hooks_dir.exists() {
@ -513,7 +513,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
); );
return Err(e); return Err(e);
} }
Ok(_) => eprintln!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"), Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
}; };
Ok(()) Ok(())
} }
@ -654,7 +654,7 @@ impl Step for Editor {
if let Some(editor_kind) = editor_kind { if let Some(editor_kind) = editor_kind {
while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {} while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {}
} else { } else {
eprintln!("Ok, skipping editor setup!"); println!("Ok, skipping editor setup!");
} }
} }
Err(e) => eprintln!("Could not determine the editor: {e}"), Err(e) => eprintln!("Could not determine the editor: {e}"),
@ -687,7 +687,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
mismatched_settings = Some(false); mismatched_settings = Some(false);
} }
} }
eprintln!( println!(
"\nx.py can automatically install the recommended `{settings_filename}` file for rustc development" "\nx.py can automatically install the recommended `{settings_filename}` file for rustc development"
); );
@ -706,7 +706,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
Some(PromptResult::Yes) => true, Some(PromptResult::Yes) => true,
Some(PromptResult::Print) => false, Some(PromptResult::Print) => false,
_ => { _ => {
eprintln!("Ok, skipping settings!"); println!("Ok, skipping settings!");
return Ok(true); return Ok(true);
} }
}; };
@ -733,9 +733,9 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
_ => "Created", _ => "Created",
}; };
fs::write(&settings_path, editor.settings_template())?; fs::write(&settings_path, editor.settings_template())?;
eprintln!("{verb} `{}`", settings_filename); println!("{verb} `{}`", settings_filename);
} else { } else {
eprintln!("\n{}", editor.settings_template()); println!("\n{}", editor.settings_template());
} }
Ok(should_create) Ok(should_create)
} }

View file

@ -66,6 +66,6 @@ pub fn suggest(builder: &Builder<'_>, run: bool) {
build.build(); build.build();
} }
} else { } else {
eprintln!("HELP: consider using the `--run` flag to automatically run suggested tests"); println!("HELP: consider using the `--run` flag to automatically run suggested tests");
} }
} }

View file

@ -471,11 +471,11 @@ impl Miri {
// We re-use the `cargo` from above. // We re-use the `cargo` from above.
cargo.arg("--print-sysroot"); cargo.arg("--print-sysroot");
builder.verbose(|| eprintln!("running: {cargo:?}")); builder.verbose(|| println!("running: {cargo:?}"));
let stdout = cargo.run_capture_stdout(builder).stdout(); let stdout = cargo.run_capture_stdout(builder).stdout();
// Output is "<sysroot>\n". // Output is "<sysroot>\n".
let sysroot = stdout.trim_end(); let sysroot = stdout.trim_end();
builder.verbose(|| eprintln!("`cargo miri setup --print-sysroot` said: {sysroot:?}")); builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
PathBuf::from(sysroot) PathBuf::from(sysroot)
} }
} }
@ -2478,7 +2478,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
} }
} }
builder.verbose(|| eprintln!("doc tests for: {}", markdown.display())); builder.verbose(|| println!("doc tests for: {}", markdown.display()));
let mut cmd = builder.rustdoc_cmd(compiler); let mut cmd = builder.rustdoc_cmd(compiler);
builder.add_rust_test_threads(&mut cmd); builder.add_rust_test_threads(&mut cmd);
// allow for unstable options such as new editions // allow for unstable options such as new editions

View file

@ -523,7 +523,7 @@ impl Builder<'_> {
let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8"); let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
if self.is_verbose() && !matches!(self.config.dry_run, DryRun::SelfCheck) { if self.is_verbose() && !matches!(self.config.dry_run, DryRun::SelfCheck) {
eprintln!("using sysroot {sysroot_str}"); println!("using sysroot {sysroot_str}");
} }
let mut rustflags = Rustflags::new(target); let mut rustflags = Rustflags::new(target);

View file

@ -392,14 +392,14 @@ impl StepDescription {
fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool { fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
if builder.config.skip.iter().any(|e| pathset.has(e, builder.kind)) { if builder.config.skip.iter().any(|e| pathset.has(e, builder.kind)) {
if !matches!(builder.config.dry_run, DryRun::SelfCheck) { if !matches!(builder.config.dry_run, DryRun::SelfCheck) {
eprintln!("Skipping {pathset:?} because it is excluded"); println!("Skipping {pathset:?} because it is excluded");
} }
return true; return true;
} }
if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) { if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) {
builder.verbose(|| { builder.verbose(|| {
eprintln!( println!(
"{:?} not skipped for {:?} -- not in {:?}", "{:?} not skipped for {:?} -- not in {:?}",
pathset, self.name, builder.config.skip pathset, self.name, builder.config.skip
) )
@ -1437,11 +1437,11 @@ impl<'a> Builder<'a> {
panic!("{}", out); panic!("{}", out);
} }
if let Some(out) = self.cache.get(&step) { if let Some(out) = self.cache.get(&step) {
self.verbose_than(1, || eprintln!("{}c {:?}", " ".repeat(stack.len()), step)); self.verbose_than(1, || println!("{}c {:?}", " ".repeat(stack.len()), step));
return out; return out;
} }
self.verbose_than(1, || eprintln!("{}> {:?}", " ".repeat(stack.len()), step)); self.verbose_than(1, || println!("{}> {:?}", " ".repeat(stack.len()), step));
stack.push(Box::new(step.clone())); stack.push(Box::new(step.clone()));
} }
@ -1462,7 +1462,7 @@ impl<'a> Builder<'a> {
let step_string = format!("{step:?}"); let step_string = format!("{step:?}");
let brace_index = step_string.find('{').unwrap_or(0); let brace_index = step_string.find('{').unwrap_or(0);
let type_string = type_name::<S>(); let type_string = type_name::<S>();
eprintln!( println!(
"[TIMING] {} {} -- {}.{:03}", "[TIMING] {} {} -- {}.{:03}",
&type_string.strip_prefix("bootstrap::").unwrap_or(type_string), &type_string.strip_prefix("bootstrap::").unwrap_or(type_string),
&step_string[brace_index..], &step_string[brace_index..],
@ -1479,9 +1479,7 @@ impl<'a> Builder<'a> {
let cur_step = stack.pop().expect("step stack empty"); let cur_step = stack.pop().expect("step stack empty");
assert_eq!(cur_step.downcast_ref(), Some(&step)); assert_eq!(cur_step.downcast_ref(), Some(&step));
} }
self.verbose_than(1, || { self.verbose_than(1, || println!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
eprintln!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)
});
self.cache.put(step, out.clone()); self.cache.put(step, out.clone());
out out
} }

View file

@ -1293,7 +1293,7 @@ impl Config {
.map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids)) .map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
{ {
if !changes.is_empty() { if !changes.is_empty() {
eprintln!( println!(
"WARNING: There have been changes to x.py since you last updated:\n{}", "WARNING: There have been changes to x.py since you last updated:\n{}",
crate::human_readable_changes(&changes) crate::human_readable_changes(&changes)
); );
@ -1559,7 +1559,7 @@ impl Config {
} }
if cargo_clippy.is_some() && rustc.is_none() { if cargo_clippy.is_some() && rustc.is_none() {
eprintln!( println!(
"WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict." "WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict."
); );
} }
@ -1841,7 +1841,7 @@ impl Config {
// FIXME: Remove this option at the end of 2024. // FIXME: Remove this option at the end of 2024.
if parallel_compiler.is_some() { if parallel_compiler.is_some() {
eprintln!( println!(
"WARNING: The `rust.parallel-compiler` option is deprecated and does nothing. The parallel compiler (with one thread) is now the default" "WARNING: The `rust.parallel-compiler` option is deprecated and does nothing. The parallel compiler (with one thread) is now the default"
); );
} }
@ -1873,7 +1873,7 @@ impl Config {
if available_backends.contains(&backend) { if available_backends.contains(&backend) {
panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'."); panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'.");
} else { } else {
eprintln!("HELP: '{s}' for 'rust.codegen-backends' might fail. \ println!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \ Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
In this case, it would be referred to as '{backend}'."); In this case, it would be referred to as '{backend}'.");
} }
@ -1902,7 +1902,7 @@ impl Config {
// tests may fail due to using a different channel than the one used by the compiler during tests. // tests may fail due to using a different channel than the one used by the compiler during tests.
if let Some(commit) = &config.download_rustc_commit { if let Some(commit) = &config.download_rustc_commit {
if is_user_configured_rust_channel { if is_user_configured_rust_channel {
eprintln!( println!(
"WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel." "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel."
); );
@ -1992,10 +1992,10 @@ impl Config {
if config.llvm_from_ci { if config.llvm_from_ci {
let warn = |option: &str| { let warn = |option: &str| {
eprintln!( println!(
"WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build." "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
); );
eprintln!( println!(
"HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false." "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
); );
}; };
@ -2014,12 +2014,12 @@ impl Config {
// if they've chosen a different value. // if they've chosen a different value.
if libzstd.is_some() { if libzstd.is_some() {
eprintln!( println!(
"WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \ "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \
like almost all `llvm.*` options, will be ignored and set by the LLVM CI \ like almost all `llvm.*` options, will be ignored and set by the LLVM CI \
artifacts builder config." artifacts builder config."
); );
eprintln!( println!(
"HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false." "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
); );
} }
@ -2088,7 +2088,7 @@ impl Config {
if available_backends.contains(&backend) { if available_backends.contains(&backend) {
panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'."); panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'.");
} else { } else {
eprintln!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \ println!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \ Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
In this case, it would be referred to as '{backend}'."); In this case, it would be referred to as '{backend}'.");
} }
@ -2304,7 +2304,7 @@ impl Config {
if self.dry_run() { if self.dry_run() {
return Ok(()); return Ok(());
} }
self.verbose(|| eprintln!("running: {cmd:?}")); self.verbose(|| println!("running: {cmd:?}"));
build_helper::util::try_run(cmd, self.is_verbose()) build_helper::util::try_run(cmd, self.is_verbose())
} }
@ -2479,7 +2479,7 @@ impl Config {
// This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error
// to not break CI. For non-CI environments, we should return an error. // to not break CI. For non-CI environments, we should return an error.
if CiEnv::is_ci() { if CiEnv::is_ci() {
eprintln!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled."); println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
return None; return None;
} else { } else {
panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used."); panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used.");
@ -2490,8 +2490,8 @@ impl Config {
let ci_config_toml = match self.get_builder_toml("ci-rustc") { let ci_config_toml = match self.get_builder_toml("ci-rustc") {
Ok(ci_config_toml) => ci_config_toml, Ok(ci_config_toml) => ci_config_toml,
Err(e) if e.to_string().contains("unknown field") => { Err(e) if e.to_string().contains("unknown field") => {
eprintln!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled."); println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
eprintln!("HELP: Consider rebasing to a newer commit if available."); println!("HELP: Consider rebasing to a newer commit if available.");
return None; return None;
}, },
Err(e) => { Err(e) => {
@ -2516,7 +2516,7 @@ impl Config {
.is_some_and(|s| s == "1" || s == "true"); .is_some_and(|s| s == "1" || s == "true");
if disable_ci_rustc_if_incompatible && res.is_err() { if disable_ci_rustc_if_incompatible && res.is_err() {
eprintln!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env."); println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
return None; return None;
} }
@ -2701,7 +2701,7 @@ impl Config {
return; return;
} }
eprintln!("Updating submodule {relative_path}"); println!("Updating submodule {relative_path}");
self.check_run( self.check_run(
helpers::git(Some(&self.src)) helpers::git(Some(&self.src))
.run_always() .run_always()
@ -2824,7 +2824,7 @@ impl Config {
Some(StringOrBool::Bool(true)) => false, Some(StringOrBool::Bool(true)) => false,
Some(StringOrBool::String(s)) if s == "if-unchanged" => { Some(StringOrBool::String(s)) if s == "if-unchanged" => {
if !self.rust_info.is_managed_git_subrepository() { if !self.rust_info.is_managed_git_subrepository() {
eprintln!( println!(
"ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources." "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources."
); );
crate::exit!(1); crate::exit!(1);
@ -2857,10 +2857,10 @@ impl Config {
if if_unchanged { if if_unchanged {
return None; return None;
} }
eprintln!("ERROR: could not find commit hash for downloading rustc"); println!("ERROR: could not find commit hash for downloading rustc");
eprintln!("HELP: maybe your repository history is too shallow?"); println!("HELP: maybe your repository history is too shallow?");
eprintln!("HELP: consider setting `rust.download-rustc=false` in config.toml"); println!("HELP: consider setting `rust.download-rustc=false` in config.toml");
eprintln!("HELP: or fetch enough history to include one upstream commit"); println!("HELP: or fetch enough history to include one upstream commit");
crate::exit!(1); crate::exit!(1);
} }
}; };
@ -2899,7 +2899,7 @@ impl Config {
let if_unchanged = || { let if_unchanged = || {
if self.rust_info.is_from_tarball() { if self.rust_info.is_from_tarball() {
// Git is needed for running "if-unchanged" logic. // Git is needed for running "if-unchanged" logic.
eprintln!( println!(
"WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`." "WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`."
); );
return false; return false;
@ -2948,10 +2948,10 @@ impl Config {
// Only commits merged by bors will have CI artifacts. // Only commits merged by bors will have CI artifacts.
let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap(); let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
if commit.is_empty() { if commit.is_empty() {
eprintln!("error: could not find commit hash for downloading components from CI"); println!("error: could not find commit hash for downloading components from CI");
eprintln!("help: maybe your repository history is too shallow?"); println!("help: maybe your repository history is too shallow?");
eprintln!("help: consider disabling `{option_name}`"); println!("help: consider disabling `{option_name}`");
eprintln!("help: or fetch enough history to include one upstream commit"); println!("help: or fetch enough history to include one upstream commit");
crate::exit!(1); crate::exit!(1);
} }
@ -2963,14 +2963,14 @@ impl Config {
if has_changes { if has_changes {
if if_unchanged { if if_unchanged {
if self.is_verbose() { if self.is_verbose() {
eprintln!( println!(
"warning: saw changes to one of {modified_paths:?} since {commit}; \ "warning: saw changes to one of {modified_paths:?} since {commit}; \
ignoring `{option_name}`" ignoring `{option_name}`"
); );
} }
return None; return None;
} }
eprintln!( println!(
"warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}" "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
); );
} }
@ -3007,7 +3007,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
($current:expr, $expected:expr) => { ($current:expr, $expected:expr) => {
if let Some(current) = &$current { if let Some(current) = &$current {
if Some(current) != $expected.as_ref() { if Some(current) != $expected.as_ref() {
eprintln!( println!(
"WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \ "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
Current value: {:?}, Expected value(s): {}{:?}", Current value: {:?}, Expected value(s): {}{:?}",
stringify!($expected).replace("_", "-"), stringify!($expected).replace("_", "-"),
@ -3112,7 +3112,7 @@ fn check_incompatible_options_for_ci_rustc(
($current:expr, $expected:expr, $config_section:expr) => { ($current:expr, $expected:expr, $config_section:expr) => {
if let Some(current) = &$current { if let Some(current) = &$current {
if Some(current) != $expected.as_ref() { if Some(current) != $expected.as_ref() {
eprintln!( println!(
"WARNING: `{}` has no effect with `rust.download-rustc`. \ "WARNING: `{}` has no effect with `rust.download-rustc`. \
Current value: {:?}, Expected value(s): {}{:?}", Current value: {:?}, Expected value(s): {}{:?}",
format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")), format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")),

View file

@ -196,12 +196,12 @@ impl Flags {
if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) = if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) =
HelpVerboseOnly::try_parse_from(normalize_args(args)) HelpVerboseOnly::try_parse_from(normalize_args(args))
{ {
eprintln!("NOTE: updating submodules before printing available paths"); println!("NOTE: updating submodules before printing available paths");
let config = Config::parse(Self::parse(&[String::from("build")])); let config = Config::parse(Self::parse(&[String::from("build")]));
let build = Build::new(config); let build = Build::new(config);
let paths = Builder::get_help(&build, subcommand); let paths = Builder::get_help(&build, subcommand);
if let Some(s) = paths { if let Some(s) = paths {
eprintln!("{s}"); println!("{s}");
} else { } else {
panic!("No paths available for subcommand `{}`", subcommand.as_str()); panic!("No paths available for subcommand `{}`", subcommand.as_str());
} }

View file

@ -77,7 +77,7 @@ impl Config {
if self.dry_run() && !cmd.run_always { if self.dry_run() && !cmd.run_always {
return true; return true;
} }
self.verbose(|| eprintln!("running: {cmd:?}")); self.verbose(|| println!("running: {cmd:?}"));
check_run(cmd, self.is_verbose()) check_run(cmd, self.is_verbose())
} }
@ -144,7 +144,7 @@ impl Config {
/// Please see <https://nixos.org/patchelf.html> for more information /// Please see <https://nixos.org/patchelf.html> for more information
fn fix_bin_or_dylib(&self, fname: &Path) { fn fix_bin_or_dylib(&self, fname: &Path) {
assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true)); assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
eprintln!("attempting to patch {}", fname.display()); println!("attempting to patch {}", fname.display());
// Only build `.nix-deps` once. // Only build `.nix-deps` once.
static NIX_DEPS_DIR: OnceLock<PathBuf> = OnceLock::new(); static NIX_DEPS_DIR: OnceLock<PathBuf> = OnceLock::new();
@ -206,7 +206,7 @@ impl Config {
} }
fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) { fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
self.verbose(|| eprintln!("download {url}")); self.verbose(|| println!("download {url}"));
// Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/. // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
let tempfile = self.tempdir().join(dest_path.file_name().unwrap()); let tempfile = self.tempdir().join(dest_path.file_name().unwrap());
// While bootstrap itself only supports http and https downloads, downstream forks might // While bootstrap itself only supports http and https downloads, downstream forks might
@ -226,7 +226,7 @@ impl Config {
} }
fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
eprintln!("downloading {url}"); println!("downloading {url}");
// Try curl. If that fails and we are on windows, fallback to PowerShell. // Try curl. If that fails and we are on windows, fallback to PowerShell.
// options should be kept in sync with // options should be kept in sync with
// src/bootstrap/src/core/download.rs // src/bootstrap/src/core/download.rs
@ -341,7 +341,7 @@ impl Config {
short_path = short_path.strip_prefix(pattern).unwrap_or(short_path); short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
let dst_path = dst.join(short_path); let dst_path = dst.join(short_path);
self.verbose(|| { self.verbose(|| {
eprintln!("extracting {} to {}", original_path.display(), dst.display()) println!("extracting {} to {}", original_path.display(), dst.display())
}); });
if !t!(member.unpack_in(dst)) { if !t!(member.unpack_in(dst)) {
panic!("path traversal attack ??"); panic!("path traversal attack ??");
@ -365,7 +365,7 @@ impl Config {
pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool { pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
use sha2::Digest; use sha2::Digest;
self.verbose(|| eprintln!("verifying {}", path.display())); self.verbose(|| println!("verifying {}", path.display()));
if self.dry_run() { if self.dry_run() {
return false; return false;
@ -391,7 +391,7 @@ impl Config {
let verified = checksum == expected; let verified = checksum == expected;
if !verified { if !verified {
eprintln!( println!(
"invalid checksum: \n\ "invalid checksum: \n\
found: {checksum}\n\ found: {checksum}\n\
expected: {expected}", expected: {expected}",
@ -421,7 +421,7 @@ enum DownloadSource {
/// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions. /// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
impl Config { impl Config {
pub(crate) fn download_clippy(&self) -> PathBuf { pub(crate) fn download_clippy(&self) -> PathBuf {
self.verbose(|| eprintln!("downloading stage0 clippy artifacts")); self.verbose(|| println!("downloading stage0 clippy artifacts"));
let date = &self.stage0_metadata.compiler.date; let date = &self.stage0_metadata.compiler.date;
let version = &self.stage0_metadata.compiler.version; let version = &self.stage0_metadata.compiler.version;
@ -518,7 +518,7 @@ impl Config {
} }
pub(crate) fn download_ci_rustc(&self, commit: &str) { pub(crate) fn download_ci_rustc(&self, commit: &str) {
self.verbose(|| eprintln!("using downloaded stage2 artifacts from CI (commit {commit})")); self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})"));
let version = self.artifact_version_part(commit); let version = self.artifact_version_part(commit);
// download-rustc doesn't need its own cargo, it can just use beta's. But it does need the // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
@ -539,7 +539,7 @@ impl Config {
#[cfg(not(feature = "bootstrap-self-test"))] #[cfg(not(feature = "bootstrap-self-test"))]
pub(crate) fn download_beta_toolchain(&self) { pub(crate) fn download_beta_toolchain(&self) {
self.verbose(|| eprintln!("downloading stage0 beta artifacts")); self.verbose(|| println!("downloading stage0 beta artifacts"));
let date = &self.stage0_metadata.compiler.date; let date = &self.stage0_metadata.compiler.date;
let version = &self.stage0_metadata.compiler.version; let version = &self.stage0_metadata.compiler.version;
@ -677,7 +677,7 @@ impl Config {
return; return;
} else { } else {
self.verbose(|| { self.verbose(|| {
eprintln!( println!(
"ignoring cached file {} due to failed verification", "ignoring cached file {} due to failed verification",
tarball.display() tarball.display()
) )
@ -776,10 +776,10 @@ download-rustc = false
t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml)); t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml));
} }
Err(e) if e.to_string().contains("unknown field") => { Err(e) if e.to_string().contains("unknown field") => {
eprintln!( println!(
"WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled." "WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled."
); );
eprintln!("HELP: Consider rebasing to a newer commit if available."); println!("HELP: Consider rebasing to a newer commit if available.");
} }
Err(e) => { Err(e) => {
eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}"); eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}");

View file

@ -237,11 +237,11 @@ than building it.
stage0_supported_target_list.intersection(&missing_targets_hashset).collect(); stage0_supported_target_list.intersection(&missing_targets_hashset).collect();
if !duplicated_targets.is_empty() { if !duplicated_targets.is_empty() {
eprintln!( println!(
"Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list." "Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list."
); );
for duplicated_target in duplicated_targets { for duplicated_target in duplicated_targets {
eprintln!(" {duplicated_target}"); println!(" {duplicated_target}");
} }
std::process::exit(1); std::process::exit(1);
} }

View file

@ -406,11 +406,11 @@ impl Build {
.unwrap() .unwrap()
.trim(); .trim();
if local_release.split('.').take(2).eq(version.split('.').take(2)) { if local_release.split('.').take(2).eq(version.split('.').take(2)) {
build.verbose(|| eprintln!("auto-detected local-rebuild {local_release}")); build.verbose(|| println!("auto-detected local-rebuild {local_release}"));
build.local_rebuild = true; build.local_rebuild = true;
} }
build.verbose(|| eprintln!("finding compilers")); build.verbose(|| println!("finding compilers"));
utils::cc_detect::find(&build); utils::cc_detect::find(&build);
// When running `setup`, the profile is about to change, so any requirements we have now may // When running `setup`, the profile is about to change, so any requirements we have now may
// be different on the next invocation. Don't check for them until the next time x.py is // be different on the next invocation. Don't check for them until the next time x.py is
@ -418,7 +418,7 @@ impl Build {
// //
// Similarly, for `setup` we don't actually need submodules or cargo metadata. // Similarly, for `setup` we don't actually need submodules or cargo metadata.
if !matches!(build.config.cmd, Subcommand::Setup { .. }) { if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
build.verbose(|| eprintln!("running sanity check")); build.verbose(|| println!("running sanity check"));
crate::core::sanity::check(&mut build); crate::core::sanity::check(&mut build);
// Make sure we update these before gathering metadata so we don't get an error about missing // Make sure we update these before gathering metadata so we don't get an error about missing
@ -436,7 +436,7 @@ impl Build {
// Now, update all existing submodules. // Now, update all existing submodules.
build.update_existing_submodules(); build.update_existing_submodules();
build.verbose(|| eprintln!("learning about cargo")); build.verbose(|| println!("learning about cargo"));
crate::core::metadata::build(&mut build); crate::core::metadata::build(&mut build);
} }
@ -605,7 +605,7 @@ impl Build {
let stamp = dir.join(".stamp"); let stamp = dir.join(".stamp");
let mut cleared = false; let mut cleared = false;
if mtime(&stamp) < mtime(input) { if mtime(&stamp) < mtime(input) {
self.verbose(|| eprintln!("Dirty - {}", dir.display())); self.verbose(|| println!("Dirty - {}", dir.display()));
let _ = fs::remove_dir_all(dir); let _ = fs::remove_dir_all(dir);
cleared = true; cleared = true;
} else if stamp.exists() { } else if stamp.exists() {
@ -890,7 +890,7 @@ impl Build {
let executed_at = std::panic::Location::caller(); let executed_at = std::panic::Location::caller();
self.verbose(|| { self.verbose(|| {
eprintln!("running: {command:?} (created at {created_at}, executed at {executed_at})") println!("running: {command:?} (created at {created_at}, executed at {executed_at})")
}); });
let cmd = command.as_command_mut(); let cmd = command.as_command_mut();
@ -947,7 +947,7 @@ Executed at: {executed_at}"#,
let fail = |message: &str, output: CommandOutput| -> ! { let fail = |message: &str, output: CommandOutput| -> ! {
if self.is_verbose() { if self.is_verbose() {
eprintln!("{message}"); println!("{message}");
} else { } else {
let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present()); let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present());
// If the command captures output, the user would not see any indication that // If the command captures output, the user would not see any indication that
@ -957,16 +957,16 @@ Executed at: {executed_at}"#,
if let Some(stdout) = if let Some(stdout) =
output.stdout_if_present().take_if(|s| !s.trim().is_empty()) output.stdout_if_present().take_if(|s| !s.trim().is_empty())
{ {
eprintln!("STDOUT:\n{stdout}\n"); println!("STDOUT:\n{stdout}\n");
} }
if let Some(stderr) = if let Some(stderr) =
output.stderr_if_present().take_if(|s| !s.trim().is_empty()) output.stderr_if_present().take_if(|s| !s.trim().is_empty())
{ {
eprintln!("STDERR:\n{stderr}\n"); println!("STDERR:\n{stderr}\n");
} }
eprintln!("Command {command:?} has failed. Rerun with -v to see more details."); println!("Command {command:?} has failed. Rerun with -v to see more details.");
} else { } else {
eprintln!("Command has failed. Rerun with -v to see more details."); println!("Command has failed. Rerun with -v to see more details.");
} }
} }
exit!(1); exit!(1);
@ -1011,7 +1011,7 @@ Executed at: {executed_at}"#,
match self.config.dry_run { match self.config.dry_run {
DryRun::SelfCheck => (), DryRun::SelfCheck => (),
DryRun::Disabled | DryRun::UserSelected => { DryRun::Disabled | DryRun::UserSelected => {
eprintln!("{msg}"); println!("{msg}");
} }
} }
} }
@ -1666,7 +1666,7 @@ Executed at: {executed_at}"#,
if self.config.dry_run() { if self.config.dry_run() {
return; return;
} }
self.verbose_than(1, || eprintln!("Copy/Link {src:?} to {dst:?}")); self.verbose_than(1, || println!("Copy/Link {src:?} to {dst:?}"));
if src == dst { if src == dst {
return; return;
} }
@ -1775,7 +1775,7 @@ Executed at: {executed_at}"#,
return; return;
} }
let dst = dstdir.join(src.file_name().unwrap()); let dst = dstdir.join(src.file_name().unwrap());
self.verbose_than(1, || eprintln!("Install {src:?} to {dst:?}")); self.verbose_than(1, || println!("Install {src:?} to {dst:?}"));
t!(fs::create_dir_all(dstdir)); t!(fs::create_dir_all(dstdir));
if !src.exists() { if !src.exists() {
panic!("ERROR: File \"{}\" not found!", src.display()); panic!("ERROR: File \"{}\" not found!", src.display());

View file

@ -155,15 +155,15 @@ pub fn find_target(build: &Build, target: TargetSelection) {
build.cxx.borrow_mut().insert(target, compiler); build.cxx.borrow_mut().insert(target, compiler);
} }
build.verbose(|| eprintln!("CC_{} = {:?}", target.triple, build.cc(target))); build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target)));
build.verbose(|| eprintln!("CFLAGS_{} = {cflags:?}", target.triple)); build.verbose(|| println!("CFLAGS_{} = {cflags:?}", target.triple));
if let Ok(cxx) = build.cxx(target) { if let Ok(cxx) = build.cxx(target) {
let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx); let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
build.verbose(|| eprintln!("CXX_{} = {cxx:?}", target.triple)); build.verbose(|| println!("CXX_{} = {cxx:?}", target.triple));
build.verbose(|| eprintln!("CXXFLAGS_{} = {cxxflags:?}", target.triple)); build.verbose(|| println!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
} }
if let Some(ar) = ar { if let Some(ar) = ar {
build.verbose(|| eprintln!("AR_{} = {ar:?}", target.triple)); build.verbose(|| println!("AR_{} = {ar:?}", target.triple));
build.ar.borrow_mut().insert(target, ar); build.ar.borrow_mut().insert(target, ar);
} }

View file

@ -135,7 +135,7 @@ impl Drop for TimeIt {
fn drop(&mut self) { fn drop(&mut self) {
let time = self.1.elapsed(); let time = self.1.elapsed();
if !self.0 { if !self.0 {
eprintln!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis()); println!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
} }
} }
} }
@ -267,12 +267,12 @@ pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool {
let status = match cmd.as_command_mut().status() { let status = match cmd.as_command_mut().status() {
Ok(status) => status, Ok(status) => status,
Err(e) => { Err(e) => {
eprintln!("failed to execute command: {cmd:?}\nERROR: {e}"); println!("failed to execute command: {cmd:?}\nERROR: {e}");
return false; return false;
} }
}; };
if !status.success() && print_cmd_on_fail { if !status.success() && print_cmd_on_fail {
eprintln!( println!(
"\n\ncommand did not execute successfully: {cmd:?}\n\ "\n\ncommand did not execute successfully: {cmd:?}\n\
expected success, got: {status}\n\n" expected success, got: {status}\n\n"
); );

View file

@ -185,7 +185,7 @@ impl BuildMetrics {
if version.format_version == CURRENT_FORMAT_VERSION { if version.format_version == CURRENT_FORMAT_VERSION {
t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations
} else { } else {
eprintln!( println!(
"WARNING: overriding existing build/metrics.json, as it's not \ "WARNING: overriding existing build/metrics.json, as it's not \
compatible with build metrics format version {CURRENT_FORMAT_VERSION}." compatible with build metrics format version {CURRENT_FORMAT_VERSION}."
); );

View file

@ -56,7 +56,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
let cmd = cmd.as_command_mut(); let cmd = cmd.as_command_mut();
cmd.stdout(Stdio::piped()); cmd.stdout(Stdio::piped());
builder.verbose(|| eprintln!("running: {cmd:?}")); builder.verbose(|| println!("running: {cmd:?}"));
let mut process = cmd.spawn().unwrap(); let mut process = cmd.spawn().unwrap();
@ -71,7 +71,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
let result = process.wait_with_output().unwrap(); let result = process.wait_with_output().unwrap();
if !result.status.success() && builder.is_verbose() { if !result.status.success() && builder.is_verbose() {
eprintln!( println!(
"\n\ncommand did not execute successfully: {cmd:?}\n\ "\n\ncommand did not execute successfully: {cmd:?}\n\
expected success, got: {}", expected success, got: {}",
result.status result.status
@ -135,9 +135,7 @@ impl<'a> Renderer<'a> {
if self.up_to_date_tests > 0 { if self.up_to_date_tests > 0 {
let n = self.up_to_date_tests; let n = self.up_to_date_tests;
let s = if n > 1 { "s" } else { "" }; let s = if n > 1 { "s" } else { "" };
eprintln!( println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n");
"help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n"
);
} }
} }
@ -192,7 +190,7 @@ impl<'a> Renderer<'a> {
if let Some(exec_time) = test.exec_time { if let Some(exec_time) = test.exec_time {
print!(" ({exec_time:.2?})"); print!(" ({exec_time:.2?})");
} }
eprintln!(); println!();
} }
fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, test: &TestOutcome) { fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, test: &TestOutcome) {
@ -202,7 +200,7 @@ impl<'a> Renderer<'a> {
let executed = format!("{:>width$}", self.executed_tests - 1, width = total.len()); let executed = format!("{:>width$}", self.executed_tests - 1, width = total.len());
print!(" {executed}/{total}"); print!(" {executed}/{total}");
} }
eprintln!(); println!();
self.terse_tests_in_line = 0; self.terse_tests_in_line = 0;
} }
@ -214,31 +212,31 @@ impl<'a> Renderer<'a> {
fn render_suite_outcome(&self, outcome: Outcome<'_>, suite: &SuiteOutcome) { fn render_suite_outcome(&self, outcome: Outcome<'_>, suite: &SuiteOutcome) {
// The terse output doesn't end with a newline, so we need to add it ourselves. // The terse output doesn't end with a newline, so we need to add it ourselves.
if !self.builder.config.verbose_tests { if !self.builder.config.verbose_tests {
eprintln!(); println!();
} }
if !self.failures.is_empty() { if !self.failures.is_empty() {
eprintln!("\nfailures:\n"); println!("\nfailures:\n");
for failure in &self.failures { for failure in &self.failures {
if failure.stdout.is_some() || failure.message.is_some() { if failure.stdout.is_some() || failure.message.is_some() {
eprintln!("---- {} stdout ----", failure.name); println!("---- {} stdout ----", failure.name);
if let Some(stdout) = &failure.stdout { if let Some(stdout) = &failure.stdout {
eprintln!("{stdout}"); println!("{stdout}");
} }
if let Some(message) = &failure.message { if let Some(message) = &failure.message {
eprintln!("NOTE: {message}"); println!("NOTE: {message}");
} }
} }
} }
eprintln!("\nfailures:"); println!("\nfailures:");
for failure in &self.failures { for failure in &self.failures {
eprintln!(" {}", failure.name); println!(" {}", failure.name);
} }
} }
if !self.benches.is_empty() { if !self.benches.is_empty() {
eprintln!("\nbenchmarks:"); println!("\nbenchmarks:");
let mut rows = Vec::new(); let mut rows = Vec::new();
for bench in &self.benches { for bench in &self.benches {
@ -253,13 +251,13 @@ impl<'a> Renderer<'a> {
let max_1 = rows.iter().map(|r| r.1.len()).max().unwrap_or(0); let max_1 = rows.iter().map(|r| r.1.len()).max().unwrap_or(0);
let max_2 = rows.iter().map(|r| r.2.len()).max().unwrap_or(0); let max_2 = rows.iter().map(|r| r.2.len()).max().unwrap_or(0);
for row in &rows { for row in &rows {
eprintln!(" {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2); println!(" {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
} }
} }
print!("\ntest result: "); print!("\ntest result: ");
self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap(); self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
eprintln!( println!(
". {} passed; {} failed; {} ignored; {} measured; {} filtered out{time}\n", ". {} passed; {} failed; {} ignored; {} measured; {} filtered out{time}\n",
suite.passed, suite.passed,
suite.failed, suite.failed,
@ -276,7 +274,7 @@ impl<'a> Renderer<'a> {
fn render_message(&mut self, message: Message) { fn render_message(&mut self, message: Message) {
match message { match message {
Message::Suite(SuiteMessage::Started { test_count }) => { Message::Suite(SuiteMessage::Started { test_count }) => {
eprintln!("\nrunning {test_count} tests"); println!("\nrunning {test_count} tests");
self.executed_tests = 0; self.executed_tests = 0;
self.terse_tests_in_line = 0; self.terse_tests_in_line = 0;
self.tests_count = Some(test_count); self.tests_count = Some(test_count);
@ -316,7 +314,7 @@ impl<'a> Renderer<'a> {
self.failures.push(outcome); self.failures.push(outcome);
} }
Message::Test(TestMessage::Timeout { name }) => { Message::Test(TestMessage::Timeout { name }) => {
eprintln!("test {name} has been running for a long time"); println!("test {name} has been running for a long time");
} }
Message::Test(TestMessage::Started) => {} // Not useful Message::Test(TestMessage::Started) => {} // Not useful
} }

View file

@ -344,7 +344,7 @@ impl<'a> Tarball<'a> {
// For `x install` tarball files aren't needed, so we can speed up the process by not producing them. // For `x install` tarball files aren't needed, so we can speed up the process by not producing them.
let compression_profile = if self.builder.kind == Kind::Install { let compression_profile = if self.builder.kind == Kind::Install {
self.builder.verbose(|| { self.builder.verbose(|| {
eprintln!("Forcing dist.compression-profile = 'no-op' for `x install`.") println!("Forcing dist.compression-profile = 'no-op' for `x install`.")
}); });
// "no-op" indicates that the rust-installer won't produce compressed tarball sources. // "no-op" indicates that the rust-installer won't produce compressed tarball sources.
"no-op" "no-op"

@ -1 +1 @@
Subproject commit e16dd73690a6cc3ecdc5f5d94bbc3ce158a42e16 Subproject commit 614c19cb4025636eb2ba68ebb3d44e3bd3a5e6e4

@ -1 +1 @@
Subproject commit f48b0e842a3911c63240e955d042089e9e0894c7 Subproject commit 128669297c8a7fdf771042eaec18b8adfaeaf0cd

@ -1 +1 @@
Subproject commit 5c86c739ec71b8bc839310ff47fa94e94635bba9 Subproject commit ede56d1bbe132bac476b5029cd6d7508ca9572e9

@ -1 +1 @@
Subproject commit 787b4166ccc67bd8f72a6e3ef6685ce9ce82909a Subproject commit b21d99b770f9aceb0810c843847c52f86f45d2ed

View file

@ -744,7 +744,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::unit_types::LET_UNIT_VALUE_INFO, crate::unit_types::LET_UNIT_VALUE_INFO,
crate::unit_types::UNIT_ARG_INFO, crate::unit_types::UNIT_ARG_INFO,
crate::unit_types::UNIT_CMP_INFO, crate::unit_types::UNIT_CMP_INFO,
crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO, crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO, crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO,
crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO, crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO,

View file

@ -74,6 +74,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
#[clippy::version = "1.53.0"] #[clippy::version = "1.53.0"]
("clippy::filter_map", "clippy::manual_filter_map"), ("clippy::filter_map", "clippy::manual_filter_map"),
#[clippy::version = ""] #[clippy::version = ""]
("clippy::fn_address_comparisons", "unpredictable_function_pointer_comparisons"),
#[clippy::version = ""]
("clippy::identity_conversion", "clippy::useless_conversion"), ("clippy::identity_conversion", "clippy::useless_conversion"),
#[clippy::version = "pre 1.29.0"] #[clippy::version = "pre 1.29.0"]
("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"), ("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"),

View file

@ -363,7 +363,6 @@ mod uninhabited_references;
mod uninit_vec; mod uninit_vec;
mod unit_return_expecting_ord; mod unit_return_expecting_ord;
mod unit_types; mod unit_types;
mod unnamed_address;
mod unnecessary_box_returns; mod unnecessary_box_returns;
mod unnecessary_literal_bound; mod unnecessary_literal_bound;
mod unnecessary_map_on_constructor; mod unnecessary_map_on_constructor;
@ -786,7 +785,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap)); store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf))); store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf)));
store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default()); store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default()); store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default());
store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));

View file

@ -1,60 +0,0 @@
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
declare_clippy_lint! {
/// ### What it does
/// Checks for comparisons with an address of a function item.
///
/// ### Why is this bad?
/// Function item address is not guaranteed to be unique and could vary
/// between different code generation units. Furthermore different function items could have
/// the same address after being merged together.
///
/// ### Example
/// ```no_run
/// type F = fn();
/// fn a() {}
/// let f: F = a;
/// if f == a {
/// // ...
/// }
/// ```
#[clippy::version = "1.44.0"]
pub FN_ADDRESS_COMPARISONS,
correctness,
"comparison with an address of a function item"
}
declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]);
impl LateLintPass<'_> for UnnamedAddress {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
fn is_comparison(binop: BinOpKind) -> bool {
matches!(
binop,
BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt
)
}
fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
}
if let ExprKind::Binary(binop, left, right) = expr.kind
&& is_comparison(binop.node)
&& cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr()
&& cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr()
&& (is_fn_def(cx, left) || is_fn_def(cx, right))
{
span_lint(
cx,
FN_ADDRESS_COMPARISONS,
expr.span,
"comparing with a non-unique address of a function item",
);
}
}
}

View file

@ -1,23 +0,0 @@
use std::fmt::Debug;
use std::ptr;
use std::rc::Rc;
use std::sync::Arc;
fn a() {}
#[warn(clippy::fn_address_comparisons)]
fn main() {
type F = fn();
let f: F = a;
let g: F = f;
// These should fail:
let _ = f == a;
//~^ ERROR: comparing with a non-unique address of a function item
//~| NOTE: `-D clippy::fn-address-comparisons` implied by `-D warnings`
let _ = f != a;
//~^ ERROR: comparing with a non-unique address of a function item
// These should be fine:
let _ = f == g;
}

View file

@ -1,17 +0,0 @@
error: comparing with a non-unique address of a function item
--> tests/ui/fn_address_comparisons.rs:15:13
|
LL | let _ = f == a;
| ^^^^^^
|
= note: `-D clippy::fn-address-comparisons` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::fn_address_comparisons)]`
error: comparing with a non-unique address of a function item
--> tests/ui/fn_address_comparisons.rs:18:13
|
LL | let _ = f != a;
| ^^^^^^
error: aborting due to 2 previous errors

View file

@ -59,6 +59,7 @@
#![allow(unknown_lints)] #![allow(unknown_lints)]
#![allow(unused_labels)] #![allow(unused_labels)]
#![allow(ambiguous_wide_pointer_comparisons)] #![allow(ambiguous_wide_pointer_comparisons)]
#![allow(unpredictable_function_pointer_comparisons)]
#![allow(clippy::reversed_empty_ranges)] #![allow(clippy::reversed_empty_ranges)]
#![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range` #![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
#![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name` #![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name`
@ -74,6 +75,7 @@
#![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence` #![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_find_map)] //~ ERROR: lint `clippy::find_map`
#![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map` #![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map`
#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
#![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion` #![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion`
#![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching` #![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` #![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result`

View file

@ -59,6 +59,7 @@
#![allow(unknown_lints)] #![allow(unknown_lints)]
#![allow(unused_labels)] #![allow(unused_labels)]
#![allow(ambiguous_wide_pointer_comparisons)] #![allow(ambiguous_wide_pointer_comparisons)]
#![allow(unpredictable_function_pointer_comparisons)]
#![allow(clippy::reversed_empty_ranges)] #![allow(clippy::reversed_empty_ranges)]
#![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range` #![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
#![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name` #![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name`
@ -74,6 +75,7 @@
#![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence` #![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence`
#![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map`
#![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map` #![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map`
#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
#![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion` #![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_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
#![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result` #![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result`

View file

@ -1,5 +1,5 @@
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
--> tests/ui/rename.rs:63:9 --> tests/ui/rename.rs:64:9
| |
LL | #![warn(clippy::almost_complete_letter_range)] LL | #![warn(clippy::almost_complete_letter_range)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@ -8,394 +8,400 @@ LL | #![warn(clippy::almost_complete_letter_range)]
= help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]` = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
--> tests/ui/rename.rs:64:9 --> tests/ui/rename.rs:65:9
| |
LL | #![warn(clippy::blacklisted_name)] LL | #![warn(clippy::blacklisted_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions`
--> tests/ui/rename.rs:65:9 --> tests/ui/rename.rs:66:9
| |
LL | #![warn(clippy::block_in_if_condition_expr)] LL | #![warn(clippy::block_in_if_condition_expr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions`
--> tests/ui/rename.rs:66:9 --> tests/ui/rename.rs:67:9
| |
LL | #![warn(clippy::block_in_if_condition_stmt)] LL | #![warn(clippy::block_in_if_condition_stmt)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions` error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions`
--> tests/ui/rename.rs:67:9 --> tests/ui/rename.rs:68:9
| |
LL | #![warn(clippy::blocks_in_if_conditions)] LL | #![warn(clippy::blocks_in_if_conditions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
--> tests/ui/rename.rs:68:9 --> tests/ui/rename.rs:69:9
| |
LL | #![warn(clippy::box_vec)] LL | #![warn(clippy::box_vec)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
--> tests/ui/rename.rs:69:9 --> tests/ui/rename.rs:70:9
| |
LL | #![warn(clippy::const_static_lifetime)] LL | #![warn(clippy::const_static_lifetime)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
--> tests/ui/rename.rs:70:9 --> tests/ui/rename.rs:71:9
| |
LL | #![warn(clippy::cyclomatic_complexity)] LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
--> tests/ui/rename.rs:71:9 --> tests/ui/rename.rs:72:9
| |
LL | #![warn(clippy::derive_hash_xor_eq)] LL | #![warn(clippy::derive_hash_xor_eq)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
--> tests/ui/rename.rs:72:9 --> tests/ui/rename.rs:73:9
| |
LL | #![warn(clippy::disallowed_method)] LL | #![warn(clippy::disallowed_method)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
--> tests/ui/rename.rs:73:9 --> tests/ui/rename.rs:74:9
| |
LL | #![warn(clippy::disallowed_type)] LL | #![warn(clippy::disallowed_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
--> tests/ui/rename.rs:74:9 --> tests/ui/rename.rs:75:9
| |
LL | #![warn(clippy::eval_order_dependence)] LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map` error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
--> tests/ui/rename.rs:75:9 --> tests/ui/rename.rs:76:9
| |
LL | #![warn(clippy::find_map)] LL | #![warn(clippy::find_map)]
| ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map` | ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map` error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map`
--> tests/ui/rename.rs:76:9 --> tests/ui/rename.rs:77:9
| |
LL | #![warn(clippy::filter_map)] LL | #![warn(clippy::filter_map)]
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_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:78:9
|
LL | #![warn(clippy::fn_address_comparisons)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons`
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
--> tests/ui/rename.rs:77:9 --> tests/ui/rename.rs:79:9
| |
LL | #![warn(clippy::identity_conversion)] LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_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` error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching`
--> tests/ui/rename.rs:78:9 --> tests/ui/rename.rs:80:9
| |
LL | #![warn(clippy::if_let_redundant_pattern_matching)] LL | #![warn(clippy::if_let_redundant_pattern_matching)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::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` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
--> tests/ui/rename.rs:79:9 --> tests/ui/rename.rs:81:9
| |
LL | #![warn(clippy::if_let_some_result)] LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
--> tests/ui/rename.rs:80:9 --> tests/ui/rename.rs:82:9
| |
LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)] LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
--> tests/ui/rename.rs:81:9 --> tests/ui/rename.rs:83:9
| |
LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)] LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
--> tests/ui/rename.rs:82:9 --> tests/ui/rename.rs:84:9
| |
LL | #![warn(clippy::integer_arithmetic)] LL | #![warn(clippy::integer_arithmetic)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
--> tests/ui/rename.rs:83:9 --> tests/ui/rename.rs:85:9
| |
LL | #![warn(clippy::logic_bug)] LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` | ^^^^^^^^^^^^^^^^^ 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` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
--> tests/ui/rename.rs:84:9 --> tests/ui/rename.rs:86:9
| |
LL | #![warn(clippy::new_without_default_derive)] LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
--> tests/ui/rename.rs:85:9 --> tests/ui/rename.rs:87:9
| |
LL | #![warn(clippy::option_and_then_some)] LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
--> tests/ui/rename.rs:86:9 --> tests/ui/rename.rs:88:9
| |
LL | #![warn(clippy::option_expect_used)] LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::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` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
--> tests/ui/rename.rs:87:9 --> tests/ui/rename.rs:89:9
| |
LL | #![warn(clippy::option_map_unwrap_or)] LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::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` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
--> tests/ui/rename.rs:88:9 --> tests/ui/rename.rs:90:9
| |
LL | #![warn(clippy::option_map_unwrap_or_else)] LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
--> tests/ui/rename.rs:89:9 --> tests/ui/rename.rs:91:9
| |
LL | #![warn(clippy::option_unwrap_used)] LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks` error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks`
--> tests/ui/rename.rs:90:9 --> tests/ui/rename.rs:92:9
| |
LL | #![warn(clippy::overflow_check_conditional)] LL | #![warn(clippy::overflow_check_conditional)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
--> tests/ui/rename.rs:91:9 --> tests/ui/rename.rs:93:9
| |
LL | #![warn(clippy::ref_in_deref)] LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
--> tests/ui/rename.rs:92:9 --> tests/ui/rename.rs:94:9
| |
LL | #![warn(clippy::result_expect_used)] LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::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` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
--> tests/ui/rename.rs:93:9 --> tests/ui/rename.rs:95:9
| |
LL | #![warn(clippy::result_map_unwrap_or_else)] LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
--> tests/ui/rename.rs:94:9 --> tests/ui/rename.rs:96:9
| |
LL | #![warn(clippy::result_unwrap_used)] LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
--> tests/ui/rename.rs:95:9 --> tests/ui/rename.rs:97:9
| |
LL | #![warn(clippy::single_char_push_str)] LL | #![warn(clippy::single_char_push_str)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
--> tests/ui/rename.rs:96:9 --> tests/ui/rename.rs:98:9
| |
LL | #![warn(clippy::stutter)] LL | #![warn(clippy::stutter)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local` error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local`
--> tests/ui/rename.rs:97:9 --> tests/ui/rename.rs:99:9
| |
LL | #![warn(clippy::thread_local_initializer_can_be_made_const)] LL | #![warn(clippy::thread_local_initializer_can_be_made_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local`
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
--> tests/ui/rename.rs:98:9 --> tests/ui/rename.rs:100:9
| |
LL | #![warn(clippy::to_string_in_display)] LL | #![warn(clippy::to_string_in_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default` error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
--> tests/ui/rename.rs:99:9 --> tests/ui/rename.rs:101:9
| |
LL | #![warn(clippy::unwrap_or_else_default)] LL | #![warn(clippy::unwrap_or_else_default)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
--> tests/ui/rename.rs:100:9 --> tests/ui/rename.rs:102:9
| |
LL | #![warn(clippy::zero_width_space)] LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting` error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
--> tests/ui/rename.rs:101:9 --> tests/ui/rename.rs:103:9
| |
LL | #![warn(clippy::cast_ref_to_mut)] LL | #![warn(clippy::cast_ref_to_mut)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting` | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
--> tests/ui/rename.rs:102:9 --> tests/ui/rename.rs:104:9
| |
LL | #![warn(clippy::clone_double_ref)] LL | #![warn(clippy::clone_double_ref)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
--> tests/ui/rename.rs:103:9 --> tests/ui/rename.rs:105:9
| |
LL | #![warn(clippy::cmp_nan)] LL | #![warn(clippy::cmp_nan)]
| ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
--> tests/ui/rename.rs:104:9 --> tests/ui/rename.rs:106:9
| |
LL | #![warn(clippy::drop_bounds)] LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
--> tests/ui/rename.rs:105:9 --> tests/ui/rename.rs:107:9
| |
LL | #![warn(clippy::drop_copy)] LL | #![warn(clippy::drop_copy)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
error: lint `clippy::drop_ref` has been renamed to `dropping_references` error: lint `clippy::drop_ref` has been renamed to `dropping_references`
--> tests/ui/rename.rs:106:9 --> tests/ui/rename.rs:108:9
| |
LL | #![warn(clippy::drop_ref)] LL | #![warn(clippy::drop_ref)]
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks` error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
--> tests/ui/rename.rs:107:9 --> tests/ui/rename.rs:109:9
| |
LL | #![warn(clippy::fn_null_check)] LL | #![warn(clippy::fn_null_check)]
| ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks` | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
--> tests/ui/rename.rs:108:9 --> tests/ui/rename.rs:110:9
| |
LL | #![warn(clippy::for_loop_over_option)] LL | #![warn(clippy::for_loop_over_option)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
--> tests/ui/rename.rs:109:9 --> tests/ui/rename.rs:111:9
| |
LL | #![warn(clippy::for_loop_over_result)] LL | #![warn(clippy::for_loop_over_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
--> tests/ui/rename.rs:110:9 --> tests/ui/rename.rs:112:9
| |
LL | #![warn(clippy::for_loops_over_fallibles)] LL | #![warn(clippy::for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `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` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
--> tests/ui/rename.rs:111:9 --> tests/ui/rename.rs:113:9
| |
LL | #![warn(clippy::forget_copy)] LL | #![warn(clippy::forget_copy)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
error: lint `clippy::forget_ref` has been renamed to `forgetting_references` error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
--> tests/ui/rename.rs:112:9 --> tests/ui/rename.rs:114:9
| |
LL | #![warn(clippy::forget_ref)] LL | #![warn(clippy::forget_ref)]
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
--> tests/ui/rename.rs:113:9 --> tests/ui/rename.rs:115:9
| |
LL | #![warn(clippy::into_iter_on_array)] LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
--> tests/ui/rename.rs:114:9 --> tests/ui/rename.rs:116:9
| |
LL | #![warn(clippy::invalid_atomic_ordering)] LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value` error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
--> tests/ui/rename.rs:115:9 --> tests/ui/rename.rs:117:9
| |
LL | #![warn(clippy::invalid_ref)] LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
--> tests/ui/rename.rs:116:9 --> tests/ui/rename.rs:118:9
| |
LL | #![warn(clippy::invalid_utf8_in_unchecked)] LL | #![warn(clippy::invalid_utf8_in_unchecked)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
--> tests/ui/rename.rs:117:9 --> tests/ui/rename.rs:119:9
| |
LL | #![warn(clippy::let_underscore_drop)] LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs` error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs`
--> tests/ui/rename.rs:118:9 --> tests/ui/rename.rs:120:9
| |
LL | #![warn(clippy::maybe_misused_cfg)] LL | #![warn(clippy::maybe_misused_cfg)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
--> tests/ui/rename.rs:119:9 --> tests/ui/rename.rs:121:9
| |
LL | #![warn(clippy::mem_discriminant_non_enum)] LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs` error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs`
--> tests/ui/rename.rs:120:9 --> tests/ui/rename.rs:122:9
| |
LL | #![warn(clippy::mismatched_target_os)] LL | #![warn(clippy::mismatched_target_os)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
--> tests/ui/rename.rs:121:9 --> tests/ui/rename.rs:123:9
| |
LL | #![warn(clippy::panic_params)] LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
--> tests/ui/rename.rs:122:9 --> tests/ui/rename.rs:124:9
| |
LL | #![warn(clippy::positional_named_format_parameters)] LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
--> tests/ui/rename.rs:123:9 --> tests/ui/rename.rs:125:9
| |
LL | #![warn(clippy::temporary_cstring_as_ptr)] LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
--> tests/ui/rename.rs:124:9 --> tests/ui/rename.rs:126:9
| |
LL | #![warn(clippy::undropped_manually_drops)] LL | #![warn(clippy::undropped_manually_drops)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
--> tests/ui/rename.rs:125:9 --> tests/ui/rename.rs:127:9
| |
LL | #![warn(clippy::unknown_clippy_lints)] LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels` error: lint `clippy::unused_label` has been renamed to `unused_labels`
--> tests/ui/rename.rs:126:9 --> tests/ui/rename.rs:128:9
| |
LL | #![warn(clippy::unused_label)] LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons` error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
--> tests/ui/rename.rs:127:9 --> tests/ui/rename.rs:129:9
| |
LL | #![warn(clippy::vtable_address_comparisons)] LL | #![warn(clippy::vtable_address_comparisons)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges` error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
--> tests/ui/rename.rs:128:9 --> tests/ui/rename.rs:130:9
| |
LL | #![warn(clippy::reverse_range_loop)] LL | #![warn(clippy::reverse_range_loop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
error: aborting due to 66 previous errors error: aborting due to 67 previous errors

View file

@ -144,7 +144,7 @@ where
} }
if !wrote_data { if !wrote_data {
eprintln!("note: diff is identical to nightly rustdoc"); println!("note: diff is identical to nightly rustdoc");
assert!(diff_output.metadata().unwrap().len() == 0); assert!(diff_output.metadata().unwrap().len() == 0);
return false; return false;
} else if verbose { } else if verbose {

View file

@ -20,7 +20,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
} }
if config.remote_test_client.is_some() && !config.target.contains("android") { if config.remote_test_client.is_some() && !config.target.contains("android") {
eprintln!( println!(
"WARNING: debuginfo tests are not available when \ "WARNING: debuginfo tests are not available when \
testing with remote" testing with remote"
); );
@ -28,7 +28,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
} }
if config.target.contains("android") { if config.target.contains("android") {
eprintln!( println!(
"{} debug-info test uses tcp 5039 port.\ "{} debug-info test uses tcp 5039 port.\
please reserve it", please reserve it",
config.target config.target
@ -50,7 +50,7 @@ pub(crate) fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
config.lldb_python_dir.as_ref()?; config.lldb_python_dir.as_ref()?;
if let Some(350) = config.lldb_version { if let Some(350) = config.lldb_version {
eprintln!( println!(
"WARNING: The used version of LLDB (350) has a \ "WARNING: The used version of LLDB (350) has a \
known issue that breaks debuginfo tests. See \ known issue that breaks debuginfo tests. See \
issue #32520 for more information. Skipping all \ issue #32520 for more information. Skipping all \

View file

@ -188,8 +188,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
let (argv0, args_) = args.split_first().unwrap(); let (argv0, args_) = args.split_first().unwrap();
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
eprintln!("{}", opts.usage(&message)); println!("{}", opts.usage(&message));
eprintln!(); println!();
panic!() panic!()
} }
@ -200,8 +200,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
if matches.opt_present("h") || matches.opt_present("help") { if matches.opt_present("h") || matches.opt_present("help") {
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
eprintln!("{}", opts.usage(&message)); println!("{}", opts.usage(&message));
eprintln!(); println!();
panic!() panic!()
} }
@ -501,7 +501,7 @@ pub fn run_tests(config: Arc<Config>) {
// easy to miss which tests failed, and as such fail to reproduce // easy to miss which tests failed, and as such fail to reproduce
// the failure locally. // the failure locally.
eprintln!( println!(
"Some tests failed in compiletest suite={}{} mode={} host={} target={}", "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
config.suite, config.suite,
config config

View file

@ -774,20 +774,20 @@ impl<'test> TestCx<'test> {
unexpected.len(), unexpected.len(),
not_found.len() not_found.len()
)); ));
eprintln!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline); println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
if !unexpected.is_empty() { if !unexpected.is_empty() {
eprintln!("{}", "--- unexpected errors (from JSON output) ---".green()); println!("{}", "--- unexpected errors (from JSON output) ---".green());
for error in &unexpected { for error in &unexpected {
eprintln!("{}", error.render_for_expected()); println!("{}", error.render_for_expected());
} }
eprintln!("{}", "---".green()); println!("{}", "---".green());
} }
if !not_found.is_empty() { if !not_found.is_empty() {
eprintln!("{}", "--- not found errors (from test file) ---".red()); println!("{}", "--- not found errors (from test file) ---".red());
for error in &not_found { for error in &not_found {
eprintln!("{}", error.render_for_expected()); println!("{}", error.render_for_expected());
} }
eprintln!("{}", "---\n".red()); println!("{}", "---\n".red());
} }
panic!("errors differ from expected"); panic!("errors differ from expected");
} }
@ -1876,18 +1876,18 @@ impl<'test> TestCx<'test> {
fn maybe_dump_to_stdout(&self, out: &str, err: &str) { fn maybe_dump_to_stdout(&self, out: &str, err: &str) {
if self.config.verbose { if self.config.verbose {
eprintln!("------stdout------------------------------"); println!("------stdout------------------------------");
eprintln!("{}", out); println!("{}", out);
eprintln!("------stderr------------------------------"); println!("------stderr------------------------------");
eprintln!("{}", err); println!("{}", err);
eprintln!("------------------------------------------"); println!("------------------------------------------");
} }
} }
fn error(&self, err: &str) { fn error(&self, err: &str) {
match self.revision { match self.revision {
Some(rev) => eprintln!("\nerror in revision `{}`: {}", rev, err), Some(rev) => println!("\nerror in revision `{}`: {}", rev, err),
None => eprintln!("\nerror: {}", err), None => println!("\nerror: {}", err),
} }
} }
@ -1972,7 +1972,7 @@ impl<'test> TestCx<'test> {
if !self.config.has_html_tidy { if !self.config.has_html_tidy {
return; return;
} }
eprintln!("info: generating a diff against nightly rustdoc"); println!("info: generating a diff against nightly rustdoc");
let suffix = let suffix =
self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly"); self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly");
@ -2082,7 +2082,7 @@ impl<'test> TestCx<'test> {
.output() .output()
.unwrap(); .unwrap();
assert!(output.status.success()); assert!(output.status.success());
eprintln!("{}", String::from_utf8_lossy(&output.stdout)); println!("{}", String::from_utf8_lossy(&output.stdout));
eprintln!("{}", String::from_utf8_lossy(&output.stderr)); eprintln!("{}", String::from_utf8_lossy(&output.stderr));
} else { } else {
use colored::Colorize; use colored::Colorize;
@ -2482,7 +2482,7 @@ impl<'test> TestCx<'test> {
)"# )"#
) )
.replace_all(&output, |caps: &Captures<'_>| { .replace_all(&output, |caps: &Captures<'_>| {
eprintln!("{}", &caps[0]); println!("{}", &caps[0]);
caps[0].replace(r"\", "/") caps[0].replace(r"\", "/")
}) })
.replace("\r\n", "\n") .replace("\r\n", "\n")
@ -2581,16 +2581,16 @@ impl<'test> TestCx<'test> {
if let Err(err) = fs::write(&actual_path, &actual) { if let Err(err) = fs::write(&actual_path, &actual) {
self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",)); self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",));
} }
eprintln!("Saved the actual {stream} to {actual_path:?}"); println!("Saved the actual {stream} to {actual_path:?}");
let expected_path = let expected_path =
expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream); expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream);
if !self.config.bless { if !self.config.bless {
if expected.is_empty() { if expected.is_empty() {
eprintln!("normalized {}:\n{}\n", stream, actual); println!("normalized {}:\n{}\n", stream, actual);
} else { } else {
eprintln!("diff of {stream}:\n"); println!("diff of {stream}:\n");
if let Some(diff_command) = self.config.diff_command.as_deref() { if let Some(diff_command) = self.config.diff_command.as_deref() {
let mut args = diff_command.split_whitespace(); let mut args = diff_command.split_whitespace();
let name = args.next().unwrap(); let name = args.next().unwrap();
@ -2625,10 +2625,10 @@ impl<'test> TestCx<'test> {
if let Err(err) = fs::write(&expected_path, &actual) { if let Err(err) = fs::write(&expected_path, &actual) {
self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}")); self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}"));
} }
eprintln!("Blessing the {stream} of {test_name} in {expected_path:?}"); println!("Blessing the {stream} of {test_name} in {expected_path:?}");
} }
eprintln!("\nThe actual {0} differed from the expected {0}.", stream); println!("\nThe actual {0} differed from the expected {0}.", stream);
if self.config.bless { 0 } else { 1 } if self.config.bless { 0 } else { 1 }
} }
@ -2707,7 +2707,7 @@ impl<'test> TestCx<'test> {
fs::create_dir_all(&incremental_dir).unwrap(); fs::create_dir_all(&incremental_dir).unwrap();
if self.config.verbose { if self.config.verbose {
eprintln!("init_incremental_test: incremental_dir={}", incremental_dir.display()); println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
} }
} }
@ -2765,7 +2765,7 @@ impl ProcRes {
} }
} }
eprintln!( println!(
"status: {}\ncommand: {}\n{}\n{}\n", "status: {}\ncommand: {}\n{}\n{}\n",
self.status, self.status,
self.cmdline, self.cmdline,
@ -2776,7 +2776,7 @@ impl ProcRes {
pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! { pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
if let Some(e) = err { if let Some(e) = err {
eprintln!("\nerror: {}", e); println!("\nerror: {}", e);
} }
self.print_info(); self.print_info();
on_failure(); on_failure();

View file

@ -64,13 +64,13 @@ impl TestCx<'_> {
if !missing.is_empty() { if !missing.is_empty() {
missing.sort(); missing.sort();
eprintln!("\nThese items should have been contained but were not:\n"); println!("\nThese items should have been contained but were not:\n");
for item in &missing { for item in &missing {
eprintln!("{}", item); println!("{}", item);
} }
eprintln!("\n"); println!("\n");
} }
if !unexpected.is_empty() { if !unexpected.is_empty() {
@ -80,24 +80,24 @@ impl TestCx<'_> {
sorted sorted
}; };
eprintln!("\nThese items were contained but should not have been:\n"); println!("\nThese items were contained but should not have been:\n");
for item in sorted { for item in sorted {
eprintln!("{}", item); println!("{}", item);
} }
eprintln!("\n"); println!("\n");
} }
if !wrong_cgus.is_empty() { if !wrong_cgus.is_empty() {
wrong_cgus.sort_by_key(|pair| pair.0.name.clone()); wrong_cgus.sort_by_key(|pair| pair.0.name.clone());
eprintln!("\nThe following items were assigned to wrong codegen units:\n"); println!("\nThe following items were assigned to wrong codegen units:\n");
for &(ref expected_item, ref actual_item) in &wrong_cgus { for &(ref expected_item, ref actual_item) in &wrong_cgus {
eprintln!("{}", expected_item.name); println!("{}", expected_item.name);
eprintln!(" expected: {}", codegen_units_to_str(&expected_item.codegen_units)); println!(" expected: {}", codegen_units_to_str(&expected_item.codegen_units));
eprintln!(" actual: {}", codegen_units_to_str(&actual_item.codegen_units)); println!(" actual: {}", codegen_units_to_str(&actual_item.codegen_units));
eprintln!(); println!();
} }
} }

View file

@ -260,7 +260,7 @@ impl TestCx<'_> {
cmdline, cmdline,
}; };
if adb.kill().is_err() { if adb.kill().is_err() {
eprintln!("Adb process is already finished."); println!("Adb process is already finished.");
} }
} else { } else {
let rust_src_root = let rust_src_root =
@ -275,7 +275,7 @@ impl TestCx<'_> {
match self.config.gdb_version { match self.config.gdb_version {
Some(version) => { Some(version) => {
eprintln!("NOTE: compiletest thinks it is using GDB version {}", version); println!("NOTE: compiletest thinks it is using GDB version {}", version);
if version > extract_gdb_version("7.4").unwrap() { if version > extract_gdb_version("7.4").unwrap() {
// Add the directory containing the pretty printers to // Add the directory containing the pretty printers to
@ -297,7 +297,7 @@ impl TestCx<'_> {
} }
} }
_ => { _ => {
eprintln!( println!(
"NOTE: compiletest does not know which version of \ "NOTE: compiletest does not know which version of \
GDB it is using" GDB it is using"
); );
@ -392,10 +392,10 @@ impl TestCx<'_> {
match self.config.lldb_version { match self.config.lldb_version {
Some(ref version) => { Some(ref version) => {
eprintln!("NOTE: compiletest thinks it is using LLDB version {}", version); println!("NOTE: compiletest thinks it is using LLDB version {}", version);
} }
_ => { _ => {
eprintln!( println!(
"NOTE: compiletest does not know which version of \ "NOTE: compiletest does not know which version of \
LLDB it is using" LLDB it is using"
); );

View file

@ -29,7 +29,7 @@ impl TestCx<'_> {
if !res.status.success() { if !res.status.success() {
self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| { self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| {
eprintln!("Rustdoc Output:"); println!("Rustdoc Output:");
proc_res.print_info(); proc_res.print_info();
}) })
} }

View file

@ -109,10 +109,10 @@ impl TestCx<'_> {
} }
if errors > 0 { if errors > 0 {
eprintln!("To update references, rerun the tests and pass the `--bless` flag"); println!("To update references, rerun the tests and pass the `--bless` flag");
let relative_path_to_file = let relative_path_to_file =
self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap()); self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap());
eprintln!( println!(
"To only update this specific test, also pass `--test-args {}`", "To only update this specific test, also pass `--test-args {}`",
relative_path_to_file.display(), relative_path_to_file.display(),
); );

View file

@ -30,7 +30,7 @@ fn path_div() -> &'static str {
pub fn logv(config: &Config, s: String) { pub fn logv(config: &Config, s: String) {
debug!("{}", s); debug!("{}", s);
if config.verbose { if config.verbose {
eprintln!("{}", s); println!("{}", s);
} }
} }

View file

@ -1,3 +1,5 @@
#![allow(unpredictable_function_pointer_comparisons)]
use std::mem; use std::mem;
trait Answer { trait Answer {

View file

@ -1,3 +1,5 @@
#![allow(unpredictable_function_pointer_comparisons)]
type BuiltIn = for<'a> fn(&str); type BuiltIn = for<'a> fn(&str);
struct Function { struct Function {

View file

@ -3936,17 +3936,8 @@ The tracking issue for this feature is: [#117693]
"##, "##,
}, },
Lint { Lint {
label: "core_pattern_type", label: "pattern_type_macro",
description: r##"# `core_pattern_type` description: r##"# `pattern_type_macro`
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
------------------------
"##,
},
Lint {
label: "core_pattern_types",
description: r##"# `core_pattern_types`
This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.

View file

@ -38,7 +38,7 @@ const IGNORE_UI_TEST_CHECK: &[&str] =
macro_rules! verbose_print { macro_rules! verbose_print {
($verbose:expr, $($fmt:tt)*) => { ($verbose:expr, $($fmt:tt)*) => {
if $verbose { if $verbose {
eprintln!("{}", format_args!($($fmt)*)); println!("{}", format_args!($($fmt)*));
} }
}; };
} }
@ -49,8 +49,8 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
// Stage 1: create list // Stage 1: create list
let error_codes = extract_error_codes(root_path, &mut errors); let error_codes = extract_error_codes(root_path, &mut errors);
if verbose { if verbose {
eprintln!("Found {} error codes", error_codes.len()); println!("Found {} error codes", error_codes.len());
eprintln!("Highest error code: `{}`", error_codes.iter().max().unwrap()); println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
} }
// Stage 2: check list has docs // Stage 2: check list has docs

View file

@ -158,14 +158,14 @@ pub fn check(
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for &(name, _) in gate_untested.iter() { for &(name, _) in gate_untested.iter() {
eprintln!("Expected a gate test for the feature '{name}'."); println!("Expected a gate test for the feature '{name}'.");
eprintln!( println!(
"Hint: create a failing test file named 'tests/ui/feature-gates/feature-gate-{}.rs',\ "Hint: create a failing test file named 'tests/ui/feature-gates/feature-gate-{}.rs',\
\n with its failures due to missing usage of `#![feature({})]`.", \n with its failures due to missing usage of `#![feature({})]`.",
name.replace("_", "-"), name.replace("_", "-"),
name name
); );
eprintln!( println!(
"Hint: If you already have such a test and don't want to rename it,\ "Hint: If you already have such a test and don't want to rename it,\
\n you can also add a // gate-test-{} line to the test file.", \n you can also add a // gate-test-{} line to the test file.",
name name
@ -218,7 +218,7 @@ pub fn check(
lines.sort(); lines.sort();
for line in lines { for line in lines {
eprintln!("* {line}"); println!("* {line}");
} }
} }

View file

@ -18,7 +18,6 @@ const ALLOWLIST: &[&str] = &[
"const_eval_validation_failure_note", "const_eval_validation_failure_note",
"driver_impl_ice", "driver_impl_ice",
"incremental_corrupt_file", "incremental_corrupt_file",
"mir_build_pointer_pattern",
]; ];
fn check_period(filename: &str, contents: &str, bad: &mut bool) { fn check_period(filename: &str, contents: &str, bad: &mut bool) {

View file

@ -118,16 +118,16 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
// List unstable features that don't have Unstable Book sections. // List unstable features that don't have Unstable Book sections.
// Remove the comment marker if you want the list printed. // Remove the comment marker if you want the list printed.
/* /*
eprintln!("Lib features without unstable book sections:"); println!("Lib features without unstable book sections:");
for feature_name in &unstable_lang_feature_names - for feature_name in &unstable_lang_feature_names -
&unstable_book_lang_features_section_file_names { &unstable_book_lang_features_section_file_names {
eprintln!(" * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue); println!(" * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue);
} }
eprintln!("Lang features without unstable book sections:"); println!("Lang features without unstable book sections:");
for feature_name in &unstable_lib_feature_names- for feature_name in &unstable_lib_feature_names-
&unstable_book_lib_features_section_file_names { &unstable_book_lib_features_section_file_names {
eprintln!(" * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue); println!(" * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue);
} }
// */ // */
} }

View file

@ -42,7 +42,7 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
if let Some(expected) = get_x_wrapper_version(root, cargo) { if let Some(expected) = get_x_wrapper_version(root, cargo) {
if installed < expected { if installed < expected {
return eprintln!( return println!(
"Current version of x is {installed}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" "Current version of x is {installed}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`"
); );
} }

View file

@ -4,8 +4,7 @@
//@ compile-flags: -Csymbol-mangling-version=v0 -Copt-level=0 --crate-type=lib //@ compile-flags: -Csymbol-mangling-version=v0 -Copt-level=0 --crate-type=lib
#![feature(pattern_types)] #![feature(pattern_types)]
#![feature(core_pattern_types)] #![feature(pattern_type_macro)]
#![feature(core_pattern_type)]
use std::pat::pattern_type; use std::pat::pattern_type;

View file

@ -18,17 +18,17 @@ impl Foo for Def {
pub fn test<A: Foo, B: Foo>(arg: EFoo) { pub fn test<A: Foo, B: Foo>(arg: EFoo) {
match arg { match arg {
A::X => println!("A::X"), A::X => println!("A::X"),
//~^ error: constant pattern depends on a generic parameter //~^ ERROR constant pattern cannot depend on generic parameters
B::X => println!("B::X"), B::X => println!("B::X"),
//~^ error: constant pattern depends on a generic parameter //~^ ERROR constant pattern cannot depend on generic parameters
_ => (), _ => (),
} }
} }
pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) { pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
//~^ ERROR constant pattern depends on a generic parameter //~^ ERROR constant pattern cannot depend on generic parameters
let A::X = arg; let A::X = arg;
//~^ ERROR constant pattern depends on a generic parameter //~^ ERROR constant pattern cannot depend on generic parameters
} }
fn main() { fn main() {

View file

@ -1,26 +1,57 @@
error[E0158]: constant pattern depends on a generic parameter error[E0158]: constant pattern cannot depend on generic parameters
--> $DIR/associated-const-type-parameter-pattern.rs:20:9 --> $DIR/associated-const-type-parameter-pattern.rs:20:9
| |
LL | pub trait Foo {
| -------------
LL | const X: EFoo;
| ------------- constant defined here
...
LL | pub fn test<A: Foo, B: Foo>(arg: EFoo) {
| - constant depends on this generic parameter
LL | match arg {
LL | A::X => println!("A::X"), LL | A::X => println!("A::X"),
| ^^^^ | ^^^^ `const` depends on a generic parameter
error[E0158]: constant pattern depends on a generic parameter error[E0158]: constant pattern cannot depend on generic parameters
--> $DIR/associated-const-type-parameter-pattern.rs:22:9 --> $DIR/associated-const-type-parameter-pattern.rs:22:9
| |
LL | pub trait Foo {
| -------------
LL | const X: EFoo;
| ------------- constant defined here
...
LL | pub fn test<A: Foo, B: Foo>(arg: EFoo) {
| - constant depends on this generic parameter
...
LL | B::X => println!("B::X"), LL | B::X => println!("B::X"),
| ^^^^ | ^^^^ `const` depends on a generic parameter
error[E0158]: constant pattern depends on a generic parameter error[E0158]: constant pattern cannot depend on generic parameters
--> $DIR/associated-const-type-parameter-pattern.rs:30:9 --> $DIR/associated-const-type-parameter-pattern.rs:30:9
| |
LL | pub trait Foo {
| -------------
LL | const X: EFoo;
| ------------- constant defined here
...
LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
| - constant depends on this generic parameter
LL |
LL | let A::X = arg; LL | let A::X = arg;
| ^^^^ | ^^^^ `const` depends on a generic parameter
error[E0158]: constant pattern depends on a generic parameter error[E0158]: constant pattern cannot depend on generic parameters
--> $DIR/associated-const-type-parameter-pattern.rs:28:48 --> $DIR/associated-const-type-parameter-pattern.rs:28:48
| |
LL | pub trait Foo {
| -------------
LL | const X: EFoo;
| ------------- constant defined here
...
LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) { LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
| ^^^^ | - ^^^^ `const` depends on a generic parameter
| |
| constant depends on this generic parameter
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View file

@ -2,7 +2,7 @@
fn check<const N: usize>() { fn check<const N: usize>() {
match 1 { match 1 {
N => {} //~ ERROR const parameters cannot be referenced in patterns N => {} //~ ERROR constant parameters cannot be referenced in patterns
_ => {} _ => {}
} }
} }

View file

@ -1,8 +1,11 @@
error[E0158]: const parameters cannot be referenced in patterns error[E0158]: constant parameters cannot be referenced in patterns
--> $DIR/const-param.rs:5:9 --> $DIR/const-param.rs:5:9
| |
LL | fn check<const N: usize>() {
| -------------- constant defined here
LL | match 1 {
LL | N => {} LL | N => {}
| ^ | ^ can't be used in patterns
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,6 +1,9 @@
//@ run-pass //@ run-pass
// Tests equality between supertype and subtype of a function // Tests equality between supertype and subtype of a function
// See the issue #91636 // See the issue #91636
#![allow(unpredictable_function_pointer_comparisons)]
fn foo(_a: &str) {} fn foo(_a: &str) {}
fn main() { fn main() {

View file

@ -1,6 +1,9 @@
//@ run-pass //@ run-pass
// We used to have a __rust_abi shim that resulted in duplicated symbols // We used to have a __rust_abi shim that resulted in duplicated symbols
// whenever the item path wasn't enough to disambiguate between them. // whenever the item path wasn't enough to disambiguate between them.
#![allow(unpredictable_function_pointer_comparisons)]
fn main() { fn main() {
let a = { let a = {
extern "C" fn good() -> i32 { return 0; } extern "C" fn good() -> i32 { return 0; }

View file

@ -12,8 +12,7 @@ impl Opcode2 {
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
move |i| match msg_type { move |i| match msg_type {
Opcode2::OP2 => unimplemented!(), Opcode2::OP2 => unimplemented!(), // ok, `const` already emitted an error
//~^ ERROR: could not evaluate constant pattern
} }
} }

View file

@ -17,13 +17,7 @@ help: you might be missing a type parameter
LL | pub struct Opcode2<S>(&'a S); LL | pub struct Opcode2<S>(&'a S);
| +++ | +++
error: could not evaluate constant pattern error: aborting due to 2 previous errors
--> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
|
LL | Opcode2::OP2 => unimplemented!(),
| ^^^^^^^^^^^^
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0261, E0412. Some errors have detailed explanations: E0261, E0412.
For more information about an error, try `rustc --explain E0261`. For more information about an error, try `rustc --explain E0261`.

View file

@ -12,8 +12,7 @@ const NEG_NEG_128: i8 = -NEG_128; //~ ERROR constant
fn main() { fn main() {
match -128i8 { match -128i8 {
NEG_NEG_128 => println!("A"), NEG_NEG_128 => println!("A"), // ok, `const` error already emitted
//~^ ERROR could not evaluate constant pattern
_ => println!("B"), _ => println!("B"),
} }
} }

View file

@ -4,12 +4,6 @@ error[E0080]: evaluation of constant value failed
LL | const NEG_NEG_128: i8 = -NEG_128; LL | const NEG_NEG_128: i8 = -NEG_128;
| ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
error: could not evaluate constant pattern error: aborting due to 1 previous error
--> $DIR/const-eval-overflow-2.rs:15:9
|
LL | NEG_NEG_128 => println!("A"),
| ^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`. For more information about this error, try `rustc --explain E0080`.

View file

@ -7,12 +7,6 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
= help: this code performed an operation that depends on the underlying bytes representing a pointer = help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error: could not evaluate constant pattern error: aborting due to 1 previous error
--> $DIR/ref_to_int_match.rs:7:14
|
LL | 10..=BAR => {},
| ^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`. For more information about this error, try `rustc --explain E0080`.

View file

@ -7,12 +7,6 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
= help: this code performed an operation that depends on the underlying bytes representing a pointer = help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error: could not evaluate constant pattern error: aborting due to 1 previous error
--> $DIR/ref_to_int_match.rs:7:14
|
LL | 10..=BAR => {},
| ^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`. For more information about this error, try `rustc --explain E0080`.

View file

@ -4,7 +4,7 @@ fn main() {
let n: Int = 40; let n: Int = 40;
match n { match n {
0..=10 => {}, 0..=10 => {},
10..=BAR => {}, //~ ERROR could not evaluate constant pattern 10..=BAR => {}, // ok, `const` error already emitted
_ => {}, _ => {},
} }
} }

View file

@ -1,5 +1,7 @@
//@ run-pass //@ run-pass
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
#![allow(unpredictable_function_pointer_comparisons)]
extern "C" fn foopy() {} extern "C" fn foopy() {}

View file

@ -9,15 +9,13 @@ fn main() {
let _ = Defaulted; let _ = Defaulted;
match None { match None {
consts::SOME => panic!(), consts::SOME => panic!(),
//~^ must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `CustomEq` in a pattern
_ => {} _ => {}
} }
match None { match None {
<Defaulted as consts::AssocConst>::SOME => panic!(), <Defaulted as consts::AssocConst>::SOME => panic!(),
//~^ must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `CustomEq` in a pattern
_ => {} _ => {}
} }
} }

View file

@ -1,19 +1,33 @@
error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `CustomEq` in a pattern
--> $DIR/cross-crate-fail.rs:11:9 --> $DIR/cross-crate-fail.rs:11:9
| |
LL | consts::SOME => panic!(), LL | consts::SOME => panic!(),
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ constant of non-structural type
|
::: $DIR/auxiliary/consts.rs:1:1
|
LL | pub struct CustomEq;
| ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | pub const SOME: Option<CustomEq> = Some(CustomEq);
| -------------------------------- constant defined here
| |
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `CustomEq` in a pattern
--> $DIR/cross-crate-fail.rs:18:9 --> $DIR/cross-crate-fail.rs:17:9
| |
LL | <Defaulted as consts::AssocConst>::SOME => panic!(), LL | <Defaulted as consts::AssocConst>::SOME => panic!(),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
|
::: $DIR/auxiliary/consts.rs:1:1
|
LL | pub struct CustomEq;
| ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const SOME: Option<CustomEq> = Some(CustomEq);
| ---------------------------- constant defined here
| |
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -1,26 +1,46 @@
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:9:9 --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:9:9
| |
LL | const C: *const u8 = &0;
| ------------------ constant defined here
...
LL | C => {} LL | C => {}
| ^ | ^ can't be used in patterns
|
= note: see https://github.com/rust-lang/rust/issues/70861 for details
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:16:9 --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:16:9
| |
LL | const C_INNER: (*const u8, u8) = (C, 0);
| ------------------------------ constant defined here
...
LL | C_INNER => {} LL | C_INNER => {}
| ^^^^^^^ | ^^^^^^^ can't be used in patterns
|
= note: see https://github.com/rust-lang/rust/issues/70861 for details
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:27:9 --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:27:9
| |
LL | const D: *const [u8; 4] = b"abcd";
| ----------------------- constant defined here
...
LL | D => {} LL | D => {}
| ^ | ^ can't be used in patterns
|
= note: see https://github.com/rust-lang/rust/issues/70861 for details
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
--> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:32:9 --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:32:9
| |
LL | const STR: *const str = "abcd";
| --------------------- constant defined here
...
LL | STR => {} LL | STR => {}
| ^^^ | ^^^ can't be used in patterns
|
= note: see https://github.com/rust-lang/rust/issues/70861 for details
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View file

@ -1,14 +1,24 @@
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
--> $DIR/issue-44333.rs:15:9 --> $DIR/issue-44333.rs:15:9
| |
LL | const FOO: Func = foo;
| --------------- constant defined here
...
LL | FOO => println!("foo"), LL | FOO => println!("foo"),
| ^^^ | ^^^ can't be used in patterns
|
= note: see https://github.com/rust-lang/rust/issues/70861 for details
error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
--> $DIR/issue-44333.rs:16:9 --> $DIR/issue-44333.rs:16:9
| |
LL | const BAR: Func = bar;
| --------------- constant defined here
...
LL | BAR => println!("bar"), LL | BAR => println!("bar"),
| ^^^ | ^^^ can't be used in patterns
|
= note: see https://github.com/rust-lang/rust/issues/70861 for details
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -11,7 +11,7 @@ const C: &[O<B>] = &[O::None];
fn main() { fn main() {
let x = O::None; let x = O::None;
match &[x][..] { match &[x][..] {
C => (), //~ERROR: the type must implement `PartialEq` C => (), //~ ERROR constant of non-structural type `&[O<B>]` in a pattern
_ => (), _ => (),
} }
} }

View file

@ -1,8 +1,16 @@
error: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq` error: constant of non-structural type `&[O<B>]` in a pattern
--> $DIR/issue-65466.rs:14:9 --> $DIR/issue-65466.rs:14:9
| |
LL | struct B;
| -------- must be annotated with `#[derive(PartialEq)]` to be usable in patterns
LL |
LL | const C: &[O<B>] = &[O::None];
| ---------------- constant defined here
...
LL | C => (), LL | C => (),
| ^ | ^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -16,8 +16,7 @@ const BAR_BAZ: Foo = if 42 == 42 {
fn main() { fn main() {
match Foo::Qux(NoEq) { match Foo::Qux(NoEq) {
BAR_BAZ => panic!(), BAR_BAZ => panic!(), //~ ERROR constant of non-structural type `Foo` in a pattern
//~^ ERROR must be annotated with `#[derive(PartialEq)]`
_ => {} _ => {}
} }
} }

View file

@ -1,10 +1,15 @@
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `Foo` in a pattern
--> $DIR/no-eq-branch-fail.rs:19:9 --> $DIR/no-eq-branch-fail.rs:19:9
| |
LL | enum Foo {
| -------- `Foo` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const BAR_BAZ: Foo = if 42 == 42 {
| ------------------ constant defined here
...
LL | BAR_BAZ => panic!(), LL | BAR_BAZ => panic!(),
| ^^^^^^^ | ^^^^^^^ constant of non-structural type
| |
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -26,7 +26,7 @@ fn main() {
match None { match None {
NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
//~^ ERROR must implement `PartialEq` //~^ ERROR constant of non-structural type `Option<NoPartialEq>` in a pattern
_ => panic!("whoops"), _ => panic!("whoops"),
} }
} }

View file

@ -1,8 +1,16 @@
error: to use a constant of type `Option<NoPartialEq>` in a pattern, the type must implement `PartialEq` error: constant of non-structural type `Option<NoPartialEq>` in a pattern
--> $DIR/reject_non_partial_eq.rs:28:9 --> $DIR/reject_non_partial_eq.rs:28:9
| |
LL | struct NoPartialEq(u32);
| ------------------ must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const NO_PARTIAL_EQ_NONE: Option<NoPartialEq> = None;
| --------------------------------------------- constant defined here
...
LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^ constant of non-structural type
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -17,9 +17,29 @@ struct NoPartialEq;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct NoDerive; struct NoDerive;
//~^ NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
//~| NOTE must be annotated with `#[derive(PartialEq)]`
// This impl makes `NoDerive` irreflexive. // This impl makes `NoDerive` irreflexive.
impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
//~^ NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
//~| NOTE StructuralPartialEq.html for details
impl Eq for NoDerive { } impl Eq for NoDerive { }
@ -36,65 +56,55 @@ fn main() {
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
enum Derive<X> { Some(X), None, } enum Derive<X> { Some(X), None, }
const ENUM: Derive<NoDerive> = Derive::Some(NoDerive); const ENUM: Derive<NoDerive> = Derive::Some(NoDerive); //~ NOTE constant defined here
match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
const FIELD: OND = TrivialEq(Some(NoDerive)).0; const FIELD: OND = TrivialEq(Some(NoDerive)).0; //~ NOTE constant defined here
match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
const NO_DERIVE_SOME: OND = Some(NoDerive); const NO_DERIVE_SOME: OND = Some(NoDerive);
const INDIRECT: OND = NO_DERIVE_SOME; const INDIRECT: OND = NO_DERIVE_SOME; //~ NOTE constant defined here
match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
const TUPLE: (OND, OND) = (None, Some(NoDerive)); const TUPLE: (OND, OND) = (None, Some(NoDerive)); //~ NOTE constant defined here
match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); //~ NOTE constant defined here
match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
const ARRAY: [OND; 2] = [None, Some(NoDerive)]; const ARRAY: [OND; 2] = [None, Some(NoDerive)]; //~ NOTE constant defined here
match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
const REPEAT: [OND; 2] = [Some(NoDerive); 2]; const REPEAT: [OND; 2] = [Some(NoDerive); 2]; //~ NOTE constant defined here
match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
trait Trait: Sized { const ASSOC: Option<Self>; } trait Trait: Sized { const ASSOC: Option<Self>; } //~ NOTE constant defined here
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); } impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
const BLOCK: OND = { NoDerive; Some(NoDerive) }; const BLOCK: OND = { NoDerive; Some(NoDerive) }; //~ NOTE constant defined here
match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
const ADDR_OF: &OND = &Some(NoDerive); const ADDR_OF: &OND = &Some(NoDerive); //~ NOTE constant defined here
match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
//~^ ERROR must be annotated with `#[derive(PartialEq)]` //~^ ERROR constant of non-structural type `NoDerive` in a pattern
//~| NOTE the traits must be derived //~| NOTE constant of non-structural type
//~| NOTE StructuralPartialEq.html for details
} }

View file

@ -1,92 +1,173 @@
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:40:36 --> $DIR/reject_non_structural.rs:60:36
| |
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
| ---------------------------- constant defined here
LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
| ^^^^ | ^^^^ constant of non-structural type
| |
= note: the traits must be derived, manual `impl`s are not sufficient note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:46:28
|
LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
| ^^^^^
|
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
--> $DIR/reject_non_structural.rs:53:27
|
LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
| ^^^^^^^^
|
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
--> $DIR/reject_non_structural.rs:59:36
|
LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
| ^^^^^
|
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
--> $DIR/reject_non_structural.rs:65:28 --> $DIR/reject_non_structural.rs:65:28
| |
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const FIELD: OND = TrivialEq(Some(NoDerive)).0;
| ---------------- constant defined here
LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
| ^^^^^ constant of non-structural type
|
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
--> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:71:27
|
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const INDIRECT: OND = NO_DERIVE_SOME;
| ------------------- constant defined here
LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
| ^^^^^^^^ constant of non-structural type
|
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
--> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:76:36
|
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const TUPLE: (OND, OND) = (None, Some(NoDerive));
| ----------------------- constant defined here
LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
| ^^^^^ constant of non-structural type
|
note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
--> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:81:28
|
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND);
| -------------------------- constant defined here
LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^ constant of non-structural type
| |
= note: the traits must be derived, manual `impl`s are not sufficient note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:71:36 --> $DIR/reject_non_structural.rs:86:36
| |
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const ARRAY: [OND; 2] = [None, Some(NoDerive)];
| --------------------- constant defined here
LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
| ^^^^^ | ^^^^^ constant of non-structural type
| |
= note: the traits must be derived, manual `impl`s are not sufficient note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:77:33 --> $DIR/reject_non_structural.rs:91:33
| |
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const REPEAT: [OND; 2] = [Some(NoDerive); 2];
| ---------------------- constant defined here
LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
| ^^^^^^ | ^^^^^^ constant of non-structural type
| |
= note: the traits must be derived, manual `impl`s are not sufficient note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:84:28 --> $DIR/reject_non_structural.rs:97:28
| |
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | trait Trait: Sized { const ASSOC: Option<Self>; }
| ------------------ ------------------------- constant defined here
LL | impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^ constant of non-structural type
| |
= note: the traits must be derived, manual `impl`s are not sufficient note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:90:28 --> $DIR/reject_non_structural.rs:102:28
| |
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const BLOCK: OND = { NoDerive; Some(NoDerive) };
| ---------------- constant defined here
LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
| ^^^^^ | ^^^^^ constant of non-structural type
| |
= note: the traits must be derived, manual `impl`s are not sufficient note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` error: constant of non-structural type `NoDerive` in a pattern
--> $DIR/reject_non_structural.rs:96:29 --> $DIR/reject_non_structural.rs:107:29
| |
LL | struct NoDerive;
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
...
LL | const ADDR_OF: &OND = &Some(NoDerive);
| ------------------- constant defined here
LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
| ^^^^^^^ | ^^^^^^^ constant of non-structural type
| |
= note: the traits must be derived, manual `impl`s are not sufficient note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/reject_non_structural.rs:32:1
|
LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 10 previous errors error: aborting due to 10 previous errors

View file

@ -11,7 +11,7 @@ fn invalid() {
// This must be rejected here (or earlier), since it's not a valid `&bool`. // This must be rejected here (or earlier), since it's not a valid `&bool`.
match &true { match &true {
C => {} //~ERROR: could not evaluate constant pattern C => {} // ok, `const` already emitted an error
_ => {} _ => {}
} }
} }
@ -27,7 +27,7 @@ fn extern_() {
// This must be rejected here (or earlier), since the pattern cannot be read. // This must be rejected here (or earlier), since the pattern cannot be read.
match &0 { match &0 {
C => {} //~ERROR: could not evaluate constant pattern C => {} // ok, `const` already emitted an error
_ => {} _ => {}
} }
} }
@ -42,7 +42,7 @@ fn mutable() {
// This *must not build*, the constant we are matching against // This *must not build*, the constant we are matching against
// could change its value! // could change its value!
match &42 { match &42 {
C => {} //~ERROR: could not evaluate constant pattern C => {} // ok, `const` already emitted an error
_ => {} _ => {}
} }
} }

View file

@ -31,24 +31,6 @@ LL | const C: &i32 = unsafe { &S_MUT };
HEX_DUMP HEX_DUMP
} }
error: could not evaluate constant pattern error: aborting due to 3 previous errors
--> $DIR/const_refs_to_static_fail_invalid.rs:14:9
|
LL | C => {}
| ^
error: could not evaluate constant pattern
--> $DIR/const_refs_to_static_fail_invalid.rs:30:9
|
LL | C => {}
| ^
error: could not evaluate constant pattern
--> $DIR/const_refs_to_static_fail_invalid.rs:45:9
|
LL | C => {}
| ^
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0080`. For more information about this error, try `rustc --explain E0080`.

Some files were not shown because too many files have changed in this diff Show more