From 0925ff8300ed724f1a1760c0bedd7522f49b3203 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 14 Feb 2024 19:10:49 +0300 Subject: [PATCH 01/40] use build.rustc config and skip-stage0-validation flag This change helps us to bypass downloading the beta compiler in bootstrap tests. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/tests.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 0ae466eca7d7c..6ac573c68df18 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -11,9 +11,15 @@ use std::{ }; fn parse(config: &str) -> Config { - Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], |&_| { - toml::from_str(config).unwrap() - }) + let config = format!("{config} \r\n build.rustc = \"/does-not-exists\" "); + Config::parse_inner( + &[ + "check".to_owned(), + "--config=/does/not/exist".to_owned(), + "--skip-stage0-validation".to_owned(), + ], + |&_| toml::from_str(&config).unwrap(), + ) } #[test] From b80fc5d4e8ce95a00b14a50e8ee0561b64736480 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 14 Feb 2024 14:17:27 +0000 Subject: [PATCH 02/40] errors: only eagerly translate subdiagnostics Subdiagnostics don't need to be lazily translated, they can always be eagerly translated. Eager translation is slightly more complex as we need to have a `DiagCtxt` available to perform the translation, which involves slightly more threading of that context. This slight increase in complexity should enable later simplifications - like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages into the diagnostic structs rather than having them in separate files (working on that was what led to this change). Signed-off-by: David Wood --- .../src/diagnostics/conflict_errors.rs | 89 +++++--- .../rustc_borrowck/src/diagnostics/mod.rs | 202 +++++++++++------- .../src/diagnostics/move_errors.rs | 47 ++-- .../src/diagnostics/mutability_errors.rs | 2 +- .../src/diagnostics/region_errors.rs | 10 +- compiler/rustc_codegen_gcc/src/errors.rs | 2 +- compiler/rustc_codegen_llvm/src/errors.rs | 2 +- .../src/transform/check_consts/ops.rs | 2 +- compiler/rustc_error_messages/src/lib.rs | 36 ++-- compiler/rustc_errors/src/diagnostic.rs | 11 +- .../rustc_errors/src/diagnostic_builder.rs | 3 - compiler/rustc_errors/src/emitter.rs | 23 ++ compiler/rustc_errors/src/lib.rs | 71 ++++-- compiler/rustc_errors/src/translation.rs | 4 +- compiler/rustc_expand/src/mbe/diagnostics.rs | 15 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_hir_typeck/src/cast.rs | 24 ++- compiler/rustc_hir_typeck/src/expr.rs | 7 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 96 +++++---- .../rustc_hir_typeck/src/method/suggest.rs | 27 +-- compiler/rustc_hir_typeck/src/op.rs | 2 +- .../src/infer/error_reporting/mod.rs | 4 +- .../src/infer/error_reporting/note.rs | 2 +- .../src/infer/error_reporting/suggest.rs | 33 +-- compiler/rustc_lint/src/lints.rs | 2 +- .../src/diagnostics/diagnostic_builder.rs | 39 +--- .../src/thir/pattern/check_match.rs | 2 +- compiler/rustc_mir_transform/src/errors.rs | 2 +- .../rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 13 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 24 ++- compiler/rustc_resolve/src/imports.rs | 4 +- .../rustc_resolve/src/late/diagnostics.rs | 24 ++- compiler/rustc_session/src/parse.rs | 10 +- .../src/traits/error_reporting/suggestions.rs | 7 +- src/tools/miri/src/diagnostics.rs | 2 +- src/tools/rustfmt/src/parse/session.rs | 11 + .../session-diagnostic/diagnostic-derive.rs | 10 +- .../diagnostic-derive.stderr | 44 ++-- 43 files changed, 532 insertions(+), 388 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 18cf6f64fbc03..2b0c0e939f59b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -229,7 +229,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { seen_spans.insert(move_span); } - use_spans.var_path_only_subdiag(&mut err, desired_action); + use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action); if !is_loop_move { err.span_label( @@ -291,18 +291,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if needs_note { if let Some(local) = place.as_local() { let span = self.body.local_decls[local].source_info.span; - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move, - ty, - place: ¬e_msg, - span, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move, + ty, + place: ¬e_msg, + span, + }, + ); } else { - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note { - is_partial_move, - ty, - place: ¬e_msg, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Note { + is_partial_move, + ty, + place: ¬e_msg, + }, + ); }; } @@ -557,7 +563,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { E0381, "{used} binding {desc}{isnt_initialized}" ); - use_spans.var_path_only_subdiag(&mut err, desired_action); + use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action); if let InitializationRequiringAction::PartialAssignment | InitializationRequiringAction::Assignment = desired_action @@ -848,9 +854,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &value_msg, ); - borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow); + borrow_spans.var_path_only_subdiag( + self.dcx(), + &mut err, + crate::InitializationRequiringAction::Borrow, + ); - move_spans.var_subdiag(None, &mut err, None, |kind, var_span| { + move_spans.var_subdiag(self.dcx(), &mut err, None, |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span }, @@ -895,7 +905,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| { + borrow_spans.var_subdiag(self.dcx(), &mut err, Some(borrow.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; let place = &borrow.borrowed_place; let desc_place = self.describe_any_place(place.as_ref()); @@ -1043,7 +1053,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "mutably borrow", ); borrow_spans.var_subdiag( - None, + self.dcx(), &mut err, Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }), |kind, var_span| { @@ -1131,22 +1141,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; if issued_spans == borrow_spans { - borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| { - use crate::session_diagnostics::CaptureVarCause::*; - match kind { - hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine { - place: desc_place, - var_span, - is_single_var: false, - }, - hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { - BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false } + borrow_spans.var_subdiag( + self.dcx(), + &mut err, + Some(gen_borrow_kind), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine { + place: desc_place, + var_span, + is_single_var: false, + }, + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { + BorrowUsePlaceClosure { + place: desc_place, + var_span, + is_single_var: false, + } + } } - } - }); + }, + ); } else { issued_spans.var_subdiag( - Some(self.dcx()), + self.dcx(), &mut err, Some(issued_borrow.kind), |kind, var_span| { @@ -1165,7 +1184,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); borrow_spans.var_subdiag( - Some(self.dcx()), + self.dcx(), &mut err, Some(gen_borrow_kind), |kind, var_span| { @@ -2217,7 +2236,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, format!("`{name}` dropped here while still borrowed")); - borrow_spans.args_subdiag(&mut err, |args_span| { + borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| { crate::session_diagnostics::CaptureArgLabel::Capture { is_within: borrow_spans.for_coroutine(), args_span, @@ -2476,7 +2495,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ); - borrow_spans.args_subdiag(&mut err, |args_span| { + borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| { crate::session_diagnostics::CaptureArgLabel::Capture { is_within: borrow_spans.for_coroutine(), args_span, @@ -2935,7 +2954,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "assign", ); - loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, @@ -2953,7 +2972,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); - loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 59f3aa706edea..4ca854c857de9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -124,7 +124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { - diag.eager_subdiagnostic( + diag.subdiagnostic( self.dcx(), OnClosureNote::InvokedTwice { place_name: &ty::place_to_string_for_capture( @@ -146,7 +146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { - diag.eager_subdiagnostic( + diag.subdiagnostic( self.dcx(), OnClosureNote::MovedTwice { place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place), @@ -587,11 +587,12 @@ impl UseSpans<'_> { /// Add a span label to the arguments of the closure, if it exists. pub(super) fn args_subdiag( self, + dcx: &rustc_errors::DiagCtxt, err: &mut Diagnostic, f: impl FnOnce(Span) -> CaptureArgLabel, ) { if let UseSpans::ClosureUse { args_span, .. } = self { - err.subdiagnostic(f(args_span)); + err.subdiagnostic(dcx, f(args_span)); } } @@ -599,6 +600,7 @@ impl UseSpans<'_> { /// only adds label to the `path_span` pub(super) fn var_path_only_subdiag( self, + dcx: &rustc_errors::DiagCtxt, err: &mut Diagnostic, action: crate::InitializationRequiringAction, ) { @@ -607,20 +609,26 @@ impl UseSpans<'_> { if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self { match closure_kind { hir::ClosureKind::Coroutine(_) => { - err.subdiagnostic(match action { - Borrow => BorrowInCoroutine { path_span }, - MatchOn | Use => UseInCoroutine { path_span }, - Assignment => AssignInCoroutine { path_span }, - PartialAssignment => AssignPartInCoroutine { path_span }, - }); + err.subdiagnostic( + dcx, + match action { + Borrow => BorrowInCoroutine { path_span }, + MatchOn | Use => UseInCoroutine { path_span }, + Assignment => AssignInCoroutine { path_span }, + PartialAssignment => AssignPartInCoroutine { path_span }, + }, + ); } hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { - err.subdiagnostic(match action { - Borrow => BorrowInClosure { path_span }, - MatchOn | Use => UseInClosure { path_span }, - Assignment => AssignInClosure { path_span }, - PartialAssignment => AssignPartInClosure { path_span }, - }); + err.subdiagnostic( + dcx, + match action { + Borrow => BorrowInClosure { path_span }, + MatchOn | Use => UseInClosure { path_span }, + Assignment => AssignInClosure { path_span }, + PartialAssignment => AssignPartInClosure { path_span }, + }, + ); } } } @@ -629,32 +637,32 @@ impl UseSpans<'_> { /// Add a subdiagnostic to the use of the captured variable, if it exists. pub(super) fn var_subdiag( self, - dcx: Option<&rustc_errors::DiagCtxt>, + dcx: &rustc_errors::DiagCtxt, err: &mut Diagnostic, kind: Option, f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause, ) { if let UseSpans::ClosureUse { closure_kind, capture_kind_span, path_span, .. } = self { if capture_kind_span != path_span { - err.subdiagnostic(match kind { - Some(kd) => match kd { - rustc_middle::mir::BorrowKind::Shared - | rustc_middle::mir::BorrowKind::Fake => { - CaptureVarKind::Immut { kind_span: capture_kind_span } - } + err.subdiagnostic( + dcx, + match kind { + Some(kd) => match kd { + rustc_middle::mir::BorrowKind::Shared + | rustc_middle::mir::BorrowKind::Fake => { + CaptureVarKind::Immut { kind_span: capture_kind_span } + } - rustc_middle::mir::BorrowKind::Mut { .. } => { - CaptureVarKind::Mut { kind_span: capture_kind_span } - } + rustc_middle::mir::BorrowKind::Mut { .. } => { + CaptureVarKind::Mut { kind_span: capture_kind_span } + } + }, + None => CaptureVarKind::Move { kind_span: capture_kind_span }, }, - None => CaptureVarKind::Move { kind_span: capture_kind_span }, - }); + ); }; let diag = f(closure_kind, path_span); - match dcx { - Some(hd) => err.eager_subdiagnostic(hd, diag), - None => err.subdiagnostic(diag), - }; + err.subdiagnostic(dcx, diag); } } @@ -1025,26 +1033,33 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { CallKind::FnCall { fn_trait_id, .. } if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() => { - err.subdiagnostic(CaptureReasonLabel::Call { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); - err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::Call { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); + err.subdiagnostic(self.dcx(), CaptureReasonNote::FnOnceMoveInCall { var_span }); } CallKind::Operator { self_arg, .. } => { let self_arg = self_arg.unwrap(); - err.subdiagnostic(CaptureReasonLabel::OperatorUse { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::OperatorUse { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); if self.fn_self_span_reported.insert(fn_span) { - err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator { - span: self_arg.span, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonNote::LhsMoveByOperator { span: self_arg.span }, + ); } } CallKind::Normal { self_arg, desugaring, method_did, method_args } => { @@ -1061,11 +1076,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let func = tcx.def_path_str(method_did); - err.subdiagnostic(CaptureReasonNote::FuncTakeSelf { - func, - place_name: place_name.clone(), - span: self_arg.span, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonNote::FuncTakeSelf { + func, + place_name: place_name.clone(), + span: self_arg.span, + }, + ); } let parent_did = tcx.parent(method_did); let parent_self_ty = @@ -1079,7 +1097,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result)) }); if is_option_or_result && maybe_reinitialized_locations_is_empty { - err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::BorrowContent { var_span }, + ); } if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring { let ty = moved_place.ty(self.body, tcx).ty; @@ -1093,18 +1114,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => false, }; if suggest { - err.subdiagnostic(CaptureReasonSuggest::IterateSlice { - ty, - span: move_span.shrink_to_lo(), - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonSuggest::IterateSlice { + ty, + span: move_span.shrink_to_lo(), + }, + ); } - err.subdiagnostic(CaptureReasonLabel::ImplicitCall { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::ImplicitCall { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); // If the moved place was a `&mut` ref, then we can // suggest to reborrow it where it was moved, so it // will still be valid by the time we get to the usage. @@ -1128,19 +1155,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } else { if let Some((CallDesugaringKind::Await, _)) = desugaring { - err.subdiagnostic(CaptureReasonLabel::Await { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::Await { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); } else { - err.subdiagnostic(CaptureReasonLabel::MethodCall { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::MethodCall { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); } // Erase and shadow everything that could be passed to the new infcx. let ty = moved_place.ty(self.body, tcx).ty; @@ -1155,7 +1188,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) && self.infcx.can_eq(self.param_env, ty, self_ty) { - err.eager_subdiagnostic( + err.subdiagnostic( self.dcx(), CaptureReasonSuggest::FreshReborrow { span: move_span.shrink_to_hi(), @@ -1239,17 +1272,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } else { if move_span != span || is_loop_message { - err.subdiagnostic(CaptureReasonLabel::MovedHere { - move_span, - is_partial, - is_move_msg, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::MovedHere { + move_span, + is_partial, + is_move_msg, + is_loop_message, + }, + ); } // If the move error occurs due to a loop, don't show // another message for the same span if !is_loop_message { - move_spans.var_subdiag(None, err, None, |kind, var_span| match kind { + move_spans.var_subdiag(self.dcx(), err, None, |kind, var_span| match kind { hir::ClosureKind::Coroutine(_) => { CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial } } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 126a50c91b494..dad20690d02cc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -448,12 +448,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { None => "value".to_string(), }; - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move: false, - ty: place_ty, - place: &place_desc, - span, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }, + ); } else { binds_to.sort(); binds_to.dedup(); @@ -475,14 +478,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(desc) => format!("`{desc}`"), None => "value".to_string(), }; - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move: false, - ty: place_ty, - place: &place_desc, - span, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }, + ); - use_spans.args_subdiag(err, |args_span| { + use_spans.args_subdiag(self.dcx(), err, |args_span| { crate::session_diagnostics::CaptureArgLabel::MoveOutPlace { place: place_desc, args_span, @@ -580,12 +586,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if binds_to.len() == 1 { let place_desc = &format!("`{}`", self.local_names[*local].unwrap()); - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move: false, - ty: bind_to.ty, - place: place_desc, - span: binding_span, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: bind_to.ty, + place: place_desc, + span: binding_span, + }, + ); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index b3d684086c286..5e659a5f3c239 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -229,7 +229,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if suggest { borrow_spans.var_subdiag( - None, + self.dcx(), &mut err, Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }), |_kind, var_span| { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 7529ec53a9869..e8effd5c1633a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -616,13 +616,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap(); let upvar_def_span = self.infcx.tcx.hir().span(def_hir); let upvar_span = upvars_map.get(&def_hir).unwrap().span; - diag.subdiagnostic(VarHereDenote::Defined { span: upvar_def_span }); - diag.subdiagnostic(VarHereDenote::Captured { span: upvar_span }); + diag.subdiagnostic(self.dcx(), VarHereDenote::Defined { span: upvar_def_span }); + diag.subdiagnostic(self.dcx(), VarHereDenote::Captured { span: upvar_span }); } } if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() { - diag.subdiagnostic(VarHereDenote::FnMutInferred { span: fr_span }); + diag.subdiagnostic(self.dcx(), VarHereDenote::FnMutInferred { span: fr_span }); } self.suggest_move_on_borrowing_closure(&mut diag); @@ -788,7 +788,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }, }; - diag.subdiagnostic(err_category); + diag.subdiagnostic(self.dcx(), err_category); self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr); self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr); @@ -979,7 +979,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ident.span, "calling this method introduces the `impl`'s `'static` requirement", ); - err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); + err.subdiagnostic(self.dcx(), RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), "consider relaxing the implicit `'static` requirement", diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index cc0fbe46dcc11..79eb4406b8a33 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -122,7 +122,7 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl diag.span(span); }; if let Some(missing_features) = self.missing_features { - diag.subdiagnostic(missing_features); + diag.subdiagnostic(dcx, missing_features); } diag.arg("features", self.features.join(", ")); diag diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 587c5e9e8d235..87e3774068bcd 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -131,7 +131,7 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl diag.span(span); }; if let Some(missing_features) = self.missing_features { - diag.subdiagnostic(missing_features); + diag.subdiagnostic(dcx, missing_features); } diag.arg("features", self.features.join(", ")); diag diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 0c93cfaa54647..25ddd5e85f9f3 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -131,7 +131,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { // FIXME(effects) revisit this if !tcx.is_const_trait_impl_raw(data.impl_def_id) { let span = tcx.def_span(data.impl_def_id); - err.subdiagnostic(errors::NonConstImplNote { span }); + err.subdiagnostic(tcx.dcx(), errors::NonConstImplNote { span }); } } } diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index a1abe8fd4f306..f91b6655f6399 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -263,14 +263,10 @@ pub enum SubdiagnosticMessage { /// Translatable message which has already been translated eagerly. /// /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would - /// be instantiated multiple times with different values. As translation normally happens - /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run, - /// the setting of diagnostic arguments in the derived code will overwrite previous variable - /// values and only the final value will be set when translation occurs - resulting in - /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic - /// happening immediately after the subdiagnostic derive's logic has been run. This variant - /// stores messages which have been translated eagerly. - Eager(Cow<'static, str>), + /// be instantiated multiple times with different values. These subdiagnostics' messages + /// are translated when they are added to the parent diagnostic, producing this variant of + /// `DiagnosticMessage`. + Translated(Cow<'static, str>), /// Identifier of a Fluent message. Instances of this variant are generated by the /// `Subdiagnostic` derive. FluentIdentifier(FluentId), @@ -307,19 +303,15 @@ impl From> for SubdiagnosticMessage { pub enum DiagnosticMessage { /// Non-translatable diagnostic message. Str(Cow<'static, str>), - /// Translatable message which has already been translated eagerly. + /// Translatable message which has been already translated. /// /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would - /// be instantiated multiple times with different values. As translation normally happens - /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run, - /// the setting of diagnostic arguments in the derived code will overwrite previous variable - /// values and only the final value will be set when translation occurs - resulting in - /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic - /// happening immediately after the subdiagnostic derive's logic has been run. This variant - /// stores messages which have been translated eagerly. - Eager(Cow<'static, str>), + /// be instantiated multiple times with different values. These subdiagnostics' messages + /// are translated when they are added to the parent diagnostic, producing this variant of + /// `DiagnosticMessage`. + Translated(Cow<'static, str>), /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic - /// message. + /// message. Yet to be translated. /// /// /// @@ -336,7 +328,7 @@ impl DiagnosticMessage { pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self { let attr = match sub { SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s), - SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s), + SubdiagnosticMessage::Translated(s) => return DiagnosticMessage::Translated(s), SubdiagnosticMessage::FluentIdentifier(id) => { return DiagnosticMessage::FluentIdentifier(id, None); } @@ -345,7 +337,7 @@ impl DiagnosticMessage { match self { DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()), - DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()), + DiagnosticMessage::Translated(s) => DiagnosticMessage::Translated(s.clone()), DiagnosticMessage::FluentIdentifier(id, _) => { DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr)) } @@ -354,7 +346,7 @@ impl DiagnosticMessage { pub fn as_str(&self) -> Option<&str> { match self { - DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s), + DiagnosticMessage::Translated(s) | DiagnosticMessage::Str(s) => Some(s), DiagnosticMessage::FluentIdentifier(_, _) => None, } } @@ -396,7 +388,7 @@ impl Into for DiagnosticMessage { fn into(self) -> SubdiagnosticMessage { match self { DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s), - DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s), + DiagnosticMessage::Translated(s) => SubdiagnosticMessage::Translated(s), DiagnosticMessage::FluentIdentifier(id, None) => { SubdiagnosticMessage::FluentIdentifier(id) } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index b14a12175c79b..d31321b48d007 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -851,18 +851,11 @@ impl Diagnostic { self } - /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see - /// [rustc_macros::Subdiagnostic]). - pub fn subdiagnostic(&mut self, subdiagnostic: impl AddToDiagnostic) -> &mut Self { - subdiagnostic.add_to_diagnostic(self); - self - } - /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of /// interpolated variables). - pub fn eager_subdiagnostic( + pub fn subdiagnostic( &mut self, dcx: &crate::DiagCtxt, subdiagnostic: impl AddToDiagnostic, @@ -921,7 +914,7 @@ impl Diagnostic { /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by /// combining it with the primary message of the diagnostic (if translatable, otherwise it just /// passes the user's string along). - fn subdiagnostic_message_to_diagnostic_message( + pub(crate) fn subdiagnostic_message_to_diagnostic_message( &self, attr: impl Into, ) -> DiagnosticMessage { diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index e484bef0e0bc9..0572df69ca947 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -404,9 +404,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { name: impl Into>, arg: impl IntoDiagnosticArg, )); forward!((subdiagnostic, with_subdiagnostic)( - subdiagnostic: impl crate::AddToDiagnostic, - )); - forward!((eager_subdiagnostic, with_eager_subdiagnostic)( dcx: &DiagCtxt, subdiagnostic: impl crate::AddToDiagnostic, )); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 38c6661377b19..00b7c50ad17d3 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -10,6 +10,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::{FileLines, FileName, SourceFile, Span}; +use crate::error::TranslateError; use crate::snippet::{ Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString, }; @@ -559,6 +560,18 @@ pub struct SilentEmitter { pub fatal_note: String, } +pub fn silent_translate<'a>( + message: &'a DiagnosticMessage, +) -> Result, TranslateError<'_>> { + match message { + DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => Ok(Cow::Borrowed(msg)), + DiagnosticMessage::FluentIdentifier(identifier, _) => { + // Any value works here. + Ok(identifier.clone()) + } + } +} + impl Translate for SilentEmitter { fn fluent_bundle(&self) -> Option<&Lrc> { None @@ -567,6 +580,16 @@ impl Translate for SilentEmitter { fn fallback_fluent_bundle(&self) -> &FluentBundle { panic!("silent emitter attempted to translate message") } + + // Override `translate_message` for the silent emitter because eager translation of + // subdiagnostics result in a call to this. + fn translate_message<'a>( + &'a self, + message: &'a DiagnosticMessage, + _: &'a FluentArgs<'_>, + ) -> Result, TranslateError<'_>> { + silent_translate(message) + } } impl Emitter for SilentEmitter { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b738ecb54ffc1..986e87cd2e2ce 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -640,7 +640,8 @@ impl DiagCtxt { message: DiagnosticMessage, args: impl Iterator>, ) -> SubdiagnosticMessage { - SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args))) + let inner = self.inner.borrow(); + inner.eagerly_translate(message, args) } /// Translate `message` eagerly with `args` to `String`. @@ -650,8 +651,7 @@ impl DiagCtxt { args: impl Iterator>, ) -> String { let inner = self.inner.borrow(); - let args = crate::translation::to_fluent_args(args); - inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string() + inner.eagerly_translate_to_string(message, args) } // This is here to not allow mutation of flags; @@ -1446,6 +1446,25 @@ impl DiagCtxtInner { .or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } + /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`. + pub fn eagerly_translate<'a>( + &self, + message: DiagnosticMessage, + args: impl Iterator>, + ) -> SubdiagnosticMessage { + SubdiagnosticMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args))) + } + + /// Translate `message` eagerly with `args` to `String`. + pub fn eagerly_translate_to_string<'a>( + &self, + message: DiagnosticMessage, + args: impl Iterator>, + ) -> String { + let args = crate::translation::to_fluent_args(args); + self.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string() + } + fn flush_delayed(&mut self) { if self.delayed_bugs.is_empty() { return; @@ -1484,15 +1503,22 @@ impl DiagCtxtInner { } let mut bug = - if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; + if backtrace || self.ice_file.is_none() { bug.decorate(self) } else { bug.inner }; // "Undelay" the delayed bugs (into plain `Bug`s). if bug.level != DelayedBug { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. - bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { + let subdiag = InvalidFlushedDelayedDiagnosticLevel { span: bug.span.primary_span().unwrap(), level: bug.level, + }; + // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it + // just uses `DiagCtxtInner` functions. + subdiag.add_to_diagnostic_with(&mut bug, |diag, msg| { + let args = diag.args(); + let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); + self.eagerly_translate(msg, args) }); } bug.level = Bug; @@ -1527,25 +1553,35 @@ impl DelayedDiagnostic { DelayedDiagnostic { inner: diagnostic, note: backtrace } } - fn decorate(mut self) -> Diagnostic { + fn decorate(mut self, dcx: &DiagCtxtInner) -> Diagnostic { + // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it + // just uses `DiagCtxtInner` functions. + let subdiag_with = |diag: &mut Diagnostic, msg| { + let args = diag.args(); + let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); + dcx.eagerly_translate(msg, args) + }; + match self.note.status() { BacktraceStatus::Captured => { let inner = &self.inner; - self.inner.subdiagnostic(DelayedAtWithNewline { + let subdiag = DelayedAtWithNewline { span: inner.span.primary_span().unwrap_or(DUMMY_SP), emitted_at: inner.emitted_at.clone(), note: self.note, - }); + }; + subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with); } // Avoid the needless newline when no backtrace has been captured, // the display impl should just be a single line. _ => { let inner = &self.inner; - self.inner.subdiagnostic(DelayedAtWithoutNewline { + let subdiag = DelayedAtWithoutNewline { span: inner.span.primary_span().unwrap_or(DUMMY_SP), emitted_at: inner.emitted_at.clone(), note: self.note, - }); + }; + subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with); } } @@ -1691,15 +1727,15 @@ impl Level { } // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite. -pub fn add_elided_lifetime_in_path_suggestion( +pub fn add_elided_lifetime_in_path_suggestion( source_map: &SourceMap, - diag: &mut Diagnostic, + diag: &mut DiagnosticBuilder<'_, E>, n: usize, path_span: Span, incl_angl_brckt: bool, insertion_span: Span, ) { - diag.subdiagnostic(ExpectedLifetimeParameter { span: path_span, count: n }); + diag.subdiagnostic(diag.dcx, ExpectedLifetimeParameter { span: path_span, count: n }); if !source_map.is_span_accessible(insertion_span) { // Do not try to suggest anything if generated by a proc-macro. return; @@ -1708,11 +1744,10 @@ pub fn add_elided_lifetime_in_path_suggestion( let suggestion = if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") }; - diag.subdiagnostic(IndicateAnonymousLifetime { - span: insertion_span.shrink_to_hi(), - count: n, - suggestion, - }); + diag.subdiagnostic( + diag.dcx, + IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }, + ); } pub fn report_ambiguity_error<'a, G: EmissionGuarantee>( diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 5bdac367d55e7..5f074dbbbad30 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -2,7 +2,7 @@ use crate::error::{TranslateError, TranslateErrorKind}; use crate::snippet::Style; use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle}; use rustc_data_structures::sync::Lrc; -use rustc_error_messages::FluentArgs; +pub use rustc_error_messages::FluentArgs; use std::borrow::Cow; use std::env; use std::error::Report; @@ -61,7 +61,7 @@ pub trait Translate { ) -> Result, TranslateError<'_>> { trace!(?message, ?args); let (identifier, attr) = match message { - DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => { + DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => { return Ok(Cow::Borrowed(msg)); } DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index eec86c36aedae..b3d370a9c8dec 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -7,7 +7,7 @@ use crate::mbe::{ use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage}; +use rustc_errors::{Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticMessage}; use rustc_parse::parser::{Parser, Recovery}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Ident; @@ -58,7 +58,7 @@ pub(super) fn failed_to_match_macro<'cx>( err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); } - annotate_doc_comment(&mut err, sess.source_map(), span); + annotate_doc_comment(cx.sess.dcx(), &mut err, sess.source_map(), span); if let Some(span) = remaining_matcher.span() { err.span_note(span, format!("while trying to match {remaining_matcher}")); @@ -311,12 +311,17 @@ enum ExplainDocComment { }, } -pub(super) fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) { +pub(super) fn annotate_doc_comment( + dcx: &DiagCtxt, + err: &mut Diagnostic, + sm: &SourceMap, + span: Span, +) { if let Ok(src) = sm.span_to_snippet(span) { if src.starts_with("///") || src.starts_with("/**") { - err.subdiagnostic(ExplainDocComment::Outer { span }); + err.subdiagnostic(dcx, ExplainDocComment::Outer { span }); } else if src.starts_with("//!") || src.starts_with("/*!") { - err.subdiagnostic(ExplainDocComment::Inner { span }); + err.subdiagnostic(dcx, ExplainDocComment::Inner { span }); } } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 83e0f870c8a25..c82609503c18a 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -454,7 +454,7 @@ pub fn compile_declarative_macro( let sp = token.span.substitute_dummy(def.span); let mut err = sess.dcx().struct_span_err(sp, s); err.span_label(sp, msg); - annotate_doc_comment(&mut err, sess.source_map(), sp); + annotate_doc_comment(sess.dcx(), &mut err, sess.source_map(), sp); err.emit(); return dummy_syn_ext(); } diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 0311aa94cd485..f4ac010691cd4 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -261,7 +261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let semi = expr.span.shrink_to_hi().with_hi(semi_span.hi()); let sugg = crate::errors::RemoveSemiForCoerce { expr: expr.span, ret, semi }; - diag.subdiagnostic(sugg); + diag.subdiagnostic(self.dcx(), sugg); } /// When the previously checked expression (the scrutinee) diverges, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index f21de1609cb7f..2142bb914209a 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -993,19 +993,25 @@ impl<'a, 'tcx> CastCheck<'tcx> { if let Some((deref_ty, _)) = derefed { // Give a note about what the expr derefs to. if deref_ty != self.expr_ty.peel_refs() { - err.subdiagnostic(errors::DerefImplsIsEmpty { - span: self.expr_span, - deref_ty: fcx.ty_to_string(deref_ty), - }); + err.subdiagnostic( + fcx.dcx(), + errors::DerefImplsIsEmpty { + span: self.expr_span, + deref_ty: fcx.ty_to_string(deref_ty), + }, + ); } // Create a multipart suggestion: add `!` and `.is_empty()` in // place of the cast. - err.subdiagnostic(errors::UseIsEmpty { - lo: self.expr_span.shrink_to_lo(), - hi: self.span.with_lo(self.expr_span.hi()), - expr_ty: fcx.ty_to_string(self.expr_ty), - }); + err.subdiagnostic( + fcx.dcx(), + errors::UseIsEmpty { + lo: self.expr_span.shrink_to_lo(), + hi: self.span.with_lo(self.expr_span.hi()), + expr_ty: fcx.ty_to_string(self.expr_ty), + }, + ); } } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 19bdeab409bb7..7f30b36a1f94a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } oprnd_t = Ty::new_error(tcx, err.emit()); } @@ -2050,7 +2050,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .shrink_to_hi() .to(range_end.span); - err.subdiagnostic(TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr }); + err.subdiagnostic( + self.dcx(), + TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr }, + ); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 65b8505c09098..339bc9f0f7a99 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1269,7 +1269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // The user provided `ptr::null()`, but the function expects // `ptr::null_mut()`. - err.subdiagnostic(SuggestPtrNullMut { span: arg.span }); + err.subdiagnostic(self.dcx(), SuggestPtrNullMut { span: arg.span }); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 8b6f263b1a746..c1a32a1afa3cf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -458,13 +458,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // but those checks need to be a bit more delicate and the benefit is diminishing. if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref { let sugg = prefix_wrap(".as_ref()"); - err.subdiagnostic(errors::SuggestConvertViaMethod { - span: expr.span.shrink_to_hi(), - sugg, - expected, - found, - borrow_removal_span, - }); + err.subdiagnostic( + self.dcx(), + errors::SuggestConvertViaMethod { + span: expr.span.shrink_to_hi(), + sugg, + expected, + found, + borrow_removal_span, + }, + ); return true; } else if let Some((deref_ty, _)) = self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1) @@ -472,13 +475,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && error_tys_equate_as_ref { let sugg = prefix_wrap(".as_deref()"); - err.subdiagnostic(errors::SuggestConvertViaMethod { - span: expr.span.shrink_to_hi(), - sugg, - expected, - found, - borrow_removal_span, - }); + err.subdiagnostic( + self.dcx(), + errors::SuggestConvertViaMethod { + span: expr.span.shrink_to_hi(), + sugg, + expected, + found, + borrow_removal_span, + }, + ); return true; } else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind() && Some(adt.did()) == self.tcx.lang_items().string() @@ -565,7 +571,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { end: span.shrink_to_hi(), }, }; - err.subdiagnostic(suggest_boxing); + err.subdiagnostic(self.dcx(), suggest_boxing); true } else { @@ -799,29 +805,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &fn_decl.output { &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => { // `fn main()` must return `()`, do not suggest changing return type - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span }); + err.subdiagnostic(self.dcx(), errors::ExpectedReturnTypeLabel::Unit { span }); return true; } &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => { if let Some(found) = found.make_suggestable(self.tcx, false) { - err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { - span, - found: found.to_string(), - }); + err.subdiagnostic( + self.dcx(), + errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() }, + ); return true; } else if let ty::Closure(_, args) = found.kind() // FIXME(compiler-errors): Get better at printing binders... && let closure = args.as_closure() && closure.sig().is_suggestable(self.tcx, false) { - err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { - span, - found: closure.print_as_impl_trait().to_string(), - }); + err.subdiagnostic( + self.dcx(), + errors::AddReturnTypeSuggestion::Add { + span, + found: closure.print_as_impl_trait().to_string(), + }, + ); return true; } else { // FIXME: if `found` could be `impl Iterator` we should suggest that. - err.subdiagnostic(errors::AddReturnTypeSuggestion::MissingHere { span }); + err.subdiagnostic( + self.dcx(), + errors::AddReturnTypeSuggestion::MissingHere { span }, + ); return true; } } @@ -843,16 +855,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?found); if found.is_suggestable(self.tcx, false) { if term.span.is_empty() { - err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { - span: term.span, - found: found.to_string(), - }); + err.subdiagnostic( + self.dcx(), + errors::AddReturnTypeSuggestion::Add { + span: term.span, + found: found.to_string(), + }, + ); return true; } else { - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { - span: term.span, - expected, - }); + err.subdiagnostic( + self.dcx(), + errors::ExpectedReturnTypeLabel::Other { + span: term.span, + expected, + }, + ); } } } else { @@ -867,10 +885,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.normalize(hir_ty.span, ty); let ty = self.tcx.instantiate_bound_regions_with_erased(ty); if self.can_coerce(expected, ty) { - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { - span: hir_ty.span, - expected, - }); + err.subdiagnostic( + self.dcx(), + errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected }, + ); self.try_suggest_return_impl_trait(err, expected, ty, fn_id); return true; } @@ -1106,7 +1124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None); if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); true } else { false @@ -1220,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { return false; }; - diag.subdiagnostic(subdiag); + diag.subdiagnostic(self.dcx(), subdiag); return true; } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 729ce1f00cd8b..2269e9f7d4c3d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3173,19 +3173,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if impls_trait(trait_info.def_id) { self.suggest_valid_traits(err, vec![trait_info.def_id], false); } else { - err.subdiagnostic(CandidateTraitNote { - span: self.tcx.def_span(trait_info.def_id), - trait_name: self.tcx.def_path_str(trait_info.def_id), - item_name, - action_or_ty: if trait_missing_method { - "NONE".to_string() - } else { - param_type.map_or_else( - || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented. - ToString::to_string, - ) + err.subdiagnostic( + self.dcx(), + CandidateTraitNote { + span: self.tcx.def_span(trait_info.def_id), + trait_name: self.tcx.def_path_str(trait_info.def_id), + item_name, + action_or_ty: if trait_missing_method { + "NONE".to_string() + } else { + param_type.map_or_else( + || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented. + ToString::to_string, + ) + }, }, - }); + ); } } trait_infos => { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 9a8444e6a2bcd..929b3557f5242 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -824,7 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the previous expression was a block expression, suggest parentheses // (turning this into a binary subtraction operation instead.) // for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs) - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } else { match actual.kind() { Uint(_) if op == hir::UnOp::Neg => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b953b25d6c4cf..280701b8ec6d5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -846,7 +846,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { arm_ty, arm_span, ) { - err.subdiagnostic(subdiag); + err.subdiagnostic(self.dcx(), subdiag); } if let hir::Node::Expr(m) = self.tcx.parent_hir_node(scrut_hir_id) && let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(m.hir_id) @@ -892,7 +892,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { else_ty, else_span, ) { - err.subdiagnostic(subdiag); + err.subdiagnostic(self.dcx(), subdiag); } // don't suggest wrapping either blocks in `if .. {} else {}` let is_empty_arm = |id| { diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 02200d6a4aaf5..50ac6235debc0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -342,7 +342,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { trait_predicates: trait_predicates.join(", "), } }; - err.subdiagnostic(suggestion); + err.subdiagnostic(self.dcx(), suggestion); } pub(super) fn report_placeholder_failure( diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 248e1c0fcc878..31e980fdfabe3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -84,7 +84,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)), end_sp: return_sp.shrink_to_hi(), }; - err.subdiagnostic(sugg); + err.subdiagnostic(self.dcx(), sugg); let mut starts = Vec::new(); let mut ends = Vec::new(); @@ -93,7 +93,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ends.push(span.shrink_to_hi()); } let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends }; - err.subdiagnostic(sugg); + err.subdiagnostic(self.dcx(), sugg); } pub(super) fn suggest_tuple_pattern( @@ -138,7 +138,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span_low: cause.span.shrink_to_lo(), span_high: cause.span.shrink_to_hi(), }; - diag.subdiagnostic(sugg); + diag.subdiagnostic(self.dcx(), sugg); } _ => { // More than one matching variant. @@ -147,7 +147,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { cause_span: cause.span, compatible_variants, }; - diag.subdiagnostic(sugg); + diag.subdiagnostic(self.dcx(), sugg); } } } @@ -219,9 +219,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }, (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => { // FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic - diag.subdiagnostic(ConsiderAddingAwait::FutureSugg { - span: exp_span.shrink_to_hi(), - }); + diag.subdiagnostic( + self.dcx(), + ConsiderAddingAwait::FutureSugg { span: exp_span.shrink_to_hi() }, + ); Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span }) } (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() @@ -246,7 +247,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { _ => None, }; if let Some(subdiag) = subdiag { - diag.subdiagnostic(subdiag); + diag.subdiagnostic(self.dcx(), subdiag); } } @@ -282,7 +283,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } else { return; }; - diag.subdiagnostic(suggestion); + diag.subdiagnostic(self.dcx(), suggestion); } } } @@ -322,15 +323,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (true, false) => FunctionPointerSuggestion::UseRef { span, fn_name }, (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name }, (true, true) => { - diag.subdiagnostic(FnItemsAreDistinct); + diag.subdiagnostic(self.dcx(), FnItemsAreDistinct); FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig } } (false, false) => { - diag.subdiagnostic(FnItemsAreDistinct); + diag.subdiagnostic(self.dcx(), FnItemsAreDistinct); FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig } } }; - diag.subdiagnostic(sugg); + diag.subdiagnostic(self.dcx(), sugg); } (ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => { let expected_sig = @@ -339,7 +340,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2)); if self.same_type_modulo_infer(*expected_sig, *found_sig) { - diag.subdiagnostic(FnUniqTypes); + diag.subdiagnostic(self.dcx(), FnUniqTypes); } if !self.same_type_modulo_infer(*found_sig, *expected_sig) @@ -368,7 +369,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } }; - diag.subdiagnostic(sug); + diag.subdiagnostic(self.dcx(), sug); } (ty::FnDef(did, args), ty::FnPtr(sig)) => { let expected_sig = @@ -387,7 +388,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { format!("{fn_name} as {found_sig}") }; - diag.subdiagnostic(FnConsiderCasting { casting }); + diag.subdiagnostic(self.dcx(), FnConsiderCasting { casting }); } _ => { return; @@ -819,7 +820,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let diag = self.consider_returning_binding_diag(blk, expected_ty); match diag { Some(diag) => { - err.subdiagnostic(diag); + err.subdiagnostic(self.dcx(), diag); true } None => false, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7445e2e80b407..2987d8a5ed0b2 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1758,7 +1758,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { diag.note(note.to_string()); } if let Some(sugg) = self.suggestion { - diag.subdiagnostic(sugg); + diag.subdiagnostic(diag.dcx, sugg); } } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 85bb9584a0575..ae481efb263df 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -331,44 +331,7 @@ impl DiagnosticDeriveVariantBuilder { } } (Meta::Path(_), "subdiagnostic") => { - if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() { - let DiagnosticDeriveKind::Diagnostic = self.kind else { - // No eager translation for lints. - return Ok(quote! { diag.subdiagnostic(#binding); }); - }; - return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); - } else { - return Ok(quote! { diag.subdiagnostic(#binding); }); - } - } - (Meta::List(meta_list), "subdiagnostic") => { - let err = || { - span_err( - meta_list.span().unwrap(), - "`eager` is the only supported nested attribute for `subdiagnostic`", - ) - .emit(); - }; - - let Ok(p): Result = meta_list.parse_args() else { - err(); - return Ok(quote! {}); - }; - - if !p.is_ident("eager") { - err(); - return Ok(quote! {}); - } - - match &self.kind { - DiagnosticDeriveKind::Diagnostic => {} - DiagnosticDeriveKind::LintDiagnostic => { - throw_invalid_attr!(attr, |diag| { - diag.help("eager subdiagnostics are not supported on lints") - }) - } - }; - return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); + return Ok(quote! { diag.subdiagnostic(diag.dcx, #binding); }); } _ => (), } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 692f4511bb807..a0235f20a0570 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1109,7 +1109,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( let all_arms_have_guards = arms.iter().all(|arm_id| thir[*arm_id].guard.is_some()); if !is_empty_match && all_arms_have_guards { - err.subdiagnostic(NonExhaustiveMatchAllArmsGuarded); + err.subdiagnostic(cx.tcx.dcx(), NonExhaustiveMatchAllArmsGuarded); } if let Some((span, sugg)) = suggestion { err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders); diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 30de40e226c33..ff4918df9a262 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -270,7 +270,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { diag.span_label(self.yield_sp, fluent::_subdiag::label); if let Some(reason) = self.reason { - diag.subdiagnostic(reason); + diag.subdiagnostic(diag.dcx, reason); } diag.span_help(self.src_sp, fluent::_subdiag::help); diag.arg("pre", self.pre); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 445d5b2ce790c..e44c63f1ed760 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2350,7 +2350,7 @@ impl<'a> Parser<'a> { let mut err = self.dcx().struct_span_err(span, msg); let sp = self.sess.source_map().start_point(self.token.span); if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } err.span_label(span, "expected expression"); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1a57474bac289..06134818435ca 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1433,7 +1433,7 @@ impl<'a> Parser<'a> { // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` // then suggest parens around the lhs. if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(this.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } err }) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8050b34956ce9..a34adbe7f674d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1917,7 +1917,7 @@ impl<'a> Parser<'a> { if self.token.kind == token::Not { if let Err(mut err) = self.unexpected::() { // Encounter the macro invocation - err.subdiagnostic(MacroExpandsToAdtField { adt_ty }); + err.subdiagnostic(self.dcx(), MacroExpandsToAdtField { adt_ty }); return Err(err); } } @@ -2336,10 +2336,13 @@ impl<'a> Parser<'a> { .into_iter() .any(|s| self.prev_token.is_ident_named(s)); - err.subdiagnostic(errors::FnTraitMissingParen { - span: self.prev_token.span, - machine_applicable, - }); + err.subdiagnostic( + self.dcx(), + errors::FnTraitMissingParen { + span: self.prev_token.span, + machine_applicable, + }, + ); } return Err(err); } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 12260ec95a5b9..75fc013d3e6fe 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -843,7 +843,7 @@ impl<'a> Parser<'a> { let sp = self.sess.source_map().start_point(self.token.span); if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } Err(err) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d91a865e38aba..737481c78db68 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -403,9 +403,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let Some(suggestion) = suggestion { - err.subdiagnostic(ChangeImportBindingSuggestion { span: binding_span, suggestion }); + err.subdiagnostic( + self.dcx(), + ChangeImportBindingSuggestion { span: binding_span, suggestion }, + ); } else { - err.subdiagnostic(ChangeImportBinding { span: binding_span }); + err.subdiagnostic(self.dcx(), ChangeImportBinding { span: binding_span }); } } @@ -1430,17 +1433,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ); if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules { - err.subdiagnostic(MaybeMissingMacroRulesName { span: ident.span }); + err.subdiagnostic(self.dcx(), MaybeMissingMacroRulesName { span: ident.span }); return; } if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) { - err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident }); + err.subdiagnostic(self.dcx(), ExplicitUnsafeTraits { span: ident.span, ident }); return; } if self.macro_names.contains(&ident.normalize_to_macros_2_0()) { - err.subdiagnostic(AddedMacroUse); + err.subdiagnostic(self.dcx(), AddedMacroUse); return; } @@ -1450,10 +1453,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let span = self.def_span(def_id); let source_map = self.tcx.sess.source_map(); let head_span = source_map.guess_head_span(span); - err.subdiagnostic(ConsiderAddingADerive { - span: head_span.shrink_to_lo(), - suggestion: "#[derive(Default)]\n".to_string(), - }); + err.subdiagnostic( + self.dcx(), + ConsiderAddingADerive { + span: head_span.shrink_to_lo(), + suggestion: "#[derive(Default)]\n".to_string(), + }, + ); } for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] { if let Ok(binding) = self.early_resolve_ident_in_lexical_scope( diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 30fb35238c3c7..dcd01b9b33417 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1262,12 +1262,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // exclude decl_macro if self.get_macro_by_def_id(def_id).macro_rules => { - err.subdiagnostic(ConsiderAddingMacroExport { + err.subdiagnostic(self.dcx(), ConsiderAddingMacroExport { span: binding.span, }); } _ => { - err.subdiagnostic(ConsiderMarkingAsPub { + err.subdiagnostic(self.dcx(), ConsiderMarkingAsPub { span: import.span, ident, }); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 5d712461993d8..7f0d8374b3abc 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1095,11 +1095,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { Side::Start => (segment.ident.span.between(range.span), " @ ".into()), Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)), }; - err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg { - span, - ident: segment.ident, - snippet, - }); + err.subdiagnostic( + self.r.dcx(), + errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg { + span, + ident: segment.ident, + snippet, + }, + ); } enum Side { @@ -1191,10 +1194,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { }); if let Some(param) = param { - err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg { - span: param.shrink_to_lo(), - applicability, - }); + err.subdiagnostic( + self.r.dcx(), + errors::UnexpectedResChangeTyToConstParamSugg { + span: param.shrink_to_lo(), + applicability, + }, + ); } } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 8adb0cbcc9d76..a906d5532b5a0 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -173,21 +173,21 @@ pub fn add_feature_diagnostics_for_issue( feature_from_cli: bool, ) { if let Some(n) = find_feature_issue(feature, issue) { - err.subdiagnostic(FeatureDiagnosticForIssue { n }); + err.subdiagnostic(sess.dcx(), FeatureDiagnosticForIssue { n }); } // #23973: do not suggest `#![feature(...)]` if we are in beta/stable if sess.parse_sess.unstable_features.is_nightly_build() { if feature_from_cli { - err.subdiagnostic(CliFeatureDiagnosticHelp { feature }); + err.subdiagnostic(sess.dcx(), CliFeatureDiagnosticHelp { feature }); } else { - err.subdiagnostic(FeatureDiagnosticHelp { feature }); + err.subdiagnostic(sess.dcx(), FeatureDiagnosticHelp { feature }); } if sess.opts.unstable_opts.ui_testing { - err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); + err.subdiagnostic(sess.dcx(), SuggestUpgradeCompiler::ui_testing()); } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { - err.subdiagnostic(suggestion); + err.subdiagnostic(sess.dcx(), suggestion); } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index c7b56aac7e55b..a8b6fc1f12c26 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -4830,11 +4830,14 @@ fn hint_missing_borrow<'tcx>( } if !to_borrow.is_empty() { - err.subdiagnostic(errors::AdjustSignatureBorrow::Borrow { to_borrow }); + err.subdiagnostic(infcx.dcx(), errors::AdjustSignatureBorrow::Borrow { to_borrow }); } if !remove_borrow.is_empty() { - err.subdiagnostic(errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow }); + err.subdiagnostic( + infcx.dcx(), + errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow }, + ); } } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 7f91af59d5622..ed401d5751b69 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -504,7 +504,7 @@ pub fn report_msg<'tcx>( let is_local = machine.is_local(frame_info); // No span for non-local frames and the first frame (which is the error site). if is_local && idx > 0 { - err.eager_subdiagnostic(err.dcx, frame_info.as_note(machine.tcx)); + err.subdiagnostic(err.dcx, frame_info.as_note(machine.tcx)); } else { let sm = sess.source_map(); let span = sm.span_to_embeddable_string(frame_info.span); diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index f0af401d3da4b..cff025cf2ab3a 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; @@ -40,6 +41,16 @@ impl Translate for SilentEmitter { fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { panic!("silent emitter attempted to translate a diagnostic"); } + + // Override `translate_message` for the silent emitter because eager translation of + // subdiagnostics result in a call to this. + fn translate_message<'a>( + &'a self, + message: &'a rustc_errors::DiagnosticMessage, + _: &'a rustc_errors::translation::FluentArgs<'_>, + ) -> Result, rustc_errors::error::TranslateError<'_>> { + rustc_errors::emitter::silent_translate(message) + } } impl Emitter for SilentEmitter { diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index d3cfd28082d61..6cc6fdfc0eb2b 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -701,7 +701,7 @@ struct RawIdentDiagnosticArg { #[diag(no_crate_example)] struct SubdiagnosticBad { #[subdiagnostic(bad)] - //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute note: Note, } @@ -717,7 +717,7 @@ struct SubdiagnosticBadStr { #[diag(no_crate_example)] struct SubdiagnosticBadTwice { #[subdiagnostic(bad, bad)] - //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute note: Note, } @@ -725,7 +725,7 @@ struct SubdiagnosticBadTwice { #[diag(no_crate_example)] struct SubdiagnosticBadLitStr { #[subdiagnostic("bad")] - //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute note: Note, } @@ -739,8 +739,9 @@ struct SubdiagnosticEagerLint { #[derive(Diagnostic)] #[diag(no_crate_example)] -struct SubdiagnosticEagerCorrect { +struct SubdiagnosticEagerFormerlyCorrect { #[subdiagnostic(eager)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute note: Note, } @@ -761,6 +762,7 @@ pub(crate) struct SubdiagnosticWithSuggestion { #[diag(no_crate_example)] struct SubdiagnosticEagerSuggestion { #[subdiagnostic(eager)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute sub: SubdiagnosticWithSuggestion, } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 2032b8a972a3b..f2dbc718c7627 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -468,11 +468,11 @@ LL | #[label] | = help: `#[label]` and `#[suggestion]` can only be applied to fields -error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:703:7 +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:703:5 | LL | #[subdiagnostic(bad)] - | ^^^^^^^^^^^^^ + | ^ error: `#[subdiagnostic = ...]` is not a valid attribute --> $DIR/diagnostic-derive.rs:711:5 @@ -480,40 +480,50 @@ error: `#[subdiagnostic = ...]` is not a valid attribute LL | #[subdiagnostic = "bad"] | ^ -error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:719:7 +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:719:5 | LL | #[subdiagnostic(bad, bad)] - | ^^^^^^^^^^^^^ + | ^ -error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:727:7 +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:727:5 | LL | #[subdiagnostic("bad")] - | ^^^^^^^^^^^^^ + | ^ error: `#[subdiagnostic(...)]` is not a valid attribute --> $DIR/diagnostic-derive.rs:735:5 | LL | #[subdiagnostic(eager)] | ^ + +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:743:5 | - = help: eager subdiagnostics are not supported on lints +LL | #[subdiagnostic(eager)] + | ^ + +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:764:5 + | +LL | #[subdiagnostic(eager)] + | ^ error: expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive.rs:793:23 + --> $DIR/diagnostic-derive.rs:795:23 | LL | #[suggestion(code())] | ^ error: `code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:801:23 + --> $DIR/diagnostic-derive.rs:803:23 | LL | #[suggestion(code(foo))] | ^^^ error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:825:5 + --> $DIR/diagnostic-derive.rs:827:5 | LL | #[suggestion(no_crate_suggestion, code = "")] | ^ @@ -529,13 +539,13 @@ LL | #[diag = "E0123"] | ^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:801:23 + --> $DIR/diagnostic-derive.rs:803:23 | LL | #[suggestion(code(foo))] | ^^^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:810:25 + --> $DIR/diagnostic-derive.rs:812:25 | LL | #[suggestion(code = 3)] | ^ maybe a missing crate `core`? @@ -601,7 +611,7 @@ LL | #[diag(nonsense, code = E0123)] | ^^^^^^^^ not found in `crate::fluent_generated` error[E0425]: cannot find value `__code_34` in this scope - --> $DIR/diagnostic-derive.rs:807:10 + --> $DIR/diagnostic-derive.rs:809:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ not found in this scope @@ -622,7 +632,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 84 previous errors +error: aborting due to 86 previous errors Some errors have detailed explanations: E0277, E0425, E0433. For more information about an error, try `rustc --explain E0277`. From 17066870cd5c5ad367a0232501f6c8d71b4ddea5 Mon Sep 17 00:00:00 2001 From: Johannes Lade Date: Thu, 15 Feb 2024 17:33:37 +0100 Subject: [PATCH 03/40] Fix typo in VecDeque::handle_capacity_increase() doc comment. Strategies B and C both show a full buffer before the capacity increase, while strategy A had one empty element left. Filled the last element in. --- library/alloc/src/collections/vec_deque/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index d062587b8f533..bcba6525fda15 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -485,10 +485,10 @@ impl VecDeque { // H := head // L := last element (`self.to_physical_idx(self.len - 1)`) // - // H L - // [o o o o o o o . ] - // H L - // A [o o o o o o o . . . . . . . . . ] + // H L + // [o o o o o o o o ] + // H L + // A [o o o o o o o o . . . . . . . . ] // L H // [o o o o o o o o ] // H L From 75af3c58f9df479894465e81d374e047082e8789 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 15 Feb 2024 13:58:21 +1100 Subject: [PATCH 04/40] coverage: Regression test for a span extraction inconsistency --- tests/coverage/closure_unit_return.cov-map | 34 +++++++++++++++++++++ tests/coverage/closure_unit_return.coverage | 30 ++++++++++++++++++ tests/coverage/closure_unit_return.rs | 29 ++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 tests/coverage/closure_unit_return.cov-map create mode 100644 tests/coverage/closure_unit_return.coverage create mode 100644 tests/coverage/closure_unit_return.rs diff --git a/tests/coverage/closure_unit_return.cov-map b/tests/coverage/closure_unit_return.cov-map new file mode 100644 index 0000000000000..330a6b420b0e2 --- /dev/null +++ b/tests/coverage/closure_unit_return.cov-map @@ -0,0 +1,34 @@ +Function name: closure_unit_return::explicit_unit +Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 01, 01, 10, 01, 05, 05, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) + +Function name: closure_unit_return::explicit_unit::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 08, 16, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 8, 22) to (start + 2, 6) + +Function name: closure_unit_return::implicit_unit +Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 13, 01, 03, 06, 04, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 19) +- Code(Counter(0)) at (prev + 3, 6) to (start + 4, 2) + +Function name: closure_unit_return::implicit_unit::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 16, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 17, 22) to (start + 2, 6) + diff --git a/tests/coverage/closure_unit_return.coverage b/tests/coverage/closure_unit_return.coverage new file mode 100644 index 0000000000000..1a706b3a18d66 --- /dev/null +++ b/tests/coverage/closure_unit_return.coverage @@ -0,0 +1,30 @@ + LL| |#![feature(coverage_attribute)] + LL| |// edition: 2021 + LL| | + LL| |// Regression test for an inconsistency between functions that return the value + LL| |// of their trailing expression, and functions that implicitly return `()`. + LL| | + LL| 1|fn explicit_unit() { + LL| 1| let closure = || { + LL| 0| (); + LL| 0| }; + LL| | + LL| 1| drop(closure); + LL| 1| () // explicit return of trailing value + LL| 1|} + LL| | + LL| 1|fn implicit_unit() { + LL| 1| let closure = || { + LL| 0| (); + LL| 1| }; + LL| 1| + LL| 1| drop(closure); + LL| 1| // implicit return of `()` + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | explicit_unit(); + LL| | implicit_unit(); + LL| |} + diff --git a/tests/coverage/closure_unit_return.rs b/tests/coverage/closure_unit_return.rs new file mode 100644 index 0000000000000..d2b4ab8bd9ff9 --- /dev/null +++ b/tests/coverage/closure_unit_return.rs @@ -0,0 +1,29 @@ +#![feature(coverage_attribute)] +// edition: 2021 + +// Regression test for an inconsistency between functions that return the value +// of their trailing expression, and functions that implicitly return `()`. + +fn explicit_unit() { + let closure = || { + (); + }; + + drop(closure); + () // explicit return of trailing value +} + +fn implicit_unit() { + let closure = || { + (); + }; + + drop(closure); + // implicit return of `()` +} + +#[coverage(off)] +fn main() { + explicit_unit(); + implicit_unit(); +} From cd9021e8cb1ab6cf5bdf341d7e0538703d86fc5b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 15 Feb 2024 18:12:27 +1100 Subject: [PATCH 05/40] coverage: Discard spans that fill the entire function body When we try to extract coverage-relevant spans from MIR, sometimes we see MIR statements/terminators whose spans cover the entire function body. Those spans tend to be unhelpful for coverage purposes, because they often represent compiler-inserted code, e.g. the implicit return value of `()`. --- .../src/coverage/spans/from_mir.rs | 13 +++++++++---- tests/coverage/closure_unit_return.cov-map | 6 +++--- tests/coverage/closure_unit_return.coverage | 4 ++-- tests/coverage/coverage_attr_closure.cov-map | 8 ++++---- tests/coverage/coverage_attr_closure.coverage | 8 ++++---- tests/coverage/inline-dead.cov-map | 6 +++--- tests/coverage/macro_name_span.cov-map | 4 ++-- tests/coverage/macro_name_span.coverage | 2 +- tests/coverage/unicode.cov-map | 8 -------- tests/coverage/unicode.coverage | 3 +-- 10 files changed, 29 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 9517ede288f5d..2db358379fe51 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -132,18 +132,23 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( bcb_data.basic_blocks.iter().flat_map(move |&bb| { let data = &mir_body[bb]; + let unexpand = move |expn_span| { + unexpand_into_body_span_with_visible_macro(expn_span, body_span) + // Discard any spans that fill the entire body, because they tend + // to represent compiler-inserted code, e.g. implicitly returning `()`. + .filter(|(span, _)| !span.source_equal(body_span)) + }; + let statement_spans = data.statements.iter().filter_map(move |statement| { let expn_span = filtered_statement_span(statement)?; - let (span, visible_macro) = - unexpand_into_body_span_with_visible_macro(expn_span, body_span)?; + let (span, visible_macro) = unexpand(expn_span)?; Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement))) }); let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| { let expn_span = filtered_terminator_span(terminator)?; - let (span, visible_macro) = - unexpand_into_body_span_with_visible_macro(expn_span, body_span)?; + let (span, visible_macro) = unexpand(expn_span)?; Some(SpanFromMir::new(span, visible_macro, bcb, false)) }); diff --git a/tests/coverage/closure_unit_return.cov-map b/tests/coverage/closure_unit_return.cov-map index 330a6b420b0e2..c97b4a44dd6b2 100644 --- a/tests/coverage/closure_unit_return.cov-map +++ b/tests/coverage/closure_unit_return.cov-map @@ -16,13 +16,13 @@ Number of file 0 mappings: 1 - Code(Zero) at (prev + 8, 22) to (start + 2, 6) Function name: closure_unit_return::implicit_unit -Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 13, 01, 03, 06, 04, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 10, 01, 05, 05, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 19) -- Code(Counter(0)) at (prev + 3, 6) to (start + 4, 2) +- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) Function name: closure_unit_return::implicit_unit::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 16, 02, 06] diff --git a/tests/coverage/closure_unit_return.coverage b/tests/coverage/closure_unit_return.coverage index 1a706b3a18d66..1056baa385cb4 100644 --- a/tests/coverage/closure_unit_return.coverage +++ b/tests/coverage/closure_unit_return.coverage @@ -16,8 +16,8 @@ LL| 1|fn implicit_unit() { LL| 1| let closure = || { LL| 0| (); - LL| 1| }; - LL| 1| + LL| 0| }; + LL| | LL| 1| drop(closure); LL| 1| // implicit return of `()` LL| 1|} diff --git a/tests/coverage/coverage_attr_closure.cov-map b/tests/coverage/coverage_attr_closure.cov-map index 2208b28fd4149..5d2c6b00b40f8 100644 --- a/tests/coverage/coverage_attr_closure.cov-map +++ b/tests/coverage/coverage_attr_closure.cov-map @@ -15,14 +15,14 @@ Number of file 0 mappings: 1 - Code(Zero) at (prev + 29, 19) to (start + 2, 6) Function name: coverage_attr_closure::contains_closures_on -Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 02, 05, 01, 04, 06, 02, 05, 01, 04, 06, 01, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 01, 1a, 01, 05, 09, 00, 1b, 01, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 5) -- Code(Counter(0)) at (prev + 4, 6) to (start + 2, 5) -- Code(Counter(0)) at (prev + 4, 6) to (start + 1, 2) +- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 26) +- Code(Counter(0)) at (prev + 5, 9) to (start + 0, 27) +- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2) Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06] diff --git a/tests/coverage/coverage_attr_closure.coverage b/tests/coverage/coverage_attr_closure.coverage index 32c75b40d83c0..3474ad65063ec 100644 --- a/tests/coverage/coverage_attr_closure.coverage +++ b/tests/coverage/coverage_attr_closure.coverage @@ -14,13 +14,13 @@ LL| |#[coverage(on)] LL| 1|fn contains_closures_on() { LL| 1| let _local_closure_on = #[coverage(on)] - LL| 1| |input: &str| { + LL| 0| |input: &str| { LL| 0| println!("{input}"); - LL| 1| }; + LL| 0| }; LL| 1| let _local_closure_off = #[coverage(off)] - LL| 1| |input: &str| { + LL| | |input: &str| { LL| | println!("{input}"); - LL| 1| }; + LL| | }; LL| 1|} LL| | LL| |#[coverage(off)] diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index c669b7245ead8..f77781ca02839 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -22,13 +22,13 @@ Number of file 0 mappings: 4 = (Zero + (c0 - Zero)) Function name: inline_dead::main -Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 05, 06, 02, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) -- Code(Counter(0)) at (prev + 5, 6) to (start + 2, 2) +- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 10) +- Code(Counter(0)) at (prev + 6, 5) to (start + 1, 2) Function name: inline_dead::main::{closure#0} Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06] diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map index a18e5f1486147..f3ee44d2a5abc 100644 --- a/tests/coverage/macro_name_span.cov-map +++ b/tests/coverage/macro_name_span.cov-map @@ -1,10 +1,10 @@ Function name: macro_name_span::affected_function -Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 02, 06] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 40] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 22, 28) to (start + 2, 6) +- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64) Function name: macro_name_span::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02] diff --git a/tests/coverage/macro_name_span.coverage b/tests/coverage/macro_name_span.coverage index 28c88b1defa83..0e12ce4a27cad 100644 --- a/tests/coverage/macro_name_span.coverage +++ b/tests/coverage/macro_name_span.coverage @@ -21,6 +21,6 @@ LL| |macro_name_span_helper::macro_that_defines_a_function! { LL| 1| fn affected_function() { LL| 1| macro_with_an_unreasonably_and_egregiously_long_name!(); - LL| 1| } + LL| | } LL| |} diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map index cd40194a0831b..aedfb2071c144 100644 --- a/tests/coverage/unicode.cov-map +++ b/tests/coverage/unicode.cov-map @@ -27,14 +27,6 @@ Number of file 0 mappings: 9 - Code(Expression(5, Add)) at (prev + 2, 5) to (start + 1, 2) = (c4 + ((((c0 + c1) - c1) - c2) + c3)) -Function name: unicode::サビ -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 14, 00, 18] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 30, 20) to (start + 0, 24) - Function name: unicode::他 (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 19, 00, 25] Number of files: 1 diff --git a/tests/coverage/unicode.coverage b/tests/coverage/unicode.coverage index b284a557d5754..af586111ba348 100644 --- a/tests/coverage/unicode.coverage +++ b/tests/coverage/unicode.coverage @@ -29,8 +29,7 @@ LL| | LL| |macro_rules! macro_that_defines_a_function { LL| | (fn $名:ident () $体:tt) => { - LL| 1| fn $名 () $体 fn 他 () {} - ^0 + LL| 0| fn $名 () $体 fn 他 () {} LL| | } LL| |} LL| | From ec95d259e41a9da382cf0b35769f71fe23b49986 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 10:25:25 +0000 Subject: [PATCH 06/40] simplify codegen for trivially droppable types --- library/alloc/src/collections/vec_deque/drain.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 0be274a3822d3..7d40ce65ad75b 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -96,8 +96,9 @@ impl Drop for Drain<'_, T, A> { struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + #[inline] fn drop(&mut self) { - if self.0.remaining != 0 { + if mem::needs_drop::() && self.0.remaining != 0 { unsafe { // SAFETY: We just checked that `self.remaining != 0`. let (front, back) = self.0.as_slices(); @@ -158,7 +159,7 @@ impl Drop for Drain<'_, T, A> { } let guard = DropGuard(self); - if guard.0.remaining != 0 { + if mem::needs_drop::() && guard.0.remaining != 0 { unsafe { // SAFETY: We just checked that `self.remaining != 0`. let (front, back) = guard.0.as_slices(); From 500ef678770d9a0840e913ec02fab801ea455187 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 10:41:35 +0000 Subject: [PATCH 07/40] reduce amount of math --- .../alloc/src/collections/vec_deque/drain.rs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 7d40ce65ad75b..aa5cc0fb1ce2b 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -27,8 +27,8 @@ pub struct Drain< drain_len: usize, // index into the logical array, not the physical one (always lies in [0..deque.len)) idx: usize, - // number of elements after the drain range - tail_len: usize, + // number of elements remaining after dropping the drain + new_len: usize, remaining: usize, // Needed to make Drain covariant over T _marker: PhantomData<&'a T>, @@ -41,12 +41,12 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { drain_len: usize, ) -> Self { let orig_len = mem::replace(&mut deque.len, drain_start); - let tail_len = orig_len - drain_start - drain_len; + let new_len = orig_len - drain_len; Drain { deque: NonNull::from(deque), drain_len, idx: drain_start, - tail_len, + new_len, remaining: drain_len, _marker: PhantomData, } @@ -79,7 +79,7 @@ impl fmt::Debug for Drain<'_, T, A> { f.debug_tuple("Drain") .field(&self.drain_len) .field(&self.idx) - .field(&self.tail_len) + .field(&self.new_len) .field(&self.remaining) .finish() } @@ -111,18 +111,16 @@ impl Drop for Drain<'_, T, A> { let drain_start = source_deque.len(); let drain_len = self.0.drain_len; - let drain_end = drain_start + drain_len; - - let orig_len = self.0.tail_len + drain_end; + let new_len = self.0.new_len; if T::IS_ZST { // no need to copy around any memory if T is a ZST - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; return; } let head_len = drain_start; - let tail_len = self.0.tail_len; + let tail_len = new_len - head_len; match (head_len, tail_len) { (0, 0) => { @@ -131,10 +129,10 @@ impl Drop for Drain<'_, T, A> { } (0, _) => { source_deque.head = source_deque.to_physical_idx(drain_len); - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; } (_, 0) => { - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; } _ => unsafe { if head_len <= tail_len { @@ -144,14 +142,14 @@ impl Drop for Drain<'_, T, A> { head_len, ); source_deque.head = source_deque.to_physical_idx(drain_len); - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; } else { source_deque.wrap_copy( source_deque.to_physical_idx(head_len + drain_len), source_deque.to_physical_idx(head_len), tail_len, ); - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; } }, } From 1e3849aed010c3ff2a4c7b7b644ca67d087ab4c1 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 16:03:21 +0000 Subject: [PATCH 08/40] reduce branchiness --- .../alloc/src/collections/vec_deque/drain.rs | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index aa5cc0fb1ce2b..7a413ddf971d7 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -109,7 +109,6 @@ impl Drop for Drain<'_, T, A> { let source_deque = unsafe { self.0.deque.as_mut() }; - let drain_start = source_deque.len(); let drain_len = self.0.drain_len; let new_len = self.0.new_len; @@ -119,40 +118,32 @@ impl Drop for Drain<'_, T, A> { return; } - let head_len = drain_start; + let head_len = source_deque.len(); let tail_len = new_len - head_len; - match (head_len, tail_len) { - (0, 0) => { - source_deque.head = 0; - source_deque.len = 0; - } - (0, _) => { - source_deque.head = source_deque.to_physical_idx(drain_len); - source_deque.len = new_len; - } - (_, 0) => { - source_deque.len = new_len; + if head_len != 0 && tail_len != 0 { + let (src, dst, len); + if head_len < tail_len { + src = source_deque.head; + dst = source_deque.to_physical_idx(drain_len); + len = head_len; + } else { + src = source_deque.to_physical_idx(head_len + drain_len); + dst = source_deque.to_physical_idx(head_len); + len = tail_len; + }; + + unsafe { + source_deque.wrap_copy(src, dst, len); } - _ => unsafe { - if head_len <= tail_len { - source_deque.wrap_copy( - source_deque.head, - source_deque.to_physical_idx(drain_len), - head_len, - ); - source_deque.head = source_deque.to_physical_idx(drain_len); - source_deque.len = new_len; - } else { - source_deque.wrap_copy( - source_deque.to_physical_idx(head_len + drain_len), - source_deque.to_physical_idx(head_len), - tail_len, - ); - source_deque.len = new_len; - } - }, } + + if new_len == 0 { + source_deque.head = 0; + } else if head_len < tail_len { + source_deque.head = source_deque.to_physical_idx(drain_len); + } + source_deque.len = new_len; } } From b6702939f72c6c55a74fc5f343d34c01e3d8521b Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 23:31:19 +0100 Subject: [PATCH 09/40] outline large copies --- .../alloc/src/collections/vec_deque/drain.rs | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 7a413ddf971d7..bf8c9b2d47aed 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -121,7 +121,27 @@ impl Drop for Drain<'_, T, A> { let head_len = source_deque.len(); let tail_len = new_len - head_len; + // When draining at the front (`.drain(..n)`) or at the back (`.drain(n..)`), + // we don't need to copy any data. + // Outlining this function helps LLVM to eliminate the copies in these cases. if head_len != 0 && tail_len != 0 { + copy_data(source_deque, drain_len, head_len, tail_len); + } + + if new_len == 0 { + source_deque.head = 0; + } else if head_len < tail_len { + source_deque.head = source_deque.to_physical_idx(drain_len); + } + source_deque.len = new_len; + + #[cold] + fn copy_data( + source_deque: &mut VecDeque, + drain_len: usize, + head_len: usize, + tail_len: usize, + ) { let (src, dst, len); if head_len < tail_len { src = source_deque.head; @@ -137,13 +157,6 @@ impl Drop for Drain<'_, T, A> { source_deque.wrap_copy(src, dst, len); } } - - if new_len == 0 { - source_deque.head = 0; - } else if head_len < tail_len { - source_deque.head = source_deque.to_physical_idx(drain_len); - } - source_deque.len = new_len; } } From 8f259ade66fa051b7918412a83f2fb8ef3ded92f Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 23:11:22 +0100 Subject: [PATCH 10/40] add codegen test --- tests/codegen/vecdeque-drain.rs | 69 +++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tests/codegen/vecdeque-drain.rs diff --git a/tests/codegen/vecdeque-drain.rs b/tests/codegen/vecdeque-drain.rs new file mode 100644 index 0000000000000..f8263c6957244 --- /dev/null +++ b/tests/codegen/vecdeque-drain.rs @@ -0,0 +1,69 @@ +// Check that draining at the front or back doesn't copy memory. + +// compile-flags: -O +// ignore-debug: the debug assertions get in the way + +#![crate_type = "lib"] + +use std::collections::VecDeque; + +// CHECK-LABEL: @clear +// CHECK-NOT: call +// CHECK-NOT: br +// CHECK: getelementptr inbounds +// CHECK-NEXT: {{call void @llvm.memset|store}} +// CHECK-NEXT: ret void +#[no_mangle] +pub fn clear(v: &mut VecDeque) { + v.drain(..); +} + +// CHECK-LABEL: @truncate +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK-NOT: br +// CHECK: ret void +#[no_mangle] +pub fn truncate(v: &mut VecDeque, n: usize) { + if n < v.len() { + v.drain(n..); + } +} + +// CHECK-LABEL: @advance +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK-NOT: br +// CHECK: ret void +#[no_mangle] +pub fn advance(v: &mut VecDeque, n: usize) { + if n < v.len() { + v.drain(..n); + } else { + v.clear(); + } +} + +// CHECK-LABEL: @remove +// CHECK: call +// CHECK: ret void +#[no_mangle] +pub fn remove(v: &mut VecDeque, a: usize, b: usize) { + v.drain(a..b); +} From 5d989770f285b6680a2540502fbfd0b4b21b16b3 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 11 Feb 2024 17:13:23 +0100 Subject: [PATCH 11/40] address review comments --- .../alloc/src/collections/vec_deque/drain.rs | 143 ++++++++++++------ 1 file changed, 99 insertions(+), 44 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index bf8c9b2d47aed..1373e60149274 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -95,6 +95,22 @@ impl Drop for Drain<'_, T, A> { fn drop(&mut self) { struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + let guard = DropGuard(self); + + if mem::needs_drop::() && guard.0.remaining != 0 { + unsafe { + // SAFETY: We just checked that `self.remaining != 0`. + let (front, back) = guard.0.as_slices(); + // since idx is a logical index, we don't need to worry about wrapping. + guard.0.idx += front.len(); + guard.0.remaining -= front.len(); + ptr::drop_in_place(front); + guard.0.remaining = 0; + ptr::drop_in_place(back); + } + } + + // Dropping `guard` handles moving the remaining elements into place. impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { #[inline] fn drop(&mut self) { @@ -118,63 +134,102 @@ impl Drop for Drain<'_, T, A> { return; } - let head_len = source_deque.len(); - let tail_len = new_len - head_len; + let head_len = source_deque.len; // #elements in front of the drain + let tail_len = new_len - head_len; // #elements behind the drain + + // Next, we will fill the hole left by the drain with as few writes as possible. + // The code below handles the following control flow and reduces the amount of + // branches under the assumption that `head_len == 0 || tail_len == 0`, i.e. + // draining at the front or at the back of the dequeue is especially common. + // + // H = "head index" = `deque.head` + // h = elements in front of the drain + // d = elements in the drain + // t = elements behind the drain + // + // Note that the buffer may wrap at any point and the wrapping is handled by + // `wrap_copy` and `to_physical_idx`. + // + // Case 1: if `head_len == 0 && tail_len == 0` + // Everything was drained, reset the head index back to 0. + // H + // [ . . . . . d d d d . . . . . ] + // H + // [ . . . . . . . . . . . . . . ] + // + // Case 2: else if `tail_len == 0` + // Don't move data or the head index. + // H + // [ . . . h h h h d d d d . . . ] + // H + // [ . . . h h h h . . . . . . . ] + // + // Case 3: else if `head_len == 0` + // Don't move data, but move the head index. + // H + // [ . . . d d d d t t t t . . . ] + // H + // [ . . . . . . . t t t t . . . ] + // + // Case 4: else if `tail_len <= head_len` + // Move data, but not the head index. + // H + // [ . . h h h h d d d d t t . . ] + // H + // [ . . h h h h t t . . . . . . ] + // + // Case 5: else + // Move data and the head index. + // H + // [ . . h h d d d d t t t t . . ] + // H + // [ . . . . . . h h t t t t . . ] // When draining at the front (`.drain(..n)`) or at the back (`.drain(n..)`), - // we don't need to copy any data. - // Outlining this function helps LLVM to eliminate the copies in these cases. + // we don't need to copy any data. The number of elements copied would be 0. if head_len != 0 && tail_len != 0 { - copy_data(source_deque, drain_len, head_len, tail_len); + join_head_and_tail_wrapping(source_deque, drain_len, head_len, tail_len); + // Marking this function as cold helps LLVM to eliminate it entirely if + // this branch is never taken. + // We use `#[cold]` instead of `#[inline(never)]`, because inlining this + // function into the general case (`.drain(n..m)`) is fine. + // See `tests/codegen/vecdeque-drain.rs` for a test. + #[cold] + fn join_head_and_tail_wrapping( + source_deque: &mut VecDeque, + drain_len: usize, + head_len: usize, + tail_len: usize, + ) { + // Pick whether to move the head or the tail here. + let (src, dst, len); + if head_len < tail_len { + src = source_deque.head; + dst = source_deque.to_physical_idx(drain_len); + len = head_len; + } else { + src = source_deque.to_physical_idx(head_len + drain_len); + dst = source_deque.to_physical_idx(head_len); + len = tail_len; + }; + + unsafe { + source_deque.wrap_copy(src, dst, len); + } + } } if new_len == 0 { + // Special case: If the entire dequeue was drained, reset the head back to 0, + // like `.clear()` does. source_deque.head = 0; } else if head_len < tail_len { + // If we moved the head above, then we need to adjust the head index here. source_deque.head = source_deque.to_physical_idx(drain_len); } source_deque.len = new_len; - - #[cold] - fn copy_data( - source_deque: &mut VecDeque, - drain_len: usize, - head_len: usize, - tail_len: usize, - ) { - let (src, dst, len); - if head_len < tail_len { - src = source_deque.head; - dst = source_deque.to_physical_idx(drain_len); - len = head_len; - } else { - src = source_deque.to_physical_idx(head_len + drain_len); - dst = source_deque.to_physical_idx(head_len); - len = tail_len; - }; - - unsafe { - source_deque.wrap_copy(src, dst, len); - } - } - } - } - - let guard = DropGuard(self); - if mem::needs_drop::() && guard.0.remaining != 0 { - unsafe { - // SAFETY: We just checked that `self.remaining != 0`. - let (front, back) = guard.0.as_slices(); - // since idx is a logical index, we don't need to worry about wrapping. - guard.0.idx += front.len(); - guard.0.remaining -= front.len(); - ptr::drop_in_place(front); - guard.0.remaining = 0; - ptr::drop_in_place(back); } } - - // Dropping `guard` handles moving the remaining elements into place. } } From b49bd0bba00e5622917db09cb70f42e47d322df8 Mon Sep 17 00:00:00 2001 From: Takashiidobe Date: Fri, 16 Feb 2024 09:20:51 -0500 Subject: [PATCH 12/40] Add examples to document the return type of `select_nth_unstable`, `select_nth_unstable_by`, and `select_nth_unstable_by_key`. --- library/core/src/slice/mod.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 1d8ac6aa04394..c948337ba6c2d 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3016,8 +3016,13 @@ impl [T] { /// ``` /// let mut v = [-5i32, 4, 2, -3, 1]; /// - /// // Find the median - /// v.select_nth_unstable(2); + /// // Find the items less than or equal to the median, the median, and greater than or equal to + /// // the median. + /// let (lesser, median, greater) = v.select_nth_unstable(2); + /// + /// assert!(lesser == [-3, -5] || lesser == [-5, -3]); + /// assert_eq!(median, &mut 1); + /// assert!(greater == [4, 2] || greater == [2, 4]); /// /// // We are only guaranteed the slice will be one of the following, based on the way we sort /// // about the specified index. @@ -3067,8 +3072,13 @@ impl [T] { /// ``` /// let mut v = [-5i32, 4, 2, -3, 1]; /// - /// // Find the median as if the slice were sorted in descending order. - /// v.select_nth_unstable_by(2, |a, b| b.cmp(a)); + /// // Find the items less than or equal to the median, the median, and greater than or equal to + /// // the median as if the slice were sorted in descending order. + /// let (lesser, median, greater) = v.select_nth_unstable_by(2, |a, b| b.cmp(a)); + /// + /// assert!(lesser == [4, 2] || lesser == [2, 4]); + /// assert_eq!(median, &mut 1); + /// assert!(greater == [-3, -5] || greater == [-5, -3]); /// /// // We are only guaranteed the slice will be one of the following, based on the way we sort /// // about the specified index. @@ -3122,8 +3132,13 @@ impl [T] { /// ``` /// let mut v = [-5i32, 4, 1, -3, 2]; /// - /// // Return the median as if the array were sorted according to absolute value. - /// v.select_nth_unstable_by_key(2, |a| a.abs()); + /// // Find the items less than or equal to the median, the median, and greater than or equal to + /// // the median as if the slice were sorted according to absolute value. + /// let (lesser, median, greater) = v.select_nth_unstable_by_key(2, |a| a.abs()); + /// + /// assert!(lesser == [1, 2] || lesser == [2, 1]); + /// assert_eq!(median, &mut -3); + /// assert!(greater == [4, -5] || greater == [-5, 4]); /// /// // We are only guaranteed the slice will be one of the following, based on the way we sort /// // about the specified index. From 3250e953050be1a6867aac3745742f86ab406361 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 13 Feb 2024 23:49:28 +0000 Subject: [PATCH 13/40] Add a simple extension trait derive --- compiler/rustc_macros/src/extension.rs | 136 +++++++++++++++++++++++++ compiler/rustc_macros/src/lib.rs | 6 ++ 2 files changed, 142 insertions(+) create mode 100644 compiler/rustc_macros/src/extension.rs diff --git a/compiler/rustc_macros/src/extension.rs b/compiler/rustc_macros/src/extension.rs new file mode 100644 index 0000000000000..7bb07285ae205 --- /dev/null +++ b/compiler/rustc_macros/src/extension.rs @@ -0,0 +1,136 @@ +use proc_macro2::Ident; +use quote::quote; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::spanned::Spanned; +use syn::{ + braced, parse_macro_input, Attribute, Generics, ImplItem, Pat, PatIdent, Path, Signature, + Token, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility, +}; + +pub(crate) fn extension(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + // Parse the input tokens into a syntax tree + let Extension { attrs, generics, vis, trait_, self_ty, items } = + parse_macro_input!(input as Extension); + let headers: Vec<_> = items + .iter() + .map(|item| match item { + ImplItem::Fn(f) => TraitItem::Fn(TraitItemFn { + attrs: scrub_attrs(&f.attrs), + sig: scrub_header(f.sig.clone()), + default: None, + semi_token: Some(Token![;](f.block.span())), + }), + ImplItem::Const(ct) => TraitItem::Const(TraitItemConst { + attrs: scrub_attrs(&ct.attrs), + const_token: ct.const_token, + ident: ct.ident.clone(), + generics: ct.generics.clone(), + colon_token: ct.colon_token, + ty: ct.ty.clone(), + default: None, + semi_token: ct.semi_token, + }), + ImplItem::Type(ty) => TraitItem::Type(TraitItemType { + attrs: scrub_attrs(&ty.attrs), + type_token: ty.type_token, + ident: ty.ident.clone(), + generics: ty.generics.clone(), + colon_token: None, + bounds: Punctuated::new(), + default: None, + semi_token: ty.semi_token, + }), + ImplItem::Macro(mac) => TraitItem::Macro(TraitItemMacro { + attrs: scrub_attrs(&mac.attrs), + mac: mac.mac.clone(), + semi_token: mac.semi_token, + }), + ImplItem::Verbatim(stream) => TraitItem::Verbatim(stream.clone()), + _ => unimplemented!(), + }) + .collect(); + + quote! { + #(#attrs)* + #vis trait #trait_ { + #(#headers)* + } + + impl #generics #trait_ for #self_ty { + #(#items)* + } + } + .into() +} + +/// Only keep `#[doc]` attrs. +fn scrub_attrs(attrs: &[Attribute]) -> Vec { + attrs.into_iter().cloned().filter(|attr| attr.path().segments[0].ident == "doc").collect() +} + +/// Scrub arguments so that they're valid for trait signatures. +fn scrub_header(mut sig: Signature) -> Signature { + for (idx, input) in sig.inputs.iter_mut().enumerate() { + match input { + syn::FnArg::Receiver(rcvr) => { + // `mut self` -> `self` + if rcvr.reference.is_none() { + rcvr.mutability.take(); + } + } + syn::FnArg::Typed(arg) => match &mut *arg.pat { + Pat::Ident(arg) => { + // `ref mut ident @ pat` -> `ident` + arg.by_ref.take(); + arg.mutability.take(); + arg.subpat.take(); + } + _ => { + // `pat` -> `__arg0` + arg.pat = Box::new( + PatIdent { + attrs: vec![], + by_ref: None, + mutability: None, + ident: Ident::new(&format!("__arg{idx}"), arg.pat.span()), + subpat: None, + } + .into(), + ) + } + }, + } + } + sig +} + +struct Extension { + attrs: Vec, + vis: Visibility, + generics: Generics, + trait_: Path, + self_ty: Type, + items: Vec, +} + +impl Parse for Extension { + fn parse(input: ParseStream<'_>) -> syn::Result { + let attrs = input.call(Attribute::parse_outer)?; + let vis = input.parse()?; + let _: Token![impl] = input.parse()?; + let generics = input.parse()?; + let trait_ = input.parse()?; + let _: Token![for] = input.parse()?; + let self_ty = input.parse()?; + + let content; + let _brace_token = braced!(content in input); + let mut items = Vec::new(); + while !content.is_empty() { + items.push(content.parse()?); + } + + Ok(Extension { attrs, generics, vis, trait_, self_ty, items }) + } +} diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index af65c908ee66b..841f5c06126c2 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -14,6 +14,7 @@ use proc_macro::TokenStream; mod current_version; mod diagnostics; +mod extension; mod hash_stable; mod lift; mod query; @@ -40,6 +41,11 @@ pub fn symbols(input: TokenStream) -> TokenStream { symbols::symbols(input.into()).into() } +#[proc_macro_attribute] +pub fn extension(_attr: TokenStream, input: TokenStream) -> TokenStream { + extension::extension(input) +} + decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); decl_derive!( [HashStable_Generic, attributes(stable_hasher)] => From 9c25823bb4bba6416ca4b15cd956ae92716f82eb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 13 Feb 2024 23:49:39 +0000 Subject: [PATCH 14/40] Use extension trait derive --- compiler/rustc_ast_lowering/src/lib.rs | 11 +- compiler/rustc_borrowck/src/facts.rs | 15 +- compiler/rustc_borrowck/src/place_ext.rs | 14 +- .../src/region_infer/opaque_types.rs | 12 +- .../rustc_borrowck/src/universal_regions.rs | 22 +- .../src/collect/resolve_bound_vars.rs | 12 +- .../src/infer/canonical/instantiate.rs | 26 +- .../src/infer/error_reporting/mod.rs | 15 +- compiler/rustc_infer/src/infer/mod.rs | 7 +- compiler/rustc_infer/src/traits/engine.rs | 14 +- compiler/rustc_middle/src/ty/layout.rs | 24 +- compiler/rustc_middle/src/ty/util.rs | 9 +- compiler/rustc_trait_selection/src/infer.rs | 82 ++--- compiler/rustc_trait_selection/src/regions.rs | 10 +- .../src/solve/eval_ctxt/mod.rs | 14 +- .../src/solve/eval_ctxt/select.rs | 10 +- .../src/solve/inspect/analyse.rs | 11 +- .../rustc_trait_selection/src/solve/mod.rs | 5 +- .../src/traits/engine.rs | 7 +- .../traits/error_reporting/infer_ctxt_ext.rs | 37 +-- .../error_reporting/on_unimplemented.rs | 21 +- .../src/traits/error_reporting/suggestions.rs | 276 +---------------- .../error_reporting/type_err_ctxt_ext.rs | 286 +----------------- .../src/traits/outlives_bounds.rs | 25 +- .../src/traits/project.rs | 33 +- .../src/traits/query/evaluate_obligation.rs | 34 +-- .../src/traits/query/normalize.rs | 16 +- .../traits/specialize/specialization_graph.rs | 32 +- .../src/traits/structural_normalize.rs | 11 +- 29 files changed, 119 insertions(+), 972 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e9e1095a4ae5e..e6a7c08429bd4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -57,6 +57,7 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate}; use rustc_index::{Idx, IndexSlice, IndexVec}; +use rustc_macros::extension; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::{add_feature_diagnostics, feature_err}; @@ -190,15 +191,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } -trait ResolverAstLoweringExt { - fn legacy_const_generic_args(&self, expr: &Expr) -> Option>; - fn get_partial_res(&self, id: NodeId) -> Option; - fn get_import_res(&self, id: NodeId) -> PerNS>>; - fn get_label_res(&self, id: NodeId) -> Option; - fn get_lifetime_res(&self, id: NodeId) -> Option; - fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; -} - +#[extension] impl ResolverAstLoweringExt for ResolverAstLowering { fn legacy_const_generic_args(&self, expr: &Expr) -> Option> { if let ExprKind::Path(None, path) = &expr.kind { diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index 68dc9a6764bfc..da14408fb6961 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -2,6 +2,7 @@ use crate::location::{LocationIndex, LocationTable}; use crate::BorrowIndex; use polonius_engine::AllFacts as PoloniusFacts; use polonius_engine::Atom; +use rustc_macros::extension; use rustc_middle::mir::Local; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::move_paths::MovePathIndex; @@ -24,20 +25,10 @@ impl polonius_engine::FactTypes for RustcFacts { pub type AllFacts = PoloniusFacts; -pub(crate) trait AllFactsExt { +#[extension] +pub(crate) impl AllFactsExt for AllFacts { /// Returns `true` if there is a need to gather `AllFacts` given the /// current `-Z` flags. - fn enabled(tcx: TyCtxt<'_>) -> bool; - - fn write_to_dir( - &self, - dir: impl AsRef, - location_table: &LocationTable, - ) -> Result<(), Box>; -} - -impl AllFactsExt for AllFacts { - /// Return fn enabled(tcx: TyCtxt<'_>) -> bool { tcx.sess.opts.unstable_opts.nll_facts || tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index b59ab7fafa576..ac8991ccf00bd 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -1,24 +1,16 @@ use crate::borrow_set::LocalsStateAtExit; use rustc_hir as hir; +use rustc_macros::extension; use rustc_middle::mir::ProjectionElem; use rustc_middle::mir::{Body, Mutability, Place}; use rustc_middle::ty::{self, TyCtxt}; -/// Extension methods for the `Place` type. -pub trait PlaceExt<'tcx> { +#[extension] +pub impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { /// Returns `true` if we can safely ignore borrows of this place. /// This is true whenever there is no action that the user can do /// to the place `self` that would invalidate the borrow. This is true /// for borrows of raw pointer dereferents as well as shared references. - fn ignore_borrow( - &self, - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - locals_state_at_exit: &LocalsStateAtExit, - ) -> bool; -} - -impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { fn ignore_borrow( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index cd2fe56ca4916..4aac392ef392e 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -6,6 +6,7 @@ use rustc_hir::OpaqueTyOrigin; use rustc_infer::infer::InferCtxt; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::traits::{Obligation, ObligationCause}; +use rustc_macros::extension; use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; @@ -225,15 +226,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } -pub trait InferCtxtExt<'tcx> { - fn infer_opaque_definition_from_instantiation( - &self, - opaque_type_key: OpaqueTypeKey<'tcx>, - instantiated_ty: OpaqueHiddenType<'tcx>, - ) -> Ty<'tcx>; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// Given the fully resolved, instantiated type for an opaque /// type, i.e., the value of an inference variable like C1 or C2 /// (*), computes the "definition type" for an opaque type diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 90e8f1b93b294..f9a8543e28d2b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -22,6 +22,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::BodyOwnerKind; use rustc_index::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_macros::extension; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt}; @@ -793,26 +794,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } } -trait InferCtxtExt<'tcx> { - fn replace_free_regions_with_nll_infer_vars( - &self, - origin: NllRegionVariableOrigin, - value: T, - ) -> T - where - T: TypeFoldable>; - - fn replace_bound_regions_with_nll_infer_vars( - &self, - origin: NllRegionVariableOrigin, - all_outlive_scope: LocalDefId, - value: ty::Binder<'tcx, T>, - indices: &mut UniversalRegionIndices<'tcx>, - ) -> T - where - T: TypeFoldable>; -} - +#[extension] impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { #[instrument(skip(self), level = "debug")] fn replace_free_regions_with_nll_infer_vars( diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 287cb8809086a..9fb6103183bbc 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -14,6 +14,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node}; +use rustc_macros::extension; use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::*; @@ -27,16 +28,7 @@ use std::fmt; use crate::errors; -trait RegionExt { - fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg); - - fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg); - - fn id(&self) -> Option; - - fn shifted(self, amount: u32) -> ResolvedArg; -} - +#[extension] impl RegionExt for ResolvedArg { fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { debug!("ResolvedArg::early: def_id={:?}", param.def_id); diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs index f6b583151fdf3..54940a2b4988c 100644 --- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs +++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs @@ -13,12 +13,16 @@ use rustc_middle::ty::{self, TyCtxt}; /// FIXME(-Znext-solver): This or public because it is shared with the /// new trait solver implementation. We should deduplicate canonicalization. -pub trait CanonicalExt<'tcx, V> { +#[extension] +pub impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> { /// Instantiate the wrapped value, replacing each canonical value /// with the value given in `var_values`. fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V where - V: TypeFoldable>; + V: TypeFoldable>, + { + self.instantiate_projected(tcx, var_values, |value| value.clone()) + } /// Allows one to apply a instantiation to some subset of /// `self.value`. Invoke `projection_fn` with `self.value` to get @@ -26,24 +30,6 @@ pub trait CanonicalExt<'tcx, V> { /// variables bound in `self` (usually this extracts from subset /// of `self`). Apply the instantiation `var_values` to this value /// V, replacing each of the canonical variables. - fn instantiate_projected( - &self, - tcx: TyCtxt<'tcx>, - var_values: &CanonicalVarValues<'tcx>, - projection_fn: impl FnOnce(&V) -> T, - ) -> T - where - T: TypeFoldable>; -} - -impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> { - fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V - where - V: TypeFoldable>, - { - self.instantiate_projected(tcx, var_values, |value| value.clone()) - } - fn instantiate_projected( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 104bf4a5be873..37efafc5972f2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2786,19 +2786,8 @@ pub enum FailureCode { Error0644, } -pub trait ObligationCauseExt<'tcx> { - fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode; - - fn as_failure_code_diag( - &self, - terr: TypeError<'tcx>, - span: Span, - subdiags: Vec, - ) -> ObligationCauseFailureCode; - fn as_requirement_str(&self) -> &'static str; -} - -impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { +#[extension] +pub impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode { use self::FailureCode::*; use crate::traits::ObligationCauseCode::*; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2caf3b3cc9364..b9ebd685ca9f2 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -626,11 +626,8 @@ pub struct InferCtxtBuilder<'tcx> { next_trait_solver: bool, } -pub trait TyCtxtInferExt<'tcx> { - fn infer_ctxt(self) -> InferCtxtBuilder<'tcx>; -} - -impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { +#[extension] +pub impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 64b9714c7c086..79a29e2496807 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -52,18 +52,8 @@ pub trait TraitEngine<'tcx>: 'tcx { ) -> Vec>; } -pub trait TraitEngineExt<'tcx> { - fn register_predicate_obligations( - &mut self, - infcx: &InferCtxt<'tcx>, - obligations: impl IntoIterator>, - ); - - #[must_use] - fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; -} - -impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { +#[extension] +pub impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { fn register_predicate_obligations( &mut self, infcx: &InferCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 2b34f5daaf63f..1fb04f5bbfe34 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -23,20 +23,8 @@ use std::fmt; use std::num::NonZero; use std::ops::Bound; -pub trait IntegerExt { - fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; - fn from_int_ty(cx: &C, ity: ty::IntTy) -> Integer; - fn from_uint_ty(cx: &C, uty: ty::UintTy) -> Integer; - fn repr_discr<'tcx>( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, - repr: &ReprOptions, - min: i128, - max: i128, - ) -> (Integer, bool); -} - -impl IntegerExt for Integer { +#[extension] +pub impl IntegerExt for Integer { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> { match (*self, signed) { @@ -123,12 +111,8 @@ impl IntegerExt for Integer { } } -pub trait PrimitiveExt { - fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; - fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; -} - -impl PrimitiveExt for Primitive { +#[extension] +pub impl PrimitiveExt for Primitive { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 2addfa37f8b4d..98d19083aaba7 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -96,13 +96,8 @@ impl<'tcx> Discr<'tcx> { } } -pub trait IntTypeExt { - fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; - fn disr_incr<'tcx>(&self, tcx: TyCtxt<'tcx>, val: Option>) -> Option>; - fn initial_discriminant<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Discr<'tcx>; -} - -impl IntTypeExt for IntegerType { +#[extension] +pub impl IntTypeExt for IntegerType { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self { IntegerType::Pointer(true) => tcx.types.isize, diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index ef4a0f52f9ea7..8406880477e4d 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -17,49 +17,8 @@ use std::fmt::Debug; pub use rustc_infer::infer::*; -pub trait InferCtxtExt<'tcx> { - fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; - - fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; - - /// Check whether a `ty` implements given trait(trait_def_id) without side-effects. - /// - /// The inputs are: - /// - /// - the def-id of the trait - /// - the type parameters of the trait, including the self-type - /// - the parameter environment - /// - /// Invokes `evaluate_obligation`, so in the event that evaluating - /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent - /// (or EvaluatedToAmbigStackDependent) will be returned. - fn type_implements_trait( - &self, - trait_def_id: DefId, - params: impl IntoIterator>>, - param_env: ty::ParamEnv<'tcx>, - ) -> traits::EvaluationResult; - - /// Returns `Some` if a type implements a trait shallowly, without side-effects, - /// along with any errors that would have been reported upon further obligation - /// processing. - /// - /// - If this returns `Some([])`, then the trait holds modulo regions. - /// - If this returns `Some([errors..])`, then the trait has an impl for - /// the self type, but some nested obligations do not hold. - /// - If this returns `None`, no implementation that applies could be found. - /// - /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, - /// this will probably only ever return `Some([])` or `None`. - fn type_implements_trait_shallow( - &self, - trait_def_id: DefId, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Option>>; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let ty = self.resolve_vars_if_possible(ty); @@ -81,6 +40,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item) } + /// Check whether a `ty` implements given trait(trait_def_id) without side-effects. + /// + /// The inputs are: + /// + /// - the def-id of the trait + /// - the type parameters of the trait, including the self-type + /// - the parameter environment + /// + /// Invokes `evaluate_obligation`, so in the event that evaluating + /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent + /// (or EvaluatedToAmbigStackDependent) will be returned. #[instrument(level = "debug", skip(self, params), ret)] fn type_implements_trait( &self, @@ -99,6 +69,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } + /// Returns `Some` if a type implements a trait shallowly, without side-effects, + /// along with any errors that would have been reported upon further obligation + /// processing. + /// + /// - If this returns `Some([])`, then the trait holds modulo regions. + /// - If this returns `Some([errors..])`, then the trait has an impl for + /// the self type, but some nested obligations do not hold. + /// - If this returns `None`, no implementation that applies could be found. + /// + /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, + /// this will probably only ever return `Some([])` or `None`. fn type_implements_trait_shallow( &self, trait_def_id: DefId, @@ -124,19 +105,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } } -pub trait InferCtxtBuilderExt<'tcx> { - fn enter_canonical_trait_query( - self, - canonical_key: &Canonical<'tcx, K>, - operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result, - ) -> Result, NoSolution> - where - K: TypeFoldable>, - R: Debug + TypeFoldable>, - Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>; -} - -impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { /// The "main method" for a canonicalized trait query. Given the /// canonical key `canonical_key`, this method will create a new /// inference context, instantiate the key, and run your operation diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index 756db7cc2063f..dc9edb6063d75 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -3,20 +3,14 @@ use rustc_infer::infer::{InferCtxt, RegionResolutionError}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; -pub trait InferCtxtRegionExt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { /// Resolve regions, using the deep normalizer to normalize any type-outlives /// obligations in the process. This is in `rustc_trait_selection` because /// we need to normalize. /// /// Prefer this method over `resolve_regions_with_normalize`, unless you are /// doing something specific for normalization. - fn resolve_regions( - &self, - outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Vec>; -} - -impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { fn resolve_regions( &self, outlives_env: &OutlivesEnvironment<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 803379af005f9..3abdc4a333053 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -131,22 +131,12 @@ pub enum GenerateProofTree { Never, } -pub trait InferCtxtEvalExt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { /// Evaluates a goal from **outside** of the trait solver. /// /// Using this while inside of the solver is wrong as it uses a new /// search graph which would break cycle detection. - fn evaluate_root_goal( - &self, - goal: Goal<'tcx, ty::Predicate<'tcx>>, - generate_proof_tree: GenerateProofTree, - ) -> ( - Result<(bool, Certainty, Vec>>), NoSolution>, - Option>, - ); -} - -impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { #[instrument(level = "debug", skip(self))] fn evaluate_root_goal( &self, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index eab5962443696..406f4c2f6151e 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -17,14 +17,8 @@ use crate::solve::inspect::ProofTreeBuilder; use crate::traits::StructurallyNormalizeExt; use crate::traits::TraitEngineExt; -pub trait InferCtxtSelectExt<'tcx> { - fn select_in_new_trait_solver( - &self, - obligation: &PolyTraitObligation<'tcx>, - ) -> SelectionResult<'tcx, Selection<'tcx>>; -} - -impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { fn select_in_new_trait_solver( &self, obligation: &PolyTraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index f33d0f397ce9e..1c6c2ff594a1b 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -216,15 +216,8 @@ pub trait ProofTreeVisitor<'tcx> { fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow; } -pub trait ProofTreeInferCtxtExt<'tcx> { - fn visit_proof_tree>( - &self, - goal: Goal<'tcx, ty::Predicate<'tcx>>, - visitor: &mut V, - ) -> ControlFlow; -} - -impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { fn visit_proof_tree>( &self, goal: Goal<'tcx, ty::Predicate<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 94a3cef8ad14e..11e1e72e04e23 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -61,10 +61,7 @@ enum GoalEvaluationKind { Nested { is_normalizes_to_hack: IsNormalizesToHack }, } -trait CanonicalResponseExt { - fn has_no_inference_or_external_constraints(&self) -> bool; -} - +#[extension] impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> { fn has_no_inference_or_external_constraints(&self) -> bool { self.value.external_constraints.region_constraints.is_empty() diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index caf950037fdfd..b234b8a9d0327 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -27,11 +27,8 @@ use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::Variance; use rustc_middle::ty::{self, Ty, TyCtxt}; -pub trait TraitEngineExt<'tcx> { - fn new(infcx: &InferCtxt<'tcx>) -> Box; -} - -impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { +#[extension] +pub impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { fn new(infcx: &InferCtxt<'tcx>) -> Box { if infcx.next_trait_solver() { Box::new(NextFulfillmentCtxt::new(infcx)) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs index 15d064d4036ea..80581d01f6b0a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs @@ -11,38 +11,8 @@ use super::ArgKind; pub use rustc_infer::traits::error_reporting::*; -pub trait InferCtxtExt<'tcx> { - /// Given some node representing a fn-like thing in the HIR map, - /// returns a span and `ArgKind` information that describes the - /// arguments it expects. This can be supplied to - /// `report_arg_count_mismatch`. - fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option, Vec)>; - - /// Reports an error when the number of arguments needed by a - /// trait match doesn't match the number that the expression - /// provides. - fn report_arg_count_mismatch( - &self, - span: Span, - found_span: Option, - expected_args: Vec, - found_args: Vec, - is_closure: bool, - closure_pipe_span: Option, - ) -> DiagnosticBuilder<'tcx>; - - /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` - /// in that order, and returns the generic type corresponding to the - /// argument of that trait (corresponding to the closure arguments). - fn type_implements_fn_trait( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: ty::Binder<'tcx, Ty<'tcx>>, - polarity: ty::ImplPolarity, - ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// Given some node representing a fn-like thing in the HIR map, /// returns a span and `ArgKind` information that describes the /// arguments it expects. This can be supplied to @@ -229,6 +199,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { err } + /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` + /// in that order, and returns the generic type corresponding to the + /// argument of that trait (corresponding to the closure arguments). fn type_implements_fn_trait( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index f0773fd1671e2..7d7f415c7bb7a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -23,24 +23,6 @@ use crate::errors::{ use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt; -pub trait TypeErrCtxtExt<'tcx> { - /*private*/ - fn impl_similar_to( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - obligation: &PredicateObligation<'tcx>, - ) -> Option<(DefId, GenericArgsRef<'tcx>)>; - - /*private*/ - fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str>; - - fn on_unimplemented_note( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - obligation: &PredicateObligation<'tcx>, - ) -> OnUnimplementedNote; -} - /// The symbols which are always allowed in a format string static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ kw::SelfUpper, @@ -56,7 +38,8 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ sym::Trait, ]; -impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension] +pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn impl_similar_to( &self, trait_ref: ty::PolyTraitRef<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 335e6ff28226e..58c731a8ed7f4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -106,279 +106,6 @@ impl<'tcx, 'a> CoroutineData<'tcx, 'a> { } } -// This trait is public to expose the diagnostics methods to clippy. -pub trait TypeErrCtxtExt<'tcx> { - fn suggest_restricting_param_bound( - &self, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - associated_item: Option<(&'static str, Ty<'tcx>)>, - body_id: LocalDefId, - ); - - fn suggest_dereferences( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn get_closure_name( - &self, - def_id: DefId, - err: &mut Diagnostic, - msg: Cow<'static, str>, - ) -> Option; - - fn suggest_fn_call( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn check_for_binding_assigned_block_without_tail_expression( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ); - - fn suggest_add_clone_to_arg( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn extract_callable_info( - &self, - body_id: LocalDefId, - param_env: ty::ParamEnv<'tcx>, - found: Ty<'tcx>, - ) -> Option<(DefIdOrName, Ty<'tcx>, Vec>)>; - - fn suggest_add_reference_to_arg( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - has_custom_message: bool, - ) -> bool; - - fn suggest_borrowing_for_object_cast( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - self_ty: Ty<'tcx>, - object_ty: Ty<'tcx>, - ); - - fn suggest_remove_reference( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic); - - fn suggest_change_mut( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ); - - fn suggest_semicolon_removal( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - span: Span, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option; - - fn suggest_impl_trait( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn point_at_returns_when_relevant( - &self, - err: &mut DiagnosticBuilder<'tcx>, - obligation: &PredicateObligation<'tcx>, - ); - - fn report_closure_arg_mismatch( - &self, - span: Span, - found_span: Option, - found: ty::PolyTraitRef<'tcx>, - expected: ty::PolyTraitRef<'tcx>, - cause: &ObligationCauseCode<'tcx>, - found_node: Option>, - param_env: ty::ParamEnv<'tcx>, - ) -> DiagnosticBuilder<'tcx>; - - fn note_conflicting_fn_args( - &self, - err: &mut Diagnostic, - cause: &ObligationCauseCode<'tcx>, - expected: Ty<'tcx>, - found: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ); - - fn note_conflicting_closure_bounds( - &self, - cause: &ObligationCauseCode<'tcx>, - err: &mut DiagnosticBuilder<'tcx>, - ); - - fn suggest_fully_qualified_path( - &self, - err: &mut Diagnostic, - item_def_id: DefId, - span: Span, - trait_ref: DefId, - ); - - fn maybe_note_obligation_cause_for_async_await( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - ) -> bool; - - fn note_obligation_cause_for_async_await( - &self, - err: &mut Diagnostic, - interior_or_upvar_span: CoroutineInteriorOrUpvar, - is_async: bool, - outer_coroutine: Option, - trait_pred: ty::TraitPredicate<'tcx>, - target_ty: Ty<'tcx>, - obligation: &PredicateObligation<'tcx>, - next_code: Option<&ObligationCauseCode<'tcx>>, - ); - - fn note_obligation_cause_code( - &self, - body_id: LocalDefId, - err: &mut Diagnostic, - predicate: T, - param_env: ty::ParamEnv<'tcx>, - cause_code: &ObligationCauseCode<'tcx>, - obligated_types: &mut Vec>, - seen_requirements: &mut FxHashSet, - ) where - T: ToPredicate<'tcx>; - - /// Suggest to await before try: future? => future.await? - fn suggest_await_before_try( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - trait_pred: ty::PolyTraitPredicate<'tcx>, - span: Span, - ); - - fn suggest_floating_point_literal( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_ref: &ty::PolyTraitRef<'tcx>, - ); - - fn suggest_derive( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ); - - fn suggest_dereferencing_index( - &self, - obligation: &PredicateObligation<'tcx>, - err: &mut Diagnostic, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ); - - fn suggest_option_method_if_applicable( - &self, - failed_pred: ty::Predicate<'tcx>, - param_env: ty::ParamEnv<'tcx>, - err: &mut Diagnostic, - expr: &hir::Expr<'_>, - ); - - fn note_function_argument_obligation( - &self, - body_id: LocalDefId, - err: &mut Diagnostic, - arg_hir_id: HirId, - parent_code: &ObligationCauseCode<'tcx>, - param_env: ty::ParamEnv<'tcx>, - predicate: ty::Predicate<'tcx>, - call_hir_id: HirId, - ); - - fn look_for_iterator_item_mistakes( - &self, - assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], - typeck_results: &TypeckResults<'tcx>, - type_diffs: &[TypeError<'tcx>], - param_env: ty::ParamEnv<'tcx>, - path_segment: &hir::PathSegment<'_>, - args: &[hir::Expr<'_>], - err: &mut Diagnostic, - ); - - fn point_at_chain( - &self, - expr: &hir::Expr<'_>, - typeck_results: &TypeckResults<'tcx>, - type_diffs: Vec>, - param_env: ty::ParamEnv<'tcx>, - err: &mut Diagnostic, - ); - - fn probe_assoc_types_at_expr( - &self, - type_diffs: &[TypeError<'tcx>], - span: Span, - prev_ty: Ty<'tcx>, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - ) -> Vec))>>; - - fn suggest_convert_to_slice( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - candidate_impls: &[ImplCandidate<'tcx>], - span: Span, - ); - - fn explain_hrtb_projection( - &self, - diag: &mut Diagnostic, - pred: ty::PolyTraitPredicate<'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: &ObligationCause<'tcx>, - ); - - fn suggest_desugaring_async_fn_in_trait( - &self, - err: &mut Diagnostic, - trait_ref: ty::PolyTraitRef<'tcx>, - ); -} - fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) { ( generics.tail_span_for_predicate_suggestion(), @@ -509,7 +236,8 @@ pub fn suggest_restriction<'tcx>( } } -impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension] +pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn suggest_restricting_param_bound( &self, err: &mut Diagnostic, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 68b1a0d4e61cd..92992de64ffb9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -57,78 +57,8 @@ use super::{ pub use rustc_infer::traits::error_reporting::*; -pub trait TypeErrCtxtExt<'tcx> { - fn build_overflow_error( - &self, - predicate: &T, - span: Span, - suggest_increasing_limit: bool, - ) -> DiagnosticBuilder<'tcx> - where - T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; - - fn report_overflow_error( - &self, - predicate: &T, - span: Span, - suggest_increasing_limit: bool, - mutate: impl FnOnce(&mut Diagnostic), - ) -> ! - where - T: fmt::Display + TypeFoldable> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; - - fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed; - - fn report_fulfillment_errors(&self, errors: Vec>) -> ErrorGuaranteed; - - fn report_overflow_obligation( - &self, - obligation: &Obligation<'tcx, T>, - suggest_increasing_limit: bool, - ) -> ! - where - T: ToPredicate<'tcx> + Clone; - - fn suggest_new_overflow_limit(&self, err: &mut Diagnostic); - - fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; - - /// The `root_obligation` parameter should be the `root_obligation` field - /// from a `FulfillmentError`. If no `FulfillmentError` is available, - /// then it should be the same as `obligation`. - fn report_selection_error( - &self, - obligation: PredicateObligation<'tcx>, - root_obligation: &PredicateObligation<'tcx>, - error: &SelectionError<'tcx>, - ) -> ErrorGuaranteed; - - fn emit_specialized_closure_kind_error( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Option; - - fn fn_arg_obligation( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> Result<(), ErrorGuaranteed>; - - fn try_conversion_context( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - err: &mut Diagnostic, - ) -> bool; - - fn report_const_param_not_wf( - &self, - ty: Ty<'tcx>, - obligation: &PredicateObligation<'tcx>, - ) -> DiagnosticBuilder<'tcx>; -} - -impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension] +pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn report_fulfillment_errors( &self, mut errors: Vec>, @@ -382,6 +312,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.emit() } + /// The `root_obligation` parameter should be the `root_obligation` field + /// from a `FulfillmentError`. If no `FulfillmentError` is available, + /// then it should be the same as `obligation`. fn report_selection_error( &self, mut obligation: PredicateObligation<'tcx>, @@ -1393,209 +1326,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } -pub(super) trait InferCtxtPrivExt<'tcx> { - // returns if `cond` not occurring implies that `error` does not occur - i.e., that - // `error` occurring implies that `cond` occurs. - fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; - - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed; - - fn report_projection_error( - &self, - obligation: &PredicateObligation<'tcx>, - error: &MismatchedProjectionTypes<'tcx>, - ) -> ErrorGuaranteed; - - fn maybe_detailed_projection_msg( - &self, - pred: ty::ProjectionPredicate<'tcx>, - normalized_ty: ty::Term<'tcx>, - expected_ty: ty::Term<'tcx>, - ) -> Option; - - fn fuzzy_match_tys( - &self, - a: Ty<'tcx>, - b: Ty<'tcx>, - ignoring_lifetimes: bool, - ) -> Option; - - fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str; - - fn find_similar_impl_candidates( - &self, - trait_pred: ty::PolyTraitPredicate<'tcx>, - ) -> Vec>; - - fn report_similar_impl_candidates( - &self, - impl_candidates: &[ImplCandidate<'tcx>], - trait_ref: ty::PolyTraitRef<'tcx>, - body_def_id: LocalDefId, - err: &mut Diagnostic, - other: bool, - param_env: ty::ParamEnv<'tcx>, - ) -> bool; - - fn report_similar_impl_candidates_for_root_obligation( - &self, - obligation: &PredicateObligation<'tcx>, - trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, - body_def_id: LocalDefId, - err: &mut Diagnostic, - ); - - /// Gets the parent trait chain start - fn get_parent_trait_ref( - &self, - code: &ObligationCauseCode<'tcx>, - ) -> Option<(Ty<'tcx>, Option)>; - - /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait - /// with the same path as `trait_ref`, a help message about - /// a probable version mismatch is added to `err` - fn note_version_mismatch( - &self, - err: &mut Diagnostic, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> bool; - - /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the - /// `trait_ref`. - /// - /// For this to work, `new_self_ty` must have no escaping bound variables. - fn mk_trait_obligation_with_new_self_ty( - &self, - param_env: ty::ParamEnv<'tcx>, - trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, - ) -> PredicateObligation<'tcx>; - - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed; - - fn predicate_can_apply( - &self, - param_env: ty::ParamEnv<'tcx>, - pred: ty::PolyTraitPredicate<'tcx>, - ) -> bool; - - fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>); - - fn suggest_unsized_bound_if_applicable( - &self, - err: &mut Diagnostic, - obligation: &PredicateObligation<'tcx>, - ); - - fn annotate_source_of_ambiguity( - &self, - err: &mut Diagnostic, - impls: &[ambiguity::Ambiguity], - predicate: ty::Predicate<'tcx>, - ); - - fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>); - - fn maybe_indirection_for_unsized( - &self, - err: &mut Diagnostic, - item: &'tcx Item<'tcx>, - param: &'tcx GenericParam<'tcx>, - ) -> bool; - - fn is_recursive_obligation( - &self, - obligated_types: &mut Vec>, - cause_code: &ObligationCauseCode<'tcx>, - ) -> bool; - - fn get_standard_error_message( - &self, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - message: Option, - predicate_is_const: bool, - append_const_msg: Option, - post_message: String, - ) -> String; - - fn get_safe_transmute_error_and_reason( - &self, - obligation: PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - span: Span, - ) -> GetSafeTransmuteErrorAndReason; - - fn add_tuple_trait_message( - &self, - obligation_cause_code: &ObligationCauseCode<'tcx>, - err: &mut Diagnostic, - ); - - fn try_to_add_help_message( - &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, - is_fn_trait: bool, - suggested: bool, - unsatisfied_const: bool, - ); - - fn add_help_message_for_fn_trait( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - err: &mut Diagnostic, - implemented_kind: ty::ClosureKind, - params: ty::Binder<'tcx, Ty<'tcx>>, - ); - - fn maybe_add_note_for_unsatisfied_const( - &self, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, - ) -> UnsatisfiedConst; - - fn report_closure_error( - &self, - obligation: &PredicateObligation<'tcx>, - closure_def_id: DefId, - found_kind: ty::ClosureKind, - kind: ty::ClosureKind, - trait_prefix: &'static str, - ) -> DiagnosticBuilder<'tcx>; - - fn report_cyclic_signature_error( - &self, - obligation: &PredicateObligation<'tcx>, - found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - terr: TypeError<'tcx>, - ) -> DiagnosticBuilder<'tcx>; - - fn report_opaque_type_auto_trait_leakage( - &self, - obligation: &PredicateObligation<'tcx>, - def_id: DefId, - ) -> DiagnosticBuilder<'tcx>; - - fn report_signature_mismatch_error( - &self, - obligation: &PredicateObligation<'tcx>, - span: Span, - found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Result, ErrorGuaranteed>; - - fn report_not_const_evaluatable_error( - &self, - obligation: &PredicateObligation<'tcx>, - span: Span, - ) -> Result, ErrorGuaranteed>; -} - -impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension] +pub(super) impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { @@ -2414,6 +2146,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { suggested } + /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the + /// `trait_ref`. + /// + /// For this to work, `new_self_ty` must have no escaping bound variables. fn mk_trait_obligation_with_new_self_ty( &self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index 52631d4353bfa..c4e8ea45dd32e 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -11,25 +11,6 @@ pub use rustc_middle::traits::query::OutlivesBound; pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator> + 'a; pub type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; -pub trait InferCtxtExt<'a, 'tcx> { - /// Do *NOT* call this directly. - fn implied_bounds_tys_compat( - &'a self, - param_env: ty::ParamEnv<'tcx>, - body_id: LocalDefId, - tys: &'a FxIndexSet>, - compat: bool, - ) -> BoundsCompat<'a, 'tcx>; - - /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` - /// with `compat` set to `true`, otherwise `false`. - fn implied_bounds_tys( - &'a self, - param_env: ty::ParamEnv<'tcx>, - body_id: LocalDefId, - tys: &'a FxIndexSet>, - ) -> Bounds<'a, 'tcx>; -} /// Implied bounds are region relationships that we deduce /// automatically. The idea is that (e.g.) a caller must check that a @@ -130,7 +111,9 @@ fn implied_outlives_bounds<'a, 'tcx>( bounds } -impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { + /// Do *NOT* call this directly. fn implied_bounds_tys_compat( &'a self, param_env: ParamEnv<'tcx>, @@ -142,6 +125,8 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, compat)) } + /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` + /// with `compat` set to `true`, otherwise `false`. fn implied_bounds_tys( &'a self, param_env: ParamEnv<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 049877bc5fed4..807540a1720a2 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -52,12 +52,22 @@ pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>; pub(super) struct InProgress; -pub trait NormalizeExt<'tcx> { +#[extension] +pub impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { /// Normalize a value using the `AssocTypeNormalizer`. /// /// This normalization should be used when the type contains inference variables or the /// projection may be fallible. - fn normalize>>(&self, t: T) -> InferOk<'tcx, T>; + fn normalize>>(&self, value: T) -> InferOk<'tcx, T> { + if self.infcx.next_trait_solver() { + InferOk { value, obligations: Vec::new() } + } else { + let mut selcx = SelectionContext::new(self.infcx); + let Normalized { value, obligations } = + normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); + InferOk { value, obligations } + } + } /// Deeply normalizes `value`, replacing all aliases which can by normalized in /// the current environment. In the new solver this errors in case normalization @@ -73,25 +83,6 @@ pub trait NormalizeExt<'tcx> { /// existing fulfillment context in the old solver. Once we also eagerly prove goals with /// the old solver or have removed the old solver, remove `traits::fully_normalize` and /// rename this function to `At::fully_normalize`. - fn deeply_normalize>>( - self, - value: T, - fulfill_cx: &mut dyn TraitEngine<'tcx>, - ) -> Result>>; -} - -impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { - fn normalize>>(&self, value: T) -> InferOk<'tcx, T> { - if self.infcx.next_trait_solver() { - InferOk { value, obligations: Vec::new() } - } else { - let mut selcx = SelectionContext::new(self.infcx); - let Normalized { value, obligations } = - normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); - InferOk { value, obligations } - } - } - fn deeply_normalize>>( self, value: T, diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index a050b30317a05..e56ad101d2997 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -4,32 +4,8 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext}; -pub trait InferCtxtExt<'tcx> { - fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool; - - fn predicate_must_hold_considering_regions( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> bool; - - fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool; - - fn evaluate_obligation( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> Result; - - // Helper function that canonicalizes and runs the query. If an - // overflow results, we re-run it in the local context so we can - // report a nice error. - /*crate*/ - fn evaluate_obligation_no_overflow( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> EvaluationResult; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension] +pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// Evaluates whether the predicate can be satisfied (by any means) /// in the given `ParamEnv`. fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { @@ -114,9 +90,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } } - // Helper function that canonicalizes and runs the query. If an - // overflow results, we re-run it in the local context so we can - // report a nice error. + /// Helper function that canonicalizes and runs the query. If an + /// overflow results, we re-run it in the local context so we can + /// report a nice error. fn evaluate_obligation_no_overflow( &self, obligation: &PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 0b73fefd2da9d..7dd8a990c3fd6 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -22,20 +22,8 @@ use super::NoSolution; pub use rustc_middle::traits::query::NormalizationResult; -pub trait QueryNormalizeExt<'tcx> { - /// Normalize a value using the `QueryNormalizer`. - /// - /// This normalization should *only* be used when the projection does not - /// have possible ambiguity or may not be well-formed. - /// - /// After codegen, when lifetimes do not matter, it is preferable to instead - /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure. - fn query_normalize(self, value: T) -> Result, NoSolution> - where - T: TypeFoldable>; -} - -impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { +#[extension] +pub impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { /// Normalize `value` in the context of the inference context, /// yielding a resulting type, or an error if `value` cannot be /// normalized. If you don't care about regions, you should prefer diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index e9a592bdee799..57e3f72a2f3de 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -33,19 +33,7 @@ enum Inserted<'tcx> { ShouldRecurseOn(DefId), } -trait ChildrenExt<'tcx> { - fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); - fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); - - fn insert( - &mut self, - tcx: TyCtxt<'tcx>, - impl_def_id: DefId, - simplified_self: Option, - overlap_mode: OverlapMode, - ) -> Result, OverlapError<'tcx>>; -} - +#[extension] impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { @@ -247,22 +235,8 @@ where } } -pub trait GraphExt<'tcx> { - /// Insert a local impl into the specialization graph. If an existing impl - /// conflicts with it (has overlap, but neither specializes the other), - /// information about the area of overlap is returned in the `Err`. - fn insert( - &mut self, - tcx: TyCtxt<'tcx>, - impl_def_id: DefId, - overlap_mode: OverlapMode, - ) -> Result>, OverlapError<'tcx>>; - - /// Insert cached metadata mapping from a child impl back to its parent. - fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId); -} - -impl<'tcx> GraphExt<'tcx> for Graph { +#[extension] +pub impl<'tcx> GraphExt<'tcx> for Graph { /// Insert a local impl into the specialization graph. If an existing impl /// conflicts with it (has overlap, but neither specializes the other), /// information about the area of overlap is returned in the `Err`. diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index ed5d01d7048e6..7b0a4a69501ad 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -5,15 +5,8 @@ use rustc_middle::ty::{self, Ty}; use crate::traits::{NormalizeExt, Obligation}; -pub trait StructurallyNormalizeExt<'tcx> { - fn structurally_normalize( - &self, - ty: Ty<'tcx>, - fulfill_cx: &mut dyn TraitEngine<'tcx>, - ) -> Result, Vec>>; -} - -impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { +#[extension] +pub impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { fn structurally_normalize( &self, ty: Ty<'tcx>, From a9dbf63087049549a74c0f31705df92bcf15098f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 14 Feb 2024 17:18:56 +0000 Subject: [PATCH 15/40] Move trait into attr so it's greppable --- compiler/rustc_ast_lowering/src/lib.rs | 4 +-- compiler/rustc_borrowck/src/facts.rs | 4 +-- compiler/rustc_borrowck/src/place_ext.rs | 4 +-- .../src/region_infer/opaque_types.rs | 4 +-- .../rustc_borrowck/src/universal_regions.rs | 4 +-- .../src/collect/resolve_bound_vars.rs | 4 +-- .../src/infer/canonical/instantiate.rs | 4 +-- .../src/infer/error_reporting/mod.rs | 4 +-- compiler/rustc_infer/src/infer/mod.rs | 4 +-- compiler/rustc_infer/src/traits/engine.rs | 4 +-- compiler/rustc_macros/src/extension.rs | 35 ++++++++++++------- compiler/rustc_macros/src/lib.rs | 4 +-- compiler/rustc_middle/src/ty/layout.rs | 8 ++--- compiler/rustc_middle/src/ty/util.rs | 4 +-- compiler/rustc_trait_selection/src/infer.rs | 8 ++--- compiler/rustc_trait_selection/src/regions.rs | 4 +-- .../src/solve/eval_ctxt/mod.rs | 4 +-- .../src/solve/eval_ctxt/select.rs | 4 +-- .../src/solve/inspect/analyse.rs | 4 +-- .../rustc_trait_selection/src/solve/mod.rs | 4 +-- .../src/traits/engine.rs | 4 +-- .../traits/error_reporting/infer_ctxt_ext.rs | 4 +-- .../error_reporting/on_unimplemented.rs | 4 +-- .../src/traits/error_reporting/suggestions.rs | 4 +-- .../error_reporting/type_err_ctxt_ext.rs | 8 ++--- .../src/traits/outlives_bounds.rs | 4 +-- .../src/traits/project.rs | 4 +-- .../src/traits/query/evaluate_obligation.rs | 4 +-- .../src/traits/query/normalize.rs | 4 +-- .../traits/specialize/specialization_graph.rs | 8 ++--- .../src/traits/structural_normalize.rs | 4 +-- 31 files changed, 91 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e6a7c08429bd4..a5be91bb87209 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -191,8 +191,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } -#[extension] -impl ResolverAstLoweringExt for ResolverAstLowering { +#[extension(trait ResolverAstLoweringExt)] +impl ResolverAstLowering { fn legacy_const_generic_args(&self, expr: &Expr) -> Option> { if let ExprKind::Path(None, path) = &expr.kind { // Don't perform legacy const generics rewriting if the path already diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index da14408fb6961..e7faec7bbac1e 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -25,8 +25,8 @@ impl polonius_engine::FactTypes for RustcFacts { pub type AllFacts = PoloniusFacts; -#[extension] -pub(crate) impl AllFactsExt for AllFacts { +#[extension(pub(crate) trait AllFactsExt)] +impl AllFacts { /// Returns `true` if there is a need to gather `AllFacts` given the /// current `-Z` flags. fn enabled(tcx: TyCtxt<'_>) -> bool { diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index ac8991ccf00bd..0f806df9da1da 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -5,8 +5,8 @@ use rustc_middle::mir::ProjectionElem; use rustc_middle::mir::{Body, Mutability, Place}; use rustc_middle::ty::{self, TyCtxt}; -#[extension] -pub impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { +#[extension(pub trait PlaceExt<'tcx>)] +impl<'tcx> Place<'tcx> { /// Returns `true` if we can safely ignore borrows of this place. /// This is true whenever there is no action that the user can do /// to the place `self` that would invalidate the borrow. This is true diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4aac392ef392e..a5a906658b89f 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -226,8 +226,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } -#[extension] -pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension(pub trait InferCtxtExt<'tcx>)] +impl<'tcx> InferCtxt<'tcx> { /// Given the fully resolved, instantiated type for an opaque /// type, i.e., the value of an inference variable like C1 or C2 /// (*), computes the "definition type" for an opaque type diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index f9a8543e28d2b..a69f5335f7186 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -794,8 +794,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } } -#[extension] -impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { +#[extension(trait InferCtxtExt<'tcx>)] +impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { #[instrument(skip(self), level = "debug")] fn replace_free_regions_with_nll_infer_vars( &self, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 9fb6103183bbc..325a0ee9a18fd 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -28,8 +28,8 @@ use std::fmt; use crate::errors; -#[extension] -impl RegionExt for ResolvedArg { +#[extension(trait RegionExt)] +impl ResolvedArg { fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { debug!("ResolvedArg::early: def_id={:?}", param.def_id); (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id())) diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs index 54940a2b4988c..c8adbf7f57ab4 100644 --- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs +++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs @@ -13,8 +13,8 @@ use rustc_middle::ty::{self, TyCtxt}; /// FIXME(-Znext-solver): This or public because it is shared with the /// new trait solver implementation. We should deduplicate canonicalization. -#[extension] -pub impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> { +#[extension(pub trait CanonicalExt<'tcx, V>)] +impl<'tcx, V> Canonical<'tcx, V> { /// Instantiate the wrapped value, replacing each canonical value /// with the value given in `var_values`. fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 37efafc5972f2..8f06a5eeb5f43 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2786,8 +2786,8 @@ pub enum FailureCode { Error0644, } -#[extension] -pub impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { +#[extension(pub trait ObligationCauseExt<'tcx>)] +impl<'tcx> ObligationCause<'tcx> { fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode { use self::FailureCode::*; use crate::traits::ObligationCauseCode::*; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b9ebd685ca9f2..243558b11a863 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -626,8 +626,8 @@ pub struct InferCtxtBuilder<'tcx> { next_trait_solver: bool, } -#[extension] -pub impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { +#[extension(pub trait TyCtxtInferExt<'tcx>)] +impl<'tcx> TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 79a29e2496807..ffd120fa4a42c 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -52,8 +52,8 @@ pub trait TraitEngine<'tcx>: 'tcx { ) -> Vec>; } -#[extension] -pub impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { +#[extension(pub trait TraitEngineExt<'tcx>)] +impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T { fn register_predicate_obligations( &mut self, infcx: &InferCtxt<'tcx>, diff --git a/compiler/rustc_macros/src/extension.rs b/compiler/rustc_macros/src/extension.rs index 7bb07285ae205..7830137f21891 100644 --- a/compiler/rustc_macros/src/extension.rs +++ b/compiler/rustc_macros/src/extension.rs @@ -8,10 +8,12 @@ use syn::{ Token, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility, }; -pub(crate) fn extension(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - // Parse the input tokens into a syntax tree - let Extension { attrs, generics, vis, trait_, self_ty, items } = - parse_macro_input!(input as Extension); +pub(crate) fn extension( + attr: proc_macro::TokenStream, + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let ExtensionAttr { vis, trait_ } = parse_macro_input!(attr as ExtensionAttr); + let Impl { attrs, generics, self_ty, items } = parse_macro_input!(input as Impl); let headers: Vec<_> = items .iter() .map(|item| match item { @@ -105,23 +107,32 @@ fn scrub_header(mut sig: Signature) -> Signature { sig } -struct Extension { - attrs: Vec, +struct ExtensionAttr { vis: Visibility, - generics: Generics, trait_: Path, +} + +impl Parse for ExtensionAttr { + fn parse(input: ParseStream<'_>) -> syn::Result { + let vis = input.parse()?; + let _: Token![trait] = input.parse()?; + let trait_ = input.parse()?; + Ok(ExtensionAttr { vis, trait_ }) + } +} + +struct Impl { + attrs: Vec, + generics: Generics, self_ty: Type, items: Vec, } -impl Parse for Extension { +impl Parse for Impl { fn parse(input: ParseStream<'_>) -> syn::Result { let attrs = input.call(Attribute::parse_outer)?; - let vis = input.parse()?; let _: Token![impl] = input.parse()?; let generics = input.parse()?; - let trait_ = input.parse()?; - let _: Token![for] = input.parse()?; let self_ty = input.parse()?; let content; @@ -131,6 +142,6 @@ impl Parse for Extension { items.push(content.parse()?); } - Ok(Extension { attrs, generics, vis, trait_, self_ty, items }) + Ok(Impl { attrs, generics, self_ty, items }) } } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 841f5c06126c2..619f93c8a533a 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -42,8 +42,8 @@ pub fn symbols(input: TokenStream) -> TokenStream { } #[proc_macro_attribute] -pub fn extension(_attr: TokenStream, input: TokenStream) -> TokenStream { - extension::extension(input) +pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream { + extension::extension(attr, input) } decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 1fb04f5bbfe34..c1e33fe114fb5 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -23,8 +23,8 @@ use std::fmt; use std::num::NonZero; use std::ops::Bound; -#[extension] -pub impl IntegerExt for Integer { +#[extension(pub trait IntegerExt)] +impl Integer { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> { match (*self, signed) { @@ -111,8 +111,8 @@ pub impl IntegerExt for Integer { } } -#[extension] -pub impl PrimitiveExt for Primitive { +#[extension(pub trait PrimitiveExt)] +impl Primitive { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 98d19083aaba7..3f539945841b6 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -96,8 +96,8 @@ impl<'tcx> Discr<'tcx> { } } -#[extension] -pub impl IntTypeExt for IntegerType { +#[extension(pub trait IntTypeExt)] +impl IntegerType { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self { IntegerType::Pointer(true) => tcx.types.isize, diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 8406880477e4d..f694dd0070363 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -17,8 +17,8 @@ use std::fmt::Debug; pub use rustc_infer::infer::*; -#[extension] -pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension(pub trait InferCtxtExt<'tcx>)] +impl<'tcx> InferCtxt<'tcx> { fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let ty = self.resolve_vars_if_possible(ty); @@ -105,8 +105,8 @@ pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } } -#[extension] -pub impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { +#[extension(pub trait InferCtxtBuilderExt<'tcx>)] +impl<'tcx> InferCtxtBuilder<'tcx> { /// The "main method" for a canonicalized trait query. Given the /// canonical key `canonical_key`, this method will create a new /// inference context, instantiate the key, and run your operation diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index dc9edb6063d75..222d0b4d5e75d 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -3,8 +3,8 @@ use rustc_infer::infer::{InferCtxt, RegionResolutionError}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; -#[extension] -pub impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { +#[extension(pub trait InferCtxtRegionExt<'tcx>)] +impl<'tcx> InferCtxt<'tcx> { /// Resolve regions, using the deep normalizer to normalize any type-outlives /// obligations in the process. This is in `rustc_trait_selection` because /// we need to normalize. diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 3abdc4a333053..5c1e8bf616fd4 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -131,8 +131,8 @@ pub enum GenerateProofTree { Never, } -#[extension] -pub impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { +#[extension(pub trait InferCtxtEvalExt<'tcx>)] +impl<'tcx> InferCtxt<'tcx> { /// Evaluates a goal from **outside** of the trait solver. /// /// Using this while inside of the solver is wrong as it uses a new diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 406f4c2f6151e..7196a5af259fe 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -17,8 +17,8 @@ use crate::solve::inspect::ProofTreeBuilder; use crate::traits::StructurallyNormalizeExt; use crate::traits::TraitEngineExt; -#[extension] -pub impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { +#[extension(pub trait InferCtxtSelectExt<'tcx>)] +impl<'tcx> InferCtxt<'tcx> { fn select_in_new_trait_solver( &self, obligation: &PolyTraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 1c6c2ff594a1b..47f207e1d75c1 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -216,8 +216,8 @@ pub trait ProofTreeVisitor<'tcx> { fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow; } -#[extension] -pub impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension(pub trait ProofTreeInferCtxtExt<'tcx>)] +impl<'tcx> InferCtxt<'tcx> { fn visit_proof_tree>( &self, goal: Goal<'tcx, ty::Predicate<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 11e1e72e04e23..8b163d47d3475 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -61,8 +61,8 @@ enum GoalEvaluationKind { Nested { is_normalizes_to_hack: IsNormalizesToHack }, } -#[extension] -impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> { +#[extension(trait CanonicalResponseExt)] +impl<'tcx> Canonical<'tcx, Response<'tcx>> { fn has_no_inference_or_external_constraints(&self) -> bool { self.value.external_constraints.region_constraints.is_empty() && self.value.var_values.is_identity() diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index b234b8a9d0327..1aaadf6cf044a 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -27,8 +27,8 @@ use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::Variance; use rustc_middle::ty::{self, Ty, TyCtxt}; -#[extension] -pub impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { +#[extension(pub trait TraitEngineExt<'tcx>)] +impl<'tcx> dyn TraitEngine<'tcx> { fn new(infcx: &InferCtxt<'tcx>) -> Box { if infcx.next_trait_solver() { Box::new(NextFulfillmentCtxt::new(infcx)) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs index 80581d01f6b0a..4788ecbe3e290 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs @@ -11,8 +11,8 @@ use super::ArgKind; pub use rustc_infer::traits::error_reporting::*; -#[extension] -pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension(pub trait InferCtxtExt<'tcx>)] +impl<'tcx> InferCtxt<'tcx> { /// Given some node representing a fn-like thing in the HIR map, /// returns a span and `ArgKind` information that describes the /// arguments it expects. This can be supplied to diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 7d7f415c7bb7a..4ba2da95fb324 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -38,8 +38,8 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ sym::Trait, ]; -#[extension] -pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension(pub trait TypeErrCtxtExt<'tcx>)] +impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn impl_similar_to( &self, trait_ref: ty::PolyTraitRef<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 58c731a8ed7f4..7de13bf0c0299 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -236,8 +236,8 @@ pub fn suggest_restriction<'tcx>( } } -#[extension] -pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension(pub trait TypeErrCtxtExt<'tcx>)] +impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn suggest_restricting_param_bound( &self, err: &mut Diagnostic, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 92992de64ffb9..bec6cda5fece9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -57,8 +57,8 @@ use super::{ pub use rustc_infer::traits::error_reporting::*; -#[extension] -pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension(pub trait TypeErrCtxtExt<'tcx>)] +impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn report_fulfillment_errors( &self, mut errors: Vec>, @@ -1326,8 +1326,8 @@ pub impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } -#[extension] -pub(super) impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { +#[extension(pub(super) trait InferCtxtPrivExt<'tcx>)] +impl<'tcx> TypeErrCtxt<'_, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index c4e8ea45dd32e..6825dd4ac713d 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -111,8 +111,8 @@ fn implied_outlives_bounds<'a, 'tcx>( bounds } -#[extension] -pub impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { +#[extension(pub trait InferCtxtExt<'a, 'tcx>)] +impl<'a, 'tcx: 'a> InferCtxt<'tcx> { /// Do *NOT* call this directly. fn implied_bounds_tys_compat( &'a self, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 807540a1720a2..279c00031875a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -52,8 +52,8 @@ pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>; pub(super) struct InProgress; -#[extension] -pub impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { +#[extension(pub trait NormalizeExt<'tcx>)] +impl<'tcx> At<'_, 'tcx> { /// Normalize a value using the `AssocTypeNormalizer`. /// /// This normalization should be used when the type contains inference variables or the diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index e56ad101d2997..16ee9fadab4fc 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -4,8 +4,8 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext}; -#[extension] -pub impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { +#[extension(pub trait InferCtxtExt<'tcx>)] +impl<'tcx> InferCtxt<'tcx> { /// Evaluates whether the predicate can be satisfied (by any means) /// in the given `ParamEnv`. fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 7dd8a990c3fd6..6ed9ac910272b 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -22,8 +22,8 @@ use super::NoSolution; pub use rustc_middle::traits::query::NormalizationResult; -#[extension] -pub impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { +#[extension(pub trait QueryNormalizeExt<'tcx>)] +impl<'cx, 'tcx> At<'cx, 'tcx> { /// Normalize `value` in the context of the inference context, /// yielding a resulting type, or an error if `value` cannot be /// normalized. If you don't care about regions, you should prefer diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 57e3f72a2f3de..f3b77d689225c 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -33,8 +33,8 @@ enum Inserted<'tcx> { ShouldRecurseOn(DefId), } -#[extension] -impl<'tcx> ChildrenExt<'tcx> for Children { +#[extension(trait ChildrenExt<'tcx>)] +impl<'tcx> Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); @@ -235,8 +235,8 @@ where } } -#[extension] -pub impl<'tcx> GraphExt<'tcx> for Graph { +#[extension(pub trait GraphExt<'tcx>)] +impl<'tcx> Graph { /// Insert a local impl into the specialization graph. If an existing impl /// conflicts with it (has overlap, but neither specializes the other), /// information about the area of overlap is returned in the `Err`. diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index 7b0a4a69501ad..2f428564ae736 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -5,8 +5,8 @@ use rustc_middle::ty::{self, Ty}; use crate::traits::{NormalizeExt, Obligation}; -#[extension] -pub impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { +#[extension(pub trait StructurallyNormalizeExt<'tcx>)] +impl<'tcx> At<'_, 'tcx> { fn structurally_normalize( &self, ty: Ty<'tcx>, From f624d55ea77b1b24e9294818ee1d6b1da9d0ec2d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Feb 2024 15:07:32 +0000 Subject: [PATCH 16/40] Nits --- compiler/rustc_infer/src/traits/engine.rs | 1 + compiler/rustc_macros/src/extension.rs | 9 ++++++++- .../rustc_trait_selection/src/traits/query/normalize.rs | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index ffd120fa4a42c..c495810858f7f 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -64,6 +64,7 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T { } } + #[must_use] fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { let errors = self.select_where_possible(infcx); if !errors.is_empty() { diff --git a/compiler/rustc_macros/src/extension.rs b/compiler/rustc_macros/src/extension.rs index 7830137f21891..5377bbdfeabd0 100644 --- a/compiler/rustc_macros/src/extension.rs +++ b/compiler/rustc_macros/src/extension.rs @@ -68,7 +68,14 @@ pub(crate) fn extension( /// Only keep `#[doc]` attrs. fn scrub_attrs(attrs: &[Attribute]) -> Vec { - attrs.into_iter().cloned().filter(|attr| attr.path().segments[0].ident == "doc").collect() + attrs + .into_iter() + .cloned() + .filter(|attr| { + let ident = &attr.path().segments[0].ident; + ident == "doc" || ident == "must_use" + }) + .collect() } /// Scrub arguments so that they're valid for trait signatures. diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 6ed9ac910272b..0f6c0abd280e4 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -37,6 +37,12 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { /// normalizing, but for now should be used only when we actually /// know that normalization will succeed, since error reporting /// and other details are still "under development". + /// + /// This normalization should *only* be used when the projection does not + /// have possible ambiguity or may not be well-formed. + /// + /// After codegen, when lifetimes do not matter, it is preferable to instead + /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure. fn query_normalize(self, value: T) -> Result, NoSolution> where T: TypeFoldable>, From 7c2db703b0b56cede3d8ce264e9d1fcdb1397f94 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 11 Feb 2024 17:18:57 -0500 Subject: [PATCH 17/40] Don't use mem::zeroed in vec::IntoIter --- library/alloc/src/vec/into_iter.rs | 63 ++++++++++++++---------------- tests/codegen/vec-iter.rs | 17 +++++++- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 63d8fe19ac35c..dfd42ca06193a 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -11,7 +11,7 @@ use core::iter::{ TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; +use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::num::NonZero; #[cfg(not(no_global_oom_handling))] use core::ops::Deref; @@ -200,27 +200,23 @@ impl Iterator for IntoIter { #[inline] fn next(&mut self) -> Option { - if T::IS_ZST { - if self.ptr.as_ptr() == self.end as *mut _ { - None - } else { - // `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by - // reducing the `end`. - self.end = self.end.wrapping_byte_sub(1); - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) + let ptr = if T::IS_ZST { + if self.ptr.as_ptr() == self.end as *mut T { + return None; } + // `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by + // reducing the `end`. + self.end = self.end.wrapping_byte_sub(1); + self.ptr } else { if self.ptr == non_null!(self.end, T) { - None - } else { - let old = self.ptr; - self.ptr = unsafe { old.add(1) }; - - Some(unsafe { ptr::read(old.as_ptr()) }) + return None; } - } + let old = self.ptr; + self.ptr = unsafe { old.add(1) }; + old + }; + Some(unsafe { ptr.read() }) } #[inline] @@ -305,7 +301,7 @@ impl Iterator for IntoIter { // Also note the implementation of `Self: TrustedRandomAccess` requires // that `T: Copy` so reading elements from the buffer doesn't invalidate // them for `Drop`. - unsafe { if T::IS_ZST { mem::zeroed() } else { self.ptr.add(i).read() } } + unsafe { self.ptr.add(i).read() } } } @@ -314,23 +310,22 @@ impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { if T::IS_ZST { - if self.end as *mut _ == self.ptr.as_ptr() { - None - } else { - // See above for why 'ptr.offset' isn't used - self.end = self.end.wrapping_byte_sub(1); - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) + if self.ptr.as_ptr() == self.end as *mut _ { + return None; } + // See above for why 'ptr.offset' isn't used + self.end = self.end.wrapping_byte_sub(1); + // Note that even though this is next_back() we're reading from `self.ptr`, not + // `self.end`. We track our length using the byte offset from `self.ptr` to `self.end`, + // so the end pointer may not be suitably aligned for T. + Some(unsafe { ptr::read(self.ptr.as_ptr()) }) } else { - if non_null!(self.end, T) == self.ptr { - None - } else { - let new_end = unsafe { non_null!(self.end, T).sub(1) }; - *non_null!(mut self.end, T) = new_end; - - Some(unsafe { ptr::read(new_end.as_ptr()) }) + if self.ptr == non_null!(self.end, T) { + return None; + } + unsafe { + self.end = self.end.sub(1); + Some(ptr::read(self.end)) } } } diff --git a/tests/codegen/vec-iter.rs b/tests/codegen/vec-iter.rs index 0282791e9d169..4e2068587510c 100644 --- a/tests/codegen/vec-iter.rs +++ b/tests/codegen/vec-iter.rs @@ -32,9 +32,9 @@ pub fn vec_iter_is_empty_nonnull(it: &vec::IntoIter) -> bool { it.is_empty() } -// CHECK-LABEL: @vec_iter_next +// CHECK-LABEL: @vec_iter_next_nonnull #[no_mangle] -pub fn vec_iter_next(it: &mut vec::IntoIter) -> Option { +pub fn vec_iter_next_nonnull(it: &mut vec::IntoIter) -> Option { // CHECK: load ptr // CHECK-SAME: !nonnull // CHECK-SAME: !noundef @@ -44,3 +44,16 @@ pub fn vec_iter_next(it: &mut vec::IntoIter) -> Option { // CHECK: ret it.next() } + +// CHECK-LABEL: @vec_iter_next_back_nonnull +#[no_mangle] +pub fn vec_iter_next_back_nonnull(it: &mut vec::IntoIter) -> Option { + // CHECK: load ptr + // CHECK-SAME: !nonnull + // CHECK-SAME: !noundef + // CHECK: load ptr + // CHECK-SAME: !nonnull + // CHECK-SAME: !noundef + // CHECK: ret + it.next_back() +} From 4b732c990d9bf6b2de86f05db714da896fb113ce Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 16 Feb 2024 18:26:34 +0100 Subject: [PATCH 18/40] Let rustbot ping me on changes to match lowering --- triagebot.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 383b89b18df57..94d8601e193bb 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -480,12 +480,16 @@ cc = ["@lcnr", "@compiler-errors"] message = "Some changes occurred in diagnostic error codes" cc = ["@GuillaumeGomez"] +[mentions."compiler/rustc_mir_build/src/build/matches"] +message = "Some changes occurred in match lowering" +cc = ["@Nadrieril"] + [mentions."compiler/rustc_mir_build/src/thir/pattern"] -message = "Some changes might have occurred in exhaustiveness checking" +message = "Some changes occurred in match checking" cc = ["@Nadrieril"] [mentions."compiler/rustc_pattern_analysis"] -message = "Some changes might have occurred in exhaustiveness checking" +message = "Some changes occurred in exhaustiveness checking" cc = ["@Nadrieril"] [mentions."library/core/src/intrinsics/simd.rs"] From 6c7827c03e11135a27e446d806ada126bf64a7c1 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 16 Feb 2024 18:31:13 +0100 Subject: [PATCH 19/40] Add myself to review rotation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 94d8601e193bb..32b22e52a20a2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -662,6 +662,7 @@ compiler-team = [ ] compiler-team-contributors = [ "@TaKO8Ki", + "@Nadrieril", "@nnethercote", "@fmease", ] From d855ca044da4ed42eb60dbd20cc1341f35d8e0fc Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 16 Feb 2024 18:51:22 +0000 Subject: [PATCH 20/40] Ensure `./configure` works when `configure.py` path contains spaces --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 81e2001e4a583..e8627c9f0d50c 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #!/bin/sh -script="$(dirname $0)"/src/bootstrap/configure.py +script="$(dirname "$0")"/src/bootstrap/configure.py try() { cmd=$1 @@ -15,4 +15,4 @@ try python3 "$@" try python2.7 "$@" try python27 "$@" try python2 "$@" -exec python $script "$@" +exec python "$script" "$@" From 974bc455ee2d623ecda20e86ceed5907a47630e0 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 16 Feb 2024 13:49:29 -0800 Subject: [PATCH 21/40] Specialize flattening iterators with only one inner item For iterators like `Once` and `option::IntoIter` that only ever have a single item at most, the front and back iterator states in `FlatMap` and `Flatten` are a waste, as they're always consumed already. We can use specialization for these types to simplify the iterator methods. It's a somewhat common pattern to use `flatten()` for options and results, even recommended by [multiple][1] [clippy][2] [lints][3]. The implementation is more efficient with `filter_map`, as mentioned in [clippy#9377], but this new specialization should close some of that gap for existing code that flattens. [1]: https://rust-lang.github.io/rust-clippy/master/#filter_map_identity [2]: https://rust-lang.github.io/rust-clippy/master/#option_filter_map [3]: https://rust-lang.github.io/rust-clippy/master/#result_filter_map [clippy#9377]: https://github.com/rust-lang/rust-clippy/issues/9377 --- library/core/src/iter/adapters/flatten.rs | 221 ++++++++++++++++++-- library/core/tests/iter/adapters/flatten.rs | 66 ++++++ 2 files changed, 275 insertions(+), 12 deletions(-) diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 99344a88efc3f..64a2ca3d2b870 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -3,7 +3,7 @@ use crate::iter::{ Cloned, Copied, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable, Map, TrustedFused, TrustedLen, }; -use crate::iter::{Once, OnceWith}; +use crate::iter::{Empty, Once, OnceWith}; use crate::num::NonZero; use crate::ops::{ControlFlow, Try}; use crate::result; @@ -593,6 +593,7 @@ where } } +// See also the `OneShot` specialization below. impl Iterator for FlattenCompat where I: Iterator>, @@ -601,7 +602,7 @@ where type Item = U::Item; #[inline] - fn next(&mut self) -> Option { + default fn next(&mut self) -> Option { loop { if let elt @ Some(_) = and_then_or_clear(&mut self.frontiter, Iterator::next) { return elt; @@ -614,7 +615,7 @@ where } #[inline] - fn size_hint(&self) -> (usize, Option) { + default fn size_hint(&self) -> (usize, Option) { let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint); let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint); let lo = flo.saturating_add(blo); @@ -636,7 +637,7 @@ where } #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R + default fn try_fold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, @@ -653,7 +654,7 @@ where } #[inline] - fn fold(self, init: Acc, fold: Fold) -> Acc + default fn fold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { @@ -669,7 +670,7 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + default fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { #[inline] #[rustc_inherit_overflow_checks] fn advance(n: usize, iter: &mut U) -> ControlFlow<(), usize> { @@ -686,7 +687,7 @@ where } #[inline] - fn count(self) -> usize { + default fn count(self) -> usize { #[inline] #[rustc_inherit_overflow_checks] fn count(acc: usize, iter: U) -> usize { @@ -697,7 +698,7 @@ where } #[inline] - fn last(self) -> Option { + default fn last(self) -> Option { #[inline] fn last(last: Option, iter: U) -> Option { iter.last().or(last) @@ -707,13 +708,14 @@ where } } +// See also the `OneShot` specialization below. impl DoubleEndedIterator for FlattenCompat where I: DoubleEndedIterator>, U: DoubleEndedIterator, { #[inline] - fn next_back(&mut self) -> Option { + default fn next_back(&mut self) -> Option { loop { if let elt @ Some(_) = and_then_or_clear(&mut self.backiter, |b| b.next_back()) { return elt; @@ -726,7 +728,7 @@ where } #[inline] - fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + default fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, @@ -743,7 +745,7 @@ where } #[inline] - fn rfold(self, init: Acc, fold: Fold) -> Acc + default fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { @@ -759,7 +761,7 @@ where #[inline] #[rustc_inherit_overflow_checks] - fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + default fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { #[inline] #[rustc_inherit_overflow_checks] fn advance(n: usize, iter: &mut U) -> ControlFlow<(), usize> { @@ -841,3 +843,198 @@ fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option } x } + +/// Specialization trait for iterator types that never return more than one item. +/// +/// Note that we still have to deal with the possibility that the iterator was +/// already exhausted before it came into our control. +#[rustc_specialization_trait] +trait OneShot {} + +// These all have exactly one item, if not already consumed. +impl OneShot for Once {} +impl OneShot for OnceWith {} +impl OneShot for array::IntoIter {} +impl OneShot for option::IntoIter {} +impl OneShot for option::Iter<'_, T> {} +impl OneShot for option::IterMut<'_, T> {} +impl OneShot for result::IntoIter {} +impl OneShot for result::Iter<'_, T> {} +impl OneShot for result::IterMut<'_, T> {} + +// These are always empty, which is fine to optimize too. +impl OneShot for Empty {} +impl OneShot for array::IntoIter {} + +// These adaptors never increase the number of items. +// (There are more possible, but for now this matches BoundedSize above.) +impl OneShot for Cloned {} +impl OneShot for Copied {} +impl OneShot for Filter {} +impl OneShot for FilterMap {} +impl OneShot for Map {} + +// Blanket impls pass this property through as well +// (but we can't do `Box` unless we expose this trait to alloc) +impl OneShot for &mut I {} + +#[inline] +fn into_item(inner: I) -> Option +where + I: IntoIterator, +{ + inner.into_iter().next() +} + +#[inline] +fn flatten_one, Acc>( + mut fold: impl FnMut(Acc, I::Item) -> Acc, +) -> impl FnMut(Acc, I) -> Acc { + move |acc, inner| match inner.into_iter().next() { + Some(item) => fold(acc, item), + None => acc, + } +} + +#[inline] +fn try_flatten_one, Acc, R: Try>( + mut fold: impl FnMut(Acc, I::Item) -> R, +) -> impl FnMut(Acc, I) -> R { + move |acc, inner| match inner.into_iter().next() { + Some(item) => fold(acc, item), + None => try { acc }, + } +} + +#[inline] +fn advance_by_one(n: NonZero, inner: I) -> Option> +where + I: IntoIterator, +{ + match inner.into_iter().next() { + Some(_) => NonZero::new(n.get() - 1), + None => Some(n), + } +} + +// Specialization: For iterators that never return more than one item, the `frontiter` and +// `backiter` states are a waste, because they'll always have already consumed their item. So in +// this impl, we completely ignore them and just focus on `self.iter`, and we only call the inner +// `next()` one time. +// +// It's mostly fine if we accidentally mix this with the more generic impls, e.g. by forgetting to +// specialize one of the methods. If the other impl did set the front or back, we wouldn't see it +// here, but it would be empty anyway; and if the other impl looked for a front or back that we +// didn't bother setting, it would just see `None` (or a previous empty) and move on. +// +// An exception to that is `advance_by(0)` and `advance_back_by(0)`, where the generic impls may set +// `frontiter` or `backiter` without consuming the item, so we **must** override those. +impl Iterator for FlattenCompat +where + I: Iterator>, + U: Iterator + OneShot, +{ + #[inline] + fn next(&mut self) -> Option { + while let Some(inner) = self.iter.next() { + if let item @ Some(_) = inner.into_iter().next() { + return item; + } + } + None + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + match ::size() { + Some(0) => (0, Some(0)), + Some(1) => (lower, upper), + _ => (0, upper), + } + } + + #[inline] + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_fold(init, try_flatten_one(fold)) + } + + #[inline] + fn fold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.fold(init, flatten_one(fold)) + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + if let Some(n) = NonZero::new(n) { + self.iter.try_fold(n, advance_by_one).map_or(Ok(()), Err) + } else { + // Just advance the outer iterator + self.iter.advance_by(0) + } + } + + #[inline] + fn count(self) -> usize { + self.iter.filter_map(into_item).count() + } + + #[inline] + fn last(self) -> Option { + self.iter.filter_map(into_item).last() + } +} + +// Note: We don't actually care about `U: DoubleEndedIterator`, since forward and backward are the +// same for a one-shot iterator, but we have to keep that to match the default specialization. +impl DoubleEndedIterator for FlattenCompat +where + I: DoubleEndedIterator>, + U: DoubleEndedIterator + OneShot, +{ + #[inline] + fn next_back(&mut self) -> Option { + while let Some(inner) = self.iter.next_back() { + if let item @ Some(_) = inner.into_iter().next() { + return item; + } + } + None + } + + #[inline] + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + self.iter.try_rfold(init, try_flatten_one(fold)) + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.iter.rfold(init, flatten_one(fold)) + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + if let Some(n) = NonZero::new(n) { + self.iter.try_rfold(n, advance_by_one).map_or(Ok(()), Err) + } else { + // Just advance the outer iterator + self.iter.advance_back_by(0) + } + } +} diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index 2af7e0c388a3b..1f953f2aa0110 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -212,3 +212,69 @@ fn test_flatten_last() { assert_eq!(it.advance_by(3), Ok(())); // 22..22 assert_eq!(it.clone().last(), None); } + +#[test] +fn test_flatten_one_shot() { + // This could be `filter_map`, but people often do flatten options. + let mut it = (0i8..10).flat_map(|i| NonZero::new(i % 7)); + assert_eq!(it.size_hint(), (0, Some(10))); + assert_eq!(it.clone().count(), 8); + assert_eq!(it.clone().last(), NonZero::new(2)); + + // sum -> fold + let sum: i8 = it.clone().map(|n| n.get()).sum(); + assert_eq!(sum, 24); + + // the product overflows at 6, remaining are 7,8,9 -> 1,2 + let one = NonZero::new(1i8).unwrap(); + let product = it.try_fold(one, |acc, x| acc.checked_mul(x)); + assert_eq!(product, None); + assert_eq!(it.size_hint(), (0, Some(3))); + assert_eq!(it.clone().count(), 2); + + assert_eq!(it.advance_by(0), Ok(())); + assert_eq!(it.clone().next(), NonZero::new(1)); + assert_eq!(it.advance_by(1), Ok(())); + assert_eq!(it.clone().next(), NonZero::new(2)); + assert_eq!(it.advance_by(100), Err(NonZero::new(99).unwrap())); + assert_eq!(it.next(), None); +} + +#[test] +fn test_flatten_one_shot_rev() { + let mut it = (0i8..10).flat_map(|i| NonZero::new(i % 7)).rev(); + assert_eq!(it.size_hint(), (0, Some(10))); + assert_eq!(it.clone().count(), 8); + assert_eq!(it.clone().last(), NonZero::new(1)); + + // sum -> Rev fold -> rfold + let sum: i8 = it.clone().map(|n| n.get()).sum(); + assert_eq!(sum, 24); + + // Rev try_fold -> try_rfold + // the product overflows at 4, remaining are 3,2,1,0 -> 3,2,1 + let one = NonZero::new(1i8).unwrap(); + let product = it.try_fold(one, |acc, x| acc.checked_mul(x)); + assert_eq!(product, None); + assert_eq!(it.size_hint(), (0, Some(4))); + assert_eq!(it.clone().count(), 3); + + // Rev advance_by -> advance_back_by + assert_eq!(it.advance_by(0), Ok(())); + assert_eq!(it.clone().next(), NonZero::new(3)); + assert_eq!(it.advance_by(1), Ok(())); + assert_eq!(it.clone().next(), NonZero::new(2)); + assert_eq!(it.advance_by(100), Err(NonZero::new(98).unwrap())); + assert_eq!(it.next(), None); +} + +#[test] +fn test_flatten_one_shot_arrays() { + let it = (0..10).flat_map(|i| [i]); + assert_eq!(it.size_hint(), (10, Some(10))); + assert_eq!(it.sum::(), 45); + + let mut it = (0..10).flat_map(|_| -> [i32; 0] { [] }); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} From 6a671bdbf1c0b68af05dd34595e4c10d6fe3abe7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 16 Feb 2024 17:29:34 +0000 Subject: [PATCH 22/40] Give the `assume` intrinsic a fallback body --- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- library/core/src/intrinsics.rs | 36 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index f0f6bfff64aaa..fcc0ec69d5e6f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -407,7 +407,7 @@ pub fn check_intrinsic_type( } sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)), - sym::assume => (0, 0, vec![tcx.types.bool], Ty::new_unit(tcx)), + sym::assume => (0, 1, vec![tcx.types.bool], Ty::new_unit(tcx)), sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool), sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool), diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index fc6c1eab803d7..7b73396afc688 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -937,20 +937,30 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn unreachable() -> !; - /// Informs the optimizer that a condition is always true. - /// If the condition is false, the behavior is undefined. - /// - /// No code is generated for this intrinsic, but the optimizer will try - /// to preserve it (and its condition) between passes, which may interfere - /// with optimization of surrounding code and reduce performance. It should - /// not be used if the invariant can be discovered by the optimizer on its - /// own, or if it does not enable any significant optimizations. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_const_stable(feature = "const_assume", since = "1.77.0")] - #[rustc_nounwind] - pub fn assume(b: bool); +} + +/// Informs the optimizer that a condition is always true. +/// If the condition is false, the behavior is undefined. +/// +/// No code is generated for this intrinsic, but the optimizer will try +/// to preserve it (and its condition) between passes, which may interfere +/// with optimization of surrounding code and reduce performance. It should +/// not be used if the invariant can be discovered by the optimizer on its +/// own, or if it does not enable any significant optimizations. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_const_stable(feature = "const_assume", since = "1.77.0")] +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const unsafe fn assume(b: bool) { + if !b { + // SAFETY: the caller must guarantee the argument is never `false` + unsafe { unreachable() } + } +} +extern "rust-intrinsic" { /// Hints to the compiler that branch condition is likely to be true. /// Returns the value passed to it. /// From dd40a80102950a06d0467a2e7d7203ee85911470 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 16 Feb 2024 17:45:46 +0000 Subject: [PATCH 23/40] Give the (`un`)`likely` intrinsics fallback bodies --- .../rustc_hir_analysis/src/check/intrinsic.rs | 4 +- library/core/src/intrinsics.rs | 68 ++++++++++--------- .../ui/intrinsics/safe-intrinsic-mismatch.rs | 8 +-- .../intrinsics/safe-intrinsic-mismatch.stderr | 21 +++--- tests/ui/reify-intrinsic.rs | 5 +- tests/ui/reify-intrinsic.stderr | 11 ++- 6 files changed, 61 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index fcc0ec69d5e6f..903c98e8317fb 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -408,8 +408,8 @@ pub fn check_intrinsic_type( sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)), sym::assume => (0, 1, vec![tcx.types.bool], Ty::new_unit(tcx)), - sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool), - sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool), + sym::likely => (0, 1, vec![tcx.types.bool], tcx.types.bool), + sym::unlikely => (0, 1, vec![tcx.types.bool], tcx.types.bool), sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)), sym::write_via_move => { diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 7b73396afc688..ce1876d5a2f2f 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -960,39 +960,45 @@ pub const unsafe fn assume(b: bool) { } } -extern "rust-intrinsic" { - /// Hints to the compiler that branch condition is likely to be true. - /// Returns the value passed to it. - /// - /// Any use other than with `if` statements will probably not have an effect. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_likely", issue = "none")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn likely(b: bool) -> bool; +/// Hints to the compiler that branch condition is likely to be true. +/// Returns the value passed to it. +/// +/// Any use other than with `if` statements will probably not have an effect. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_const_unstable(feature = "const_likely", issue = "none")] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +#[rustc_nounwind] +pub const fn likely(b: bool) -> bool { + b +} - /// Hints to the compiler that branch condition is likely to be false. - /// Returns the value passed to it. - /// - /// Any use other than with `if` statements will probably not have an effect. - /// - /// Note that, unlike most intrinsics, this is safe to call; - /// it does not require an `unsafe` block. - /// Therefore, implementations must not require the user to uphold - /// any safety invariants. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_likely", issue = "none")] - #[rustc_safe_intrinsic] - #[rustc_nounwind] - pub fn unlikely(b: bool) -> bool; +/// Hints to the compiler that branch condition is likely to be false. +/// Returns the value passed to it. +/// +/// Any use other than with `if` statements will probably not have an effect. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_const_unstable(feature = "const_likely", issue = "none")] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +#[rustc_nounwind] +pub const fn unlikely(b: bool) -> bool { + b +} +extern "rust-intrinsic" { /// Executes a breakpoint trap, for inspection by a debugger. /// /// This intrinsic does not have a stable counterpart. diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs index fcd6612f1259d..23cd5f1083534 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs @@ -5,12 +5,12 @@ extern "rust-intrinsic" { fn size_of() -> usize; //~ ERROR intrinsic safety mismatch //~^ ERROR intrinsic safety mismatch - - #[rustc_safe_intrinsic] - fn assume(b: bool); //~ ERROR intrinsic safety mismatch - //~^ ERROR intrinsic safety mismatch } +#[rustc_intrinsic] +const fn assume(_b: bool) {} //~ ERROR intrinsic safety mismatch +//~| ERROR intrinsic has wrong type + #[rustc_intrinsic] const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} //~^ ERROR intrinsic safety mismatch diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr index 0b579121ac18e..2e0812d6472b6 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr @@ -4,12 +4,6 @@ error: intrinsic safety mismatch between list of intrinsics within the compiler LL | fn size_of() -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` - --> $DIR/safe-intrinsic-mismatch.rs:10:5 - | -LL | fn assume(b: bool); - | ^^^^^^^^^^^^^^^^^^ - error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` --> $DIR/safe-intrinsic-mismatch.rs:6:5 | @@ -19,12 +13,19 @@ LL | fn size_of() -> usize; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` - --> $DIR/safe-intrinsic-mismatch.rs:10:5 + --> $DIR/safe-intrinsic-mismatch.rs:11:1 | -LL | fn assume(b: bool); - | ^^^^^^^^^^^^^^^^^^ +LL | const fn assume(_b: bool) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: intrinsic has wrong type + --> $DIR/safe-intrinsic-mismatch.rs:11:16 | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +LL | const fn assume(_b: bool) {} + | ^ expected unsafe fn, found normal fn + | + = note: expected signature `unsafe fn(_)` + found signature `fn(_)` error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `const_deallocate` --> $DIR/safe-intrinsic-mismatch.rs:15:1 diff --git a/tests/ui/reify-intrinsic.rs b/tests/ui/reify-intrinsic.rs index 9eb2f724017ed..d8a268bd33a81 100644 --- a/tests/ui/reify-intrinsic.rs +++ b/tests/ui/reify-intrinsic.rs @@ -13,10 +13,9 @@ fn b() { } fn c() { - let _ = [ - std::intrinsics::likely, + let _: [unsafe extern "rust-intrinsic" fn(bool) -> bool; 2] = [ + std::intrinsics::likely, //~ ERROR cannot coerce std::intrinsics::unlikely, - //~^ ERROR cannot coerce ]; } diff --git a/tests/ui/reify-intrinsic.stderr b/tests/ui/reify-intrinsic.stderr index 310b6c224e0e7..0119a1a6650d0 100644 --- a/tests/ui/reify-intrinsic.stderr +++ b/tests/ui/reify-intrinsic.stderr @@ -16,14 +16,13 @@ LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: cannot coerce intrinsics to function pointers - --> $DIR/reify-intrinsic.rs:18:9 + --> $DIR/reify-intrinsic.rs:17:9 | -LL | std::intrinsics::unlikely, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers +LL | std::intrinsics::likely, + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | - = note: expected fn item `extern "rust-intrinsic" fn(_) -> _ {likely}` - found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}` - = note: different fn items have unique types, even if their signatures are the same + = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _` + found fn item `fn(_) -> _ {likely}` error: aborting due to 3 previous errors From ede99234c48c120b909990ee2ee51dd87cfed6f5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 17 Feb 2024 10:51:35 +1100 Subject: [PATCH 24/40] Make `CodegenBackend::join_codegen` infallible. Because they all are, in practice. --- compiler/rustc_codegen_cranelift/src/lib.rs | 6 +++--- compiler/rustc_codegen_gcc/src/lib.rs | 8 +++----- compiler/rustc_codegen_llvm/src/lib.rs | 4 ++-- compiler/rustc_codegen_ssa/src/traits/backend.rs | 2 +- compiler/rustc_interface/src/queries.rs | 2 +- .../hotplug_codegen_backend/the_backend.rs | 4 ++-- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 7c432e9c59051..7e2e1f7c6ac07 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -233,11 +233,11 @@ impl CodegenBackend for CraneliftCodegenBackend { ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { - Ok(ongoing_codegen + ) -> (CodegenResults, FxIndexMap) { + ongoing_codegen .downcast::() .unwrap() - .join(sess, self.config.borrow().as_ref().unwrap())) + .join(sess, self.config.borrow().as_ref().unwrap()) } fn link( diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 863b6333bcc29..09ce059476ec7 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -217,13 +217,11 @@ impl CodegenBackend for GccCodegenBackend { Box::new(res) } - fn join_codegen(&self, ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { - let (codegen_results, work_products) = ongoing_codegen + fn join_codegen(&self, ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames) -> (CodegenResults, FxIndexMap) { + ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") - .join(sess); - - Ok((codegen_results, work_products)) + .join(sess) } fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index e688e84db61a5..35210b0b2e86d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -369,7 +369,7 @@ impl CodegenBackend for LlvmCodegenBackend { ongoing_codegen: Box, sess: &Session, outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { + ) -> (CodegenResults, FxIndexMap) { let (codegen_results, work_products) = ongoing_codegen .downcast::>() .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box") @@ -382,7 +382,7 @@ impl CodegenBackend for LlvmCodegenBackend { }); } - Ok((codegen_results, work_products)) + (codegen_results, work_products) } fn link( diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 8e9907ed8bb03..cb1feff13363e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -102,7 +102,7 @@ pub trait CodegenBackend { ongoing_codegen: Box, sess: &Session, outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed>; + ) -> (CodegenResults, FxIndexMap); /// This is called on the returned `CodegenResults` from `join_codegen` fn link( diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 2a4eefb7f771b..211bcb9da94db 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -259,7 +259,7 @@ pub struct Linker { impl Linker { pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> { let (codegen_results, work_products) = - codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)?; + codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames); sess.compile_status()?; diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 9e0a7ba63d05f..28a1e27cccccd 100644 --- a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -49,11 +49,11 @@ impl CodegenBackend for TheBackend { ongoing_codegen: Box, _sess: &Session, _outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { + ) -> (CodegenResults, FxIndexMap) { let codegen_results = ongoing_codegen .downcast::() .expect("in join_codegen: ongoing_codegen is not a CodegenResults"); - Ok((*codegen_results, FxIndexMap::default())) + (*codegen_results, FxIndexMap::default()) } fn link( From 40719384e1da64776d0ee67a84ffdfacc67816b0 Mon Sep 17 00:00:00 2001 From: Steven Date: Sat, 16 Dec 2023 19:29:45 -0500 Subject: [PATCH 25/40] Use a hardcoded constant instead of calling OpenProcessToken. Now that Win 7 support is dropped, we can resurrect #90144. GetCurrentProcessToken is defined in processthreadsapi.h as: FORCEINLINE HANDLE GetCurrentProcessToken ( VOID ) { return (HANDLE)(LONG_PTR) -4; } Since it's very unlikely that this constant will ever change, let's just use it instead of making calls to get the same information. --- library/std/src/sys/pal/windows/os.rs | 31 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs index 829dd5eb97ac2..58163f7a73faf 100644 --- a/library/std/src/sys/pal/windows/os.rs +++ b/library/std/src/sys/pal/windows/os.rs @@ -1,5 +1,6 @@ //! Implementation of `std::os` functionality for Windows. +#![cfg_attr(bootstrap, allow(unexpected_cfgs))] #![allow(nonstandard_style)] #[cfg(test)] @@ -318,13 +319,33 @@ pub fn temp_dir() -> PathBuf { super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap() } -#[cfg(not(target_vendor = "uwp"))] +#[cfg(all(not(target_vendor = "uwp"), not(target_vendor = "win7")))] +fn home_dir_crt() -> Option { + unsafe { + // Defined in processthreadsapi.h. + const CURRENT_PROCESS_TOKEN: usize = -4_isize as usize; + + super::fill_utf16_buf( + |buf, mut sz| { + match c::GetUserProfileDirectoryW( + ptr::invalid_mut(CURRENT_PROCESS_TOKEN), + buf, + &mut sz, + ) { + 0 if api::get_last_error().code != c::ERROR_INSUFFICIENT_BUFFER => 0, + 0 => sz, + _ => sz - 1, // sz includes the null terminator + } + }, + super::os2path, + ) + .ok() + } +} + +#[cfg(target_vendor = "win7")] fn home_dir_crt() -> Option { unsafe { - // The magic constant -4 can be used as the token passed to GetUserProfileDirectoryW below - // instead of us having to go through these multiple steps to get a token. However this is - // not implemented on Windows 7, only Windows 8 and up. When we drop support for Windows 7 - // we can simplify this code. See #90144 for details. use crate::sys::handle::Handle; let me = c::GetCurrentProcess(); From 228441dbd6e9fc823da545ed29499f6f8e5d7101 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Feb 2024 17:56:15 +0000 Subject: [PATCH 26/40] Use fulfillment in next trait solver coherence --- .../src/solve/inspect/analyse.rs | 8 ++- .../src/traits/coherence.rs | 70 ++++++++++--------- tests/ui/coherence/coherent-due-to-fulfill.rs | 20 ++++++ .../incoherent-even-though-we-fulfill.rs | 22 ++++++ .../incoherent-even-though-we-fulfill.stderr | 14 ++++ 5 files changed, 97 insertions(+), 37 deletions(-) create mode 100644 tests/ui/coherence/coherent-due-to-fulfill.rs create mode 100644 tests/ui/coherence/incoherent-even-though-we-fulfill.rs create mode 100644 tests/ui/coherence/incoherent-even-though-we-fulfill.stderr diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index f33d0f397ce9e..9020c11b2559e 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -230,8 +230,10 @@ impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { goal: Goal<'tcx, ty::Predicate<'tcx>>, visitor: &mut V, ) -> ControlFlow { - let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); - let proof_tree = proof_tree.unwrap(); - visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree)) + self.probe(|_| { + let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); + let proof_tree = proof_tree.unwrap(); + visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree)) + }) } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index e48bd437f59c5..f663f02f87289 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -8,23 +8,21 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; use crate::regions::InferCtxtRegionExt; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::solve::{deeply_normalize_for_diagnostics, inspect}; -use crate::traits::engine::TraitEngineExt; -use crate::traits::query::evaluate_obligation::InferCtxtExt; +use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt}; +use crate::traits::engine::TraitEngineExt as _; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::structural_normalize::StructurallyNormalizeExt; use crate::traits::NormalizeExt; use crate::traits::SkipLeakCheck; use crate::traits::{ - Obligation, ObligationCause, ObligationCtxt, PredicateObligation, PredicateObligations, - SelectionContext, + Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, }; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::{util, TraitEngine}; +use rustc_infer::traits::{util, TraitEngine, TraitEngineExt}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; @@ -310,29 +308,35 @@ fn equate_impl_headers<'tcx>( fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligations: &'a [PredicateObligation<'tcx>], -) -> Option<&'a PredicateObligation<'tcx>> { +) -> Option> { let infcx = selcx.infcx; - obligations.iter().find(|obligation| { - let evaluation_result = if infcx.next_trait_solver() { - infcx.evaluate_obligation(obligation) - } else { + if infcx.next_trait_solver() { + let mut fulfill_cx = FulfillmentCtxt::new(infcx); + fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned()); + + // We only care about the obligations that are *definitely* true errors. + // Ambiguities do not prove the disjointness of two impls. + let mut errors = fulfill_cx.select_where_possible(infcx); + errors.pop().map(|err| err.obligation) + } else { + obligations.iter().cloned().find(|obligation| { // We use `evaluate_root_obligation` to correctly track intercrate // ambiguity clauses. We cannot use this in the new solver. - selcx.evaluate_root_obligation(obligation) - }; - - match evaluation_result { - Ok(result) => !result.may_apply(), - // If overflow occurs, we need to conservatively treat the goal as possibly holding, - // since there can be instantiations of this goal that don't overflow and result in - // success. This isn't much of a problem in the old solver, since we treat overflow - // fatally (this still can be encountered: ), - // but in the new solver, this is very important for correctness, since overflow - // *must* be treated as ambiguity for completeness. - Err(_overflow) => false, - } - }) + let evaluation_result = selcx.evaluate_root_obligation(obligation); + + match evaluation_result { + Ok(result) => !result.may_apply(), + // If overflow occurs, we need to conservatively treat the goal as possibly holding, + // since there can be instantiations of this goal that don't overflow and result in + // success. This isn't much of a problem in the old solver, since we treat overflow + // fatally (this still can be encountered: ), + // but in the new solver, this is very important for correctness, since overflow + // *must* be treated as ambiguity for completeness. + Err(_overflow) => false, + } + }) + } } /// Check if both impls can be satisfied by a common type by considering whether @@ -522,15 +526,13 @@ fn try_prove_negated_where_clause<'tcx>( // Without this, we over-eagerly register coherence ambiguity candidates when // impl candidates do exist. let ref infcx = root_infcx.fork_with_intercrate(false); - let ocx = ObligationCtxt::new(infcx); - - ocx.register_obligation(Obligation::new( - infcx.tcx, - ObligationCause::dummy(), - param_env, - negative_predicate, - )); - if !ocx.select_all_or_error().is_empty() { + let mut fulfill_cx = FulfillmentCtxt::new(infcx); + + fulfill_cx.register_predicate_obligation( + infcx, + Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, negative_predicate), + ); + if !fulfill_cx.select_all_or_error(infcx).is_empty() { return false; } diff --git a/tests/ui/coherence/coherent-due-to-fulfill.rs b/tests/ui/coherence/coherent-due-to-fulfill.rs new file mode 100644 index 0000000000000..084f9be0a8c3f --- /dev/null +++ b/tests/ui/coherence/coherent-due-to-fulfill.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -Znext-solver=coherence +//@ check-pass + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +trait Foo {} +trait Bar {} + +// self type starts out as `?0` but is constrained to `()` +// due to the where clause below. Because `(): Bar` does not +// hold in intercrate mode, we can prove the impls disjoint. +impl Foo for T where (): Mirror {} +impl Foo for T where T: Bar {} + +fn main() {} diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs new file mode 100644 index 0000000000000..b3c9cf328c21c --- /dev/null +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver=coherence + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +trait Foo {} + +// Even though using fulfillment in coherence allows us to figure out that +// `?T = ()`, we still treat it as incoherent because `(): Iterator` may be +// added upstream. +impl Foo for T where (): Mirror {} +//~^ NOTE first implementation here +impl Foo for T where T: Iterator {} +//~^ ERROR conflicting implementations of trait `Foo` for type `()` +//~| NOTE conflicting implementation for `()` +//~| NOTE upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +fn main() {} diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr new file mode 100644 index 0000000000000..b16465d201140 --- /dev/null +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `()` + --> $DIR/incoherent-even-though-we-fulfill.rs:17:1 + | +LL | impl Foo for T where (): Mirror {} + | --------------------------------------------- first implementation here +LL | +LL | impl Foo for T where T: Iterator {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. From 3b63edeb9999b5b29826f018b2eabe702bee4e97 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 16 Feb 2024 23:55:58 +0000 Subject: [PATCH 27/40] Remove cfg_attr --- library/std/src/sys/pal/windows/os.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs index 58163f7a73faf..73cb2db8b79e5 100644 --- a/library/std/src/sys/pal/windows/os.rs +++ b/library/std/src/sys/pal/windows/os.rs @@ -1,6 +1,5 @@ //! Implementation of `std::os` functionality for Windows. -#![cfg_attr(bootstrap, allow(unexpected_cfgs))] #![allow(nonstandard_style)] #[cfg(test)] From c36ae932f901d452e78e1dd69400f6b2169c8fa7 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 16 Feb 2024 16:08:01 -0800 Subject: [PATCH 28/40] Clarify the flatten specialization comment --- library/core/src/iter/adapters/flatten.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 64a2ca3d2b870..145c9d3dacc84 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -917,10 +917,10 @@ where } } -// Specialization: For iterators that never return more than one item, the `frontiter` and +// Specialization: When the inner iterator `U` never returns more than one item, the `frontiter` and // `backiter` states are a waste, because they'll always have already consumed their item. So in // this impl, we completely ignore them and just focus on `self.iter`, and we only call the inner -// `next()` one time. +// `U::next()` one time. // // It's mostly fine if we accidentally mix this with the more generic impls, e.g. by forgetting to // specialize one of the methods. If the other impl did set the front or back, we wouldn't see it From dae22a598bc28fd03522fcba5d09150ca53cdc4f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 17 Feb 2024 01:15:08 +0100 Subject: [PATCH 29/40] Fix `cfg(target_abi = "sim")` on i386-apple-ios i386-apple-ios is also a simulator target --- compiler/rustc_target/src/spec/base/apple/mod.rs | 15 ++++++++------- .../src/spec/targets/i386_apple_ios.rs | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index afd60b40c3be1..460e7e034f3a8 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -17,6 +17,7 @@ pub enum Arch { Arm64e, Arm64_32, I386, + I386_sim, I686, X86_64, X86_64h, @@ -34,7 +35,7 @@ impl Arch { Arm64 | Arm64_macabi | Arm64_sim => "arm64", Arm64e => "arm64e", Arm64_32 => "arm64_32", - I386 => "i386", + I386 | I386_sim => "i386", I686 => "i686", X86_64 | X86_64_sim | X86_64_macabi => "x86_64", X86_64h => "x86_64h", @@ -45,7 +46,7 @@ impl Arch { Cow::Borrowed(match self { Armv7k | Armv7s => "arm", Arm64 | Arm64e | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64", - I386 | I686 => "x86", + I386 | I386_sim | I686 => "x86", X86_64 | X86_64_sim | X86_64_macabi | X86_64h => "x86_64", }) } @@ -56,7 +57,7 @@ impl Arch { X86_64_macabi | Arm64_macabi => "macabi", // x86_64-apple-ios is a simulator target, even though it isn't // declared that way in the target like the other ones... - Arm64_sim | X86_64_sim => "sim", + I386_sim | Arm64_sim | X86_64_sim => "sim", } } @@ -70,7 +71,7 @@ impl Arch { // Only macOS 10.12+ is supported, which means // all x86_64/x86 CPUs must be running at least penryn // https://github.com/llvm/llvm-project/blob/01f924d0e37a5deae51df0d77e10a15b63aa0c0f/clang/lib/Driver/ToolChains/Arch/X86.cpp#L79-L82 - I386 | I686 => "penryn", + I386 | I386_sim | I686 => "penryn", X86_64 | X86_64_sim => "penryn", X86_64_macabi => "penryn", // Note: `core-avx2` is slightly more advanced than `x86_64h`, see @@ -85,7 +86,7 @@ impl Arch { fn stack_probes(self) -> StackProbeType { match self { Armv7k | Armv7s => StackProbeType::None, - Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h | X86_64_sim + Arm64 | Arm64e | Arm64_32 | I386 | I386_sim | I686 | X86_64 | X86_64h | X86_64_sim | X86_64_macabi | Arm64_macabi | Arm64_sim => StackProbeType::Inline, } } @@ -302,8 +303,8 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow]> // Otherwise if cross-compiling for a different OS/SDK, remove any part // of the linking environment that's wrong and reversed. match arch { - Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim - | X86_64h | Arm64_sim => { + Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I386_sim | I686 | X86_64 + | X86_64_sim | X86_64h | Arm64_sim => { cvs!["MACOSX_DEPLOYMENT_TARGET"] } X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index a221538b9022f..63133ff99ea4a 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -2,7 +2,7 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::I386; + let arch = Arch::I386_sim; Target { // Clang automatically chooses a more specific target based on // IPHONEOS_DEPLOYMENT_TARGET. From d80198595c926949a84944220a8176940a32654b Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 17 Feb 2024 01:16:11 +0100 Subject: [PATCH 30/40] Fix comment --- compiler/rustc_target/src/spec/base/apple/mod.rs | 2 -- compiler/rustc_target/src/spec/targets/i386_apple_ios.rs | 2 ++ compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs | 2 ++ compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 460e7e034f3a8..aee5d60626e31 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -55,8 +55,6 @@ impl Arch { match self { Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "", X86_64_macabi | Arm64_macabi => "macabi", - // x86_64-apple-ios is a simulator target, even though it isn't - // declared that way in the target like the other ones... I386_sim | Arm64_sim | X86_64_sim => "sim", } } diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index 63133ff99ea4a..d78acdbd1aad5 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -2,6 +2,8 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { + // i386-apple-ios is a simulator target, even though it isn't declared + // that way in the target name like the other ones... let arch = Arch::I386_sim; Target { // Clang automatically chooses a more specific target based on diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index 55165ea4ec68c..5b34390141e0e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs @@ -2,6 +2,8 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { + // x86_64-apple-ios is a simulator target, even though it isn't declared + // that way in the target name like the other ones... let arch = Arch::X86_64_sim; let mut base = opts("ios", arch); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index 20b0161255314..95033699f1af3 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs @@ -2,6 +2,8 @@ use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { + // x86_64-apple-tvos is a simulator target, even though it isn't declared + // that way in the target name like the other ones... let arch = Arch::X86_64_sim; Target { llvm_target: tvos_sim_llvm_target(arch).into(), From 5010ca001cb7cad425b906136fe251e8d8192b2e Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Sat, 17 Feb 2024 10:44:46 +0530 Subject: [PATCH 31/40] Enable `ConstPropLint` for promoteds This fixes the issue wherein the lint didn't fire for promoteds in the case of SHL/SHR operators in non-optimized builds and all arithmetic operators in optimized builds --- .../src/const_prop_lint.rs | 5 - .../miri/tests/pass/overflow_checks_off.rs | 7 +- .../defaults-cyclic-fail.stderr | 2 +- .../defaults-not-assumed-fail.stderr | 8 + tests/ui/consts/const-err2.noopt.stderr | 48 - tests/ui/consts/const-err2.opt.stderr | 48 - ...const-err2.opt_with_overflow_checks.stderr | 48 - tests/ui/consts/const-err2.rs | 39 - tests/ui/consts/const-eval/issue-44578.stderr | 8 + tests/ui/consts/const-eval/issue-50814.rs | 1 + tests/ui/consts/const-eval/issue-50814.stderr | 22 +- .../ui/consts/overflowing-consts.noopt.stderr | 1023 ++++++++++++++++ tests/ui/consts/overflowing-consts.opt.stderr | 1023 ++++++++++++++++ ...ing-consts.opt_with_overflow_checks.stderr | 1023 ++++++++++++++++ tests/ui/consts/overflowing-consts.rs | 288 +++++ tests/ui/consts/promotion.rs | 3 +- tests/ui/lint/issue-117949.noopt.stderr | 54 + tests/ui/lint/issue-117949.opt.stderr | 54 + ...sue-117949.opt_with_overflow_checks.stderr | 54 + tests/ui/lint/issue-117949.rs | 20 + .../lint-exceeding-bitshifts.noopt.stderr | 152 --- .../lint/lint-exceeding-bitshifts.opt.stderr | 152 --- ...-bitshifts.opt_with_overflow_checks.stderr | 152 --- tests/ui/lint/lint-exceeding-bitshifts.rs | 79 -- .../ui/lint/lint-overflowing-ops.noopt.stderr | 1030 +++++++++++++++++ tests/ui/lint/lint-overflowing-ops.opt.stderr | 1030 +++++++++++++++++ ...lowing-ops.opt_with_overflow_checks.stderr | 1030 +++++++++++++++++ tests/ui/lint/lint-overflowing-ops.rs | 294 +++++ .../promoted_overflow_opt.rs | 8 - 29 files changed, 6967 insertions(+), 738 deletions(-) delete mode 100644 tests/ui/consts/const-err2.noopt.stderr delete mode 100644 tests/ui/consts/const-err2.opt.stderr delete mode 100644 tests/ui/consts/const-err2.opt_with_overflow_checks.stderr delete mode 100644 tests/ui/consts/const-err2.rs create mode 100644 tests/ui/consts/overflowing-consts.noopt.stderr create mode 100644 tests/ui/consts/overflowing-consts.opt.stderr create mode 100644 tests/ui/consts/overflowing-consts.opt_with_overflow_checks.stderr create mode 100644 tests/ui/consts/overflowing-consts.rs create mode 100644 tests/ui/lint/issue-117949.noopt.stderr create mode 100644 tests/ui/lint/issue-117949.opt.stderr create mode 100644 tests/ui/lint/issue-117949.opt_with_overflow_checks.stderr create mode 100644 tests/ui/lint/issue-117949.rs delete mode 100644 tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr delete mode 100644 tests/ui/lint/lint-exceeding-bitshifts.opt.stderr delete mode 100644 tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr delete mode 100644 tests/ui/lint/lint-exceeding-bitshifts.rs create mode 100644 tests/ui/lint/lint-overflowing-ops.noopt.stderr create mode 100644 tests/ui/lint/lint-overflowing-ops.opt.stderr create mode 100644 tests/ui/lint/lint-overflowing-ops.opt_with_overflow_checks.stderr create mode 100644 tests/ui/lint/lint-overflowing-ops.rs delete mode 100644 tests/ui/numbers-arithmetic/promoted_overflow_opt.rs diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index f8e6905282c59..6212155a8fe95 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -32,11 +32,6 @@ impl<'tcx> MirLint<'tcx> for ConstPropLint { return; } - // will be evaluated by miri and produce its errors there - if body.source.promoted.is_some() { - return; - } - let def_id = body.source.def_id().expect_local(); let def_kind = tcx.def_kind(def_id); let is_fn_like = def_kind.is_fn_like(); diff --git a/src/tools/miri/tests/pass/overflow_checks_off.rs b/src/tools/miri/tests/pass/overflow_checks_off.rs index 79aa510ef97fe..7b9d4f8fff5d5 100644 --- a/src/tools/miri/tests/pass/overflow_checks_off.rs +++ b/src/tools/miri/tests/pass/overflow_checks_off.rs @@ -1,12 +1,17 @@ //@compile-flags: -C overflow-checks=off // Check that we correctly implement the intended behavior of these operators -// when they are not being overflow-checked. +// when they are not being overflow-checked at runtime. // FIXME: if we call the functions in `std::ops`, we still get the panics. // Miri does not implement the codegen-time hack that backs `#[rustc_inherit_overflow_checks]`. // use std::ops::*; + +// Disable _compile-time_ overflow linting +// so that we can test runtime overflow checks + #![allow(arithmetic_overflow)] + fn main() { assert_eq!(-{ -0x80i8 }, -0x80); diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.stderr b/tests/ui/associated-consts/defaults-cyclic-fail.stderr index 9cee03041fe6d..31974d955611f 100644 --- a/tests/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/tests/ui/associated-consts/defaults-cyclic-fail.stderr @@ -20,7 +20,7 @@ note: ...which requires const-evaluating + checking `Tr::B`... LL | const B: u8 = Self::A; | ^^^^^^^ = note: ...which again requires simplifying constant for the type system `Tr::A`, completing the cycle -note: cycle used when const-evaluating + checking `main::promoted[1]` +note: cycle used when optimizing promoted MIR for `main` --> $DIR/defaults-cyclic-fail.rs:16:16 | LL | assert_eq!(<() as Tr>::A, 0); diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr index 091a50f9463b9..4b53603cfe851 100644 --- a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr +++ b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -10,6 +10,14 @@ note: erroneous constant encountered LL | assert_eq!(<() as Tr>::B, 0); // causes the error above | ^^^^^^^^^^^^^ +note: erroneous constant encountered + --> $DIR/defaults-not-assumed-fail.rs:33:16 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + note: erroneous constant encountered --> $DIR/defaults-not-assumed-fail.rs:33:5 | diff --git a/tests/ui/consts/const-err2.noopt.stderr b/tests/ui/consts/const-err2.noopt.stderr deleted file mode 100644 index 8b1688c4a8989..0000000000000 --- a/tests/ui/consts/const-err2.noopt.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:19:13 - | -LL | let a = -i8::MIN; - | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow - | - = note: `#[deny(arithmetic_overflow)]` on by default - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:21:18 - | -LL | let a_i128 = -i128::MIN; - | ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:23:13 - | -LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:25:18 - | -LL | let b_i128 = i128::MIN - i128::MAX; - | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:27:13 - | -LL | let c = 200u8 * 4; - | ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:29:13 - | -LL | let d = 42u8 - (42u8 + 1); - | ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow - -error: this operation will panic at runtime - --> $DIR/const-err2.rs:31:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 - | - = note: `#[deny(unconditional_panic)]` on by default - -error: aborting due to 7 previous errors - diff --git a/tests/ui/consts/const-err2.opt.stderr b/tests/ui/consts/const-err2.opt.stderr deleted file mode 100644 index 8b1688c4a8989..0000000000000 --- a/tests/ui/consts/const-err2.opt.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:19:13 - | -LL | let a = -i8::MIN; - | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow - | - = note: `#[deny(arithmetic_overflow)]` on by default - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:21:18 - | -LL | let a_i128 = -i128::MIN; - | ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:23:13 - | -LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:25:18 - | -LL | let b_i128 = i128::MIN - i128::MAX; - | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:27:13 - | -LL | let c = 200u8 * 4; - | ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:29:13 - | -LL | let d = 42u8 - (42u8 + 1); - | ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow - -error: this operation will panic at runtime - --> $DIR/const-err2.rs:31:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 - | - = note: `#[deny(unconditional_panic)]` on by default - -error: aborting due to 7 previous errors - diff --git a/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr b/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr deleted file mode 100644 index 8b1688c4a8989..0000000000000 --- a/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:19:13 - | -LL | let a = -i8::MIN; - | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow - | - = note: `#[deny(arithmetic_overflow)]` on by default - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:21:18 - | -LL | let a_i128 = -i128::MIN; - | ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:23:13 - | -LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:25:18 - | -LL | let b_i128 = i128::MIN - i128::MAX; - | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:27:13 - | -LL | let c = 200u8 * 4; - | ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:29:13 - | -LL | let d = 42u8 - (42u8 + 1); - | ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow - -error: this operation will panic at runtime - --> $DIR/const-err2.rs:31:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 - | - = note: `#[deny(unconditional_panic)]` on by default - -error: aborting due to 7 previous errors - diff --git a/tests/ui/consts/const-err2.rs b/tests/ui/consts/const-err2.rs deleted file mode 100644 index 67c85d35401d5..0000000000000 --- a/tests/ui/consts/const-err2.rs +++ /dev/null @@ -1,39 +0,0 @@ -// needed because negating int::MIN will behave differently between -// optimized compilation and unoptimized compilation and thus would -// lead to different lints being emitted - -//@ revisions: noopt opt opt_with_overflow_checks -//@[noopt]compile-flags: -C opt-level=0 -//@[opt]compile-flags: -O -//@[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O - -//@ build-fail - -#![feature(rustc_attrs)] - -fn black_box(_: T) { - unimplemented!() -} - -fn main() { - let a = -i8::MIN; - //~^ ERROR arithmetic operation will overflow - let a_i128 = -i128::MIN; - //~^ ERROR arithmetic operation will overflow - let b = 200u8 + 200u8 + 200u8; - //~^ ERROR arithmetic operation will overflow - let b_i128 = i128::MIN - i128::MAX; - //~^ ERROR arithmetic operation will overflow - let c = 200u8 * 4; - //~^ ERROR arithmetic operation will overflow - let d = 42u8 - (42u8 + 1); - //~^ ERROR arithmetic operation will overflow - let _e = [5u8][1]; - //~^ ERROR operation will panic - black_box(a); - black_box(a_i128); - black_box(b); - black_box(b_i128); - black_box(c); - black_box(d); -} diff --git a/tests/ui/consts/const-eval/issue-44578.stderr b/tests/ui/consts/const-eval/issue-44578.stderr index 6aabe53011c96..7d5cf86d3965d 100644 --- a/tests/ui/consts/const-eval/issue-44578.stderr +++ b/tests/ui/consts/const-eval/issue-44578.stderr @@ -10,6 +10,14 @@ note: erroneous constant encountered LL | println!("{}", as Foo>::AMT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: erroneous constant encountered + --> $DIR/issue-44578.rs:25:20 + | +LL | println!("{}", as Foo>::AMT); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + note: erroneous constant encountered --> $DIR/issue-44578.rs:25:20 | diff --git a/tests/ui/consts/const-eval/issue-50814.rs b/tests/ui/consts/const-eval/issue-50814.rs index ca26f51f111d3..27b5b39ad7371 100644 --- a/tests/ui/consts/const-eval/issue-50814.rs +++ b/tests/ui/consts/const-eval/issue-50814.rs @@ -14,6 +14,7 @@ struct Sum(A, B); impl Unsigned for Sum { const MAX: u8 = A::MAX + B::MAX; //~^ ERROR evaluation of ` as Unsigned>::MAX` failed + //~| ERROR evaluation of ` as Unsigned>::MAX` failed } fn foo(_: T) -> &'static u8 { diff --git a/tests/ui/consts/const-eval/issue-50814.stderr b/tests/ui/consts/const-eval/issue-50814.stderr index 65c49956f1859..8d01816140152 100644 --- a/tests/ui/consts/const-eval/issue-50814.stderr +++ b/tests/ui/consts/const-eval/issue-50814.stderr @@ -5,17 +5,33 @@ LL | const MAX: u8 = A::MAX + B::MAX; | ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow note: erroneous constant encountered - --> $DIR/issue-50814.rs:20:6 + --> $DIR/issue-50814.rs:21:6 | LL | &Sum::::MAX | ^^^^^^^^^^^^^^^^^^ +error[E0080]: evaluation of ` as Unsigned>::MAX` failed + --> $DIR/issue-50814.rs:15:21 + | +LL | const MAX: u8 = A::MAX + B::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: erroneous constant encountered + --> $DIR/issue-50814.rs:21:6 + | +LL | &Sum::::MAX + | ^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + note: the above error was encountered while instantiating `fn foo::` - --> $DIR/issue-50814.rs:25:5 + --> $DIR/issue-50814.rs:26:5 | LL | foo(0); | ^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/overflowing-consts.noopt.stderr b/tests/ui/consts/overflowing-consts.noopt.stderr new file mode 100644 index 0000000000000..81f22944adbe7 --- /dev/null +++ b/tests/ui/consts/overflowing-consts.noopt.stderr @@ -0,0 +1,1023 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:19:22 + | +LL | const _NI8_SHL: i8 = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:20:26 + | +LL | const _NI8_SHL_P: &i8 = &(1i8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:22:24 + | +LL | const _NI16_SHL: i16 = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:23:28 + | +LL | const _NI16_SHL_P: &i16 = &(1i16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:25:24 + | +LL | const _NI32_SHL: i32 = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:26:28 + | +LL | const _NI32_SHL_P: &i32 = &(1i32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:28:24 + | +LL | const _NI64_SHL: i64 = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:29:28 + | +LL | const _NI64_SHL_P: &i64 = &(1i64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:31:26 + | +LL | const _NI128_SHL: i128 = 1i128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:32:30 + | +LL | const _NI128_SHL_P: &i128 = &(1i128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:34:22 + | +LL | const _NU8_SHL: u8 = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:35:26 + | +LL | const _NU8_SHL_P: &u8 = &(1u8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:37:24 + | +LL | const _NU16_SHL: u16 = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:38:28 + | +LL | const _NU16_SHL_P: &u16 = &(1u16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:40:24 + | +LL | const _NU32_SHL: u32 = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:41:28 + | +LL | const _NU32_SHL_P: &u32 = &(1u32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:43:24 + | +LL | const _NU64_SHL: u64 = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:44:28 + | +LL | const _NU64_SHL_P: &u64 = &(1u64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:46:26 + | +LL | const _NU128_SHL: u128 = 1u128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:47:30 + | +LL | const _NU128_SHL_P: &u128 = &(1u128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:49:28 + | +LL | const _NISIZE_SHL: isize = 1isize << BITS; + | ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:50:32 + | +LL | const _NISIZE_SHL_P: &isize = &(1isize << BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:52:28 + | +LL | const _NUSIZE_SHL: usize = 1usize << BITS; + | ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:53:32 + | +LL | const _NUSIZE_SHL_P: &usize = &(1usize << BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:57:22 + | +LL | const _NI8_SHR: i8 = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:58:26 + | +LL | const _NI8_SHR_P: &i8 = &(1i8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:60:24 + | +LL | const _NI16_SHR: i16 = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:61:28 + | +LL | const _NI16_SHR_P: &i16 = &(1i16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:63:24 + | +LL | const _NI32_SHR: i32 = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:64:28 + | +LL | const _NI32_SHR_P: &i32 = &(1i32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:66:24 + | +LL | const _NI64_SHR: i64 = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:67:28 + | +LL | const _NI64_SHR_P: &i64 = &(1i64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:69:26 + | +LL | const _NI128_SHR: i128 = 1i128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:70:30 + | +LL | const _NI128_SHR_P: &i128 = &(1i128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:72:22 + | +LL | const _NU8_SHR: u8 = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:73:26 + | +LL | const _NU8_SHR_P: &u8 = &(1u8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:75:24 + | +LL | const _NU16_SHR: u16 = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:76:28 + | +LL | const _NU16_SHR_P: &u16 = &(1u16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:78:24 + | +LL | const _NU32_SHR: u32 = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:79:28 + | +LL | const _NU32_SHR_P: &u32 = &(1u32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:81:24 + | +LL | const _NU64_SHR: u64 = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:82:28 + | +LL | const _NU64_SHR_P: &u64 = &(1u64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:84:26 + | +LL | const _NU128_SHR: u128 = 1u128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:85:30 + | +LL | const _NU128_SHR_P: &u128 = &(1u128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:87:28 + | +LL | const _NISIZE_SHR: isize = 1isize >> BITS; + | ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:88:32 + | +LL | const _NISIZE_SHR_P: &isize = &(1isize >> BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:90:28 + | +LL | const _NUSIZE_SHR: usize = 1usize >> BITS; + | ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:91:32 + | +LL | const _NUSIZE_SHR_P: &usize = &(1usize >> BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:95:22 + | +LL | const _NI8_ADD: i8 = 1i8 + i8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:96:26 + | +LL | const _NI8_ADD_P: &i8 = &(1i8 + i8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:98:24 + | +LL | const _NI16_ADD: i16 = 1i16 + i16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:99:28 + | +LL | const _NI16_ADD_P: &i16 = &(1i16 + i16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:101:24 + | +LL | const _NI32_ADD: i32 = 1i32 + i32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:102:28 + | +LL | const _NI32_ADD_P: &i32 = &(1i32 + i32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:104:24 + | +LL | const _NI64_ADD: i64 = 1i64 + i64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:105:28 + | +LL | const _NI64_ADD_P: &i64 = &(1i64 + i64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:107:26 + | +LL | const _NI128_ADD: i128 = 1i128 + i128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:108:30 + | +LL | const _NI128_ADD_P: &i128 = &(1i128 + i128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:110:22 + | +LL | const _NU8_ADD: u8 = 1u8 + u8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:111:26 + | +LL | const _NU8_ADD_P: &u8 = &(1u8 + u8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:113:24 + | +LL | const _NU16_ADD: u16 = 1u16 + u16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:114:28 + | +LL | const _NU16_ADD_P: &u16 = &(1u16 + u16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:116:24 + | +LL | const _NU32_ADD: u32 = 1u32 + u32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:117:28 + | +LL | const _NU32_ADD_P: &u32 = &(1u32 + u32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:119:24 + | +LL | const _NU64_ADD: u64 = 1u64 + u64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:120:28 + | +LL | const _NU64_ADD_P: &u64 = &(1u64 + u64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:122:26 + | +LL | const _NU128_ADD: u128 = 1u128 + u128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:123:30 + | +LL | const _NU128_ADD_P: &u128 = &(1u128 + u128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:125:28 + | +LL | const _NISIZE_ADD: isize = 1isize + isize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:126:32 + | +LL | const _NISIZE_ADD_P: &isize = &(1isize + isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:128:28 + | +LL | const _NUSIZE_ADD: usize = 1usize + usize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:129:32 + | +LL | const _NUSIZE_ADD_P: &usize = &(1usize + usize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:133:22 + | +LL | const _NI8_SUB: i8 = -5i8 - i8::MAX; + | ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:134:26 + | +LL | const _NI8_SUB_P: &i8 = &(-5i8 - i8::MAX); + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:136:24 + | +LL | const _NI16_SUB: i16 = -5i16 - i16::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:137:28 + | +LL | const _NI16_SUB_P: &i16 = &(-5i16 - i16::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:139:24 + | +LL | const _NI32_SUB: i32 = -5i32 - i32::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:140:28 + | +LL | const _NI32_SUB_P: &i32 = &(-5i32 - i32::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:142:24 + | +LL | const _NI64_SUB: i64 = -5i64 - i64::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:143:28 + | +LL | const _NI64_SUB_P: &i64 = &(-5i64 - i64::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:145:26 + | +LL | const _NI128_SUB: i128 = -5i128 - i128::MAX; + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:146:30 + | +LL | const _NI128_SUB_P: &i128 = &(-5i128 - i128::MAX); + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:148:22 + | +LL | const _NU8_SUB: u8 = 1u8 - 5; + | ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:149:26 + | +LL | const _NU8_SUB_P: &u8 = &(1u8 - 5); + | ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:151:24 + | +LL | const _NU16_SUB: u16 = 1u16 - 5; + | ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:152:28 + | +LL | const _NU16_SUB_P: &u16 = &(1u16 - 5); + | ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:154:24 + | +LL | const _NU32_SUB: u32 = 1u32 - 5; + | ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:155:28 + | +LL | const _NU32_SUB_P: &u32 = &(1u32 - 5); + | ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:157:24 + | +LL | const _NU64_SUB: u64 = 1u64 - 5; + | ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:158:28 + | +LL | const _NU64_SUB_P: &u64 = &(1u64 - 5); + | ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:160:26 + | +LL | const _NU128_SUB: u128 = 1u128 - 5; + | ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:161:30 + | +LL | const _NU128_SUB_P: &u128 = &(1u128 - 5); + | ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:163:28 + | +LL | const _NISIZE_SUB: isize = -5isize - isize::MAX; + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:164:32 + | +LL | const _NISIZE_SUB_P: &isize = &(-5isize - isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:166:28 + | +LL | const _NUSIZE_SUB: usize = 1usize - 5 ; + | ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:167:32 + | +LL | const _NUSIZE_SUB_P: &usize = &(1usize - 5 ); + | ^^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:171:22 + | +LL | const _NI8_MUL: i8 = i8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:172:26 + | +LL | const _NI8_MUL_P: &i8 = &(i8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:174:24 + | +LL | const _NI16_MUL: i16 = i16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:175:28 + | +LL | const _NI16_MUL_P: &i16 = &(i16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:177:24 + | +LL | const _NI32_MUL: i32 = i32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:178:28 + | +LL | const _NI32_MUL_P: &i32 = &(i32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:180:24 + | +LL | const _NI64_MUL: i64 = i64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:181:28 + | +LL | const _NI64_MUL_P: &i64 = &(i64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:183:26 + | +LL | const _NI128_MUL: i128 = i128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:184:30 + | +LL | const _NI128_MUL_P: &i128 = &(i128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:186:22 + | +LL | const _NU8_MUL: u8 = u8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:187:26 + | +LL | const _NU8_MUL_P: &u8 = &(u8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:189:24 + | +LL | const _NU16_MUL: u16 = u16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:190:28 + | +LL | const _NU16_MUL_P: &u16 = &(u16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:192:24 + | +LL | const _NU32_MUL: u32 = u32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:193:28 + | +LL | const _NU32_MUL_P: &u32 = &(u32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:195:24 + | +LL | const _NU64_MUL: u64 = u64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:196:28 + | +LL | const _NU64_MUL_P: &u64 = &(u64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:198:26 + | +LL | const _NU128_MUL: u128 = u128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:199:30 + | +LL | const _NU128_MUL_P: &u128 = &(u128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:201:28 + | +LL | const _NISIZE_MUL: isize = isize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:202:32 + | +LL | const _NISIZE_MUL_P: &isize = &(isize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:204:28 + | +LL | const _NUSIZE_MUL: usize = usize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:205:32 + | +LL | const _NUSIZE_MUL_P: &usize = &(usize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:209:22 + | +LL | const _NI8_DIV: i8 = 1i8 / 0; + | ^^^^^^^ attempt to divide `1_i8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:210:26 + | +LL | const _NI8_DIV_P: &i8 = &(1i8 / 0); + | ^^^^^^^^^ attempt to divide `1_i8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:212:24 + | +LL | const _NI16_DIV: i16 = 1i16 / 0; + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:213:28 + | +LL | const _NI16_DIV_P: &i16 = &(1i16 / 0); + | ^^^^^^^^^^ attempt to divide `1_i16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:215:24 + | +LL | const _NI32_DIV: i32 = 1i32 / 0; + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:216:28 + | +LL | const _NI32_DIV_P: &i32 = &(1i32 / 0); + | ^^^^^^^^^^ attempt to divide `1_i32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:218:24 + | +LL | const _NI64_DIV: i64 = 1i64 / 0; + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:219:28 + | +LL | const _NI64_DIV_P: &i64 = &(1i64 / 0); + | ^^^^^^^^^^ attempt to divide `1_i64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:221:26 + | +LL | const _NI128_DIV: i128 = 1i128 / 0; + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:222:30 + | +LL | const _NI128_DIV_P: &i128 = &(1i128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_i128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:224:22 + | +LL | const _NU8_DIV: u8 = 1u8 / 0; + | ^^^^^^^ attempt to divide `1_u8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:225:26 + | +LL | const _NU8_DIV_P: &u8 = &(1u8 / 0); + | ^^^^^^^^^ attempt to divide `1_u8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:227:24 + | +LL | const _NU16_DIV: u16 = 1u16 / 0; + | ^^^^^^^^ attempt to divide `1_u16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:228:28 + | +LL | const _NU16_DIV_P: &u16 = &(1u16 / 0); + | ^^^^^^^^^^ attempt to divide `1_u16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:230:24 + | +LL | const _NU32_DIV: u32 = 1u32 / 0; + | ^^^^^^^^ attempt to divide `1_u32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:231:28 + | +LL | const _NU32_DIV_P: &u32 = &(1u32 / 0); + | ^^^^^^^^^^ attempt to divide `1_u32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:233:24 + | +LL | const _NU64_DIV: u64 = 1u64 / 0; + | ^^^^^^^^ attempt to divide `1_u64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:234:28 + | +LL | const _NU64_DIV_P: &u64 = &(1u64 / 0); + | ^^^^^^^^^^ attempt to divide `1_u64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:236:26 + | +LL | const _NU128_DIV: u128 = 1u128 / 0; + | ^^^^^^^^^ attempt to divide `1_u128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:237:30 + | +LL | const _NU128_DIV_P: &u128 = &(1u128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_u128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:239:28 + | +LL | const _NISIZE_DIV: isize = 1isize / 0; + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:240:32 + | +LL | const _NISIZE_DIV_P: &isize = &(1isize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_isize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:242:28 + | +LL | const _NUSIZE_DIV: usize = 1usize / 0; + | ^^^^^^^^^^ attempt to divide `1_usize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:243:32 + | +LL | const _NUSIZE_DIV_P: &usize = &(1usize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_usize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:246:22 + | +LL | const _NI8_MOD: i8 = 1i8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:247:26 + | +LL | const _NI8_MOD_P: &i8 = &(1i8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:249:24 + | +LL | const _NI16_MOD: i16 = 1i16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:250:28 + | +LL | const _NI16_MOD_P: &i16 = &(1i16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:252:24 + | +LL | const _NI32_MOD: i32 = 1i32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:253:28 + | +LL | const _NI32_MOD_P: &i32 = &(1i32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:255:24 + | +LL | const _NI64_MOD: i64 = 1i64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:256:28 + | +LL | const _NI64_MOD_P: &i64 = &(1i64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:258:26 + | +LL | const _NI128_MOD: i128 = 1i128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:259:30 + | +LL | const _NI128_MOD_P: &i128 = &(1i128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:261:22 + | +LL | const _NU8_MOD: u8 = 1u8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:262:26 + | +LL | const _NU8_MOD_P: &u8 = &(1u8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:264:24 + | +LL | const _NU16_MOD: u16 = 1u16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:265:28 + | +LL | const _NU16_MOD_P: &u16 = &(1u16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:267:24 + | +LL | const _NU32_MOD: u32 = 1u32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:268:28 + | +LL | const _NU32_MOD_P: &u32 = &(1u32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:270:24 + | +LL | const _NU64_MOD: u64 = 1u64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:271:28 + | +LL | const _NU64_MOD_P: &u64 = &(1u64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:273:26 + | +LL | const _NU128_MOD: u128 = 1u128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:274:30 + | +LL | const _NU128_MOD_P: &u128 = &(1u128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:276:28 + | +LL | const _NISIZE_MOD: isize = 1isize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:277:32 + | +LL | const _NISIZE_MOD_P: &isize = &(1isize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:279:28 + | +LL | const _NUSIZE_MOD: usize = 1usize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:280:32 + | +LL | const _NUSIZE_MOD_P: &usize = &(1usize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:284:24 + | +LL | const _NI32_OOB: i32 = [1, 2, 3][4]; + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:285:28 + | +LL | const _NI32_OOB_P: &i32 = &([1, 2, 3][4]); + | ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 170 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/overflowing-consts.opt.stderr b/tests/ui/consts/overflowing-consts.opt.stderr new file mode 100644 index 0000000000000..81f22944adbe7 --- /dev/null +++ b/tests/ui/consts/overflowing-consts.opt.stderr @@ -0,0 +1,1023 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:19:22 + | +LL | const _NI8_SHL: i8 = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:20:26 + | +LL | const _NI8_SHL_P: &i8 = &(1i8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:22:24 + | +LL | const _NI16_SHL: i16 = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:23:28 + | +LL | const _NI16_SHL_P: &i16 = &(1i16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:25:24 + | +LL | const _NI32_SHL: i32 = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:26:28 + | +LL | const _NI32_SHL_P: &i32 = &(1i32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:28:24 + | +LL | const _NI64_SHL: i64 = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:29:28 + | +LL | const _NI64_SHL_P: &i64 = &(1i64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:31:26 + | +LL | const _NI128_SHL: i128 = 1i128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:32:30 + | +LL | const _NI128_SHL_P: &i128 = &(1i128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:34:22 + | +LL | const _NU8_SHL: u8 = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:35:26 + | +LL | const _NU8_SHL_P: &u8 = &(1u8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:37:24 + | +LL | const _NU16_SHL: u16 = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:38:28 + | +LL | const _NU16_SHL_P: &u16 = &(1u16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:40:24 + | +LL | const _NU32_SHL: u32 = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:41:28 + | +LL | const _NU32_SHL_P: &u32 = &(1u32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:43:24 + | +LL | const _NU64_SHL: u64 = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:44:28 + | +LL | const _NU64_SHL_P: &u64 = &(1u64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:46:26 + | +LL | const _NU128_SHL: u128 = 1u128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:47:30 + | +LL | const _NU128_SHL_P: &u128 = &(1u128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:49:28 + | +LL | const _NISIZE_SHL: isize = 1isize << BITS; + | ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:50:32 + | +LL | const _NISIZE_SHL_P: &isize = &(1isize << BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:52:28 + | +LL | const _NUSIZE_SHL: usize = 1usize << BITS; + | ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:53:32 + | +LL | const _NUSIZE_SHL_P: &usize = &(1usize << BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:57:22 + | +LL | const _NI8_SHR: i8 = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:58:26 + | +LL | const _NI8_SHR_P: &i8 = &(1i8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:60:24 + | +LL | const _NI16_SHR: i16 = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:61:28 + | +LL | const _NI16_SHR_P: &i16 = &(1i16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:63:24 + | +LL | const _NI32_SHR: i32 = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:64:28 + | +LL | const _NI32_SHR_P: &i32 = &(1i32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:66:24 + | +LL | const _NI64_SHR: i64 = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:67:28 + | +LL | const _NI64_SHR_P: &i64 = &(1i64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:69:26 + | +LL | const _NI128_SHR: i128 = 1i128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:70:30 + | +LL | const _NI128_SHR_P: &i128 = &(1i128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:72:22 + | +LL | const _NU8_SHR: u8 = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:73:26 + | +LL | const _NU8_SHR_P: &u8 = &(1u8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:75:24 + | +LL | const _NU16_SHR: u16 = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:76:28 + | +LL | const _NU16_SHR_P: &u16 = &(1u16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:78:24 + | +LL | const _NU32_SHR: u32 = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:79:28 + | +LL | const _NU32_SHR_P: &u32 = &(1u32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:81:24 + | +LL | const _NU64_SHR: u64 = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:82:28 + | +LL | const _NU64_SHR_P: &u64 = &(1u64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:84:26 + | +LL | const _NU128_SHR: u128 = 1u128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:85:30 + | +LL | const _NU128_SHR_P: &u128 = &(1u128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:87:28 + | +LL | const _NISIZE_SHR: isize = 1isize >> BITS; + | ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:88:32 + | +LL | const _NISIZE_SHR_P: &isize = &(1isize >> BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:90:28 + | +LL | const _NUSIZE_SHR: usize = 1usize >> BITS; + | ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:91:32 + | +LL | const _NUSIZE_SHR_P: &usize = &(1usize >> BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:95:22 + | +LL | const _NI8_ADD: i8 = 1i8 + i8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:96:26 + | +LL | const _NI8_ADD_P: &i8 = &(1i8 + i8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:98:24 + | +LL | const _NI16_ADD: i16 = 1i16 + i16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:99:28 + | +LL | const _NI16_ADD_P: &i16 = &(1i16 + i16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:101:24 + | +LL | const _NI32_ADD: i32 = 1i32 + i32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:102:28 + | +LL | const _NI32_ADD_P: &i32 = &(1i32 + i32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:104:24 + | +LL | const _NI64_ADD: i64 = 1i64 + i64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:105:28 + | +LL | const _NI64_ADD_P: &i64 = &(1i64 + i64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:107:26 + | +LL | const _NI128_ADD: i128 = 1i128 + i128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:108:30 + | +LL | const _NI128_ADD_P: &i128 = &(1i128 + i128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:110:22 + | +LL | const _NU8_ADD: u8 = 1u8 + u8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:111:26 + | +LL | const _NU8_ADD_P: &u8 = &(1u8 + u8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:113:24 + | +LL | const _NU16_ADD: u16 = 1u16 + u16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:114:28 + | +LL | const _NU16_ADD_P: &u16 = &(1u16 + u16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:116:24 + | +LL | const _NU32_ADD: u32 = 1u32 + u32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:117:28 + | +LL | const _NU32_ADD_P: &u32 = &(1u32 + u32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:119:24 + | +LL | const _NU64_ADD: u64 = 1u64 + u64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:120:28 + | +LL | const _NU64_ADD_P: &u64 = &(1u64 + u64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:122:26 + | +LL | const _NU128_ADD: u128 = 1u128 + u128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:123:30 + | +LL | const _NU128_ADD_P: &u128 = &(1u128 + u128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:125:28 + | +LL | const _NISIZE_ADD: isize = 1isize + isize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:126:32 + | +LL | const _NISIZE_ADD_P: &isize = &(1isize + isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:128:28 + | +LL | const _NUSIZE_ADD: usize = 1usize + usize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:129:32 + | +LL | const _NUSIZE_ADD_P: &usize = &(1usize + usize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:133:22 + | +LL | const _NI8_SUB: i8 = -5i8 - i8::MAX; + | ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:134:26 + | +LL | const _NI8_SUB_P: &i8 = &(-5i8 - i8::MAX); + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:136:24 + | +LL | const _NI16_SUB: i16 = -5i16 - i16::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:137:28 + | +LL | const _NI16_SUB_P: &i16 = &(-5i16 - i16::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:139:24 + | +LL | const _NI32_SUB: i32 = -5i32 - i32::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:140:28 + | +LL | const _NI32_SUB_P: &i32 = &(-5i32 - i32::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:142:24 + | +LL | const _NI64_SUB: i64 = -5i64 - i64::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:143:28 + | +LL | const _NI64_SUB_P: &i64 = &(-5i64 - i64::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:145:26 + | +LL | const _NI128_SUB: i128 = -5i128 - i128::MAX; + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:146:30 + | +LL | const _NI128_SUB_P: &i128 = &(-5i128 - i128::MAX); + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:148:22 + | +LL | const _NU8_SUB: u8 = 1u8 - 5; + | ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:149:26 + | +LL | const _NU8_SUB_P: &u8 = &(1u8 - 5); + | ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:151:24 + | +LL | const _NU16_SUB: u16 = 1u16 - 5; + | ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:152:28 + | +LL | const _NU16_SUB_P: &u16 = &(1u16 - 5); + | ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:154:24 + | +LL | const _NU32_SUB: u32 = 1u32 - 5; + | ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:155:28 + | +LL | const _NU32_SUB_P: &u32 = &(1u32 - 5); + | ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:157:24 + | +LL | const _NU64_SUB: u64 = 1u64 - 5; + | ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:158:28 + | +LL | const _NU64_SUB_P: &u64 = &(1u64 - 5); + | ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:160:26 + | +LL | const _NU128_SUB: u128 = 1u128 - 5; + | ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:161:30 + | +LL | const _NU128_SUB_P: &u128 = &(1u128 - 5); + | ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:163:28 + | +LL | const _NISIZE_SUB: isize = -5isize - isize::MAX; + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:164:32 + | +LL | const _NISIZE_SUB_P: &isize = &(-5isize - isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:166:28 + | +LL | const _NUSIZE_SUB: usize = 1usize - 5 ; + | ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:167:32 + | +LL | const _NUSIZE_SUB_P: &usize = &(1usize - 5 ); + | ^^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:171:22 + | +LL | const _NI8_MUL: i8 = i8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:172:26 + | +LL | const _NI8_MUL_P: &i8 = &(i8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:174:24 + | +LL | const _NI16_MUL: i16 = i16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:175:28 + | +LL | const _NI16_MUL_P: &i16 = &(i16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:177:24 + | +LL | const _NI32_MUL: i32 = i32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:178:28 + | +LL | const _NI32_MUL_P: &i32 = &(i32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:180:24 + | +LL | const _NI64_MUL: i64 = i64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:181:28 + | +LL | const _NI64_MUL_P: &i64 = &(i64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:183:26 + | +LL | const _NI128_MUL: i128 = i128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:184:30 + | +LL | const _NI128_MUL_P: &i128 = &(i128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:186:22 + | +LL | const _NU8_MUL: u8 = u8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:187:26 + | +LL | const _NU8_MUL_P: &u8 = &(u8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:189:24 + | +LL | const _NU16_MUL: u16 = u16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:190:28 + | +LL | const _NU16_MUL_P: &u16 = &(u16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:192:24 + | +LL | const _NU32_MUL: u32 = u32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:193:28 + | +LL | const _NU32_MUL_P: &u32 = &(u32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:195:24 + | +LL | const _NU64_MUL: u64 = u64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:196:28 + | +LL | const _NU64_MUL_P: &u64 = &(u64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:198:26 + | +LL | const _NU128_MUL: u128 = u128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:199:30 + | +LL | const _NU128_MUL_P: &u128 = &(u128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:201:28 + | +LL | const _NISIZE_MUL: isize = isize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:202:32 + | +LL | const _NISIZE_MUL_P: &isize = &(isize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:204:28 + | +LL | const _NUSIZE_MUL: usize = usize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:205:32 + | +LL | const _NUSIZE_MUL_P: &usize = &(usize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:209:22 + | +LL | const _NI8_DIV: i8 = 1i8 / 0; + | ^^^^^^^ attempt to divide `1_i8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:210:26 + | +LL | const _NI8_DIV_P: &i8 = &(1i8 / 0); + | ^^^^^^^^^ attempt to divide `1_i8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:212:24 + | +LL | const _NI16_DIV: i16 = 1i16 / 0; + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:213:28 + | +LL | const _NI16_DIV_P: &i16 = &(1i16 / 0); + | ^^^^^^^^^^ attempt to divide `1_i16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:215:24 + | +LL | const _NI32_DIV: i32 = 1i32 / 0; + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:216:28 + | +LL | const _NI32_DIV_P: &i32 = &(1i32 / 0); + | ^^^^^^^^^^ attempt to divide `1_i32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:218:24 + | +LL | const _NI64_DIV: i64 = 1i64 / 0; + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:219:28 + | +LL | const _NI64_DIV_P: &i64 = &(1i64 / 0); + | ^^^^^^^^^^ attempt to divide `1_i64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:221:26 + | +LL | const _NI128_DIV: i128 = 1i128 / 0; + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:222:30 + | +LL | const _NI128_DIV_P: &i128 = &(1i128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_i128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:224:22 + | +LL | const _NU8_DIV: u8 = 1u8 / 0; + | ^^^^^^^ attempt to divide `1_u8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:225:26 + | +LL | const _NU8_DIV_P: &u8 = &(1u8 / 0); + | ^^^^^^^^^ attempt to divide `1_u8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:227:24 + | +LL | const _NU16_DIV: u16 = 1u16 / 0; + | ^^^^^^^^ attempt to divide `1_u16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:228:28 + | +LL | const _NU16_DIV_P: &u16 = &(1u16 / 0); + | ^^^^^^^^^^ attempt to divide `1_u16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:230:24 + | +LL | const _NU32_DIV: u32 = 1u32 / 0; + | ^^^^^^^^ attempt to divide `1_u32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:231:28 + | +LL | const _NU32_DIV_P: &u32 = &(1u32 / 0); + | ^^^^^^^^^^ attempt to divide `1_u32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:233:24 + | +LL | const _NU64_DIV: u64 = 1u64 / 0; + | ^^^^^^^^ attempt to divide `1_u64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:234:28 + | +LL | const _NU64_DIV_P: &u64 = &(1u64 / 0); + | ^^^^^^^^^^ attempt to divide `1_u64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:236:26 + | +LL | const _NU128_DIV: u128 = 1u128 / 0; + | ^^^^^^^^^ attempt to divide `1_u128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:237:30 + | +LL | const _NU128_DIV_P: &u128 = &(1u128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_u128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:239:28 + | +LL | const _NISIZE_DIV: isize = 1isize / 0; + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:240:32 + | +LL | const _NISIZE_DIV_P: &isize = &(1isize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_isize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:242:28 + | +LL | const _NUSIZE_DIV: usize = 1usize / 0; + | ^^^^^^^^^^ attempt to divide `1_usize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:243:32 + | +LL | const _NUSIZE_DIV_P: &usize = &(1usize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_usize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:246:22 + | +LL | const _NI8_MOD: i8 = 1i8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:247:26 + | +LL | const _NI8_MOD_P: &i8 = &(1i8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:249:24 + | +LL | const _NI16_MOD: i16 = 1i16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:250:28 + | +LL | const _NI16_MOD_P: &i16 = &(1i16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:252:24 + | +LL | const _NI32_MOD: i32 = 1i32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:253:28 + | +LL | const _NI32_MOD_P: &i32 = &(1i32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:255:24 + | +LL | const _NI64_MOD: i64 = 1i64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:256:28 + | +LL | const _NI64_MOD_P: &i64 = &(1i64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:258:26 + | +LL | const _NI128_MOD: i128 = 1i128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:259:30 + | +LL | const _NI128_MOD_P: &i128 = &(1i128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:261:22 + | +LL | const _NU8_MOD: u8 = 1u8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:262:26 + | +LL | const _NU8_MOD_P: &u8 = &(1u8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:264:24 + | +LL | const _NU16_MOD: u16 = 1u16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:265:28 + | +LL | const _NU16_MOD_P: &u16 = &(1u16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:267:24 + | +LL | const _NU32_MOD: u32 = 1u32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:268:28 + | +LL | const _NU32_MOD_P: &u32 = &(1u32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:270:24 + | +LL | const _NU64_MOD: u64 = 1u64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:271:28 + | +LL | const _NU64_MOD_P: &u64 = &(1u64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:273:26 + | +LL | const _NU128_MOD: u128 = 1u128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:274:30 + | +LL | const _NU128_MOD_P: &u128 = &(1u128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:276:28 + | +LL | const _NISIZE_MOD: isize = 1isize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:277:32 + | +LL | const _NISIZE_MOD_P: &isize = &(1isize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:279:28 + | +LL | const _NUSIZE_MOD: usize = 1usize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:280:32 + | +LL | const _NUSIZE_MOD_P: &usize = &(1usize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:284:24 + | +LL | const _NI32_OOB: i32 = [1, 2, 3][4]; + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:285:28 + | +LL | const _NI32_OOB_P: &i32 = &([1, 2, 3][4]); + | ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 170 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/overflowing-consts.opt_with_overflow_checks.stderr b/tests/ui/consts/overflowing-consts.opt_with_overflow_checks.stderr new file mode 100644 index 0000000000000..81f22944adbe7 --- /dev/null +++ b/tests/ui/consts/overflowing-consts.opt_with_overflow_checks.stderr @@ -0,0 +1,1023 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:19:22 + | +LL | const _NI8_SHL: i8 = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:20:26 + | +LL | const _NI8_SHL_P: &i8 = &(1i8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:22:24 + | +LL | const _NI16_SHL: i16 = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:23:28 + | +LL | const _NI16_SHL_P: &i16 = &(1i16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:25:24 + | +LL | const _NI32_SHL: i32 = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:26:28 + | +LL | const _NI32_SHL_P: &i32 = &(1i32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:28:24 + | +LL | const _NI64_SHL: i64 = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:29:28 + | +LL | const _NI64_SHL_P: &i64 = &(1i64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:31:26 + | +LL | const _NI128_SHL: i128 = 1i128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:32:30 + | +LL | const _NI128_SHL_P: &i128 = &(1i128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:34:22 + | +LL | const _NU8_SHL: u8 = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:35:26 + | +LL | const _NU8_SHL_P: &u8 = &(1u8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:37:24 + | +LL | const _NU16_SHL: u16 = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:38:28 + | +LL | const _NU16_SHL_P: &u16 = &(1u16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:40:24 + | +LL | const _NU32_SHL: u32 = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:41:28 + | +LL | const _NU32_SHL_P: &u32 = &(1u32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:43:24 + | +LL | const _NU64_SHL: u64 = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:44:28 + | +LL | const _NU64_SHL_P: &u64 = &(1u64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:46:26 + | +LL | const _NU128_SHL: u128 = 1u128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:47:30 + | +LL | const _NU128_SHL_P: &u128 = &(1u128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:49:28 + | +LL | const _NISIZE_SHL: isize = 1isize << BITS; + | ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:50:32 + | +LL | const _NISIZE_SHL_P: &isize = &(1isize << BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:52:28 + | +LL | const _NUSIZE_SHL: usize = 1usize << BITS; + | ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:53:32 + | +LL | const _NUSIZE_SHL_P: &usize = &(1usize << BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:57:22 + | +LL | const _NI8_SHR: i8 = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:58:26 + | +LL | const _NI8_SHR_P: &i8 = &(1i8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:60:24 + | +LL | const _NI16_SHR: i16 = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:61:28 + | +LL | const _NI16_SHR_P: &i16 = &(1i16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:63:24 + | +LL | const _NI32_SHR: i32 = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:64:28 + | +LL | const _NI32_SHR_P: &i32 = &(1i32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:66:24 + | +LL | const _NI64_SHR: i64 = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:67:28 + | +LL | const _NI64_SHR_P: &i64 = &(1i64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:69:26 + | +LL | const _NI128_SHR: i128 = 1i128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:70:30 + | +LL | const _NI128_SHR_P: &i128 = &(1i128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:72:22 + | +LL | const _NU8_SHR: u8 = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:73:26 + | +LL | const _NU8_SHR_P: &u8 = &(1u8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:75:24 + | +LL | const _NU16_SHR: u16 = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:76:28 + | +LL | const _NU16_SHR_P: &u16 = &(1u16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:78:24 + | +LL | const _NU32_SHR: u32 = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:79:28 + | +LL | const _NU32_SHR_P: &u32 = &(1u32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:81:24 + | +LL | const _NU64_SHR: u64 = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:82:28 + | +LL | const _NU64_SHR_P: &u64 = &(1u64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:84:26 + | +LL | const _NU128_SHR: u128 = 1u128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:85:30 + | +LL | const _NU128_SHR_P: &u128 = &(1u128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:87:28 + | +LL | const _NISIZE_SHR: isize = 1isize >> BITS; + | ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:88:32 + | +LL | const _NISIZE_SHR_P: &isize = &(1isize >> BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:90:28 + | +LL | const _NUSIZE_SHR: usize = 1usize >> BITS; + | ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:91:32 + | +LL | const _NUSIZE_SHR_P: &usize = &(1usize >> BITS); + | ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:95:22 + | +LL | const _NI8_ADD: i8 = 1i8 + i8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:96:26 + | +LL | const _NI8_ADD_P: &i8 = &(1i8 + i8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:98:24 + | +LL | const _NI16_ADD: i16 = 1i16 + i16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:99:28 + | +LL | const _NI16_ADD_P: &i16 = &(1i16 + i16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:101:24 + | +LL | const _NI32_ADD: i32 = 1i32 + i32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:102:28 + | +LL | const _NI32_ADD_P: &i32 = &(1i32 + i32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:104:24 + | +LL | const _NI64_ADD: i64 = 1i64 + i64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:105:28 + | +LL | const _NI64_ADD_P: &i64 = &(1i64 + i64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:107:26 + | +LL | const _NI128_ADD: i128 = 1i128 + i128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:108:30 + | +LL | const _NI128_ADD_P: &i128 = &(1i128 + i128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:110:22 + | +LL | const _NU8_ADD: u8 = 1u8 + u8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:111:26 + | +LL | const _NU8_ADD_P: &u8 = &(1u8 + u8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:113:24 + | +LL | const _NU16_ADD: u16 = 1u16 + u16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:114:28 + | +LL | const _NU16_ADD_P: &u16 = &(1u16 + u16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:116:24 + | +LL | const _NU32_ADD: u32 = 1u32 + u32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:117:28 + | +LL | const _NU32_ADD_P: &u32 = &(1u32 + u32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:119:24 + | +LL | const _NU64_ADD: u64 = 1u64 + u64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:120:28 + | +LL | const _NU64_ADD_P: &u64 = &(1u64 + u64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:122:26 + | +LL | const _NU128_ADD: u128 = 1u128 + u128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:123:30 + | +LL | const _NU128_ADD_P: &u128 = &(1u128 + u128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:125:28 + | +LL | const _NISIZE_ADD: isize = 1isize + isize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:126:32 + | +LL | const _NISIZE_ADD_P: &isize = &(1isize + isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:128:28 + | +LL | const _NUSIZE_ADD: usize = 1usize + usize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:129:32 + | +LL | const _NUSIZE_ADD_P: &usize = &(1usize + usize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:133:22 + | +LL | const _NI8_SUB: i8 = -5i8 - i8::MAX; + | ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:134:26 + | +LL | const _NI8_SUB_P: &i8 = &(-5i8 - i8::MAX); + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:136:24 + | +LL | const _NI16_SUB: i16 = -5i16 - i16::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:137:28 + | +LL | const _NI16_SUB_P: &i16 = &(-5i16 - i16::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:139:24 + | +LL | const _NI32_SUB: i32 = -5i32 - i32::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:140:28 + | +LL | const _NI32_SUB_P: &i32 = &(-5i32 - i32::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:142:24 + | +LL | const _NI64_SUB: i64 = -5i64 - i64::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:143:28 + | +LL | const _NI64_SUB_P: &i64 = &(-5i64 - i64::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:145:26 + | +LL | const _NI128_SUB: i128 = -5i128 - i128::MAX; + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:146:30 + | +LL | const _NI128_SUB_P: &i128 = &(-5i128 - i128::MAX); + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:148:22 + | +LL | const _NU8_SUB: u8 = 1u8 - 5; + | ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:149:26 + | +LL | const _NU8_SUB_P: &u8 = &(1u8 - 5); + | ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:151:24 + | +LL | const _NU16_SUB: u16 = 1u16 - 5; + | ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:152:28 + | +LL | const _NU16_SUB_P: &u16 = &(1u16 - 5); + | ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:154:24 + | +LL | const _NU32_SUB: u32 = 1u32 - 5; + | ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:155:28 + | +LL | const _NU32_SUB_P: &u32 = &(1u32 - 5); + | ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:157:24 + | +LL | const _NU64_SUB: u64 = 1u64 - 5; + | ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:158:28 + | +LL | const _NU64_SUB_P: &u64 = &(1u64 - 5); + | ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:160:26 + | +LL | const _NU128_SUB: u128 = 1u128 - 5; + | ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:161:30 + | +LL | const _NU128_SUB_P: &u128 = &(1u128 - 5); + | ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:163:28 + | +LL | const _NISIZE_SUB: isize = -5isize - isize::MAX; + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:164:32 + | +LL | const _NISIZE_SUB_P: &isize = &(-5isize - isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:166:28 + | +LL | const _NUSIZE_SUB: usize = 1usize - 5 ; + | ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:167:32 + | +LL | const _NUSIZE_SUB_P: &usize = &(1usize - 5 ); + | ^^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:171:22 + | +LL | const _NI8_MUL: i8 = i8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:172:26 + | +LL | const _NI8_MUL_P: &i8 = &(i8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:174:24 + | +LL | const _NI16_MUL: i16 = i16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:175:28 + | +LL | const _NI16_MUL_P: &i16 = &(i16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:177:24 + | +LL | const _NI32_MUL: i32 = i32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:178:28 + | +LL | const _NI32_MUL_P: &i32 = &(i32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:180:24 + | +LL | const _NI64_MUL: i64 = i64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:181:28 + | +LL | const _NI64_MUL_P: &i64 = &(i64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:183:26 + | +LL | const _NI128_MUL: i128 = i128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:184:30 + | +LL | const _NI128_MUL_P: &i128 = &(i128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:186:22 + | +LL | const _NU8_MUL: u8 = u8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:187:26 + | +LL | const _NU8_MUL_P: &u8 = &(u8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:189:24 + | +LL | const _NU16_MUL: u16 = u16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:190:28 + | +LL | const _NU16_MUL_P: &u16 = &(u16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:192:24 + | +LL | const _NU32_MUL: u32 = u32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:193:28 + | +LL | const _NU32_MUL_P: &u32 = &(u32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:195:24 + | +LL | const _NU64_MUL: u64 = u64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:196:28 + | +LL | const _NU64_MUL_P: &u64 = &(u64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:198:26 + | +LL | const _NU128_MUL: u128 = u128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:199:30 + | +LL | const _NU128_MUL_P: &u128 = &(u128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:201:28 + | +LL | const _NISIZE_MUL: isize = isize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:202:32 + | +LL | const _NISIZE_MUL_P: &isize = &(isize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:204:28 + | +LL | const _NUSIZE_MUL: usize = usize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:205:32 + | +LL | const _NUSIZE_MUL_P: &usize = &(usize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:209:22 + | +LL | const _NI8_DIV: i8 = 1i8 / 0; + | ^^^^^^^ attempt to divide `1_i8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:210:26 + | +LL | const _NI8_DIV_P: &i8 = &(1i8 / 0); + | ^^^^^^^^^ attempt to divide `1_i8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:212:24 + | +LL | const _NI16_DIV: i16 = 1i16 / 0; + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:213:28 + | +LL | const _NI16_DIV_P: &i16 = &(1i16 / 0); + | ^^^^^^^^^^ attempt to divide `1_i16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:215:24 + | +LL | const _NI32_DIV: i32 = 1i32 / 0; + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:216:28 + | +LL | const _NI32_DIV_P: &i32 = &(1i32 / 0); + | ^^^^^^^^^^ attempt to divide `1_i32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:218:24 + | +LL | const _NI64_DIV: i64 = 1i64 / 0; + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:219:28 + | +LL | const _NI64_DIV_P: &i64 = &(1i64 / 0); + | ^^^^^^^^^^ attempt to divide `1_i64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:221:26 + | +LL | const _NI128_DIV: i128 = 1i128 / 0; + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:222:30 + | +LL | const _NI128_DIV_P: &i128 = &(1i128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_i128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:224:22 + | +LL | const _NU8_DIV: u8 = 1u8 / 0; + | ^^^^^^^ attempt to divide `1_u8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:225:26 + | +LL | const _NU8_DIV_P: &u8 = &(1u8 / 0); + | ^^^^^^^^^ attempt to divide `1_u8` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:227:24 + | +LL | const _NU16_DIV: u16 = 1u16 / 0; + | ^^^^^^^^ attempt to divide `1_u16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:228:28 + | +LL | const _NU16_DIV_P: &u16 = &(1u16 / 0); + | ^^^^^^^^^^ attempt to divide `1_u16` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:230:24 + | +LL | const _NU32_DIV: u32 = 1u32 / 0; + | ^^^^^^^^ attempt to divide `1_u32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:231:28 + | +LL | const _NU32_DIV_P: &u32 = &(1u32 / 0); + | ^^^^^^^^^^ attempt to divide `1_u32` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:233:24 + | +LL | const _NU64_DIV: u64 = 1u64 / 0; + | ^^^^^^^^ attempt to divide `1_u64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:234:28 + | +LL | const _NU64_DIV_P: &u64 = &(1u64 / 0); + | ^^^^^^^^^^ attempt to divide `1_u64` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:236:26 + | +LL | const _NU128_DIV: u128 = 1u128 / 0; + | ^^^^^^^^^ attempt to divide `1_u128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:237:30 + | +LL | const _NU128_DIV_P: &u128 = &(1u128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_u128` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:239:28 + | +LL | const _NISIZE_DIV: isize = 1isize / 0; + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:240:32 + | +LL | const _NISIZE_DIV_P: &isize = &(1isize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_isize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:242:28 + | +LL | const _NUSIZE_DIV: usize = 1usize / 0; + | ^^^^^^^^^^ attempt to divide `1_usize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:243:32 + | +LL | const _NUSIZE_DIV_P: &usize = &(1usize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_usize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:246:22 + | +LL | const _NI8_MOD: i8 = 1i8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:247:26 + | +LL | const _NI8_MOD_P: &i8 = &(1i8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:249:24 + | +LL | const _NI16_MOD: i16 = 1i16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:250:28 + | +LL | const _NI16_MOD_P: &i16 = &(1i16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:252:24 + | +LL | const _NI32_MOD: i32 = 1i32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:253:28 + | +LL | const _NI32_MOD_P: &i32 = &(1i32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:255:24 + | +LL | const _NI64_MOD: i64 = 1i64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:256:28 + | +LL | const _NI64_MOD_P: &i64 = &(1i64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:258:26 + | +LL | const _NI128_MOD: i128 = 1i128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:259:30 + | +LL | const _NI128_MOD_P: &i128 = &(1i128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:261:22 + | +LL | const _NU8_MOD: u8 = 1u8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:262:26 + | +LL | const _NU8_MOD_P: &u8 = &(1u8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:264:24 + | +LL | const _NU16_MOD: u16 = 1u16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:265:28 + | +LL | const _NU16_MOD_P: &u16 = &(1u16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:267:24 + | +LL | const _NU32_MOD: u32 = 1u32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:268:28 + | +LL | const _NU32_MOD_P: &u32 = &(1u32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:270:24 + | +LL | const _NU64_MOD: u64 = 1u64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:271:28 + | +LL | const _NU64_MOD_P: &u64 = &(1u64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:273:26 + | +LL | const _NU128_MOD: u128 = 1u128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:274:30 + | +LL | const _NU128_MOD_P: &u128 = &(1u128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:276:28 + | +LL | const _NISIZE_MOD: isize = 1isize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:277:32 + | +LL | const _NISIZE_MOD_P: &isize = &(1isize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:279:28 + | +LL | const _NUSIZE_MOD: usize = 1usize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:280:32 + | +LL | const _NUSIZE_MOD_P: &usize = &(1usize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:284:24 + | +LL | const _NI32_OOB: i32 = [1, 2, 3][4]; + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error[E0080]: evaluation of constant value failed + --> $DIR/overflowing-consts.rs:285:28 + | +LL | const _NI32_OOB_P: &i32 = &([1, 2, 3][4]); + | ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 170 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/overflowing-consts.rs b/tests/ui/consts/overflowing-consts.rs new file mode 100644 index 0000000000000..52c0623f2c037 --- /dev/null +++ b/tests/ui/consts/overflowing-consts.rs @@ -0,0 +1,288 @@ +// Tests that overflowing or bound-exceeding operations +// for compile-time consts raise errors + +//@ revisions: noopt opt opt_with_overflow_checks +//@ [noopt]compile-flags: -C opt-level=0 +//@ [opt]compile-flags: -O +//@ [opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O +//@ ignore-pass (test tests codegen-time behaviour) +//@ normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which" +//@ normalize-stderr-test "shift right by `(64|32)_usize`, which" -> "shift right by `%BITS%`, which" + + +#[cfg(target_pointer_width = "32")] +const BITS: usize = 32; +#[cfg(target_pointer_width = "64")] +const BITS: usize = 64; + +// Shift left +const _NI8_SHL: i8 = 1i8 << 8; //~ ERROR: evaluation of constant value failed +const _NI8_SHL_P: &i8 = &(1i8 << 8); //~ ERROR: evaluation of constant value failed + +const _NI16_SHL: i16 = 1i16 << 16; //~ ERROR: evaluation of constant value failed +const _NI16_SHL_P: &i16 = &(1i16 << 16); //~ ERROR: evaluation of constant value failed + +const _NI32_SHL: i32 = 1i32 << 32; //~ ERROR: evaluation of constant value failed +const _NI32_SHL_P: &i32 = &(1i32 << 32); //~ ERROR: evaluation of constant value failed + +const _NI64_SHL: i64 = 1i64 << 64; //~ ERROR: evaluation of constant value failed +const _NI64_SHL_P: &i64 = &(1i64 << 64); //~ ERROR: evaluation of constant value failed + +const _NI128_SHL: i128 = 1i128 << 128; //~ ERROR: evaluation of constant value failed +const _NI128_SHL_P: &i128 = &(1i128 << 128); //~ ERROR: evaluation of constant value failed + +const _NU8_SHL: u8 = 1u8 << 8; //~ ERROR: evaluation of constant value failed +const _NU8_SHL_P: &u8 = &(1u8 << 8); //~ ERROR: evaluation of constant value failed + +const _NU16_SHL: u16 = 1u16 << 16; //~ ERROR: evaluation of constant value failed +const _NU16_SHL_P: &u16 = &(1u16 << 16); //~ ERROR: evaluation of constant value failed + +const _NU32_SHL: u32 = 1u32 << 32; //~ ERROR: evaluation of constant value failed +const _NU32_SHL_P: &u32 = &(1u32 << 32); //~ ERROR: evaluation of constant value failed + +const _NU64_SHL: u64 = 1u64 << 64; //~ ERROR: evaluation of constant value failed +const _NU64_SHL_P: &u64 = &(1u64 << 64); //~ ERROR: evaluation of constant value failed + +const _NU128_SHL: u128 = 1u128 << 128; //~ ERROR: evaluation of constant value failed +const _NU128_SHL_P: &u128 = &(1u128 << 128); //~ ERROR: evaluation of constant value failed + +const _NISIZE_SHL: isize = 1isize << BITS; //~ ERROR: evaluation of constant value failed +const _NISIZE_SHL_P: &isize = &(1isize << BITS); //~ ERROR: evaluation of constant value failed + +const _NUSIZE_SHL: usize = 1usize << BITS; //~ ERROR: evaluation of constant value failed +const _NUSIZE_SHL_P: &usize = &(1usize << BITS); //~ ERROR: evaluation of constant value failed + + +// Shift right +const _NI8_SHR: i8 = 1i8 >> 8; //~ ERROR: evaluation of constant value failed +const _NI8_SHR_P: &i8 = &(1i8 >> 8); //~ ERROR: evaluation of constant value failed + +const _NI16_SHR: i16 = 1i16 >> 16; //~ ERROR: evaluation of constant value failed +const _NI16_SHR_P: &i16 = &(1i16 >> 16); //~ ERROR: evaluation of constant value failed + +const _NI32_SHR: i32 = 1i32 >> 32; //~ ERROR: evaluation of constant value failed +const _NI32_SHR_P: &i32 = &(1i32 >> 32); //~ ERROR: evaluation of constant value failed + +const _NI64_SHR: i64 = 1i64 >> 64; //~ ERROR: evaluation of constant value failed +const _NI64_SHR_P: &i64 = &(1i64 >> 64); //~ ERROR: evaluation of constant value failed + +const _NI128_SHR: i128 = 1i128 >> 128; //~ ERROR: evaluation of constant value failed +const _NI128_SHR_P: &i128 = &(1i128 >> 128); //~ ERROR: evaluation of constant value failed + +const _NU8_SHR: u8 = 1u8 >> 8; //~ ERROR: evaluation of constant value failed +const _NU8_SHR_P: &u8 = &(1u8 >> 8); //~ ERROR: evaluation of constant value failed + +const _NU16_SHR: u16 = 1u16 >> 16; //~ ERROR: evaluation of constant value failed +const _NU16_SHR_P: &u16 = &(1u16 >> 16); //~ ERROR: evaluation of constant value failed + +const _NU32_SHR: u32 = 1u32 >> 32; //~ ERROR: evaluation of constant value failed +const _NU32_SHR_P: &u32 = &(1u32 >> 32); //~ ERROR: evaluation of constant value failed + +const _NU64_SHR: u64 = 1u64 >> 64; //~ ERROR: evaluation of constant value failed +const _NU64_SHR_P: &u64 = &(1u64 >> 64); //~ ERROR: evaluation of constant value failed + +const _NU128_SHR: u128 = 1u128 >> 128; //~ ERROR: evaluation of constant value failed +const _NU128_SHR_P: &u128 = &(1u128 >> 128); //~ ERROR: evaluation of constant value failed + +const _NISIZE_SHR: isize = 1isize >> BITS; //~ ERROR: evaluation of constant value failed +const _NISIZE_SHR_P: &isize = &(1isize >> BITS); //~ ERROR: evaluation of constant value failed + +const _NUSIZE_SHR: usize = 1usize >> BITS; //~ ERROR: evaluation of constant value failed +const _NUSIZE_SHR_P: &usize = &(1usize >> BITS); //~ ERROR: evaluation of constant value failed + + +// Addition +const _NI8_ADD: i8 = 1i8 + i8::MAX; //~ ERROR: evaluation of constant value failed +const _NI8_ADD_P: &i8 = &(1i8 + i8::MAX); //~ ERROR: evaluation of constant value failed + +const _NI16_ADD: i16 = 1i16 + i16::MAX; //~ ERROR: evaluation of constant value failed +const _NI16_ADD_P: &i16 = &(1i16 + i16::MAX); //~ ERROR: evaluation of constant value failed + +const _NI32_ADD: i32 = 1i32 + i32::MAX; //~ ERROR: evaluation of constant value failed +const _NI32_ADD_P: &i32 = &(1i32 + i32::MAX); //~ ERROR: evaluation of constant value failed + +const _NI64_ADD: i64 = 1i64 + i64::MAX; //~ ERROR: evaluation of constant value failed +const _NI64_ADD_P: &i64 = &(1i64 + i64::MAX); //~ ERROR: evaluation of constant value failed + +const _NI128_ADD: i128 = 1i128 + i128::MAX; //~ ERROR: evaluation of constant value failed +const _NI128_ADD_P: &i128 = &(1i128 + i128::MAX); //~ ERROR: evaluation of constant value failed + +const _NU8_ADD: u8 = 1u8 + u8::MAX; //~ ERROR: evaluation of constant value failed +const _NU8_ADD_P: &u8 = &(1u8 + u8::MAX); //~ ERROR: evaluation of constant value failed + +const _NU16_ADD: u16 = 1u16 + u16::MAX; //~ ERROR: evaluation of constant value failed +const _NU16_ADD_P: &u16 = &(1u16 + u16::MAX); //~ ERROR: evaluation of constant value failed + +const _NU32_ADD: u32 = 1u32 + u32::MAX; //~ ERROR: evaluation of constant value failed +const _NU32_ADD_P: &u32 = &(1u32 + u32::MAX); //~ ERROR: evaluation of constant value failed + +const _NU64_ADD: u64 = 1u64 + u64::MAX; //~ ERROR: evaluation of constant value failed +const _NU64_ADD_P: &u64 = &(1u64 + u64::MAX); //~ ERROR: evaluation of constant value failed + +const _NU128_ADD: u128 = 1u128 + u128::MAX; //~ ERROR: evaluation of constant value failed +const _NU128_ADD_P: &u128 = &(1u128 + u128::MAX); //~ ERROR: evaluation of constant value failed + +const _NISIZE_ADD: isize = 1isize + isize::MAX; //~ ERROR: evaluation of constant value failed +const _NISIZE_ADD_P: &isize = &(1isize + isize::MAX); //~ ERROR: evaluation of constant value failed + +const _NUSIZE_ADD: usize = 1usize + usize::MAX; //~ ERROR: evaluation of constant value failed +const _NUSIZE_ADD_P: &usize = &(1usize + usize::MAX); //~ ERROR: evaluation of constant value failed + + +// Subtraction +const _NI8_SUB: i8 = -5i8 - i8::MAX; //~ ERROR: evaluation of constant value failed +const _NI8_SUB_P: &i8 = &(-5i8 - i8::MAX); //~ ERROR: evaluation of constant value failed + +const _NI16_SUB: i16 = -5i16 - i16::MAX; //~ ERROR: evaluation of constant value failed +const _NI16_SUB_P: &i16 = &(-5i16 - i16::MAX); //~ ERROR: evaluation of constant value failed + +const _NI32_SUB: i32 = -5i32 - i32::MAX; //~ ERROR: evaluation of constant value failed +const _NI32_SUB_P: &i32 = &(-5i32 - i32::MAX); //~ ERROR: evaluation of constant value failed + +const _NI64_SUB: i64 = -5i64 - i64::MAX; //~ ERROR: evaluation of constant value failed +const _NI64_SUB_P: &i64 = &(-5i64 - i64::MAX); //~ ERROR: evaluation of constant value failed + +const _NI128_SUB: i128 = -5i128 - i128::MAX; //~ ERROR: evaluation of constant value failed +const _NI128_SUB_P: &i128 = &(-5i128 - i128::MAX); //~ ERROR: evaluation of constant value failed + +const _NU8_SUB: u8 = 1u8 - 5; //~ ERROR: evaluation of constant value failed +const _NU8_SUB_P: &u8 = &(1u8 - 5); //~ ERROR: evaluation of constant value failed + +const _NU16_SUB: u16 = 1u16 - 5; //~ ERROR: evaluation of constant value failed +const _NU16_SUB_P: &u16 = &(1u16 - 5); //~ ERROR: evaluation of constant value failed + +const _NU32_SUB: u32 = 1u32 - 5; //~ ERROR: evaluation of constant value failed +const _NU32_SUB_P: &u32 = &(1u32 - 5); //~ ERROR: evaluation of constant value failed + +const _NU64_SUB: u64 = 1u64 - 5; //~ ERROR: evaluation of constant value failed +const _NU64_SUB_P: &u64 = &(1u64 - 5); //~ ERROR: evaluation of constant value failed + +const _NU128_SUB: u128 = 1u128 - 5; //~ ERROR: evaluation of constant value failed +const _NU128_SUB_P: &u128 = &(1u128 - 5); //~ ERROR: evaluation of constant value failed + +const _NISIZE_SUB: isize = -5isize - isize::MAX; //~ ERROR: evaluation of constant value failed +const _NISIZE_SUB_P: &isize = &(-5isize - isize::MAX); //~ ERROR: evaluation of constant value failed + +const _NUSIZE_SUB: usize = 1usize - 5 ; //~ ERROR: evaluation of constant value failed +const _NUSIZE_SUB_P: &usize = &(1usize - 5 ); //~ ERROR: evaluation of constant value failed + + +// Multiplication +const _NI8_MUL: i8 = i8::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NI8_MUL_P: &i8 = &(i8::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NI16_MUL: i16 = i16::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NI16_MUL_P: &i16 = &(i16::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NI32_MUL: i32 = i32::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NI32_MUL_P: &i32 = &(i32::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NI64_MUL: i64 = i64::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NI64_MUL_P: &i64 = &(i64::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NI128_MUL: i128 = i128::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NI128_MUL_P: &i128 = &(i128::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NU8_MUL: u8 = u8::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NU8_MUL_P: &u8 = &(u8::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NU16_MUL: u16 = u16::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NU16_MUL_P: &u16 = &(u16::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NU32_MUL: u32 = u32::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NU32_MUL_P: &u32 = &(u32::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NU64_MUL: u64 = u64::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NU64_MUL_P: &u64 = &(u64::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NU128_MUL: u128 = u128::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NU128_MUL_P: &u128 = &(u128::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NISIZE_MUL: isize = isize::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NISIZE_MUL_P: &isize = &(isize::MAX * 5); //~ ERROR: evaluation of constant value failed + +const _NUSIZE_MUL: usize = usize::MAX * 5; //~ ERROR: evaluation of constant value failed +const _NUSIZE_MUL_P: &usize = &(usize::MAX * 5); //~ ERROR: evaluation of constant value failed + + +// Division +const _NI8_DIV: i8 = 1i8 / 0; //~ ERROR: evaluation of constant value failed +const _NI8_DIV_P: &i8 = &(1i8 / 0); //~ ERROR: evaluation of constant value failed + +const _NI16_DIV: i16 = 1i16 / 0; //~ ERROR: evaluation of constant value failed +const _NI16_DIV_P: &i16 = &(1i16 / 0); //~ ERROR: evaluation of constant value failed + +const _NI32_DIV: i32 = 1i32 / 0; //~ ERROR: evaluation of constant value failed +const _NI32_DIV_P: &i32 = &(1i32 / 0); //~ ERROR: evaluation of constant value failed + +const _NI64_DIV: i64 = 1i64 / 0; //~ ERROR: evaluation of constant value failed +const _NI64_DIV_P: &i64 = &(1i64 / 0); //~ ERROR: evaluation of constant value failed + +const _NI128_DIV: i128 = 1i128 / 0; //~ ERROR: evaluation of constant value failed +const _NI128_DIV_P: &i128 = &(1i128 / 0); //~ ERROR: evaluation of constant value failed + +const _NU8_DIV: u8 = 1u8 / 0; //~ ERROR: evaluation of constant value failed +const _NU8_DIV_P: &u8 = &(1u8 / 0); //~ ERROR: evaluation of constant value failed + +const _NU16_DIV: u16 = 1u16 / 0; //~ ERROR: evaluation of constant value failed +const _NU16_DIV_P: &u16 = &(1u16 / 0); //~ ERROR: evaluation of constant value failed + +const _NU32_DIV: u32 = 1u32 / 0; //~ ERROR: evaluation of constant value failed +const _NU32_DIV_P: &u32 = &(1u32 / 0); //~ ERROR: evaluation of constant value failed + +const _NU64_DIV: u64 = 1u64 / 0; //~ ERROR: evaluation of constant value failed +const _NU64_DIV_P: &u64 = &(1u64 / 0); //~ ERROR: evaluation of constant value failed + +const _NU128_DIV: u128 = 1u128 / 0; //~ ERROR: evaluation of constant value failed +const _NU128_DIV_P: &u128 = &(1u128 / 0); //~ ERROR: evaluation of constant value failed + +const _NISIZE_DIV: isize = 1isize / 0; //~ ERROR: evaluation of constant value failed +const _NISIZE_DIV_P: &isize = &(1isize / 0); //~ ERROR: evaluation of constant value failed + +const _NUSIZE_DIV: usize = 1usize / 0; //~ ERROR: evaluation of constant value failed +const _NUSIZE_DIV_P: &usize = &(1usize / 0); //~ ERROR: evaluation of constant value failed + +// Modulus +const _NI8_MOD: i8 = 1i8 % 0; //~ ERROR: evaluation of constant value failed +const _NI8_MOD_P: &i8 = &(1i8 % 0); //~ ERROR: evaluation of constant value failed + +const _NI16_MOD: i16 = 1i16 % 0; //~ ERROR: evaluation of constant value failed +const _NI16_MOD_P: &i16 = &(1i16 % 0); //~ ERROR: evaluation of constant value failed + +const _NI32_MOD: i32 = 1i32 % 0; //~ ERROR: evaluation of constant value failed +const _NI32_MOD_P: &i32 = &(1i32 % 0); //~ ERROR: evaluation of constant value failed + +const _NI64_MOD: i64 = 1i64 % 0; //~ ERROR: evaluation of constant value failed +const _NI64_MOD_P: &i64 = &(1i64 % 0); //~ ERROR: evaluation of constant value failed + +const _NI128_MOD: i128 = 1i128 % 0; //~ ERROR: evaluation of constant value failed +const _NI128_MOD_P: &i128 = &(1i128 % 0); //~ ERROR: evaluation of constant value failed + +const _NU8_MOD: u8 = 1u8 % 0; //~ ERROR: evaluation of constant value failed +const _NU8_MOD_P: &u8 = &(1u8 % 0); //~ ERROR: evaluation of constant value failed + +const _NU16_MOD: u16 = 1u16 % 0; //~ ERROR: evaluation of constant value failed +const _NU16_MOD_P: &u16 = &(1u16 % 0); //~ ERROR: evaluation of constant value failed + +const _NU32_MOD: u32 = 1u32 % 0; //~ ERROR: evaluation of constant value failed +const _NU32_MOD_P: &u32 = &(1u32 % 0); //~ ERROR: evaluation of constant value failed + +const _NU64_MOD: u64 = 1u64 % 0; //~ ERROR: evaluation of constant value failed +const _NU64_MOD_P: &u64 = &(1u64 % 0); //~ ERROR: evaluation of constant value failed + +const _NU128_MOD: u128 = 1u128 % 0; //~ ERROR: evaluation of constant value failed +const _NU128_MOD_P: &u128 = &(1u128 % 0); //~ ERROR: evaluation of constant value failed + +const _NISIZE_MOD: isize = 1isize % 0; //~ ERROR: evaluation of constant value failed +const _NISIZE_MOD_P: &isize = &(1isize % 0); //~ ERROR: evaluation of constant value failed + +const _NUSIZE_MOD: usize = 1usize % 0; //~ ERROR: evaluation of constant value failed +const _NUSIZE_MOD_P: &usize = &(1usize % 0); //~ ERROR: evaluation of constant value failed + + +// Out of bounds access +const _NI32_OOB: i32 = [1, 2, 3][4]; //~ ERROR: evaluation of constant value failed +const _NI32_OOB_P: &i32 = &([1, 2, 3][4]); //~ ERROR: evaluation of constant value failed + + +pub fn main() {} diff --git a/tests/ui/consts/promotion.rs b/tests/ui/consts/promotion.rs index 783ca47d2c62e..211dcf8a4e8f2 100644 --- a/tests/ui/consts/promotion.rs +++ b/tests/ui/consts/promotion.rs @@ -25,9 +25,8 @@ fn main() { assert_static(&["d", "e", "f"]); assert_eq!(C, 42); - // make sure that these do not cause trouble despite overflowing + // make sure that this does not cause trouble despite overflowing assert_static(&(0-1)); - assert_static(&-i32::MIN); // div-by-non-0 is okay assert_static(&(1/1)); diff --git a/tests/ui/lint/issue-117949.noopt.stderr b/tests/ui/lint/issue-117949.noopt.stderr new file mode 100644 index 0000000000000..607488e2a4af8 --- /dev/null +++ b/tests/ui/lint/issue-117949.noopt.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:16:24 + | +LL | format_args!("{}", 5 * i32::MAX); + | ^^^^^^^^^^^^ attempt to compute `5_i32 * i32::MAX`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:15:24 + | +LL | format_args!("{}", -5 - i32::MAX); + | ^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:14:24 + | +LL | format_args!("{}", 1 + i32::MAX); + | ^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:13:24 + | +LL | format_args!("{}", 1 >> 32); + | ^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:12:24 + | +LL | format_args!("{}", 1 << 32); + | ^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:17:24 + | +LL | format_args!("{}", 1 / 0); + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:18:24 + | +LL | format_args!("{}", 1 % 0); + | ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:19:24 + | +LL | format_args!("{}", [1, 2, 3][4]); + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/issue-117949.opt.stderr b/tests/ui/lint/issue-117949.opt.stderr new file mode 100644 index 0000000000000..607488e2a4af8 --- /dev/null +++ b/tests/ui/lint/issue-117949.opt.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:16:24 + | +LL | format_args!("{}", 5 * i32::MAX); + | ^^^^^^^^^^^^ attempt to compute `5_i32 * i32::MAX`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:15:24 + | +LL | format_args!("{}", -5 - i32::MAX); + | ^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:14:24 + | +LL | format_args!("{}", 1 + i32::MAX); + | ^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:13:24 + | +LL | format_args!("{}", 1 >> 32); + | ^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:12:24 + | +LL | format_args!("{}", 1 << 32); + | ^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:17:24 + | +LL | format_args!("{}", 1 / 0); + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:18:24 + | +LL | format_args!("{}", 1 % 0); + | ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:19:24 + | +LL | format_args!("{}", [1, 2, 3][4]); + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/issue-117949.opt_with_overflow_checks.stderr b/tests/ui/lint/issue-117949.opt_with_overflow_checks.stderr new file mode 100644 index 0000000000000..607488e2a4af8 --- /dev/null +++ b/tests/ui/lint/issue-117949.opt_with_overflow_checks.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:16:24 + | +LL | format_args!("{}", 5 * i32::MAX); + | ^^^^^^^^^^^^ attempt to compute `5_i32 * i32::MAX`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:15:24 + | +LL | format_args!("{}", -5 - i32::MAX); + | ^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:14:24 + | +LL | format_args!("{}", 1 + i32::MAX); + | ^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:13:24 + | +LL | format_args!("{}", 1 >> 32); + | ^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-117949.rs:12:24 + | +LL | format_args!("{}", 1 << 32); + | ^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:17:24 + | +LL | format_args!("{}", 1 / 0); + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:18:24 + | +LL | format_args!("{}", 1 % 0); + | ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-117949.rs:19:24 + | +LL | format_args!("{}", [1, 2, 3][4]); + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/issue-117949.rs b/tests/ui/lint/issue-117949.rs new file mode 100644 index 0000000000000..5673227f35d39 --- /dev/null +++ b/tests/ui/lint/issue-117949.rs @@ -0,0 +1,20 @@ +// Regression test for issue #117949 + +//@ revisions: noopt opt opt_with_overflow_checks +//@ [noopt]compile-flags: -C opt-level=0 -Z deduplicate-diagnostics=yes +//@ [opt]compile-flags: -O +//@ [opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O -Z deduplicate-diagnostics=yes +//@ build-fail +//@ ignore-pass (test tests codegen-time behaviour) + + +fn main() { + format_args!("{}", 1 << 32); //~ ERROR: arithmetic operation will overflow + format_args!("{}", 1 >> 32); //~ ERROR: arithmetic operation will overflow + format_args!("{}", 1 + i32::MAX); //~ ERROR: arithmetic operation will overflow + format_args!("{}", -5 - i32::MAX); //~ ERROR: arithmetic operation will overflow + format_args!("{}", 5 * i32::MAX); //~ ERROR: arithmetic operation will overflow + format_args!("{}", 1 / 0); //~ ERROR: this operation will panic at runtime + format_args!("{}", 1 % 0); //~ ERROR: this operation will panic at runtime + format_args!("{}", [1, 2, 3][4]); //~ ERROR: this operation will panic at runtime +} diff --git a/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr deleted file mode 100644 index 3a84c6c1fb1f9..0000000000000 --- a/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr +++ /dev/null @@ -1,152 +0,0 @@ -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:18:20 - | -LL | const N: i32 = T::N << 42; - | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow - | -note: the lint level is defined here - --> $DIR/lint-exceeding-bitshifts.rs:10:9 - | -LL | #![warn(arithmetic_overflow)] - | ^^^^^^^^^^^^^^^^^^^ - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:22:13 - | -LL | let _ = x << 42; - | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:27:15 - | -LL | let n = 1u8 << 8; - | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:29:15 - | -LL | let n = 1u16 << 16; - | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:31:15 - | -LL | let n = 1u32 << 32; - | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:33:15 - | -LL | let n = 1u64 << 64; - | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:35:15 - | -LL | let n = 1i8 << 8; - | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:37:15 - | -LL | let n = 1i16 << 16; - | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:39:15 - | -LL | let n = 1i32 << 32; - | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:41:15 - | -LL | let n = 1i64 << 64; - | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:44:15 - | -LL | let n = 1u8 >> 8; - | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:46:15 - | -LL | let n = 1u16 >> 16; - | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:48:15 - | -LL | let n = 1u32 >> 32; - | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:50:15 - | -LL | let n = 1u64 >> 64; - | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:52:15 - | -LL | let n = 1i8 >> 8; - | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:54:15 - | -LL | let n = 1i16 >> 16; - | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:56:15 - | -LL | let n = 1i32 >> 32; - | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:58:15 - | -LL | let n = 1i64 >> 64; - | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:62:15 - | -LL | let n = n << 8; - | ^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:64:15 - | -LL | let n = 1u8 << -8; - | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:69:15 - | -LL | let n = 1u8 << (4+4); - | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:71:15 - | -LL | let n = 1i64 >> [64][0]; - | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:77:15 - | -LL | let n = 1_isize << BITS; - | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:78:15 - | -LL | let n = 1_usize << BITS; - | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow - -warning: 24 warnings emitted - diff --git a/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr b/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr deleted file mode 100644 index 3a84c6c1fb1f9..0000000000000 --- a/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr +++ /dev/null @@ -1,152 +0,0 @@ -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:18:20 - | -LL | const N: i32 = T::N << 42; - | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow - | -note: the lint level is defined here - --> $DIR/lint-exceeding-bitshifts.rs:10:9 - | -LL | #![warn(arithmetic_overflow)] - | ^^^^^^^^^^^^^^^^^^^ - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:22:13 - | -LL | let _ = x << 42; - | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:27:15 - | -LL | let n = 1u8 << 8; - | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:29:15 - | -LL | let n = 1u16 << 16; - | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:31:15 - | -LL | let n = 1u32 << 32; - | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:33:15 - | -LL | let n = 1u64 << 64; - | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:35:15 - | -LL | let n = 1i8 << 8; - | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:37:15 - | -LL | let n = 1i16 << 16; - | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:39:15 - | -LL | let n = 1i32 << 32; - | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:41:15 - | -LL | let n = 1i64 << 64; - | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:44:15 - | -LL | let n = 1u8 >> 8; - | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:46:15 - | -LL | let n = 1u16 >> 16; - | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:48:15 - | -LL | let n = 1u32 >> 32; - | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:50:15 - | -LL | let n = 1u64 >> 64; - | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:52:15 - | -LL | let n = 1i8 >> 8; - | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:54:15 - | -LL | let n = 1i16 >> 16; - | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:56:15 - | -LL | let n = 1i32 >> 32; - | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:58:15 - | -LL | let n = 1i64 >> 64; - | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:62:15 - | -LL | let n = n << 8; - | ^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:64:15 - | -LL | let n = 1u8 << -8; - | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:69:15 - | -LL | let n = 1u8 << (4+4); - | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:71:15 - | -LL | let n = 1i64 >> [64][0]; - | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:77:15 - | -LL | let n = 1_isize << BITS; - | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:78:15 - | -LL | let n = 1_usize << BITS; - | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow - -warning: 24 warnings emitted - diff --git a/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr deleted file mode 100644 index 3a84c6c1fb1f9..0000000000000 --- a/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr +++ /dev/null @@ -1,152 +0,0 @@ -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:18:20 - | -LL | const N: i32 = T::N << 42; - | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow - | -note: the lint level is defined here - --> $DIR/lint-exceeding-bitshifts.rs:10:9 - | -LL | #![warn(arithmetic_overflow)] - | ^^^^^^^^^^^^^^^^^^^ - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:22:13 - | -LL | let _ = x << 42; - | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:27:15 - | -LL | let n = 1u8 << 8; - | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:29:15 - | -LL | let n = 1u16 << 16; - | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:31:15 - | -LL | let n = 1u32 << 32; - | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:33:15 - | -LL | let n = 1u64 << 64; - | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:35:15 - | -LL | let n = 1i8 << 8; - | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:37:15 - | -LL | let n = 1i16 << 16; - | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:39:15 - | -LL | let n = 1i32 << 32; - | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:41:15 - | -LL | let n = 1i64 << 64; - | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:44:15 - | -LL | let n = 1u8 >> 8; - | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:46:15 - | -LL | let n = 1u16 >> 16; - | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:48:15 - | -LL | let n = 1u32 >> 32; - | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:50:15 - | -LL | let n = 1u64 >> 64; - | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:52:15 - | -LL | let n = 1i8 >> 8; - | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:54:15 - | -LL | let n = 1i16 >> 16; - | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:56:15 - | -LL | let n = 1i32 >> 32; - | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:58:15 - | -LL | let n = 1i64 >> 64; - | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:62:15 - | -LL | let n = n << 8; - | ^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:64:15 - | -LL | let n = 1u8 << -8; - | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:69:15 - | -LL | let n = 1u8 << (4+4); - | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:71:15 - | -LL | let n = 1i64 >> [64][0]; - | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:77:15 - | -LL | let n = 1_isize << BITS; - | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow - -warning: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:78:15 - | -LL | let n = 1_usize << BITS; - | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow - -warning: 24 warnings emitted - diff --git a/tests/ui/lint/lint-exceeding-bitshifts.rs b/tests/ui/lint/lint-exceeding-bitshifts.rs deleted file mode 100644 index ea9d5ce6781fb..0000000000000 --- a/tests/ui/lint/lint-exceeding-bitshifts.rs +++ /dev/null @@ -1,79 +0,0 @@ -//@ revisions: noopt opt opt_with_overflow_checks -//@[noopt]compile-flags: -C opt-level=0 -//@[opt]compile-flags: -O -//@[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O -//@ build-pass -//@ ignore-pass (test emits codegen-time warnings and verifies that they are not errors) -//@ normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which" - -#![crate_type="lib"] -#![warn(arithmetic_overflow)] - - -pub trait Foo { - const N: i32; -} - -impl Foo for Vec { - const N: i32 = T::N << 42; //~ WARN: arithmetic operation will overflow -} - -pub fn foo(x: i32) { - let _ = x << 42; //~ WARN: arithmetic operation will overflow -} - -pub fn main() { - let n = 1u8 << 7; - let n = 1u8 << 8; //~ WARN: arithmetic operation will overflow - let n = 1u16 << 15; - let n = 1u16 << 16; //~ WARN: arithmetic operation will overflow - let n = 1u32 << 31; - let n = 1u32 << 32; //~ WARN: arithmetic operation will overflow - let n = 1u64 << 63; - let n = 1u64 << 64; //~ WARN: arithmetic operation will overflow - let n = 1i8 << 7; - let n = 1i8 << 8; //~ WARN: arithmetic operation will overflow - let n = 1i16 << 15; - let n = 1i16 << 16; //~ WARN: arithmetic operation will overflow - let n = 1i32 << 31; - let n = 1i32 << 32; //~ WARN: arithmetic operation will overflow - let n = 1i64 << 63; - let n = 1i64 << 64; //~ WARN: arithmetic operation will overflow - - let n = 1u8 >> 7; - let n = 1u8 >> 8; //~ WARN: arithmetic operation will overflow - let n = 1u16 >> 15; - let n = 1u16 >> 16; //~ WARN: arithmetic operation will overflow - let n = 1u32 >> 31; - let n = 1u32 >> 32; //~ WARN: arithmetic operation will overflow - let n = 1u64 >> 63; - let n = 1u64 >> 64; //~ WARN: arithmetic operation will overflow - let n = 1i8 >> 7; - let n = 1i8 >> 8; //~ WARN: arithmetic operation will overflow - let n = 1i16 >> 15; - let n = 1i16 >> 16; //~ WARN: arithmetic operation will overflow - let n = 1i32 >> 31; - let n = 1i32 >> 32; //~ WARN: arithmetic operation will overflow - let n = 1i64 >> 63; - let n = 1i64 >> 64; //~ WARN: arithmetic operation will overflow - - let n = 1u8; - let n = n << 7; - let n = n << 8; //~ WARN: arithmetic operation will overflow - - let n = 1u8 << -8; //~ WARN: arithmetic operation will overflow - - let n = 1i8<<(1isize+-1); - - let n = 1u8 << (4+3); - let n = 1u8 << (4+4); //~ WARN: arithmetic operation will overflow - let n = 1i64 >> [63][0]; - let n = 1i64 >> [64][0]; //~ WARN: arithmetic operation will overflow - - #[cfg(target_pointer_width = "32")] - const BITS: usize = 32; - #[cfg(target_pointer_width = "64")] - const BITS: usize = 64; - let n = 1_isize << BITS; //~ WARN: arithmetic operation will overflow - let n = 1_usize << BITS; //~ WARN: arithmetic operation will overflow -} diff --git a/tests/ui/lint/lint-overflowing-ops.noopt.stderr b/tests/ui/lint/lint-overflowing-ops.noopt.stderr new file mode 100644 index 0000000000000..93fc19ce79e44 --- /dev/null +++ b/tests/ui/lint/lint-overflowing-ops.noopt.stderr @@ -0,0 +1,1030 @@ +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:26:14 + | +LL | let _n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-overflowing-ops.rs:17:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:212:15 + | +LL | let _n = &(usize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:209:15 + | +LL | let _n = &(isize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:206:15 + | +LL | let _n = &(i128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:203:15 + | +LL | let _n = &(i64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:200:15 + | +LL | let _n = &(i32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:197:15 + | +LL | let _n = &(i16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:194:15 + | +LL | let _n = &(i8::MAX * i8::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:191:15 + | +LL | let _n = &(u128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:188:15 + | +LL | let _n = &(u64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:185:15 + | +LL | let _n = &(u32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:182:15 + | +LL | let _n = &(u16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:179:15 + | +LL | let _n = &(u8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:174:15 + | +LL | let _n = &(1usize - 5); + | ^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:171:15 + | +LL | let _n = &(-5isize - isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:168:15 + | +LL | let _n = &(-5i128 - i128::MAX); + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:165:15 + | +LL | let _n = &(-5i64 - i64::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:162:15 + | +LL | let _n = &(-5i32 - i32::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:159:15 + | +LL | let _n = &(-5i16 - i16::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:156:15 + | +LL | let _n = &(-5i8 - i8::MAX); + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:153:15 + | +LL | let _n = &(1u128 - 5); + | ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:150:15 + | +LL | let _n = &(1u64 - 5); + | ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:147:15 + | +LL | let _n = &(1u32 - 5); + | ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:144:15 + | +LL | let _n = &(1u16 - 5); + | ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:141:15 + | +LL | let _n = &(1u8 - 5); + | ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:136:15 + | +LL | let _n = &(1usize + usize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:133:15 + | +LL | let _n = &(1isize + isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:130:15 + | +LL | let _n = &(1i128 + i128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:127:15 + | +LL | let _n = &(1i64 + i64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:124:15 + | +LL | let _n = &(1i32 + i32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:121:15 + | +LL | let _n = &(1i16 + i16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:118:15 + | +LL | let _n = &(1i8 + i8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:115:15 + | +LL | let _n = &(1u128 + u128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:112:15 + | +LL | let _n = &(1u64 + u64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:109:15 + | +LL | let _n = &(1u32 + u32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:106:15 + | +LL | let _n = &(1u16 + u16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:103:15 + | +LL | let _n = &(1u8 + u8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:98:15 + | +LL | let _n = &(1_usize >> BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:95:15 + | +LL | let _n = &(1_isize >> BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:92:15 + | +LL | let _n = &(1i128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:89:15 + | +LL | let _n = &(1i64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:86:15 + | +LL | let _n = &(1i32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:83:15 + | +LL | let _n = &(1i16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:80:15 + | +LL | let _n = &(1i8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:77:15 + | +LL | let _n = &(1u128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:74:15 + | +LL | let _n = &(1u64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:71:15 + | +LL | let _n = &(1u32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:68:15 + | +LL | let _n = &(1u16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:65:15 + | +LL | let _n = &(1u8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:60:15 + | +LL | let _n = &(1_usize << BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:57:15 + | +LL | let _n = &(1_isize << BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:54:15 + | +LL | let _n = &(1i128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:51:15 + | +LL | let _n = &(1i64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:48:15 + | +LL | let _n = &(1i32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:45:15 + | +LL | let _n = &(1i16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:42:15 + | +LL | let _n = &(1i8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:39:15 + | +LL | let _n = &(1u128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:36:15 + | +LL | let _n = &(1u64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:33:15 + | +LL | let _n = &(1u32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:30:15 + | +LL | let _n = &(1u16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:27:15 + | +LL | let _n = &(1u8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:29:14 + | +LL | let _n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:32:14 + | +LL | let _n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:35:14 + | +LL | let _n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:38:14 + | +LL | let _n = 1u128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:41:14 + | +LL | let _n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:44:14 + | +LL | let _n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:47:14 + | +LL | let _n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:50:14 + | +LL | let _n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:53:14 + | +LL | let _n = 1i128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:56:14 + | +LL | let _n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:59:14 + | +LL | let _n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:64:14 + | +LL | let _n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:67:14 + | +LL | let _n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:70:14 + | +LL | let _n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:73:14 + | +LL | let _n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:76:14 + | +LL | let _n = 1u128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:79:14 + | +LL | let _n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:82:14 + | +LL | let _n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:85:14 + | +LL | let _n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:88:14 + | +LL | let _n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:91:14 + | +LL | let _n = 1i128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:94:14 + | +LL | let _n = 1_isize >> BITS; + | ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:97:14 + | +LL | let _n = 1_usize >> BITS; + | ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:102:14 + | +LL | let _n = 1u8 + u8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:105:14 + | +LL | let _n = 1u16 + u16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:108:14 + | +LL | let _n = 1u32 + u32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:111:14 + | +LL | let _n = 1u64 + u64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:114:14 + | +LL | let _n = 1u128 + u128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:117:14 + | +LL | let _n = 1i8 + i8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:120:14 + | +LL | let _n = 1i16 + i16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:123:14 + | +LL | let _n = 1i32 + i32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:126:14 + | +LL | let _n = 1i64 + i64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:129:14 + | +LL | let _n = 1i128 + i128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:132:14 + | +LL | let _n = 1isize + isize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:135:14 + | +LL | let _n = 1usize + usize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:140:14 + | +LL | let _n = 1u8 - 5; + | ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:143:14 + | +LL | let _n = 1u16 - 5; + | ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:146:14 + | +LL | let _n = 1u32 - 5; + | ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:149:14 + | +LL | let _n = 1u64 - 5 ; + | ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:152:14 + | +LL | let _n = 1u128 - 5 ; + | ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:155:14 + | +LL | let _n = -5i8 - i8::MAX; + | ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:158:14 + | +LL | let _n = -5i16 - i16::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:161:14 + | +LL | let _n = -5i32 - i32::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:164:14 + | +LL | let _n = -5i64 - i64::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:167:14 + | +LL | let _n = -5i128 - i128::MAX; + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:170:14 + | +LL | let _n = -5isize - isize::MAX; + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:173:14 + | +LL | let _n = 1usize - 5; + | ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:178:14 + | +LL | let _n = u8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:181:14 + | +LL | let _n = u16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:184:14 + | +LL | let _n = u32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:187:14 + | +LL | let _n = u64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:190:14 + | +LL | let _n = u128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:193:14 + | +LL | let _n = i8::MAX * i8::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:196:14 + | +LL | let _n = i16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:199:14 + | +LL | let _n = i32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:202:14 + | +LL | let _n = i64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:205:14 + | +LL | let _n = i128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:208:14 + | +LL | let _n = isize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:211:14 + | +LL | let _n = usize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:216:14 + | +LL | let _n = 1u8 / 0; + | ^^^^^^^ attempt to divide `1_u8` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:217:15 + | +LL | let _n = &(1u8 / 0); + | ^^^^^^^^^ attempt to divide `1_u8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:219:14 + | +LL | let _n = 1u16 / 0; + | ^^^^^^^^ attempt to divide `1_u16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:220:15 + | +LL | let _n = &(1u16 / 0); + | ^^^^^^^^^^ attempt to divide `1_u16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:222:14 + | +LL | let _n = 1u32 / 0; + | ^^^^^^^^ attempt to divide `1_u32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:223:15 + | +LL | let _n = &(1u32 / 0); + | ^^^^^^^^^^ attempt to divide `1_u32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:225:14 + | +LL | let _n = 1u64 / 0; + | ^^^^^^^^ attempt to divide `1_u64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:226:15 + | +LL | let _n = &(1u64 / 0); + | ^^^^^^^^^^ attempt to divide `1_u64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:228:14 + | +LL | let _n = 1u128 / 0; + | ^^^^^^^^^ attempt to divide `1_u128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:229:15 + | +LL | let _n = &(1u128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_u128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:231:14 + | +LL | let _n = 1i8 / 0; + | ^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:232:15 + | +LL | let _n = &(1i8 / 0); + | ^^^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:234:14 + | +LL | let _n = 1i16 / 0; + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:235:15 + | +LL | let _n = &(1i16 / 0); + | ^^^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:237:14 + | +LL | let _n = 1i32 / 0; + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:238:15 + | +LL | let _n = &(1i32 / 0); + | ^^^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:240:14 + | +LL | let _n = 1i64 / 0; + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:241:15 + | +LL | let _n = &(1i64 / 0); + | ^^^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:243:14 + | +LL | let _n = 1i128 / 0; + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:244:15 + | +LL | let _n = &(1i128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:246:14 + | +LL | let _n = 1isize / 0; + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:247:15 + | +LL | let _n = &(1isize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:249:14 + | +LL | let _n = 1usize / 0; + | ^^^^^^^^^^ attempt to divide `1_usize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:250:15 + | +LL | let _n = &(1usize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_usize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:254:14 + | +LL | let _n = 1u8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:255:15 + | +LL | let _n = &(1u8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:257:14 + | +LL | let _n = 1u16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:258:15 + | +LL | let _n = &(1u16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:260:14 + | +LL | let _n = 1u32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:261:15 + | +LL | let _n = &(1u32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:263:14 + | +LL | let _n = 1u64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:264:15 + | +LL | let _n = &(1u64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:266:14 + | +LL | let _n = 1u128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:267:15 + | +LL | let _n = &(1u128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:269:14 + | +LL | let _n = 1i8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:270:15 + | +LL | let _n = &(1i8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:272:14 + | +LL | let _n = 1i16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:273:15 + | +LL | let _n = &(1i16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:275:14 + | +LL | let _n = 1i32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:276:15 + | +LL | let _n = &(1i32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:278:14 + | +LL | let _n = 1i64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:279:15 + | +LL | let _n = &(1i64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:281:14 + | +LL | let _n = 1i128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:282:15 + | +LL | let _n = &(1i128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:284:14 + | +LL | let _n = 1isize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:285:15 + | +LL | let _n = &(1isize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:287:14 + | +LL | let _n = 1usize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:288:15 + | +LL | let _n = &(1usize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:292:14 + | +LL | let _n = [1, 2, 3][4]; + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:293:15 + | +LL | let _n = &([1, 2, 3][4]); + | ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 170 previous errors + diff --git a/tests/ui/lint/lint-overflowing-ops.opt.stderr b/tests/ui/lint/lint-overflowing-ops.opt.stderr new file mode 100644 index 0000000000000..93fc19ce79e44 --- /dev/null +++ b/tests/ui/lint/lint-overflowing-ops.opt.stderr @@ -0,0 +1,1030 @@ +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:26:14 + | +LL | let _n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-overflowing-ops.rs:17:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:212:15 + | +LL | let _n = &(usize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:209:15 + | +LL | let _n = &(isize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:206:15 + | +LL | let _n = &(i128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:203:15 + | +LL | let _n = &(i64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:200:15 + | +LL | let _n = &(i32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:197:15 + | +LL | let _n = &(i16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:194:15 + | +LL | let _n = &(i8::MAX * i8::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:191:15 + | +LL | let _n = &(u128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:188:15 + | +LL | let _n = &(u64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:185:15 + | +LL | let _n = &(u32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:182:15 + | +LL | let _n = &(u16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:179:15 + | +LL | let _n = &(u8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:174:15 + | +LL | let _n = &(1usize - 5); + | ^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:171:15 + | +LL | let _n = &(-5isize - isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:168:15 + | +LL | let _n = &(-5i128 - i128::MAX); + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:165:15 + | +LL | let _n = &(-5i64 - i64::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:162:15 + | +LL | let _n = &(-5i32 - i32::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:159:15 + | +LL | let _n = &(-5i16 - i16::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:156:15 + | +LL | let _n = &(-5i8 - i8::MAX); + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:153:15 + | +LL | let _n = &(1u128 - 5); + | ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:150:15 + | +LL | let _n = &(1u64 - 5); + | ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:147:15 + | +LL | let _n = &(1u32 - 5); + | ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:144:15 + | +LL | let _n = &(1u16 - 5); + | ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:141:15 + | +LL | let _n = &(1u8 - 5); + | ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:136:15 + | +LL | let _n = &(1usize + usize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:133:15 + | +LL | let _n = &(1isize + isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:130:15 + | +LL | let _n = &(1i128 + i128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:127:15 + | +LL | let _n = &(1i64 + i64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:124:15 + | +LL | let _n = &(1i32 + i32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:121:15 + | +LL | let _n = &(1i16 + i16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:118:15 + | +LL | let _n = &(1i8 + i8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:115:15 + | +LL | let _n = &(1u128 + u128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:112:15 + | +LL | let _n = &(1u64 + u64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:109:15 + | +LL | let _n = &(1u32 + u32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:106:15 + | +LL | let _n = &(1u16 + u16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:103:15 + | +LL | let _n = &(1u8 + u8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:98:15 + | +LL | let _n = &(1_usize >> BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:95:15 + | +LL | let _n = &(1_isize >> BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:92:15 + | +LL | let _n = &(1i128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:89:15 + | +LL | let _n = &(1i64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:86:15 + | +LL | let _n = &(1i32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:83:15 + | +LL | let _n = &(1i16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:80:15 + | +LL | let _n = &(1i8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:77:15 + | +LL | let _n = &(1u128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:74:15 + | +LL | let _n = &(1u64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:71:15 + | +LL | let _n = &(1u32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:68:15 + | +LL | let _n = &(1u16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:65:15 + | +LL | let _n = &(1u8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:60:15 + | +LL | let _n = &(1_usize << BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:57:15 + | +LL | let _n = &(1_isize << BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:54:15 + | +LL | let _n = &(1i128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:51:15 + | +LL | let _n = &(1i64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:48:15 + | +LL | let _n = &(1i32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:45:15 + | +LL | let _n = &(1i16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:42:15 + | +LL | let _n = &(1i8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:39:15 + | +LL | let _n = &(1u128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:36:15 + | +LL | let _n = &(1u64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:33:15 + | +LL | let _n = &(1u32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:30:15 + | +LL | let _n = &(1u16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:27:15 + | +LL | let _n = &(1u8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:29:14 + | +LL | let _n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:32:14 + | +LL | let _n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:35:14 + | +LL | let _n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:38:14 + | +LL | let _n = 1u128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:41:14 + | +LL | let _n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:44:14 + | +LL | let _n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:47:14 + | +LL | let _n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:50:14 + | +LL | let _n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:53:14 + | +LL | let _n = 1i128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:56:14 + | +LL | let _n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:59:14 + | +LL | let _n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:64:14 + | +LL | let _n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:67:14 + | +LL | let _n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:70:14 + | +LL | let _n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:73:14 + | +LL | let _n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:76:14 + | +LL | let _n = 1u128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:79:14 + | +LL | let _n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:82:14 + | +LL | let _n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:85:14 + | +LL | let _n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:88:14 + | +LL | let _n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:91:14 + | +LL | let _n = 1i128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:94:14 + | +LL | let _n = 1_isize >> BITS; + | ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:97:14 + | +LL | let _n = 1_usize >> BITS; + | ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:102:14 + | +LL | let _n = 1u8 + u8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:105:14 + | +LL | let _n = 1u16 + u16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:108:14 + | +LL | let _n = 1u32 + u32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:111:14 + | +LL | let _n = 1u64 + u64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:114:14 + | +LL | let _n = 1u128 + u128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:117:14 + | +LL | let _n = 1i8 + i8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:120:14 + | +LL | let _n = 1i16 + i16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:123:14 + | +LL | let _n = 1i32 + i32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:126:14 + | +LL | let _n = 1i64 + i64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:129:14 + | +LL | let _n = 1i128 + i128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:132:14 + | +LL | let _n = 1isize + isize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:135:14 + | +LL | let _n = 1usize + usize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:140:14 + | +LL | let _n = 1u8 - 5; + | ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:143:14 + | +LL | let _n = 1u16 - 5; + | ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:146:14 + | +LL | let _n = 1u32 - 5; + | ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:149:14 + | +LL | let _n = 1u64 - 5 ; + | ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:152:14 + | +LL | let _n = 1u128 - 5 ; + | ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:155:14 + | +LL | let _n = -5i8 - i8::MAX; + | ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:158:14 + | +LL | let _n = -5i16 - i16::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:161:14 + | +LL | let _n = -5i32 - i32::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:164:14 + | +LL | let _n = -5i64 - i64::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:167:14 + | +LL | let _n = -5i128 - i128::MAX; + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:170:14 + | +LL | let _n = -5isize - isize::MAX; + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:173:14 + | +LL | let _n = 1usize - 5; + | ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:178:14 + | +LL | let _n = u8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:181:14 + | +LL | let _n = u16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:184:14 + | +LL | let _n = u32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:187:14 + | +LL | let _n = u64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:190:14 + | +LL | let _n = u128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:193:14 + | +LL | let _n = i8::MAX * i8::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:196:14 + | +LL | let _n = i16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:199:14 + | +LL | let _n = i32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:202:14 + | +LL | let _n = i64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:205:14 + | +LL | let _n = i128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:208:14 + | +LL | let _n = isize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:211:14 + | +LL | let _n = usize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:216:14 + | +LL | let _n = 1u8 / 0; + | ^^^^^^^ attempt to divide `1_u8` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:217:15 + | +LL | let _n = &(1u8 / 0); + | ^^^^^^^^^ attempt to divide `1_u8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:219:14 + | +LL | let _n = 1u16 / 0; + | ^^^^^^^^ attempt to divide `1_u16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:220:15 + | +LL | let _n = &(1u16 / 0); + | ^^^^^^^^^^ attempt to divide `1_u16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:222:14 + | +LL | let _n = 1u32 / 0; + | ^^^^^^^^ attempt to divide `1_u32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:223:15 + | +LL | let _n = &(1u32 / 0); + | ^^^^^^^^^^ attempt to divide `1_u32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:225:14 + | +LL | let _n = 1u64 / 0; + | ^^^^^^^^ attempt to divide `1_u64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:226:15 + | +LL | let _n = &(1u64 / 0); + | ^^^^^^^^^^ attempt to divide `1_u64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:228:14 + | +LL | let _n = 1u128 / 0; + | ^^^^^^^^^ attempt to divide `1_u128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:229:15 + | +LL | let _n = &(1u128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_u128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:231:14 + | +LL | let _n = 1i8 / 0; + | ^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:232:15 + | +LL | let _n = &(1i8 / 0); + | ^^^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:234:14 + | +LL | let _n = 1i16 / 0; + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:235:15 + | +LL | let _n = &(1i16 / 0); + | ^^^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:237:14 + | +LL | let _n = 1i32 / 0; + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:238:15 + | +LL | let _n = &(1i32 / 0); + | ^^^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:240:14 + | +LL | let _n = 1i64 / 0; + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:241:15 + | +LL | let _n = &(1i64 / 0); + | ^^^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:243:14 + | +LL | let _n = 1i128 / 0; + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:244:15 + | +LL | let _n = &(1i128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:246:14 + | +LL | let _n = 1isize / 0; + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:247:15 + | +LL | let _n = &(1isize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:249:14 + | +LL | let _n = 1usize / 0; + | ^^^^^^^^^^ attempt to divide `1_usize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:250:15 + | +LL | let _n = &(1usize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_usize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:254:14 + | +LL | let _n = 1u8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:255:15 + | +LL | let _n = &(1u8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:257:14 + | +LL | let _n = 1u16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:258:15 + | +LL | let _n = &(1u16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:260:14 + | +LL | let _n = 1u32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:261:15 + | +LL | let _n = &(1u32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:263:14 + | +LL | let _n = 1u64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:264:15 + | +LL | let _n = &(1u64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:266:14 + | +LL | let _n = 1u128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:267:15 + | +LL | let _n = &(1u128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:269:14 + | +LL | let _n = 1i8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:270:15 + | +LL | let _n = &(1i8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:272:14 + | +LL | let _n = 1i16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:273:15 + | +LL | let _n = &(1i16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:275:14 + | +LL | let _n = 1i32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:276:15 + | +LL | let _n = &(1i32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:278:14 + | +LL | let _n = 1i64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:279:15 + | +LL | let _n = &(1i64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:281:14 + | +LL | let _n = 1i128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:282:15 + | +LL | let _n = &(1i128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:284:14 + | +LL | let _n = 1isize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:285:15 + | +LL | let _n = &(1isize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:287:14 + | +LL | let _n = 1usize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:288:15 + | +LL | let _n = &(1usize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:292:14 + | +LL | let _n = [1, 2, 3][4]; + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:293:15 + | +LL | let _n = &([1, 2, 3][4]); + | ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 170 previous errors + diff --git a/tests/ui/lint/lint-overflowing-ops.opt_with_overflow_checks.stderr b/tests/ui/lint/lint-overflowing-ops.opt_with_overflow_checks.stderr new file mode 100644 index 0000000000000..93fc19ce79e44 --- /dev/null +++ b/tests/ui/lint/lint-overflowing-ops.opt_with_overflow_checks.stderr @@ -0,0 +1,1030 @@ +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:26:14 + | +LL | let _n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-overflowing-ops.rs:17:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:212:15 + | +LL | let _n = &(usize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:209:15 + | +LL | let _n = &(isize::MAX * 5); + | ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:206:15 + | +LL | let _n = &(i128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:203:15 + | +LL | let _n = &(i64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:200:15 + | +LL | let _n = &(i32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:197:15 + | +LL | let _n = &(i16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:194:15 + | +LL | let _n = &(i8::MAX * i8::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:191:15 + | +LL | let _n = &(u128::MAX * 5); + | ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:188:15 + | +LL | let _n = &(u64::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:185:15 + | +LL | let _n = &(u32::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:182:15 + | +LL | let _n = &(u16::MAX * 5); + | ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:179:15 + | +LL | let _n = &(u8::MAX * 5); + | ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:174:15 + | +LL | let _n = &(1usize - 5); + | ^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:171:15 + | +LL | let _n = &(-5isize - isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:168:15 + | +LL | let _n = &(-5i128 - i128::MAX); + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:165:15 + | +LL | let _n = &(-5i64 - i64::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:162:15 + | +LL | let _n = &(-5i32 - i32::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:159:15 + | +LL | let _n = &(-5i16 - i16::MAX); + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:156:15 + | +LL | let _n = &(-5i8 - i8::MAX); + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:153:15 + | +LL | let _n = &(1u128 - 5); + | ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:150:15 + | +LL | let _n = &(1u64 - 5); + | ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:147:15 + | +LL | let _n = &(1u32 - 5); + | ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:144:15 + | +LL | let _n = &(1u16 - 5); + | ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:141:15 + | +LL | let _n = &(1u8 - 5); + | ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:136:15 + | +LL | let _n = &(1usize + usize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:133:15 + | +LL | let _n = &(1isize + isize::MAX); + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:130:15 + | +LL | let _n = &(1i128 + i128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:127:15 + | +LL | let _n = &(1i64 + i64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:124:15 + | +LL | let _n = &(1i32 + i32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:121:15 + | +LL | let _n = &(1i16 + i16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:118:15 + | +LL | let _n = &(1i8 + i8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:115:15 + | +LL | let _n = &(1u128 + u128::MAX); + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:112:15 + | +LL | let _n = &(1u64 + u64::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:109:15 + | +LL | let _n = &(1u32 + u32::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:106:15 + | +LL | let _n = &(1u16 + u16::MAX); + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:103:15 + | +LL | let _n = &(1u8 + u8::MAX); + | ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:98:15 + | +LL | let _n = &(1_usize >> BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:95:15 + | +LL | let _n = &(1_isize >> BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:92:15 + | +LL | let _n = &(1i128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:89:15 + | +LL | let _n = &(1i64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:86:15 + | +LL | let _n = &(1i32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:83:15 + | +LL | let _n = &(1i16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:80:15 + | +LL | let _n = &(1i8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:77:15 + | +LL | let _n = &(1u128 >> 128); + | ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:74:15 + | +LL | let _n = &(1u64 >> 64); + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:71:15 + | +LL | let _n = &(1u32 >> 32); + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:68:15 + | +LL | let _n = &(1u16 >> 16); + | ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:65:15 + | +LL | let _n = &(1u8 >> 8); + | ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:60:15 + | +LL | let _n = &(1_usize << BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:57:15 + | +LL | let _n = &(1_isize << BITS); + | ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:54:15 + | +LL | let _n = &(1i128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:51:15 + | +LL | let _n = &(1i64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:48:15 + | +LL | let _n = &(1i32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:45:15 + | +LL | let _n = &(1i16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:42:15 + | +LL | let _n = &(1i8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:39:15 + | +LL | let _n = &(1u128 << 128); + | ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:36:15 + | +LL | let _n = &(1u64 << 64); + | ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:33:15 + | +LL | let _n = &(1u32 << 32); + | ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:30:15 + | +LL | let _n = &(1u16 << 16); + | ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:27:15 + | +LL | let _n = &(1u8 << 8); + | ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:29:14 + | +LL | let _n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:32:14 + | +LL | let _n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:35:14 + | +LL | let _n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:38:14 + | +LL | let _n = 1u128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:41:14 + | +LL | let _n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:44:14 + | +LL | let _n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:47:14 + | +LL | let _n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:50:14 + | +LL | let _n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:53:14 + | +LL | let _n = 1i128 << 128; + | ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:56:14 + | +LL | let _n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:59:14 + | +LL | let _n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:64:14 + | +LL | let _n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:67:14 + | +LL | let _n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:70:14 + | +LL | let _n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:73:14 + | +LL | let _n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:76:14 + | +LL | let _n = 1u128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:79:14 + | +LL | let _n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:82:14 + | +LL | let _n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:85:14 + | +LL | let _n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:88:14 + | +LL | let _n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:91:14 + | +LL | let _n = 1i128 >> 128; + | ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:94:14 + | +LL | let _n = 1_isize >> BITS; + | ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:97:14 + | +LL | let _n = 1_usize >> BITS; + | ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:102:14 + | +LL | let _n = 1u8 + u8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:105:14 + | +LL | let _n = 1u16 + u16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:108:14 + | +LL | let _n = 1u32 + u32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:111:14 + | +LL | let _n = 1u64 + u64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:114:14 + | +LL | let _n = 1u128 + u128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:117:14 + | +LL | let _n = 1i8 + i8::MAX; + | ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:120:14 + | +LL | let _n = 1i16 + i16::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:123:14 + | +LL | let _n = 1i32 + i32::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:126:14 + | +LL | let _n = 1i64 + i64::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:129:14 + | +LL | let _n = 1i128 + i128::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:132:14 + | +LL | let _n = 1isize + isize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:135:14 + | +LL | let _n = 1usize + usize::MAX; + | ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:140:14 + | +LL | let _n = 1u8 - 5; + | ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:143:14 + | +LL | let _n = 1u16 - 5; + | ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:146:14 + | +LL | let _n = 1u32 - 5; + | ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:149:14 + | +LL | let _n = 1u64 - 5 ; + | ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:152:14 + | +LL | let _n = 1u128 - 5 ; + | ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:155:14 + | +LL | let _n = -5i8 - i8::MAX; + | ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:158:14 + | +LL | let _n = -5i16 - i16::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:161:14 + | +LL | let _n = -5i32 - i32::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:164:14 + | +LL | let _n = -5i64 - i64::MAX; + | ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:167:14 + | +LL | let _n = -5i128 - i128::MAX; + | ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:170:14 + | +LL | let _n = -5isize - isize::MAX; + | ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:173:14 + | +LL | let _n = 1usize - 5; + | ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:178:14 + | +LL | let _n = u8::MAX * 5; + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:181:14 + | +LL | let _n = u16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:184:14 + | +LL | let _n = u32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:187:14 + | +LL | let _n = u64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:190:14 + | +LL | let _n = u128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:193:14 + | +LL | let _n = i8::MAX * i8::MAX; + | ^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:196:14 + | +LL | let _n = i16::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:199:14 + | +LL | let _n = i32::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:202:14 + | +LL | let _n = i64::MAX * 5; + | ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:205:14 + | +LL | let _n = i128::MAX * 5; + | ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:208:14 + | +LL | let _n = isize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-overflowing-ops.rs:211:14 + | +LL | let _n = usize::MAX * 5; + | ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:216:14 + | +LL | let _n = 1u8 / 0; + | ^^^^^^^ attempt to divide `1_u8` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:217:15 + | +LL | let _n = &(1u8 / 0); + | ^^^^^^^^^ attempt to divide `1_u8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:219:14 + | +LL | let _n = 1u16 / 0; + | ^^^^^^^^ attempt to divide `1_u16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:220:15 + | +LL | let _n = &(1u16 / 0); + | ^^^^^^^^^^ attempt to divide `1_u16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:222:14 + | +LL | let _n = 1u32 / 0; + | ^^^^^^^^ attempt to divide `1_u32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:223:15 + | +LL | let _n = &(1u32 / 0); + | ^^^^^^^^^^ attempt to divide `1_u32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:225:14 + | +LL | let _n = 1u64 / 0; + | ^^^^^^^^ attempt to divide `1_u64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:226:15 + | +LL | let _n = &(1u64 / 0); + | ^^^^^^^^^^ attempt to divide `1_u64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:228:14 + | +LL | let _n = 1u128 / 0; + | ^^^^^^^^^ attempt to divide `1_u128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:229:15 + | +LL | let _n = &(1u128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_u128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:231:14 + | +LL | let _n = 1i8 / 0; + | ^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:232:15 + | +LL | let _n = &(1i8 / 0); + | ^^^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:234:14 + | +LL | let _n = 1i16 / 0; + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:235:15 + | +LL | let _n = &(1i16 / 0); + | ^^^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:237:14 + | +LL | let _n = 1i32 / 0; + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:238:15 + | +LL | let _n = &(1i32 / 0); + | ^^^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:240:14 + | +LL | let _n = 1i64 / 0; + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:241:15 + | +LL | let _n = &(1i64 / 0); + | ^^^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:243:14 + | +LL | let _n = 1i128 / 0; + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:244:15 + | +LL | let _n = &(1i128 / 0); + | ^^^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:246:14 + | +LL | let _n = 1isize / 0; + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:247:15 + | +LL | let _n = &(1isize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:249:14 + | +LL | let _n = 1usize / 0; + | ^^^^^^^^^^ attempt to divide `1_usize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:250:15 + | +LL | let _n = &(1usize / 0); + | ^^^^^^^^^^^^ attempt to divide `1_usize` by zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:254:14 + | +LL | let _n = 1u8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:255:15 + | +LL | let _n = &(1u8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:257:14 + | +LL | let _n = 1u16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:258:15 + | +LL | let _n = &(1u16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:260:14 + | +LL | let _n = 1u32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:261:15 + | +LL | let _n = &(1u32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:263:14 + | +LL | let _n = 1u64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:264:15 + | +LL | let _n = &(1u64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:266:14 + | +LL | let _n = 1u128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:267:15 + | +LL | let _n = &(1u128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:269:14 + | +LL | let _n = 1i8 % 0; + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:270:15 + | +LL | let _n = &(1i8 % 0); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:272:14 + | +LL | let _n = 1i16 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:273:15 + | +LL | let _n = &(1i16 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:275:14 + | +LL | let _n = 1i32 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:276:15 + | +LL | let _n = &(1i32 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:278:14 + | +LL | let _n = 1i64 % 0; + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:279:15 + | +LL | let _n = &(1i64 % 0); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:281:14 + | +LL | let _n = 1i128 % 0; + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:282:15 + | +LL | let _n = &(1i128 % 0); + | ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:284:14 + | +LL | let _n = 1isize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:285:15 + | +LL | let _n = &(1isize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:287:14 + | +LL | let _n = 1usize % 0; + | ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:288:15 + | +LL | let _n = &(1usize % 0); + | ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:292:14 + | +LL | let _n = [1, 2, 3][4]; + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: this operation will panic at runtime + --> $DIR/lint-overflowing-ops.rs:293:15 + | +LL | let _n = &([1, 2, 3][4]); + | ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to 170 previous errors + diff --git a/tests/ui/lint/lint-overflowing-ops.rs b/tests/ui/lint/lint-overflowing-ops.rs new file mode 100644 index 0000000000000..e64c210badeff --- /dev/null +++ b/tests/ui/lint/lint-overflowing-ops.rs @@ -0,0 +1,294 @@ +// Tests that overflowing or bound-exceeding operations +// are correclty linted including when they are const promoted + +// We are using "-Z deduplicate-diagnostics=yes" because different +// build configurations emit different number of duplicate diagnostics +// and this flag lets us test them all with a single .rs file like this + +//@ revisions: noopt opt opt_with_overflow_checks +//@ [noopt]compile-flags: -C opt-level=0 -Z deduplicate-diagnostics=yes +//@ [opt]compile-flags: -O +//@ [opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O -Z deduplicate-diagnostics=yes +//@ build-fail +//@ ignore-pass (test tests codegen-time behaviour) +//@ normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which" +//@ normalize-stderr-test "shift right by `(64|32)_usize`, which" -> "shift right by `%BITS%`, which" + +#![deny(arithmetic_overflow)] + +#[cfg(target_pointer_width = "32")] +const BITS: usize = 32; +#[cfg(target_pointer_width = "64")] +const BITS: usize = 64; + +fn main() { + // Shift left + let _n = 1u8 << 8; //~ ERROR: arithmetic operation will overflow + let _n = &(1u8 << 8); //~ ERROR: arithmetic operation will overflow + + let _n = 1u16 << 16; //~ ERROR: arithmetic operation will overflow + let _n = &(1u16 << 16); //~ ERROR: arithmetic operation will overflow + + let _n = 1u32 << 32; //~ ERROR: arithmetic operation will overflow + let _n = &(1u32 << 32); //~ ERROR: arithmetic operation will overflow + + let _n = 1u64 << 64; //~ ERROR: arithmetic operation will overflow + let _n = &(1u64 << 64); //~ ERROR: arithmetic operation will overflow + + let _n = 1u128 << 128; //~ ERROR: arithmetic operation will overflow + let _n = &(1u128 << 128); //~ ERROR: arithmetic operation will overflow + + let _n = 1i8 << 8; //~ ERROR: arithmetic operation will overflow + let _n = &(1i8 << 8); //~ ERROR: arithmetic operation will overflow + + let _n = 1i16 << 16; //~ ERROR: arithmetic operation will overflow + let _n = &(1i16 << 16); //~ ERROR: arithmetic operation will overflow + + let _n = 1i32 << 32; //~ ERROR: arithmetic operation will overflow + let _n = &(1i32 << 32); //~ ERROR: arithmetic operation will overflow + + let _n = 1i64 << 64; //~ ERROR: arithmetic operation will overflow + let _n = &(1i64 << 64); //~ ERROR: arithmetic operation will overflow + + let _n = 1i128 << 128; //~ ERROR: arithmetic operation will overflow + let _n = &(1i128 << 128); //~ ERROR: arithmetic operation will overflow + + let _n = 1_isize << BITS; //~ ERROR: arithmetic operation will overflow + let _n = &(1_isize << BITS); //~ ERROR: arithmetic operation will overflow + + let _n = 1_usize << BITS; //~ ERROR: arithmetic operation will overflow + let _n = &(1_usize << BITS); //~ ERROR: arithmetic operation will overflow + + + // Shift right + let _n = 1u8 >> 8; //~ ERROR: arithmetic operation will overflow + let _n = &(1u8 >> 8); //~ ERROR: arithmetic operation will overflow + + let _n = 1u16 >> 16; //~ ERROR: arithmetic operation will overflow + let _n = &(1u16 >> 16); //~ ERROR: arithmetic operation will overflow + + let _n = 1u32 >> 32; //~ ERROR: arithmetic operation will overflow + let _n = &(1u32 >> 32); //~ ERROR: arithmetic operation will overflow + + let _n = 1u64 >> 64; //~ ERROR: arithmetic operation will overflow + let _n = &(1u64 >> 64); //~ ERROR: arithmetic operation will overflow + + let _n = 1u128 >> 128; //~ ERROR: arithmetic operation will overflow + let _n = &(1u128 >> 128); //~ ERROR: arithmetic operation will overflow + + let _n = 1i8 >> 8; //~ ERROR: arithmetic operation will overflow + let _n = &(1i8 >> 8); //~ ERROR: arithmetic operation will overflow + + let _n = 1i16 >> 16; //~ ERROR: arithmetic operation will overflow + let _n = &(1i16 >> 16); //~ ERROR: arithmetic operation will overflow + + let _n = 1i32 >> 32; //~ ERROR: arithmetic operation will overflow + let _n = &(1i32 >> 32); //~ ERROR: arithmetic operation will overflow + + let _n = 1i64 >> 64; //~ ERROR: arithmetic operation will overflow + let _n = &(1i64 >> 64); //~ ERROR: arithmetic operation will overflow + + let _n = 1i128 >> 128; //~ ERROR: arithmetic operation will overflow + let _n = &(1i128 >> 128); //~ ERROR: arithmetic operation will overflow + + let _n = 1_isize >> BITS; //~ ERROR: arithmetic operation will overflow + let _n = &(1_isize >> BITS); //~ ERROR: arithmetic operation will overflow + + let _n = 1_usize >> BITS; //~ ERROR: arithmetic operation will overflow + let _n = &(1_usize >> BITS); //~ ERROR: arithmetic operation will overflow + + + // Addition + let _n = 1u8 + u8::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1u8 + u8::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1u16 + u16::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1u16 + u16::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1u32 + u32::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1u32 + u32::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1u64 + u64::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1u64 + u64::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1u128 + u128::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1u128 + u128::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1i8 + i8::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1i8 + i8::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1i16 + i16::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1i16 + i16::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1i32 + i32::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1i32 + i32::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1i64 + i64::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1i64 + i64::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1i128 + i128::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1i128 + i128::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1isize + isize::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1isize + isize::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1usize + usize::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(1usize + usize::MAX); //~ ERROR: arithmetic operation will overflow + + + // Subtraction + let _n = 1u8 - 5; //~ ERROR: arithmetic operation will overflow + let _n = &(1u8 - 5); //~ ERROR: arithmetic operation will overflow + + let _n = 1u16 - 5; //~ ERROR: arithmetic operation will overflow + let _n = &(1u16 - 5); //~ ERROR: arithmetic operation will overflow + + let _n = 1u32 - 5; //~ ERROR: arithmetic operation will overflow + let _n = &(1u32 - 5); //~ ERROR: arithmetic operation will overflow + + let _n = 1u64 - 5 ; //~ ERROR: arithmetic operation will overflow + let _n = &(1u64 - 5); //~ ERROR: arithmetic operation will overflow + + let _n = 1u128 - 5 ; //~ ERROR: arithmetic operation will overflow + let _n = &(1u128 - 5); //~ ERROR: arithmetic operation will overflow + + let _n = -5i8 - i8::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(-5i8 - i8::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = -5i16 - i16::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(-5i16 - i16::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = -5i32 - i32::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(-5i32 - i32::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = -5i64 - i64::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(-5i64 - i64::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = -5i128 - i128::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(-5i128 - i128::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = -5isize - isize::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(-5isize - isize::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = 1usize - 5; //~ ERROR: arithmetic operation will overflow + let _n = &(1usize - 5); //~ ERROR: arithmetic operation will overflow + + + // Multiplication + let _n = u8::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(u8::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = u16::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(u16::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = u32::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(u32::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = u64::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(u64::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = u128::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(u128::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = i8::MAX * i8::MAX; //~ ERROR: arithmetic operation will overflow + let _n = &(i8::MAX * i8::MAX); //~ ERROR: arithmetic operation will overflow + + let _n = i16::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(i16::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = i32::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(i32::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = i64::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(i64::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = i128::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(i128::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = isize::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(isize::MAX * 5); //~ ERROR: arithmetic operation will overflow + + let _n = usize::MAX * 5; //~ ERROR: arithmetic operation will overflow + let _n = &(usize::MAX * 5); //~ ERROR: arithmetic operation will overflow + + + // Division + let _n = 1u8 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u8 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1u16 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u16 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1u32 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u32 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1u64 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u64 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1u128 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u128 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i8 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i8 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i16 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i16 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i32 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i32 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i64 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i64 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i128 / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i128 / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1isize / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1isize / 0); //~ ERROR: this operation will panic at runtime + + let _n = 1usize / 0; //~ ERROR: this operation will panic at runtime + let _n = &(1usize / 0); //~ ERROR: this operation will panic at runtime + + + // Modulus + let _n = 1u8 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u8 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1u16 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u16 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1u32 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u32 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1u64 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u64 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1u128 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1u128 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i8 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i8 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i16 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i16 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i32 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i32 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i64 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i64 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1i128 % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1i128 % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1isize % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1isize % 0); //~ ERROR: this operation will panic at runtime + + let _n = 1usize % 0; //~ ERROR: this operation will panic at runtime + let _n = &(1usize % 0); //~ ERROR: this operation will panic at runtime + + + // Out of bounds access + let _n = [1, 2, 3][4]; //~ ERROR: this operation will panic at runtime + let _n = &([1, 2, 3][4]); //~ ERROR: this operation will panic at runtime +} diff --git a/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs b/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs deleted file mode 100644 index 7004c9a366509..0000000000000 --- a/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-pass - -//@ compile-flags: -O - -fn main() { - let x = &(0u32 - 1); - assert_eq!(*x, u32::MAX) -} From 340f8aac7e2da164134338986b46fb4a26fe185b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Feb 2024 14:27:08 +0100 Subject: [PATCH 32/40] const_mut_refs: allow mutable refs to statics --- .../src/transform/check_consts/check.rs | 37 ++++++++++++++-- .../src/transform/check_consts/qualifs.rs | 24 +++++++++++ .../const-ref-to-static-linux-vtable.rs | 43 +++++++++++++++++++ .../ui/consts/issue-17718-const-bad-values.rs | 1 + .../issue-17718-const-bad-values.stderr | 12 +++++- tests/ui/consts/miri_unleashed/box.stderr | 2 +- .../mutable_references_err.32bit.stderr | 2 +- .../mutable_references_err.64bit.stderr | 2 +- tests/ui/consts/mut-ptr-to-static.rs | 40 +++++++++++++++++ tests/ui/error-codes/E0017.rs | 8 ++-- tests/ui/error-codes/E0017.stderr | 36 +++------------- tests/ui/error-codes/E0388.rs | 4 +- tests/ui/error-codes/E0388.stderr | 24 +++-------- 13 files changed, 173 insertions(+), 62 deletions(-) create mode 100644 tests/ui/consts/const-ref-to-static-linux-vtable.rs create mode 100644 tests/ui/consts/mut-ptr-to-static.rs diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 96c9e740568cc..a3c4734f0a391 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -344,7 +344,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { visitor.visit_ty(ty); } - fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) { + fn check_mut_borrow(&mut self, place: &Place<'_>, kind: hir::BorrowKind) { match self.const_kind() { // In a const fn all borrows are transient or point to the places given via // references in the arguments (so we already checked them with @@ -355,10 +355,19 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // to mutable memory. hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)), _ => { + // For indirect places, we are not creating a new permanent borrow, it's just as + // transient as the already existing one. For reborrowing references this is handled + // at the top of `visit_rvalue`, but for raw pointers we handle it here. + // Pointers/references to `static mut` and cases where the `*` is not the first + // projection also end up here. // Locals with StorageDead do not live beyond the evaluation and can // thus safely be borrowed without being able to be leaked to the final // value of the constant. - if self.local_has_storage_dead(local) { + // Note: This is only sound if every local that has a `StorageDead` has a + // `StorageDead` in every control flow path leading to a `return` terminator. + // The good news is that interning will detect if any unexpected mutable + // pointer slips through. + if place.is_indirect() || self.local_has_storage_dead(place.local) { self.check_op(ops::TransientMutBorrow(kind)); } else { self.check_op(ops::MutBorrow(kind)); @@ -390,6 +399,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location); // Special-case reborrows to be more like a copy of a reference. + // FIXME: this does not actually handle all reborrows. It only detects cases where `*` is the outermost + // projection of the borrowed place, it skips deref'ing raw pointers and it skips `static`. + // All those cases are handled below with shared/mutable borrows. + // Once `const_mut_refs` is stable, we should be able to entirely remove this special case. + // (`const_refs_to_cell` is not needed, we already allow all borrows of indirect places anyway.) match *rvalue { Rvalue::Ref(_, kind, place) => { if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) { @@ -460,7 +474,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if !is_allowed { self.check_mut_borrow( - place.local, + place, if matches!(rvalue, Rvalue::Ref(..)) { hir::BorrowKind::Ref } else { @@ -478,7 +492,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { place.as_ref(), ); - if borrowed_place_has_mut_interior { + // If the place is indirect, this is basically a reborrow. We have a reborrow + // special case above, but for raw pointers and pointers/references to `static` and + // when the `*` is not the first projection, `place_as_reborrow` does not recognize + // them as such, so we end up here. This should probably be considered a + // `TransientCellBorrow` (we consider the equivalent mutable case a + // `TransientMutBorrow`), but such reborrows got accidentally stabilized already and + // it is too much of a breaking change to take back. + if borrowed_place_has_mut_interior && !place.is_indirect() { match self.const_kind() { // In a const fn all borrows are transient or point to the places given via // references in the arguments (so we already checked them with @@ -495,6 +516,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // final value. // Note: This is only sound if every local that has a `StorageDead` has a // `StorageDead` in every control flow path leading to a `return` terminator. + // The good news is that interning will detect if any unexpected mutable + // pointer slips through. if self.local_has_storage_dead(place.local) { self.check_op(ops::TransientCellBorrow); } else { @@ -948,6 +971,12 @@ fn place_as_reborrow<'tcx>( ) -> Option> { match place.as_ref().last_projection() { Some((place_base, ProjectionElem::Deref)) => { + // FIXME: why do statics and raw pointers get excluded here? This makes + // some code involving mutable pointers unstable, but it is unclear + // why that code is treated differently from mutable references. + // Once TransientMutBorrow and TransientCellBorrow are stable, + // this can probably be cleaned up without any behavioral changes. + // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const` // that points to the allocation for the static. Don't treat these as reborrows. if body.local_decls[place_base.local].is_ref_to_static() { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 67fef20807910..7eb3c181d6958 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -74,6 +74,13 @@ pub trait Qualif { adt: AdtDef<'tcx>, args: GenericArgsRef<'tcx>, ) -> bool; + + /// Returns `true` if this `Qualif` behaves sructurally for pointers and references: + /// the pointer/reference qualifies if and only if the pointee qualifies. + /// + /// (This is currently `false` for all our instances, but that may change in the future. Also, + /// by keeping it abstract, the handling of `Deref` in `in_place` becomes more clear.) + fn deref_structural<'tcx>(cx: &ConstCx<'_, 'tcx>) -> bool; } /// Constant containing interior mutability (`UnsafeCell`). @@ -103,6 +110,10 @@ impl Qualif for HasMutInterior { // It arises structurally for all other types. adt.is_unsafe_cell() } + + fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { + false + } } /// Constant containing an ADT that implements `Drop`. @@ -131,6 +142,10 @@ impl Qualif for NeedsDrop { ) -> bool { adt.has_dtor(cx.tcx) } + + fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { + false + } } /// Constant containing an ADT that implements non-const `Drop`. @@ -210,6 +225,10 @@ impl Qualif for NeedsNonConstDrop { ) -> bool { adt.has_non_const_dtor(cx.tcx) } + + fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { + false + } } // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. @@ -303,6 +322,11 @@ where return false; } + if matches!(elem, ProjectionElem::Deref) && !Q::deref_structural(cx) { + // We have to assume that this qualifies. + return true; + } + place = place_base; } diff --git a/tests/ui/consts/const-ref-to-static-linux-vtable.rs b/tests/ui/consts/const-ref-to-static-linux-vtable.rs new file mode 100644 index 0000000000000..9325746c1e725 --- /dev/null +++ b/tests/ui/consts/const-ref-to-static-linux-vtable.rs @@ -0,0 +1,43 @@ +//@check-pass +//! This is the reduced version of the "Linux kernel vtable" use-case. +#![feature(const_mut_refs, const_refs_to_static)] +use std::ptr::addr_of_mut; + +#[repr(C)] +struct ThisModule(i32); + +trait Module { + const THIS_MODULE_PTR: *mut ThisModule; +} + +struct MyModule; + +// Generated by a macro. +extern "C" { + static mut THIS_MODULE: ThisModule; +} + +// Generated by a macro. +impl Module for MyModule { + const THIS_MODULE_PTR: *mut ThisModule = unsafe { addr_of_mut!(THIS_MODULE) }; +} + +struct Vtable { + module: *mut ThisModule, + foo_fn: fn(*mut ()) -> i32, +} + +trait Foo { + type Mod: Module; + + fn foo(&mut self) -> i32; +} + +fn generate_vtable() -> &'static Vtable { + &Vtable { + module: T::Mod::THIS_MODULE_PTR, + foo_fn: |ptr| unsafe { &mut *ptr.cast::() }.foo(), + } +} + +fn main() {} diff --git a/tests/ui/consts/issue-17718-const-bad-values.rs b/tests/ui/consts/issue-17718-const-bad-values.rs index 0299bfef1b49a..e112a346b656d 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.rs +++ b/tests/ui/consts/issue-17718-const-bad-values.rs @@ -6,5 +6,6 @@ const C1: &'static mut [usize] = &mut []; static mut S: usize = 3; const C2: &'static mut usize = unsafe { &mut S }; //~^ ERROR: referencing statics in constants +//~| ERROR: mutable references are not allowed fn main() {} diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr index 57fcb1c7e9a52..e755e5601a87d 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.stderr +++ b/tests/ui/consts/issue-17718-const-bad-values.stderr @@ -16,7 +16,17 @@ LL | const C2: &'static mut usize = unsafe { &mut S }; = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable. = help: to fix this, the value can be extracted to a `const` and then used. -error: aborting due to 2 previous errors +error[E0658]: mutable references are not allowed in constants + --> $DIR/issue-17718-const-bad-values.rs:7:41 + | +LL | const C2: &'static mut usize = unsafe { &mut S }; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0658, E0764. For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/miri_unleashed/box.stderr b/tests/ui/consts/miri_unleashed/box.stderr index 5229f1e50cd44..a0518c99cda56 100644 --- a/tests/ui/consts/miri_unleashed/box.stderr +++ b/tests/ui/consts/miri_unleashed/box.stderr @@ -16,7 +16,7 @@ help: skipping check for `const_mut_refs` feature | LL | &mut *(Box::new(0)) | ^^^^^^^^^^^^^^^^^^^ -help: skipping check that does not even have a feature gate +help: skipping check for `const_mut_refs` feature --> $DIR/box.rs:8:5 | LL | &mut *(Box::new(0)) diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 401cf46710afd..82739c08cf1bd 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -114,7 +114,7 @@ help: skipping check for `const_refs_to_static` feature | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^ -help: skipping check that does not even have a feature gate +help: skipping check for `const_mut_refs` feature --> $DIR/mutable_references_err.rs:32:35 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index 0eb01f5b77388..844483d88e934 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -114,7 +114,7 @@ help: skipping check for `const_refs_to_static` feature | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^ -help: skipping check that does not even have a feature gate +help: skipping check for `const_mut_refs` feature --> $DIR/mutable_references_err.rs:32:35 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; diff --git a/tests/ui/consts/mut-ptr-to-static.rs b/tests/ui/consts/mut-ptr-to-static.rs new file mode 100644 index 0000000000000..d8a788bb37d1b --- /dev/null +++ b/tests/ui/consts/mut-ptr-to-static.rs @@ -0,0 +1,40 @@ +//@run-pass +#![feature(const_mut_refs)] +#![feature(sync_unsafe_cell)] + +use std::cell::SyncUnsafeCell; +use std::ptr; + +#[repr(C)] +struct SyncPtr { + foo: *mut u32, +} +unsafe impl Sync for SyncPtr {} + +static mut STATIC: u32 = 42; + +static INTERIOR_MUTABLE_STATIC: SyncUnsafeCell = SyncUnsafeCell::new(42); + +// A static that mutably points to STATIC. +static PTR: SyncPtr = SyncPtr { + foo: unsafe { ptr::addr_of_mut!(STATIC) }, +}; +static INTERIOR_MUTABLE_PTR: SyncPtr = SyncPtr { + foo: ptr::addr_of!(INTERIOR_MUTABLE_STATIC) as *mut u32, +}; + +fn main() { + let ptr = PTR.foo; + unsafe { + assert_eq!(*ptr, 42); + *ptr = 0; + assert_eq!(*PTR.foo, 0); + } + + let ptr = INTERIOR_MUTABLE_PTR.foo; + unsafe { + assert_eq!(*ptr, 42); + *ptr = 0; + assert_eq!(*INTERIOR_MUTABLE_PTR.foo, 0); + } +} diff --git a/tests/ui/error-codes/E0017.rs b/tests/ui/error-codes/E0017.rs index 9d3433fa543fd..c128c2779e245 100644 --- a/tests/ui/error-codes/E0017.rs +++ b/tests/ui/error-codes/E0017.rs @@ -1,3 +1,5 @@ +#![feature(const_mut_refs)] + static X: i32 = 1; const C: i32 = 2; static mut M: i32 = 3; @@ -5,14 +7,12 @@ static mut M: i32 = 3; const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed //~| WARN taking a mutable -static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 -//~| ERROR cannot borrow -//~| ERROR mutable references are not allowed +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow immutable static item `X` as mutable static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed //~| WARN taking a mutable -static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR mutable references are not +static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] fn main() {} diff --git a/tests/ui/error-codes/E0017.stderr b/tests/ui/error-codes/E0017.stderr index 2a70f2ee0ae82..eb626a7fe3a98 100644 --- a/tests/ui/error-codes/E0017.stderr +++ b/tests/ui/error-codes/E0017.stderr @@ -14,7 +14,7 @@ LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { addr_of_mut!(M) }; | ~~~~~~~~~~~~~~~ warning: taking a mutable reference to a `const` item - --> $DIR/E0017.rs:5:30 + --> $DIR/E0017.rs:7:30 | LL | const CR: &'static mut i32 = &mut C; | ^^^^^^ @@ -22,36 +22,20 @@ LL | const CR: &'static mut i32 = &mut C; = note: each usage of a `const` item creates a new temporary = note: the mutable reference will refer to this temporary, not the original `const` item note: `const` item defined here - --> $DIR/E0017.rs:2:1 + --> $DIR/E0017.rs:4:1 | LL | const C: i32 = 2; | ^^^^^^^^^^^^ = note: `#[warn(const_item_mutation)]` on by default error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/E0017.rs:5:30 + --> $DIR/E0017.rs:7:30 | LL | const CR: &'static mut i32 = &mut C; | ^^^^^^ -error[E0658]: mutation through a reference is not allowed in statics - --> $DIR/E0017.rs:8:39 - | -LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/E0017.rs:8:39 - | -LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ - error[E0596]: cannot borrow immutable static item `X` as mutable - --> $DIR/E0017.rs:8:39 + --> $DIR/E0017.rs:10:39 | LL | static STATIC_REF: &'static mut i32 = &mut X; | ^^^^^^ cannot borrow as mutable @@ -65,7 +49,7 @@ LL | static CONST_REF: &'static mut i32 = &mut C; = note: each usage of a `const` item creates a new temporary = note: the mutable reference will refer to this temporary, not the original `const` item note: `const` item defined here - --> $DIR/E0017.rs:2:1 + --> $DIR/E0017.rs:4:1 | LL | const C: i32 = 2; | ^^^^^^^^^^^^ @@ -76,13 +60,7 @@ error[E0764]: mutable references are not allowed in the final value of statics LL | static CONST_REF: &'static mut i32 = &mut C; | ^^^^^^ -error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/E0017.rs:15:52 - | -LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; - | ^^^^^^ - -error: aborting due to 6 previous errors; 3 warnings emitted +error: aborting due to 3 previous errors; 3 warnings emitted -Some errors have detailed explanations: E0596, E0658, E0764. +Some errors have detailed explanations: E0596, E0764. For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/error-codes/E0388.rs b/tests/ui/error-codes/E0388.rs index 6049d95f0d277..bd371328e6bc9 100644 --- a/tests/ui/error-codes/E0388.rs +++ b/tests/ui/error-codes/E0388.rs @@ -3,9 +3,7 @@ const C: i32 = 2; const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed //~| WARN taking a mutable -static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow - //~| ERROR E0658 - //~| ERROR mutable references are not allowed +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed //~| WARN taking a mutable diff --git a/tests/ui/error-codes/E0388.stderr b/tests/ui/error-codes/E0388.stderr index 1f7b688899ed0..3e89e3f804b21 100644 --- a/tests/ui/error-codes/E0388.stderr +++ b/tests/ui/error-codes/E0388.stderr @@ -19,7 +19,7 @@ error[E0764]: mutable references are not allowed in the final value of constants LL | const CR: &'static mut i32 = &mut C; | ^^^^^^ -error[E0658]: mutation through a reference is not allowed in statics +error[E0658]: mutable references are not allowed in statics --> $DIR/E0388.rs:6:39 | LL | static STATIC_REF: &'static mut i32 = &mut X; @@ -29,20 +29,8 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/E0388.rs:6:39 - | -LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ - -error[E0596]: cannot borrow immutable static item `X` as mutable - --> $DIR/E0388.rs:6:39 - | -LL | static STATIC_REF: &'static mut i32 = &mut X; - | ^^^^^^ cannot borrow as mutable - warning: taking a mutable reference to a `const` item - --> $DIR/E0388.rs:10:38 + --> $DIR/E0388.rs:8:38 | LL | static CONST_REF: &'static mut i32 = &mut C; | ^^^^^^ @@ -56,12 +44,12 @@ LL | const C: i32 = 2; | ^^^^^^^^^^^^ error[E0764]: mutable references are not allowed in the final value of statics - --> $DIR/E0388.rs:10:38 + --> $DIR/E0388.rs:8:38 | LL | static CONST_REF: &'static mut i32 = &mut C; | ^^^^^^ -error: aborting due to 5 previous errors; 2 warnings emitted +error: aborting due to 3 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0596, E0658, E0764. -For more information about an error, try `rustc --explain E0596`. +Some errors have detailed explanations: E0658, E0764. +For more information about an error, try `rustc --explain E0658`. From 12f9de7d0e1502a0767c784ac717bce033b6ae65 Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 16 Jan 2024 14:45:22 +0300 Subject: [PATCH 33/40] tidy: wrap regexes with lazy_static yes, once_cell better, but ... this reduces from ==31349== Total: 1,365,199,543 bytes in 4,774,213 blocks ==31349== At t-gmax: 10,975,708 bytes in 66,093 blocks ==31349== At t-end: 2,880,947 bytes in 12,332 blocks ==31349== Reads: 5,210,008,956 bytes ==31349== Writes: 1,280,920,127 bytes to ==47796== Total: 821,467,407 bytes in 3,955,595 blocks ==47796== At t-gmax: 10,976,209 bytes in 66,100 blocks ==47796== At t-end: 2,944,016 bytes in 12,490 blocks ==47796== Reads: 4,788,959,023 bytes ==47796== Writes: 975,493,639 bytes miropt-test-tools: remove regex usage this removes regex usage and slightly refactors ext stripping in one case --- Cargo.lock | 3 --- src/tools/miropt-test-tools/Cargo.toml | 1 - src/tools/miropt-test-tools/src/lib.rs | 19 ++++++++++++------- src/tools/tidy/src/style.rs | 12 ++++++++---- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9ad78e37951d..a30ab648c3f9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2543,9 +2543,6 @@ dependencies = [ [[package]] name = "miropt-test-tools" version = "0.1.0" -dependencies = [ - "regex", -] [[package]] name = "native-tls" diff --git a/src/tools/miropt-test-tools/Cargo.toml b/src/tools/miropt-test-tools/Cargo.toml index 8589a44cf1bab..09b4c7d16dce3 100644 --- a/src/tools/miropt-test-tools/Cargo.toml +++ b/src/tools/miropt-test-tools/Cargo.toml @@ -4,4 +4,3 @@ version = "0.1.0" edition = "2021" [dependencies] -regex = "1.0" diff --git a/src/tools/miropt-test-tools/src/lib.rs b/src/tools/miropt-test-tools/src/lib.rs index 7d60033c3e824..4317f23a82219 100644 --- a/src/tools/miropt-test-tools/src/lib.rs +++ b/src/tools/miropt-test-tools/src/lib.rs @@ -100,14 +100,19 @@ pub fn files_for_miropt_test( } else { // Allow-list for file extensions that can be produced by MIR dumps. // Other extensions can be added here, as needed by new dump flags. - let ext_re = regex::Regex::new(r#"(\.(mir|dot))$"#).unwrap(); - let cap = ext_re.captures_iter(test_name).next().unwrap_or_else(|| { - panic!("in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}") - }); - let extension = cap.get(1).unwrap().as_str(); + static ALLOWED_EXT: &[&str] = &["mir", "dot"]; + let Some((test_name_wo_ext, test_name_ext)) = test_name.rsplit_once('.') else { + panic!( + "in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}, expected one of {ALLOWED_EXT:?}" + ) + }; + if !ALLOWED_EXT.contains(&test_name_ext) { + panic!( + "in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}, expected one of {ALLOWED_EXT:?}" + ) + } - expected_file = - format!("{}{}{}", test_name.trim_end_matches(extension), suffix, extension,); + expected_file = format!("{}{}.{}", test_name_wo_ext, suffix, test_name_ext); from_file = test_name.to_string(); assert!(test_names.next().is_none(), "two mir pass names specified for MIR dump"); to_file = None; diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index a8aae6f5bc9d3..28d70b4454cee 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -130,16 +130,20 @@ fn should_ignore(line: &str) -> bool { // Matches test annotations like `//~ ERROR text`. // This mirrors the regex in src/tools/compiletest/src/runtest.rs, please // update both if either are changed. - let re = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap(); + lazy_static::lazy_static! { + static ref ANNOTATION_RE: Regex = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap(); + } // For `ui_test`-style UI test directives, also ignore // - `//@[rev] compile-flags` // - `//@[rev] normalize-stderr-test` - let ui_test_long_directives = + lazy_static::lazy_static! { + static ref UI_TEST_LONG_DIRECTIVES_RE: Regex = Regex::new("\\s*//@(\\[.*\\]) (compile-flags|normalize-stderr-test|error-pattern).*") .unwrap(); - re.is_match(line) + } + ANNOTATION_RE.is_match(line) || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a)) - || ui_test_long_directives.is_match(line) + || UI_TEST_LONG_DIRECTIVES_RE.is_match(line) } /// Returns `true` if `line` is allowed to be longer than the normal limit. From f6fa03bfaed8e20adab961ef5d3f42b3246c5228 Mon Sep 17 00:00:00 2001 From: klensy Date: Sat, 17 Feb 2024 12:40:26 +0300 Subject: [PATCH 34/40] compiletest: fix regex rebuilds --- src/tools/compiletest/src/header.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 4ceb8a646e060..117828645a94f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -6,6 +6,7 @@ use std::io::BufReader; use std::path::{Path, PathBuf}; use std::process::Command; +use once_cell::sync::Lazy; use regex::Regex; use tracing::*; @@ -829,7 +830,8 @@ fn iter_header_extra( let mut ln = String::new(); let mut line_number = 0; - let revision_magic_comment = Regex::new("//(\\[.*\\])?~.*").unwrap(); + static REVISION_MAGIC_COMMENT_RE: Lazy = + Lazy::new(|| Regex::new("//(\\[.*\\])?~.*").unwrap()); loop { line_number += 1; @@ -849,7 +851,7 @@ fn iter_header_extra( // First try to accept `ui_test` style comments } else if let Some((lncfg, ln)) = line_directive(comment, ln) { it(lncfg, orig_ln, ln, line_number); - } else if mode == Mode::Ui && suite == "ui" && !revision_magic_comment.is_match(ln) { + } else if mode == Mode::Ui && suite == "ui" && !REVISION_MAGIC_COMMENT_RE.is_match(ln) { let Some((_, rest)) = line_directive("//", ln) else { continue; }; From 3ec7d0a57c3bf82877b4a40e25a8f55cfb6e94fa Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 17 Feb 2024 13:19:01 +0300 Subject: [PATCH 35/40] create stamp file for clippy in `Config::download_clippy` Due to missing stamp file, we were downloading (and applying nix patches if enabled) continuously every time `Config::download_clippy` was called. This change fixes that by creating stamp file at the end of the function. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/download.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index e63d60feff125..b4ae3578ce317 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -399,6 +399,7 @@ impl Config { self.fix_bin_or_dylib(&cargo_clippy.with_file_name(exe("clippy-driver", host))); } + self.create(&clippy_stamp, date); cargo_clippy } From 87b6f415f254345763919dcc460839be2fe9677d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 17 Feb 2024 12:46:18 +0100 Subject: [PATCH 36/40] remove a couple of redundant clones --- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_parse/src/parser/diagnostics.rs | 4 ++-- compiler/rustc_parse_format/src/lib.rs | 2 +- src/tools/clippy/clippy_utils/src/diagnostics.rs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index b0caf45b40afe..7c0de1261ef08 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -311,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: &mut bool, ) { if let Some((if_span, msg)) = ret_reason { - err.span_label(if_span, msg.clone()); + err.span_label(if_span, msg); } else if let ExprKind::Block(block, _) = then_expr.kind && let Some(expr) = block.expr { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 69518287f38ec..ba5954bc3ea71 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -452,7 +452,6 @@ impl<'a> Parser<'a> { let mut expected = self .expected_tokens .iter() - .cloned() .filter(|token| { // Filter out suggestions that suggest the same token which was found and deemed incorrect. fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool { @@ -464,7 +463,7 @@ impl<'a> Parser<'a> { false } - if *token != parser::TokenType::Token(self.token.kind.clone()) { + if **token != parser::TokenType::Token(self.token.kind.clone()) { let eq = is_ident_eq_keyword(&self.token.kind, &token); // If the suggestion is a keyword and the found token is an ident, // the content of which are equal to the suggestion's content, @@ -483,6 +482,7 @@ impl<'a> Parser<'a> { } false }) + .cloned() .collect::>(); expected.sort_by_cached_key(|x| x.to_string()); expected.dedup(); diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 0b65f400825ae..79aab47fbe717 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -893,7 +893,7 @@ impl<'a> Parser<'a> { ParseError { description: "expected format parameter to occur after `:`".to_owned(), note: None, - label: format!("expected `{}` to occur after `:`", alignment).to_owned(), + label: format!("expected `{}` to occur after `:`", alignment), span: pos.to(pos), secondary_label: None, suggestion: Suggestion::None, diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 56978eb2ee805..5199959c0f2b3 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -84,9 +84,9 @@ pub fn span_lint_and_help( cx.span_lint(lint, span, msg.to_string(), |diag| { let help = help.to_string(); if let Some(help_span) = help_span { - diag.span_help(help_span, help.to_string()); + diag.span_help(help_span, help); } else { - diag.help(help.to_string()); + diag.help(help); } docs_link(diag, lint); }); From bc2355a34d28c44222b5f6e444b1742c45b43738 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 16 Feb 2024 21:26:37 -0500 Subject: [PATCH 37/40] Update cargo perl-core is added for building OpenSSL v3 See https://github.com/openssl/openssl/blob/openssl-3.2.1/NOTES-PERL.md --- src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile | 1 + src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile | 1 + src/tools/cargo | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile index f5274104d60ac..1704bef1e4ed0 100644 --- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile @@ -25,6 +25,7 @@ RUN yum upgrade -y && \ openssl-devel \ patch \ perl \ + perl-core \ pkgconfig \ python3 \ unzip \ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 9a2fcb0ce0a1a..fe84c23a11c14 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -25,6 +25,7 @@ RUN yum upgrade -y && \ openssl-devel \ patch \ perl \ + perl-core \ pkgconfig \ python3 \ unzip \ diff --git a/src/tools/cargo b/src/tools/cargo index fc1d58fd0531a..7b7af3077bff8 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit fc1d58fd0531a57a6b942a14cdcdbcb82ece16f3 +Subproject commit 7b7af3077bff8d60b7f124189bc9de227d3063a9 From d18d4615c4f58e70799f56dc916f839a8019e2cb Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sun, 18 Feb 2024 04:53:46 +0000 Subject: [PATCH 38/40] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ab6f899cd3a5e..921a55d48c6c1 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -4316d0c6252cb1f833e582dfa68adb98efd5ddfb +1f8e824f111c972c9df8dbb378d87c33f67bbad4 From 864cee3ea383cc8254ba394ba355e648faa9cfa5 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sun, 18 Feb 2024 03:12:44 -0500 Subject: [PATCH 39/40] Allow AST and HIR visitors to return `ControlFlow` --- compiler/rustc_ast/src/lib.rs | 2 + compiler/rustc_ast/src/visit.rs | 800 ++++++++++++---------- compiler/rustc_expand/src/base.rs | 2 +- compiler/rustc_expand/src/expand.rs | 16 +- compiler/rustc_hir/src/intravisit.rs | 835 +++++++++++++---------- compiler/rustc_middle/src/hir/map/mod.rs | 73 +- 6 files changed, 959 insertions(+), 769 deletions(-) diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 6414c8e904196..6e42cf37b865c 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -12,10 +12,12 @@ #![allow(internal_features)] #![feature(rustdoc_internals)] #![feature(associated_type_bounds)] +#![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(let_chains)] #![cfg_attr(bootstrap, feature(min_specialization))] +#![feature(never_type)] #![feature(negative_impls)] #![feature(stmt_expr_attributes)] diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 83f6746bdeb23..ecf379cc2408a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -15,6 +15,8 @@ use crate::ast::*; +use core::ops::ControlFlow; + use rustc_span::symbol::Ident; use rustc_span::Span; @@ -99,6 +101,51 @@ pub enum LifetimeCtxt { GenericArg, } +/// Similar to the `Try` trait, but also implemented for `()`. +pub trait VisitorResult { + type Residual; + fn output() -> Self; + fn from_residual(residual: Self::Residual) -> Self; + fn branch(self) -> ControlFlow; +} + +impl VisitorResult for () { + type Residual = !; + + fn output() -> Self {} + fn from_residual(_: !) -> Self {} + fn branch(self) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl VisitorResult for ControlFlow { + type Residual = T; + + fn output() -> Self { + ControlFlow::Continue(()) + } + fn from_residual(residual: Self::Residual) -> Self { + ControlFlow::Break(residual) + } + fn branch(self) -> ControlFlow { + self + } +} + +#[macro_export] +macro_rules! try_visit { + ($e:expr) => { + match $crate::visit::VisitorResult::branch($e) { + core::ops::ControlFlow::Continue(()) => (), + #[allow(unreachable_code)] + core::ops::ControlFlow::Break(r) => { + return $crate::visit::VisitorResult::from_residual(r); + } + } + }; +} + /// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; @@ -109,240 +156,259 @@ pub enum LifetimeCtxt { /// to monitor future changes to `Visitor` in case a new method with a /// new default implementation gets introduced.) pub trait Visitor<'ast>: Sized { - fn visit_ident(&mut self, _ident: Ident) {} - fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { + /// The result type of the `visit_*` methods. Can be either `()`, + /// or `ControlFlow`. + type Result: VisitorResult = (); + + fn visit_ident(&mut self, _ident: Ident) -> Self::Result { + Self::Result::output() + } + fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result { walk_foreign_item(self, i) } - fn visit_item(&mut self, i: &'ast Item) { + fn visit_item(&mut self, i: &'ast Item) -> Self::Result { walk_item(self, i) } - fn visit_local(&mut self, l: &'ast Local) { + fn visit_local(&mut self, l: &'ast Local) -> Self::Result { walk_local(self, l) } - fn visit_block(&mut self, b: &'ast Block) { + fn visit_block(&mut self, b: &'ast Block) -> Self::Result { walk_block(self, b) } - fn visit_stmt(&mut self, s: &'ast Stmt) { + fn visit_stmt(&mut self, s: &'ast Stmt) -> Self::Result { walk_stmt(self, s) } - fn visit_param(&mut self, param: &'ast Param) { + fn visit_param(&mut self, param: &'ast Param) -> Self::Result { walk_param(self, param) } - fn visit_arm(&mut self, a: &'ast Arm) { + fn visit_arm(&mut self, a: &'ast Arm) -> Self::Result { walk_arm(self, a) } - fn visit_pat(&mut self, p: &'ast Pat) { + fn visit_pat(&mut self, p: &'ast Pat) -> Self::Result { walk_pat(self, p) } - fn visit_anon_const(&mut self, c: &'ast AnonConst) { + fn visit_anon_const(&mut self, c: &'ast AnonConst) -> Self::Result { walk_anon_const(self, c) } - fn visit_expr(&mut self, ex: &'ast Expr) { + fn visit_expr(&mut self, ex: &'ast Expr) -> Self::Result { walk_expr(self, ex) } /// This method is a hack to workaround unstable of `stmt_expr_attributes`. /// It can be removed once that feature is stabilized. - fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) { + fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) -> Self::Result { self.visit_expr(ex) } - fn visit_expr_post(&mut self, _ex: &'ast Expr) {} - fn visit_ty(&mut self, t: &'ast Ty) { + fn visit_expr_post(&mut self, _ex: &'ast Expr) -> Self::Result { + Self::Result::output() + } + fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result { walk_ty(self, t) } - fn visit_generic_param(&mut self, param: &'ast GenericParam) { + fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result { walk_generic_param(self, param) } - fn visit_generics(&mut self, g: &'ast Generics) { + fn visit_generics(&mut self, g: &'ast Generics) -> Self::Result { walk_generics(self, g) } - fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) { + fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) -> Self::Result { walk_closure_binder(self, b) } - fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { + fn visit_where_predicate(&mut self, p: &'ast WherePredicate) -> Self::Result { walk_where_predicate(self, p) } - fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) { + fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) -> Self::Result { walk_fn(self, fk) } - fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) { + fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) -> Self::Result { walk_assoc_item(self, i, ctxt) } - fn visit_trait_ref(&mut self, t: &'ast TraitRef) { + fn visit_trait_ref(&mut self, t: &'ast TraitRef) -> Self::Result { walk_trait_ref(self, t) } - fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) { + fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result { walk_param_bound(self, bounds) } - fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) { + fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result { walk_poly_trait_ref(self, t) } - fn visit_variant_data(&mut self, s: &'ast VariantData) { + fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result { walk_struct_def(self, s) } - fn visit_field_def(&mut self, s: &'ast FieldDef) { + fn visit_field_def(&mut self, s: &'ast FieldDef) -> Self::Result { walk_field_def(self, s) } - fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef) { + fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef) -> Self::Result { walk_enum_def(self, enum_definition) } - fn visit_variant(&mut self, v: &'ast Variant) { + fn visit_variant(&mut self, v: &'ast Variant) -> Self::Result { walk_variant(self, v) } - fn visit_variant_discr(&mut self, discr: &'ast AnonConst) { - self.visit_anon_const(discr); + fn visit_variant_discr(&mut self, discr: &'ast AnonConst) -> Self::Result { + self.visit_anon_const(discr) } - fn visit_label(&mut self, label: &'ast Label) { + fn visit_label(&mut self, label: &'ast Label) -> Self::Result { walk_label(self, label) } - fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) { + fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) -> Self::Result { walk_lifetime(self, lifetime) } - fn visit_mac_call(&mut self, mac: &'ast MacCall) { + fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result { walk_mac(self, mac) } - fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) { - // Nothing to do + fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) -> Self::Result { + Self::Result::output() } - fn visit_path(&mut self, path: &'ast Path, _id: NodeId) { + fn visit_path(&mut self, path: &'ast Path, _id: NodeId) -> Self::Result { walk_path(self, path) } - fn visit_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId, _nested: bool) { + fn visit_use_tree( + &mut self, + use_tree: &'ast UseTree, + id: NodeId, + _nested: bool, + ) -> Self::Result { walk_use_tree(self, use_tree, id) } - fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) { + fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) -> Self::Result { walk_path_segment(self, path_segment) } - fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) { + fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) -> Self::Result { walk_generic_args(self, generic_args) } - fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) { + fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result { walk_generic_arg(self, generic_arg) } - fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) { + fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) -> Self::Result { walk_assoc_constraint(self, constraint) } - fn visit_attribute(&mut self, attr: &'ast Attribute) { + fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result { walk_attribute(self, attr) } - fn visit_vis(&mut self, vis: &'ast Visibility) { + fn visit_vis(&mut self, vis: &'ast Visibility) -> Self::Result { walk_vis(self, vis) } - fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) { + fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) -> Self::Result { walk_fn_ret_ty(self, ret_ty) } - fn visit_fn_header(&mut self, _header: &'ast FnHeader) { - // Nothing to do + fn visit_fn_header(&mut self, _header: &'ast FnHeader) -> Self::Result { + Self::Result::output() } - fn visit_expr_field(&mut self, f: &'ast ExprField) { + fn visit_expr_field(&mut self, f: &'ast ExprField) -> Self::Result { walk_expr_field(self, f) } - fn visit_pat_field(&mut self, fp: &'ast PatField) { + fn visit_pat_field(&mut self, fp: &'ast PatField) -> Self::Result { walk_pat_field(self, fp) } - fn visit_crate(&mut self, krate: &'ast Crate) { + fn visit_crate(&mut self, krate: &'ast Crate) -> Self::Result { walk_crate(self, krate) } - fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) { + fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) -> Self::Result { walk_inline_asm(self, asm) } - fn visit_format_args(&mut self, fmt: &'ast FormatArgs) { + fn visit_format_args(&mut self, fmt: &'ast FormatArgs) -> Self::Result { walk_format_args(self, fmt) } - fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) { + fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) -> Self::Result { walk_inline_asm_sym(self, sym) } - fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) { - // Nothing to do + fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result { + Self::Result::output() } } #[macro_export] macro_rules! walk_list { ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { - { - #[allow(for_loops_over_fallibles)] - for elem in $list { - $visitor.$method(elem $(, $($extra_args,)* )?) - } + for elem in $list { + $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); } } } -pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) { +#[macro_export] +macro_rules! visit_opt { + ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { + if let Some(x) = $opt { + $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); + } + } +} + +pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result { walk_list!(visitor, visit_item, &krate.items); walk_list!(visitor, visit_attribute, &krate.attrs); + V::Result::output() } -pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) { - for attr in local.attrs.iter() { - visitor.visit_attribute(attr); - } - visitor.visit_pat(&local.pat); - walk_list!(visitor, visit_ty, &local.ty); +pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result { + walk_list!(visitor, visit_attribute, &local.attrs); + try_visit!(visitor.visit_pat(&local.pat)); + visit_opt!(visitor, visit_ty, &local.ty); if let Some((init, els)) = local.kind.init_else_opt() { - visitor.visit_expr(init); - walk_list!(visitor, visit_block, els); + try_visit!(visitor.visit_expr(init)); + visit_opt!(visitor, visit_block, els); } + V::Result::output() } -pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) { - visitor.visit_ident(label.ident); +pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) -> V::Result { + visitor.visit_ident(label.ident) } -pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) { - visitor.visit_ident(lifetime.ident); +pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) -> V::Result { + visitor.visit_ident(lifetime.ident) } -pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) +pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) -> V::Result where V: Visitor<'a>, { walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params); - visitor.visit_trait_ref(&trait_ref.trait_ref); + visitor.visit_trait_ref(&trait_ref.trait_ref) } -pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) { +pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) -> V::Result { visitor.visit_path(&trait_ref.path, trait_ref.ref_id) } -pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { - visitor.visit_vis(&item.vis); - visitor.visit_ident(item.ident); +pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Result { + try_visit!(visitor.visit_vis(&item.vis)); + try_visit!(visitor.visit_ident(item.ident)); match &item.kind { ItemKind::ExternCrate(_) => {} - ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false), + ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)), ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => { - visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, expr); + try_visit!(visitor.visit_ty(ty)); + visit_opt!(visitor, visit_expr, expr); } ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => { - visitor.visit_generics(generics); - visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, expr); + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_ty(ty)); + visit_opt!(visitor, visit_expr, expr); } ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref()); - visitor.visit_fn(kind, item.span, item.id) + try_visit!(visitor.visit_fn(kind, item.span, item.id)); } ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { ModKind::Loaded(items, _inline, _inner_span) => { - walk_list!(visitor, visit_item, items) + walk_list!(visitor, visit_item, items); } ModKind::Unloaded => {} }, ItemKind::ForeignMod(foreign_module) => { walk_list!(visitor, visit_foreign_item, &foreign_module.items); } - ItemKind::GlobalAsm(asm) => visitor.visit_inline_asm(asm), + ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), ItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => { - visitor.visit_generics(generics); + try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - walk_list!(visitor, visit_ty, ty); + visit_opt!(visitor, visit_ty, ty); } ItemKind::Enum(enum_definition, generics) => { - visitor.visit_generics(generics); - visitor.visit_enum_def(enum_definition) + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_enum_def(enum_definition)); } ItemKind::Impl(box Impl { defaultness: _, @@ -354,91 +420,97 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { self_ty, items, }) => { - visitor.visit_generics(generics); - walk_list!(visitor, visit_trait_ref, of_trait); - visitor.visit_ty(self_ty); + try_visit!(visitor.visit_generics(generics)); + visit_opt!(visitor, visit_trait_ref, of_trait); + try_visit!(visitor.visit_ty(self_ty)); walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl); } ItemKind::Struct(struct_definition, generics) | ItemKind::Union(struct_definition, generics) => { - visitor.visit_generics(generics); - visitor.visit_variant_data(struct_definition); + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_variant_data(struct_definition)); } ItemKind::Trait(box Trait { unsafety: _, is_auto: _, generics, bounds, items }) => { - visitor.visit_generics(generics); + try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits); walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait); } ItemKind::TraitAlias(generics, bounds) => { - visitor.visit_generics(generics); + try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } - ItemKind::MacCall(mac) => visitor.visit_mac_call(mac), - ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id), + ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), + ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)), ItemKind::Delegation(box Delegation { id, qself, path, body }) => { if let Some(qself) = qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, *id); - if let Some(body) = body { - visitor.visit_block(body); + try_visit!(visitor.visit_ty(&qself.ty)); } + try_visit!(visitor.visit_path(path, *id)); + visit_opt!(visitor, visit_block, body); } } walk_list!(visitor, visit_attribute, &item.attrs); + V::Result::output() } -pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V, enum_definition: &'a EnumDef) { +pub fn walk_enum_def<'a, V: Visitor<'a>>( + visitor: &mut V, + enum_definition: &'a EnumDef, +) -> V::Result { walk_list!(visitor, visit_variant, &enum_definition.variants); + V::Result::output() } -pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) +pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) -> V::Result where V: Visitor<'a>, { - visitor.visit_ident(variant.ident); - visitor.visit_vis(&variant.vis); - visitor.visit_variant_data(&variant.data); - walk_list!(visitor, visit_variant_discr, &variant.disr_expr); + try_visit!(visitor.visit_ident(variant.ident)); + try_visit!(visitor.visit_vis(&variant.vis)); + try_visit!(visitor.visit_variant_data(&variant.data)); + visit_opt!(visitor, visit_variant_discr, &variant.disr_expr); walk_list!(visitor, visit_attribute, &variant.attrs); + V::Result::output() } -pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) { - visitor.visit_expr(&f.expr); - visitor.visit_ident(f.ident); - walk_list!(visitor, visit_attribute, f.attrs.iter()); +pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result { + try_visit!(visitor.visit_expr(&f.expr)); + try_visit!(visitor.visit_ident(f.ident)); + walk_list!(visitor, visit_attribute, &f.attrs); + V::Result::output() } -pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) { - visitor.visit_ident(fp.ident); - visitor.visit_pat(&fp.pat); - walk_list!(visitor, visit_attribute, fp.attrs.iter()); +pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result { + try_visit!(visitor.visit_ident(fp.ident)); + try_visit!(visitor.visit_pat(&fp.pat)); + walk_list!(visitor, visit_attribute, &fp.attrs); + V::Result::output() } -pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { +pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { match &typ.kind { - TyKind::Slice(ty) | TyKind::Paren(ty) => visitor.visit_ty(ty), - TyKind::Ptr(mutable_type) => visitor.visit_ty(&mutable_type.ty), + TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)), + TyKind::Ptr(mutable_type) => try_visit!(visitor.visit_ty(&mutable_type.ty)), TyKind::Ref(opt_lifetime, mutable_type) => { - walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref); - visitor.visit_ty(&mutable_type.ty) + visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref); + try_visit!(visitor.visit_ty(&mutable_type.ty)); } TyKind::Tup(tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } TyKind::BareFn(function_declaration) => { walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); - walk_fn_decl(visitor, &function_declaration.decl); + try_visit!(walk_fn_decl(visitor, &function_declaration.decl)); } TyKind::Path(maybe_qself, path) => { if let Some(qself) = maybe_qself { - visitor.visit_ty(&qself.ty); + try_visit!(visitor.visit_ty(&qself.ty)); } - visitor.visit_path(path, typ.id); + try_visit!(visitor.visit_path(path, typ.id)); } TyKind::Array(ty, length) => { - visitor.visit_ty(ty); - visitor.visit_anon_const(length) + try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_anon_const(length)); } TyKind::TraitObject(bounds, ..) => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject); @@ -446,48 +518,53 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { TyKind::ImplTrait(_, bounds) => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl); } - TyKind::Typeof(expression) => visitor.visit_anon_const(expression), + TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)), TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {} - TyKind::MacCall(mac) => visitor.visit_mac_call(mac), + TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), TyKind::Never | TyKind::CVarArgs => {} TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => { - walk_list!(visitor, visit_field_def, fields) + walk_list!(visitor, visit_field_def, fields); } } + V::Result::output() } -pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) { - for segment in &path.segments { - visitor.visit_path_segment(segment); - } +pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) -> V::Result { + walk_list!(visitor, visit_path_segment, &path.segments); + V::Result::output() } -pub fn walk_use_tree<'a, V: Visitor<'a>>(visitor: &mut V, use_tree: &'a UseTree, id: NodeId) { - visitor.visit_path(&use_tree.prefix, id); - match &use_tree.kind { +pub fn walk_use_tree<'a, V: Visitor<'a>>( + visitor: &mut V, + use_tree: &'a UseTree, + id: NodeId, +) -> V::Result { + try_visit!(visitor.visit_path(&use_tree.prefix, id)); + match use_tree.kind { UseTreeKind::Simple(rename) => { // The extra IDs are handled during HIR lowering. - if let &Some(rename) = rename { - visitor.visit_ident(rename); - } + visit_opt!(visitor, visit_ident, rename); } UseTreeKind::Glob => {} - UseTreeKind::Nested(use_trees) => { + UseTreeKind::Nested(ref use_trees) => { for &(ref nested_tree, nested_id) in use_trees { - visitor.visit_use_tree(nested_tree, nested_id, true); + try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true)); } } } + V::Result::output() } -pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, segment: &'a PathSegment) { - visitor.visit_ident(segment.ident); - if let Some(args) = &segment.args { - visitor.visit_generic_args(args); - } +pub fn walk_path_segment<'a, V: Visitor<'a>>( + visitor: &mut V, + segment: &'a PathSegment, +) -> V::Result { + try_visit!(visitor.visit_ident(segment.ident)); + visit_opt!(visitor, visit_generic_args, &segment.args); + V::Result::output() } -pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) +pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result where V: Visitor<'a>, { @@ -495,19 +572,22 @@ where GenericArgs::AngleBracketed(data) => { for arg in &data.args { match arg { - AngleBracketedArg::Arg(a) => visitor.visit_generic_arg(a), - AngleBracketedArg::Constraint(c) => visitor.visit_assoc_constraint(c), + AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)), + AngleBracketedArg::Constraint(c) => { + try_visit!(visitor.visit_assoc_constraint(c)) + } } } } GenericArgs::Parenthesized(data) => { walk_list!(visitor, visit_ty, &data.inputs); - visitor.visit_fn_ret_ty(&data.output); + try_visit!(visitor.visit_fn_ret_ty(&data.output)); } } + V::Result::output() } -pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) +pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) -> V::Result where V: Visitor<'a>, { @@ -518,127 +598,141 @@ where } } -pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &'a AssocConstraint) { - visitor.visit_ident(constraint.ident); - if let Some(gen_args) = &constraint.gen_args { - visitor.visit_generic_args(gen_args); - } +pub fn walk_assoc_constraint<'a, V: Visitor<'a>>( + visitor: &mut V, + constraint: &'a AssocConstraint, +) -> V::Result { + try_visit!(visitor.visit_ident(constraint.ident)); + visit_opt!(visitor, visit_generic_args, &constraint.gen_args); match &constraint.kind { AssocConstraintKind::Equality { term } => match term { - Term::Ty(ty) => visitor.visit_ty(ty), - Term::Const(c) => visitor.visit_anon_const(c), + Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)), + Term::Const(c) => try_visit!(visitor.visit_anon_const(c)), }, AssocConstraintKind::Bound { bounds } => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } } + V::Result::output() } -pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { +pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Result { match &pattern.kind { PatKind::TupleStruct(opt_qself, path, elems) => { if let Some(qself) = opt_qself { - visitor.visit_ty(&qself.ty); + try_visit!(visitor.visit_ty(&qself.ty)); } - visitor.visit_path(path, pattern.id); + try_visit!(visitor.visit_path(path, pattern.id)); walk_list!(visitor, visit_pat, elems); } PatKind::Path(opt_qself, path) => { if let Some(qself) = opt_qself { - visitor.visit_ty(&qself.ty); + try_visit!(visitor.visit_ty(&qself.ty)); } - visitor.visit_path(path, pattern.id) + try_visit!(visitor.visit_path(path, pattern.id)) } PatKind::Struct(opt_qself, path, fields, _) => { if let Some(qself) = opt_qself { - visitor.visit_ty(&qself.ty); + try_visit!(visitor.visit_ty(&qself.ty)); } - visitor.visit_path(path, pattern.id); + try_visit!(visitor.visit_path(path, pattern.id)); walk_list!(visitor, visit_pat_field, fields); } PatKind::Box(subpattern) | PatKind::Ref(subpattern, _) | PatKind::Paren(subpattern) => { - visitor.visit_pat(subpattern) + try_visit!(visitor.visit_pat(subpattern)); } PatKind::Ident(_, ident, optional_subpattern) => { - visitor.visit_ident(*ident); - walk_list!(visitor, visit_pat, optional_subpattern); + try_visit!(visitor.visit_ident(*ident)); + visit_opt!(visitor, visit_pat, optional_subpattern); } - PatKind::Lit(expression) => visitor.visit_expr(expression), + PatKind::Lit(expression) => try_visit!(visitor.visit_expr(expression)), PatKind::Range(lower_bound, upper_bound, _) => { - walk_list!(visitor, visit_expr, lower_bound); - walk_list!(visitor, visit_expr, upper_bound); + visit_opt!(visitor, visit_expr, lower_bound); + visit_opt!(visitor, visit_expr, upper_bound); } PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); } - PatKind::MacCall(mac) => visitor.visit_mac_call(mac), + PatKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), } + V::Result::output() } -pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) { +pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) -> V::Result { let &Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = item; - visitor.visit_vis(vis); - visitor.visit_ident(ident); + try_visit!(visitor.visit_vis(vis)); + try_visit!(visitor.visit_ident(ident)); walk_list!(visitor, visit_attribute, attrs); match kind { ForeignItemKind::Static(ty, _, expr) => { - visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, expr); + try_visit!(visitor.visit_ty(ty)); + visit_opt!(visitor, visit_expr, expr); } ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref()); - visitor.visit_fn(kind, span, id); + try_visit!(visitor.visit_fn(kind, span, id)); } ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => { - visitor.visit_generics(generics); + try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - walk_list!(visitor, visit_ty, ty); + visit_opt!(visitor, visit_ty, ty); } ForeignItemKind::MacCall(mac) => { - visitor.visit_mac_call(mac); + try_visit!(visitor.visit_mac_call(mac)); } } + V::Result::output() } -pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) { +pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result { match bound { GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ), GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound), } } -pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) { - visitor.visit_ident(param.ident); - walk_list!(visitor, visit_attribute, param.attrs.iter()); +pub fn walk_generic_param<'a, V: Visitor<'a>>( + visitor: &mut V, + param: &'a GenericParam, +) -> V::Result { + try_visit!(visitor.visit_ident(param.ident)); + walk_list!(visitor, visit_attribute, ¶m.attrs); walk_list!(visitor, visit_param_bound, ¶m.bounds, BoundKind::Bound); match ¶m.kind { GenericParamKind::Lifetime => (), - GenericParamKind::Type { default } => walk_list!(visitor, visit_ty, default), + GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default), GenericParamKind::Const { ty, default, .. } => { - visitor.visit_ty(ty); - if let Some(default) = default { - visitor.visit_anon_const(default); - } + try_visit!(visitor.visit_ty(ty)); + visit_opt!(visitor, visit_anon_const, default); } } + V::Result::output() } -pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) { +pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result { walk_list!(visitor, visit_generic_param, &generics.params); walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); + V::Result::output() } -pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a ClosureBinder) { +pub fn walk_closure_binder<'a, V: Visitor<'a>>( + visitor: &mut V, + binder: &'a ClosureBinder, +) -> V::Result { match binder { ClosureBinder::NotPresent => {} ClosureBinder::For { generic_params, span: _ } => { walk_list!(visitor, visit_generic_param, generic_params) } } + V::Result::output() } -pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) { +pub fn walk_where_predicate<'a, V: Visitor<'a>>( + visitor: &mut V, + predicate: &'a WherePredicate, +) -> V::Result { match predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { bounded_ty, @@ -646,181 +740,196 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a bound_generic_params, .. }) => { - visitor.visit_ty(bounded_ty); + try_visit!(visitor.visit_ty(bounded_ty)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); walk_list!(visitor, visit_generic_param, bound_generic_params); } WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, .. }) => { - visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound); + try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { - visitor.visit_ty(lhs_ty); - visitor.visit_ty(rhs_ty); + try_visit!(visitor.visit_ty(lhs_ty)); + try_visit!(visitor.visit_ty(rhs_ty)); } } + V::Result::output() } -pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) { +pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result { if let FnRetTy::Ty(output_ty) = ret_ty { - visitor.visit_ty(output_ty) + try_visit!(visitor.visit_ty(output_ty)); } + V::Result::output() } -pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) { - for param in &function_declaration.inputs { - visitor.visit_param(param); - } - visitor.visit_fn_ret_ty(&function_declaration.output); +pub fn walk_fn_decl<'a, V: Visitor<'a>>( + visitor: &mut V, + function_declaration: &'a FnDecl, +) -> V::Result { + walk_list!(visitor, visit_param, &function_declaration.inputs); + visitor.visit_fn_ret_ty(&function_declaration.output) } -pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) { +pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result { match kind { FnKind::Fn(_, _, sig, _, generics, body) => { - visitor.visit_generics(generics); - visitor.visit_fn_header(&sig.header); - walk_fn_decl(visitor, &sig.decl); - walk_list!(visitor, visit_block, body); + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_fn_header(&sig.header)); + try_visit!(walk_fn_decl(visitor, &sig.decl)); + visit_opt!(visitor, visit_block, body); } FnKind::Closure(binder, decl, body) => { - visitor.visit_closure_binder(binder); - walk_fn_decl(visitor, decl); - visitor.visit_expr(body); + try_visit!(visitor.visit_closure_binder(binder)); + try_visit!(walk_fn_decl(visitor, decl)); + try_visit!(visitor.visit_expr(body)); } } + V::Result::output() } -pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) { +pub fn walk_assoc_item<'a, V: Visitor<'a>>( + visitor: &mut V, + item: &'a AssocItem, + ctxt: AssocCtxt, +) -> V::Result { let &Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = item; - visitor.visit_vis(vis); - visitor.visit_ident(ident); + try_visit!(visitor.visit_vis(vis)); + try_visit!(visitor.visit_ident(ident)); walk_list!(visitor, visit_attribute, attrs); match kind { AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => { - visitor.visit_generics(generics); - visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, expr); + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_ty(ty)); + visit_opt!(visitor, visit_expr, expr); } AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref()); - visitor.visit_fn(kind, span, id); + try_visit!(visitor.visit_fn(kind, span, id)); } AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => { - visitor.visit_generics(generics); + try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - walk_list!(visitor, visit_ty, ty); + visit_opt!(visitor, visit_ty, ty); } AssocItemKind::MacCall(mac) => { - visitor.visit_mac_call(mac); + try_visit!(visitor.visit_mac_call(mac)); } AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => { if let Some(qself) = qself { visitor.visit_ty(&qself.ty); } - visitor.visit_path(path, *id); - if let Some(body) = body { - visitor.visit_block(body); - } + try_visit!(visitor.visit_path(path, *id)); + visit_opt!(visitor, visit_block, body); } } + V::Result::output() } -pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: &'a VariantData) { +pub fn walk_struct_def<'a, V: Visitor<'a>>( + visitor: &mut V, + struct_definition: &'a VariantData, +) -> V::Result { walk_list!(visitor, visit_field_def, struct_definition.fields()); + V::Result::output() } -pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) { - visitor.visit_vis(&field.vis); - if let Some(ident) = field.ident { - visitor.visit_ident(ident); - } - visitor.visit_ty(&field.ty); +pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result { + try_visit!(visitor.visit_vis(&field.vis)); + visit_opt!(visitor, visit_ident, field.ident); + try_visit!(visitor.visit_ty(&field.ty)); walk_list!(visitor, visit_attribute, &field.attrs); + V::Result::output() } -pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) { +pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result { walk_list!(visitor, visit_stmt, &block.stmts); + V::Result::output() } -pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { +pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { match &statement.kind { - StmtKind::Local(local) => visitor.visit_local(local), - StmtKind::Item(item) => visitor.visit_item(item), - StmtKind::Expr(expr) | StmtKind::Semi(expr) => visitor.visit_expr(expr), + StmtKind::Local(local) => try_visit!(visitor.visit_local(local)), + StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), StmtKind::Empty => {} StmtKind::MacCall(mac) => { let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac; - visitor.visit_mac_call(mac); - for attr in attrs.iter() { - visitor.visit_attribute(attr); - } + try_visit!(visitor.visit_mac_call(mac)); + walk_list!(visitor, visit_attribute, attrs); } } + V::Result::output() } -pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) { - visitor.visit_path(&mac.path, DUMMY_NODE_ID); +pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result { + visitor.visit_path(&mac.path, DUMMY_NODE_ID) } -pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) { - visitor.visit_expr(&constant.value); +pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) -> V::Result { + visitor.visit_expr(&constant.value) } -pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) { +pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result { for (op, _) in &asm.operands { match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::Out { expr: Some(expr), .. } - | InlineAsmOperand::InOut { expr, .. } => visitor.visit_expr(expr), + | InlineAsmOperand::InOut { expr, .. } => try_visit!(visitor.visit_expr(expr)), InlineAsmOperand::Out { expr: None, .. } => {} InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { - visitor.visit_expr(in_expr); - if let Some(out_expr) = out_expr { - visitor.visit_expr(out_expr); - } + try_visit!(visitor.visit_expr(in_expr)); + visit_opt!(visitor, visit_expr, out_expr); + } + InlineAsmOperand::Const { anon_const, .. } => { + try_visit!(visitor.visit_anon_const(anon_const)) } - InlineAsmOperand::Const { anon_const, .. } => visitor.visit_anon_const(anon_const), - InlineAsmOperand::Sym { sym } => visitor.visit_inline_asm_sym(sym), + InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)), } } + V::Result::output() } -pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineAsmSym) { +pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>( + visitor: &mut V, + sym: &'a InlineAsmSym, +) -> V::Result { if let Some(qself) = &sym.qself { - visitor.visit_ty(&qself.ty); + try_visit!(visitor.visit_ty(&qself.ty)); } - visitor.visit_path(&sym.path, sym.id); + visitor.visit_path(&sym.path, sym.id) } -pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) { +pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result { for arg in fmt.arguments.all_args() { if let FormatArgumentKind::Named(name) = arg.kind { - visitor.visit_ident(name); + try_visit!(visitor.visit_ident(name)); } - visitor.visit_expr(&arg.expr); + try_visit!(visitor.visit_expr(&arg.expr)); } + V::Result::output() } -pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { - walk_list!(visitor, visit_attribute, expression.attrs.iter()); +pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result { + walk_list!(visitor, visit_attribute, &expression.attrs); match &expression.kind { ExprKind::Array(subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } - ExprKind::ConstBlock(anon_const) => visitor.visit_anon_const(anon_const), + ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)), ExprKind::Repeat(element, count) => { - visitor.visit_expr(element); - visitor.visit_anon_const(count) + try_visit!(visitor.visit_expr(element)); + try_visit!(visitor.visit_anon_const(count)); } ExprKind::Struct(se) => { if let Some(qself) = &se.qself { - visitor.visit_ty(&qself.ty); + try_visit!(visitor.visit_ty(&qself.ty)); } - visitor.visit_path(&se.path, expression.id); + try_visit!(visitor.visit_path(&se.path, expression.id)); walk_list!(visitor, visit_expr_field, &se.fields); match &se.rest { - StructRest::Base(expr) => visitor.visit_expr(expr), + StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)), StructRest::Rest(_span) => {} StructRest::None => {} } @@ -829,51 +938,51 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { walk_list!(visitor, visit_expr, subexpressions); } ExprKind::Call(callee_expression, arguments) => { - visitor.visit_expr(callee_expression); + try_visit!(visitor.visit_expr(callee_expression)); walk_list!(visitor, visit_expr, arguments); } ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => { - visitor.visit_path_segment(seg); - visitor.visit_expr(receiver); + try_visit!(visitor.visit_path_segment(seg)); + try_visit!(visitor.visit_expr(receiver)); walk_list!(visitor, visit_expr, args); } ExprKind::Binary(_, left_expression, right_expression) => { - visitor.visit_expr(left_expression); - visitor.visit_expr(right_expression) + try_visit!(visitor.visit_expr(left_expression)); + try_visit!(visitor.visit_expr(right_expression)); } ExprKind::AddrOf(_, _, subexpression) | ExprKind::Unary(_, subexpression) => { - visitor.visit_expr(subexpression) + try_visit!(visitor.visit_expr(subexpression)); } ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => { - visitor.visit_expr(subexpression); - visitor.visit_ty(typ) + try_visit!(visitor.visit_expr(subexpression)); + try_visit!(visitor.visit_ty(typ)); } ExprKind::Let(pat, expr, _, _) => { - visitor.visit_pat(pat); - visitor.visit_expr(expr); + try_visit!(visitor.visit_pat(pat)); + try_visit!(visitor.visit_expr(expr)); } ExprKind::If(head_expression, if_block, optional_else) => { - visitor.visit_expr(head_expression); - visitor.visit_block(if_block); - walk_list!(visitor, visit_expr, optional_else); + try_visit!(visitor.visit_expr(head_expression)); + try_visit!(visitor.visit_block(if_block)); + visit_opt!(visitor, visit_expr, optional_else); } ExprKind::While(subexpression, block, opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_expr(subexpression); - visitor.visit_block(block); + visit_opt!(visitor, visit_label, opt_label); + try_visit!(visitor.visit_expr(subexpression)); + try_visit!(visitor.visit_block(block)); } ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { - walk_list!(visitor, visit_label, label); - visitor.visit_pat(pat); - visitor.visit_expr(iter); - visitor.visit_block(body); + visit_opt!(visitor, visit_label, label); + try_visit!(visitor.visit_pat(pat)); + try_visit!(visitor.visit_expr(iter)); + try_visit!(visitor.visit_block(body)); } ExprKind::Loop(block, opt_label, _) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_block(block); + visit_opt!(visitor, visit_label, opt_label); + try_visit!(visitor.visit_block(block)); } ExprKind::Match(subexpression, arms) => { - visitor.visit_expr(subexpression); + try_visit!(visitor.visit_expr(subexpression)); walk_list!(visitor, visit_arm, arms); } ExprKind::Closure(box Closure { @@ -887,112 +996,117 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { fn_decl_span: _, fn_arg_span: _, }) => { - visitor.visit_capture_by(capture_clause); - visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id) + try_visit!(visitor.visit_capture_by(capture_clause)); + try_visit!(visitor.visit_fn( + FnKind::Closure(binder, fn_decl, body), + expression.span, + expression.id + )) } ExprKind::Block(block, opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_block(block); + visit_opt!(visitor, visit_label, opt_label); + try_visit!(visitor.visit_block(block)); } - ExprKind::Gen(_, body, _) => { - visitor.visit_block(body); - } - ExprKind::Await(expr, _) => visitor.visit_expr(expr), + ExprKind::Gen(_, body, _) => try_visit!(visitor.visit_block(body)), + ExprKind::Await(expr, _) => try_visit!(visitor.visit_expr(expr)), ExprKind::Assign(lhs, rhs, _) => { - visitor.visit_expr(lhs); - visitor.visit_expr(rhs); + try_visit!(visitor.visit_expr(lhs)); + try_visit!(visitor.visit_expr(rhs)); } ExprKind::AssignOp(_, left_expression, right_expression) => { - visitor.visit_expr(left_expression); - visitor.visit_expr(right_expression); + try_visit!(visitor.visit_expr(left_expression)); + try_visit!(visitor.visit_expr(right_expression)); } ExprKind::Field(subexpression, ident) => { - visitor.visit_expr(subexpression); - visitor.visit_ident(*ident); + try_visit!(visitor.visit_expr(subexpression)); + try_visit!(visitor.visit_ident(*ident)); } ExprKind::Index(main_expression, index_expression, _) => { - visitor.visit_expr(main_expression); - visitor.visit_expr(index_expression) + try_visit!(visitor.visit_expr(main_expression)); + try_visit!(visitor.visit_expr(index_expression)); } ExprKind::Range(start, end, _) => { - walk_list!(visitor, visit_expr, start); - walk_list!(visitor, visit_expr, end); + visit_opt!(visitor, visit_expr, start); + visit_opt!(visitor, visit_expr, end); } ExprKind::Underscore => {} ExprKind::Path(maybe_qself, path) => { if let Some(qself) = maybe_qself { - visitor.visit_ty(&qself.ty); + try_visit!(visitor.visit_ty(&qself.ty)); } - visitor.visit_path(path, expression.id) + try_visit!(visitor.visit_path(path, expression.id)); } ExprKind::Break(opt_label, opt_expr) => { - walk_list!(visitor, visit_label, opt_label); - walk_list!(visitor, visit_expr, opt_expr); + visit_opt!(visitor, visit_label, opt_label); + visit_opt!(visitor, visit_expr, opt_expr); } ExprKind::Continue(opt_label) => { - walk_list!(visitor, visit_label, opt_label); + visit_opt!(visitor, visit_label, opt_label); } ExprKind::Ret(optional_expression) => { - walk_list!(visitor, visit_expr, optional_expression); + visit_opt!(visitor, visit_expr, optional_expression); } ExprKind::Yeet(optional_expression) => { - walk_list!(visitor, visit_expr, optional_expression); + visit_opt!(visitor, visit_expr, optional_expression); } - ExprKind::Become(expr) => visitor.visit_expr(expr), - ExprKind::MacCall(mac) => visitor.visit_mac_call(mac), - ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression), - ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm), - ExprKind::FormatArgs(f) => visitor.visit_format_args(f), + ExprKind::Become(expr) => try_visit!(visitor.visit_expr(expr)), + ExprKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), + ExprKind::Paren(subexpression) => try_visit!(visitor.visit_expr(subexpression)), + ExprKind::InlineAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), + ExprKind::FormatArgs(f) => try_visit!(visitor.visit_format_args(f)), ExprKind::OffsetOf(container, fields) => { visitor.visit_ty(container); - for &field in fields { - visitor.visit_ident(field); - } + walk_list!(visitor, visit_ident, fields.iter().copied()); } ExprKind::Yield(optional_expression) => { - walk_list!(visitor, visit_expr, optional_expression); + visit_opt!(visitor, visit_expr, optional_expression); } - ExprKind::Try(subexpression) => visitor.visit_expr(subexpression), - ExprKind::TryBlock(body) => visitor.visit_block(body), + ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), + ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)), ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err => {} } visitor.visit_expr_post(expression) } -pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) { - walk_list!(visitor, visit_attribute, param.attrs.iter()); - visitor.visit_pat(¶m.pat); - visitor.visit_ty(¶m.ty); +pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result { + walk_list!(visitor, visit_attribute, ¶m.attrs); + try_visit!(visitor.visit_pat(¶m.pat)); + try_visit!(visitor.visit_ty(¶m.ty)); + V::Result::output() } -pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) { - visitor.visit_pat(&arm.pat); - walk_list!(visitor, visit_expr, &arm.guard); - walk_list!(visitor, visit_expr, &arm.body); +pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result { + try_visit!(visitor.visit_pat(&arm.pat)); + visit_opt!(visitor, visit_expr, &arm.guard); + visit_opt!(visitor, visit_expr, &arm.body); walk_list!(visitor, visit_attribute, &arm.attrs); + V::Result::output() } -pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) { +pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result { if let VisibilityKind::Restricted { ref path, id, shorthand: _ } = vis.kind { - visitor.visit_path(path, id); + try_visit!(visitor.visit_path(path, id)); } + V::Result::output() } -pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) { +pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result { match &attr.kind { - AttrKind::Normal(normal) => walk_attr_args(visitor, &normal.item.args), + AttrKind::Normal(normal) => try_visit!(walk_attr_args(visitor, &normal.item.args)), AttrKind::DocComment(..) => {} } + V::Result::output() } -pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) { +pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result { match args { AttrArgs::Empty => {} AttrArgs::Delimited(_) => {} - AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => visitor.visit_expr(expr), + AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)), AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { unreachable!("in literal form when walking mac args eq: {:?}", lit) } } + V::Result::output() } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 0914452365856..f602276aad243 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -96,7 +96,7 @@ impl Annotatable { } } - pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { + pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result { match self { Annotatable::Item(item) => visitor.visit_item(item), Annotatable::TraitItem(item) => visitor.visit_assoc_item(item, AssocCtxt::Trait), diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 9c411be9ff938..2752d3ebd68b8 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -14,7 +14,8 @@ use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::visit::{self, AssocCtxt, Visitor}; +use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult}; +use rustc_ast::{try_visit, walk_list}; use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind}; use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId}; use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind}; @@ -143,16 +144,15 @@ macro_rules! ast_fragments { } } - pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { + pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result { match self { - AstFragment::OptExpr(Some(expr)) => visitor.visit_expr(expr), + AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)), AstFragment::OptExpr(None) => {} - AstFragment::MethodReceiverExpr(expr) => visitor.visit_method_receiver_expr(expr), - $($(AstFragment::$Kind(ast) => visitor.$visit_ast(ast),)?)* - $($(AstFragment::$Kind(ast) => for ast_elt in &ast[..] { - visitor.$visit_ast_elt(ast_elt, $($args)*); - })?)* + AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)), + $($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)* + $($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)* } + V::Result::output() } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index e9337dd3586ea..1c38a45d3a32f 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -65,7 +65,8 @@ //! example coroutine inference, and possibly also HIR borrowck. use crate::hir::*; -use rustc_ast::walk_list; +use rustc_ast::visit::VisitorResult; +use rustc_ast::{try_visit, visit_opt, walk_list}; use rustc_ast::{Attribute, Label}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{Ident, Symbol}; @@ -216,6 +217,10 @@ pub trait Visitor<'v>: Sized { /// and fixed appropriately. type NestedFilter: NestedFilter<'v> = nested_filter::None; + /// The result type of the `visit_*` methods. Can be either `()`, + /// or `ControlFlow`. + type Result: VisitorResult = (); + /// If `type NestedFilter` is set to visit nested items, this method /// must also be overridden to provide a map to retrieve nested items. fn nested_visit_map(&mut self) -> Self::Map { @@ -233,287 +238,299 @@ pub trait Visitor<'v>: Sized { /// [`rustc_hir::intravisit`]. The only reason to override /// this method is if you want a nested pattern but cannot supply a /// [`Map`]; see `nested_visit_map` for advice. - fn visit_nested_item(&mut self, id: ItemId) { + fn visit_nested_item(&mut self, id: ItemId) -> Self::Result { if Self::NestedFilter::INTER { let item = self.nested_visit_map().item(id); - self.visit_item(item); + try_visit!(self.visit_item(item)); } + Self::Result::output() } /// Like `visit_nested_item()`, but for trait items. See /// `visit_nested_item()` for advice on when to override this /// method. - fn visit_nested_trait_item(&mut self, id: TraitItemId) { + fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result { if Self::NestedFilter::INTER { let item = self.nested_visit_map().trait_item(id); - self.visit_trait_item(item); + try_visit!(self.visit_trait_item(item)); } + Self::Result::output() } /// Like `visit_nested_item()`, but for impl items. See /// `visit_nested_item()` for advice on when to override this /// method. - fn visit_nested_impl_item(&mut self, id: ImplItemId) { + fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result { if Self::NestedFilter::INTER { let item = self.nested_visit_map().impl_item(id); - self.visit_impl_item(item); + try_visit!(self.visit_impl_item(item)); } + Self::Result::output() } /// Like `visit_nested_item()`, but for foreign items. See /// `visit_nested_item()` for advice on when to override this /// method. - fn visit_nested_foreign_item(&mut self, id: ForeignItemId) { + fn visit_nested_foreign_item(&mut self, id: ForeignItemId) -> Self::Result { if Self::NestedFilter::INTER { let item = self.nested_visit_map().foreign_item(id); - self.visit_foreign_item(item); + try_visit!(self.visit_foreign_item(item)); } + Self::Result::output() } /// Invoked to visit the body of a function, method or closure. Like /// `visit_nested_item`, does nothing by default unless you override /// `Self::NestedFilter`. - fn visit_nested_body(&mut self, id: BodyId) { + fn visit_nested_body(&mut self, id: BodyId) -> Self::Result { if Self::NestedFilter::INTRA { let body = self.nested_visit_map().body(id); - self.visit_body(body); + try_visit!(self.visit_body(body)); } + Self::Result::output() } - fn visit_param(&mut self, param: &'v Param<'v>) { + fn visit_param(&mut self, param: &'v Param<'v>) -> Self::Result { walk_param(self, param) } /// Visits the top-level item and (optionally) nested items / impl items. See /// `visit_nested_item` for details. - fn visit_item(&mut self, i: &'v Item<'v>) { + fn visit_item(&mut self, i: &'v Item<'v>) -> Self::Result { walk_item(self, i) } - fn visit_body(&mut self, b: &'v Body<'v>) { - walk_body(self, b); + fn visit_body(&mut self, b: &'v Body<'v>) -> Self::Result { + walk_body(self, b) } /////////////////////////////////////////////////////////////////////////// - fn visit_id(&mut self, _hir_id: HirId) { - // Nothing to do. + fn visit_id(&mut self, _hir_id: HirId) -> Self::Result { + Self::Result::output() } - fn visit_name(&mut self, _name: Symbol) { - // Nothing to do. + fn visit_name(&mut self, _name: Symbol) -> Self::Result { + Self::Result::output() } - fn visit_ident(&mut self, ident: Ident) { + fn visit_ident(&mut self, ident: Ident) -> Self::Result { walk_ident(self, ident) } - fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, n: HirId) { + fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, n: HirId) -> Self::Result { walk_mod(self, m, n) } - fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) { + fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) -> Self::Result { walk_foreign_item(self, i) } - fn visit_local(&mut self, l: &'v Local<'v>) { + fn visit_local(&mut self, l: &'v Local<'v>) -> Self::Result { walk_local(self, l) } - fn visit_block(&mut self, b: &'v Block<'v>) { + fn visit_block(&mut self, b: &'v Block<'v>) -> Self::Result { walk_block(self, b) } - fn visit_stmt(&mut self, s: &'v Stmt<'v>) { + fn visit_stmt(&mut self, s: &'v Stmt<'v>) -> Self::Result { walk_stmt(self, s) } - fn visit_arm(&mut self, a: &'v Arm<'v>) { + fn visit_arm(&mut self, a: &'v Arm<'v>) -> Self::Result { walk_arm(self, a) } - fn visit_pat(&mut self, p: &'v Pat<'v>) { + fn visit_pat(&mut self, p: &'v Pat<'v>) -> Self::Result { walk_pat(self, p) } - fn visit_pat_field(&mut self, f: &'v PatField<'v>) { + fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result { walk_pat_field(self, f) } - fn visit_array_length(&mut self, len: &'v ArrayLen) { + fn visit_array_length(&mut self, len: &'v ArrayLen) -> Self::Result { walk_array_len(self, len) } - fn visit_anon_const(&mut self, c: &'v AnonConst) { + fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { walk_anon_const(self, c) } - fn visit_inline_const(&mut self, c: &'v ConstBlock) { + fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result { walk_inline_const(self, c) } - fn visit_expr(&mut self, ex: &'v Expr<'v>) { + fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result { walk_expr(self, ex) } - fn visit_expr_field(&mut self, field: &'v ExprField<'v>) { + fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result { walk_expr_field(self, field) } - fn visit_ty(&mut self, t: &'v Ty<'v>) { + fn visit_ty(&mut self, t: &'v Ty<'v>) -> Self::Result { walk_ty(self, t) } - fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) { + fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result { walk_generic_param(self, p) } - fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) { + fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) -> Self::Result { walk_const_param_default(self, ct) } - fn visit_generics(&mut self, g: &'v Generics<'v>) { + fn visit_generics(&mut self, g: &'v Generics<'v>) -> Self::Result { walk_generics(self, g) } - fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) { + fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) -> Self::Result { walk_where_predicate(self, predicate) } - fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) { + fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) -> Self::Result { walk_fn_ret_ty(self, ret_ty) } - fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) { + fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) -> Self::Result { walk_fn_decl(self, fd) } - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: LocalDefId) { + fn visit_fn( + &mut self, + fk: FnKind<'v>, + fd: &'v FnDecl<'v>, + b: BodyId, + _: Span, + id: LocalDefId, + ) -> Self::Result { walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) { + fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) -> Self::Result { walk_use(self, path, hir_id) } - fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) { + fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) -> Self::Result { walk_trait_item(self, ti) } - fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) { + fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) -> Self::Result { walk_trait_item_ref(self, ii) } - fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) { + fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) -> Self::Result { walk_impl_item(self, ii) } - fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) { + fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) -> Self::Result { walk_foreign_item_ref(self, ii) } - fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) { + fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) -> Self::Result { walk_impl_item_ref(self, ii) } - fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) { + fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) -> Self::Result { walk_trait_ref(self, t) } - fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) { + fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) -> Self::Result { walk_param_bound(self, bounds) } - fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) { + fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) -> Self::Result { walk_poly_trait_ref(self, t) } - fn visit_variant_data(&mut self, s: &'v VariantData<'v>) { + fn visit_variant_data(&mut self, s: &'v VariantData<'v>) -> Self::Result { walk_struct_def(self, s) } - fn visit_field_def(&mut self, s: &'v FieldDef<'v>) { + fn visit_field_def(&mut self, s: &'v FieldDef<'v>) -> Self::Result { walk_field_def(self, s) } - fn visit_enum_def(&mut self, enum_definition: &'v EnumDef<'v>, item_id: HirId) { + fn visit_enum_def(&mut self, enum_definition: &'v EnumDef<'v>, item_id: HirId) -> Self::Result { walk_enum_def(self, enum_definition, item_id) } - fn visit_variant(&mut self, v: &'v Variant<'v>) { + fn visit_variant(&mut self, v: &'v Variant<'v>) -> Self::Result { walk_variant(self, v) } - fn visit_label(&mut self, label: &'v Label) { + fn visit_label(&mut self, label: &'v Label) -> Self::Result { walk_label(self, label) } - fn visit_infer(&mut self, inf: &'v InferArg) { - walk_inf(self, inf); + fn visit_infer(&mut self, inf: &'v InferArg) -> Self::Result { + walk_inf(self, inf) } - fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) { - walk_generic_arg(self, generic_arg); + fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) -> Self::Result { + walk_generic_arg(self, generic_arg) } - fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result { walk_lifetime(self, lifetime) } // The span is that of the surrounding type/pattern/expr/whatever. - fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) { + fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) -> Self::Result { walk_qpath(self, qpath, id) } - fn visit_path(&mut self, path: &Path<'v>, _id: HirId) { + fn visit_path(&mut self, path: &Path<'v>, _id: HirId) -> Self::Result { walk_path(self, path) } - fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) { + fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) -> Self::Result { walk_path_segment(self, path_segment) } - fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) { + fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) -> Self::Result { walk_generic_args(self, generic_args) } - fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) { + fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) -> Self::Result { walk_assoc_type_binding(self, type_binding) } - fn visit_attribute(&mut self, _attr: &'v Attribute) {} - fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) { - walk_associated_item_kind(self, kind); + fn visit_attribute(&mut self, _attr: &'v Attribute) -> Self::Result { + Self::Result::output() + } + fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) -> Self::Result { + walk_associated_item_kind(self, kind) } - fn visit_defaultness(&mut self, defaultness: &'v Defaultness) { - walk_defaultness(self, defaultness); + fn visit_defaultness(&mut self, defaultness: &'v Defaultness) -> Self::Result { + walk_defaultness(self, defaultness) } - fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, id: HirId) { - walk_inline_asm(self, asm, id); + fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, id: HirId) -> Self::Result { + walk_inline_asm(self, asm, id) } } -pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) { - visitor.visit_id(param.hir_id); - visitor.visit_pat(param.pat); +pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result { + try_visit!(visitor.visit_id(param.hir_id)); + visitor.visit_pat(param.pat) } -pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { - visitor.visit_ident(item.ident); +pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::Result { + try_visit!(visitor.visit_ident(item.ident)); match item.kind { ItemKind::ExternCrate(orig_name) => { - visitor.visit_id(item.hir_id()); - if let Some(orig_name) = orig_name { - visitor.visit_name(orig_name); - } + try_visit!(visitor.visit_id(item.hir_id())); + visit_opt!(visitor, visit_name, orig_name); } ItemKind::Use(ref path, _) => { - visitor.visit_use(path, item.hir_id()); + try_visit!(visitor.visit_use(path, item.hir_id())); } ItemKind::Static(ref typ, _, body) => { - visitor.visit_id(item.hir_id()); - visitor.visit_ty(typ); - visitor.visit_nested_body(body); + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_ty(typ)); + try_visit!(visitor.visit_nested_body(body)); } ItemKind::Const(ref typ, ref generics, body) => { - visitor.visit_id(item.hir_id()); - visitor.visit_ty(typ); - visitor.visit_generics(generics); - visitor.visit_nested_body(body); + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_ty(typ)); + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_nested_body(body)); } ItemKind::Fn(ref sig, ref generics, body_id) => { - visitor.visit_id(item.hir_id()); - visitor.visit_fn( + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_fn( FnKind::ItemFn(item.ident, generics, sig.header), sig.decl, body_id, item.span, item.owner_id.def_id, - ) + )); } ItemKind::Macro(..) => { - visitor.visit_id(item.hir_id()); + try_visit!(visitor.visit_id(item.hir_id())); } ItemKind::Mod(ref module) => { // `visit_mod()` takes care of visiting the `Item`'s `HirId`. - visitor.visit_mod(module, item.span, item.hir_id()) + try_visit!(visitor.visit_mod(module, item.span, item.hir_id())); } ItemKind::ForeignMod { abi: _, items } => { - visitor.visit_id(item.hir_id()); + try_visit!(visitor.visit_id(item.hir_id())); walk_list!(visitor, visit_foreign_item_ref, items); } ItemKind::GlobalAsm(asm) => { - visitor.visit_id(item.hir_id()); - visitor.visit_inline_asm(asm, item.hir_id()); + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_inline_asm(asm, item.hir_id())); } ItemKind::TyAlias(ref ty, ref generics) => { - visitor.visit_id(item.hir_id()); - visitor.visit_ty(ty); - visitor.visit_generics(generics) + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_generics(generics)); } ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => { - visitor.visit_id(item.hir_id()); - walk_generics(visitor, generics); + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(walk_generics(visitor, generics)); walk_list!(visitor, visit_param_bound, bounds); } ItemKind::Enum(ref enum_definition, ref generics) => { - visitor.visit_generics(generics); + try_visit!(visitor.visit_generics(generics)); // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`. - visitor.visit_enum_def(enum_definition, item.hir_id()) + try_visit!(visitor.visit_enum_def(enum_definition, item.hir_id())); } ItemKind::Impl(Impl { unsafety: _, @@ -525,85 +542,91 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { ref self_ty, items, }) => { - visitor.visit_id(item.hir_id()); - visitor.visit_generics(generics); - walk_list!(visitor, visit_trait_ref, of_trait); - visitor.visit_ty(self_ty); + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_generics(generics)); + visit_opt!(visitor, visit_trait_ref, of_trait); + try_visit!(visitor.visit_ty(self_ty)); walk_list!(visitor, visit_impl_item_ref, *items); } ItemKind::Struct(ref struct_definition, ref generics) | ItemKind::Union(ref struct_definition, ref generics) => { - visitor.visit_generics(generics); - visitor.visit_id(item.hir_id()); - visitor.visit_variant_data(struct_definition); + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_variant_data(struct_definition)); } ItemKind::Trait(.., ref generics, bounds, trait_item_refs) => { - visitor.visit_id(item.hir_id()); - visitor.visit_generics(generics); + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } ItemKind::TraitAlias(ref generics, bounds) => { - visitor.visit_id(item.hir_id()); - visitor.visit_generics(generics); + try_visit!(visitor.visit_id(item.hir_id())); + try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); } } + V::Result::output() } -pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) { +pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) -> V::Result { walk_list!(visitor, visit_param, body.params); - visitor.visit_expr(body.value); + visitor.visit_expr(body.value) } -pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) { - visitor.visit_name(ident.name); +pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) -> V::Result { + visitor.visit_name(ident.name) } -pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) { - visitor.visit_id(mod_hir_id); - for &item_id in module.item_ids { - visitor.visit_nested_item(item_id); - } +pub fn walk_mod<'v, V: Visitor<'v>>( + visitor: &mut V, + module: &'v Mod<'v>, + mod_hir_id: HirId, +) -> V::Result { + try_visit!(visitor.visit_id(mod_hir_id)); + walk_list!(visitor, visit_nested_item, module.item_ids.iter().copied()); + V::Result::output() } -pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) { - visitor.visit_id(foreign_item.hir_id()); - visitor.visit_ident(foreign_item.ident); +pub fn walk_foreign_item<'v, V: Visitor<'v>>( + visitor: &mut V, + foreign_item: &'v ForeignItem<'v>, +) -> V::Result { + try_visit!(visitor.visit_id(foreign_item.hir_id())); + try_visit!(visitor.visit_ident(foreign_item.ident)); match foreign_item.kind { ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => { - visitor.visit_generics(generics); - visitor.visit_fn_decl(function_declaration); - for ¶m_name in param_names { - visitor.visit_ident(param_name); - } + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_fn_decl(function_declaration)); + walk_list!(visitor, visit_ident, param_names.iter().copied()); } - ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), + ForeignItemKind::Static(ref typ, _) => try_visit!(visitor.visit_ty(typ)), ForeignItemKind::Type => (), } + V::Result::output() } -pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) { +pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) -> V::Result { // Intentionally visiting the expr first - the initialization expr // dominates the local's definition. - walk_list!(visitor, visit_expr, &local.init); - visitor.visit_id(local.hir_id); - visitor.visit_pat(local.pat); - if let Some(els) = local.els { - visitor.visit_block(els); - } - walk_list!(visitor, visit_ty, &local.ty); + visit_opt!(visitor, visit_expr, local.init); + try_visit!(visitor.visit_id(local.hir_id)); + try_visit!(visitor.visit_pat(local.pat)); + visit_opt!(visitor, visit_block, local.els); + visit_opt!(visitor, visit_ty, local.ty); + V::Result::output() } -pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) { - visitor.visit_id(block.hir_id); +pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) -> V::Result { + try_visit!(visitor.visit_id(block.hir_id)); walk_list!(visitor, visit_stmt, block.stmts); - walk_list!(visitor, visit_expr, &block.expr); + visit_opt!(visitor, visit_expr, block.expr); + V::Result::output() } -pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) { - visitor.visit_id(statement.hir_id); +pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) -> V::Result { + try_visit!(visitor.visit_id(statement.hir_id)); match statement.kind { StmtKind::Local(ref local) => visitor.visit_local(local), StmtKind::Item(item) => visitor.visit_nested_item(item), @@ -613,27 +636,25 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) { } } -pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) { - visitor.visit_id(arm.hir_id); - visitor.visit_pat(arm.pat); - if let Some(ref e) = arm.guard { - visitor.visit_expr(e); - } - visitor.visit_expr(arm.body); +pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Result { + try_visit!(visitor.visit_id(arm.hir_id)); + try_visit!(visitor.visit_pat(arm.pat)); + visit_opt!(visitor, visit_expr, arm.guard); + visitor.visit_expr(arm.body) } -pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { - visitor.visit_id(pattern.hir_id); +pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result { + try_visit!(visitor.visit_id(pattern.hir_id)); match pattern.kind { PatKind::TupleStruct(ref qpath, children, _) => { - visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); + try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span)); walk_list!(visitor, visit_pat, children); } PatKind::Path(ref qpath) => { - visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); + try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span)); } PatKind::Struct(ref qpath, fields, _) => { - visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); + try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span)); walk_list!(visitor, visit_pat_field, fields); } PatKind::Or(pats) => walk_list!(visitor, visit_pat, pats), @@ -641,33 +662,34 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) { walk_list!(visitor, visit_pat, tuple_elements); } PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) => { - visitor.visit_pat(subpattern) + try_visit!(visitor.visit_pat(subpattern)); } PatKind::Binding(_, _hir_id, ident, ref optional_subpattern) => { - visitor.visit_ident(ident); - walk_list!(visitor, visit_pat, optional_subpattern); + try_visit!(visitor.visit_ident(ident)); + visit_opt!(visitor, visit_pat, optional_subpattern); } - PatKind::Lit(ref expression) => visitor.visit_expr(expression), + PatKind::Lit(ref expression) => try_visit!(visitor.visit_expr(expression)), PatKind::Range(ref lower_bound, ref upper_bound, _) => { - walk_list!(visitor, visit_expr, lower_bound); - walk_list!(visitor, visit_expr, upper_bound); + visit_opt!(visitor, visit_expr, lower_bound); + visit_opt!(visitor, visit_expr, upper_bound); } PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { walk_list!(visitor, visit_pat, prepatterns); - walk_list!(visitor, visit_pat, slice_pattern); + visit_opt!(visitor, visit_pat, slice_pattern); walk_list!(visitor, visit_pat, postpatterns); } } + V::Result::output() } -pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) { - visitor.visit_id(field.hir_id); - visitor.visit_ident(field.ident); +pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) -> V::Result { + try_visit!(visitor.visit_id(field.hir_id)); + try_visit!(visitor.visit_ident(field.ident)); visitor.visit_pat(field.pat) } -pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { +pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) -> V::Result { match len { // FIXME: Use `visit_infer` here. ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), @@ -675,75 +697,80 @@ pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { } } -pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) { - visitor.visit_id(constant.hir_id); - visitor.visit_nested_body(constant.body); +pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result { + try_visit!(visitor.visit_id(constant.hir_id)); + visitor.visit_nested_body(constant.body) } -pub fn walk_inline_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v ConstBlock) { - visitor.visit_id(constant.hir_id); - visitor.visit_nested_body(constant.body); +pub fn walk_inline_const<'v, V: Visitor<'v>>( + visitor: &mut V, + constant: &'v ConstBlock, +) -> V::Result { + try_visit!(visitor.visit_id(constant.hir_id)); + visitor.visit_nested_body(constant.body) } -pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) { - visitor.visit_id(expression.hir_id); +pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result { + try_visit!(visitor.visit_id(expression.hir_id)); match expression.kind { ExprKind::Array(subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } - ExprKind::ConstBlock(ref const_block) => visitor.visit_inline_const(const_block), + ExprKind::ConstBlock(ref const_block) => { + try_visit!(visitor.visit_inline_const(const_block)) + } ExprKind::Repeat(ref element, ref count) => { - visitor.visit_expr(element); - visitor.visit_array_length(count) + try_visit!(visitor.visit_expr(element)); + try_visit!(visitor.visit_array_length(count)); } ExprKind::Struct(ref qpath, fields, ref optional_base) => { - visitor.visit_qpath(qpath, expression.hir_id, expression.span); + try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span)); walk_list!(visitor, visit_expr_field, fields); - walk_list!(visitor, visit_expr, optional_base); + visit_opt!(visitor, visit_expr, optional_base); } ExprKind::Tup(subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } ExprKind::Call(ref callee_expression, arguments) => { - visitor.visit_expr(callee_expression); + try_visit!(visitor.visit_expr(callee_expression)); walk_list!(visitor, visit_expr, arguments); } ExprKind::MethodCall(ref segment, receiver, arguments, _) => { - visitor.visit_path_segment(segment); - visitor.visit_expr(receiver); + try_visit!(visitor.visit_path_segment(segment)); + try_visit!(visitor.visit_expr(receiver)); walk_list!(visitor, visit_expr, arguments); } ExprKind::Binary(_, ref left_expression, ref right_expression) => { - visitor.visit_expr(left_expression); - visitor.visit_expr(right_expression) + try_visit!(visitor.visit_expr(left_expression)); + try_visit!(visitor.visit_expr(right_expression)); } ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { - visitor.visit_expr(subexpression) + try_visit!(visitor.visit_expr(subexpression)); } ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { - visitor.visit_expr(subexpression); - visitor.visit_ty(typ) + try_visit!(visitor.visit_expr(subexpression)); + try_visit!(visitor.visit_ty(typ)); } ExprKind::DropTemps(ref subexpression) => { - visitor.visit_expr(subexpression); + try_visit!(visitor.visit_expr(subexpression)); } ExprKind::Let(Let { span: _, pat, ty, init, is_recovered: _ }) => { // match the visit order in walk_local - visitor.visit_expr(init); - visitor.visit_pat(pat); - walk_list!(visitor, visit_ty, ty); + try_visit!(visitor.visit_expr(init)); + try_visit!(visitor.visit_pat(pat)); + visit_opt!(visitor, visit_ty, ty); } ExprKind::If(ref cond, ref then, ref else_opt) => { - visitor.visit_expr(cond); - visitor.visit_expr(then); - walk_list!(visitor, visit_expr, else_opt); + try_visit!(visitor.visit_expr(cond)); + try_visit!(visitor.visit_expr(then)); + visit_opt!(visitor, visit_expr, else_opt); } ExprKind::Loop(ref block, ref opt_label, _, _) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_block(block); + visit_opt!(visitor, visit_label, opt_label); + try_visit!(visitor.visit_block(block)); } ExprKind::Match(ref subexpression, arms, _) => { - visitor.visit_expr(subexpression); + try_visit!(visitor.visit_expr(subexpression)); walk_list!(visitor, visit_arm, arms); } ExprKind::Closure(&Closure { @@ -759,71 +786,72 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) constness: _, }) => { walk_list!(visitor, visit_generic_param, bound_generic_params); - visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, def_id) + try_visit!(visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, def_id)); } ExprKind::Block(ref block, ref opt_label) => { - walk_list!(visitor, visit_label, opt_label); - visitor.visit_block(block); + visit_opt!(visitor, visit_label, opt_label); + try_visit!(visitor.visit_block(block)); } ExprKind::Assign(ref lhs, ref rhs, _) => { - visitor.visit_expr(rhs); - visitor.visit_expr(lhs) + try_visit!(visitor.visit_expr(rhs)); + try_visit!(visitor.visit_expr(lhs)); } ExprKind::AssignOp(_, ref left_expression, ref right_expression) => { - visitor.visit_expr(right_expression); - visitor.visit_expr(left_expression); + try_visit!(visitor.visit_expr(right_expression)); + try_visit!(visitor.visit_expr(left_expression)); } ExprKind::Field(ref subexpression, ident) => { - visitor.visit_expr(subexpression); - visitor.visit_ident(ident); + try_visit!(visitor.visit_expr(subexpression)); + try_visit!(visitor.visit_ident(ident)); } ExprKind::Index(ref main_expression, ref index_expression, _) => { - visitor.visit_expr(main_expression); - visitor.visit_expr(index_expression) + try_visit!(visitor.visit_expr(main_expression)); + try_visit!(visitor.visit_expr(index_expression)); } ExprKind::Path(ref qpath) => { - visitor.visit_qpath(qpath, expression.hir_id, expression.span); + try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span)); } ExprKind::Break(ref destination, ref opt_expr) => { - walk_list!(visitor, visit_label, &destination.label); - walk_list!(visitor, visit_expr, opt_expr); + visit_opt!(visitor, visit_label, &destination.label); + visit_opt!(visitor, visit_expr, opt_expr); } ExprKind::Continue(ref destination) => { - walk_list!(visitor, visit_label, &destination.label); + visit_opt!(visitor, visit_label, &destination.label); } ExprKind::Ret(ref optional_expression) => { - walk_list!(visitor, visit_expr, optional_expression); + visit_opt!(visitor, visit_expr, optional_expression); } - ExprKind::Become(ref expr) => visitor.visit_expr(expr), + ExprKind::Become(ref expr) => try_visit!(visitor.visit_expr(expr)), ExprKind::InlineAsm(ref asm) => { - visitor.visit_inline_asm(asm, expression.hir_id); + try_visit!(visitor.visit_inline_asm(asm, expression.hir_id)); } ExprKind::OffsetOf(ref container, ref fields) => { - visitor.visit_ty(container); + try_visit!(visitor.visit_ty(container)); walk_list!(visitor, visit_ident, fields.iter().copied()); } ExprKind::Yield(ref subexpression, _) => { - visitor.visit_expr(subexpression); + try_visit!(visitor.visit_expr(subexpression)); } ExprKind::Lit(_) | ExprKind::Err(_) => {} } + V::Result::output() } -pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) { - visitor.visit_id(field.hir_id); - visitor.visit_ident(field.ident); +pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) -> V::Result { + try_visit!(visitor.visit_id(field.hir_id)); + try_visit!(visitor.visit_ident(field.ident)); visitor.visit_expr(field.expr) } -pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { - visitor.visit_id(typ.hir_id); +pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Result { + try_visit!(visitor.visit_id(typ.hir_id)); match typ.kind { - TyKind::Slice(ref ty) => visitor.visit_ty(ty), - TyKind::Ptr(ref mutable_type) => visitor.visit_ty(mutable_type.ty), + TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty(ty)), + TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty(mutable_type.ty)), TyKind::Ref(ref lifetime, ref mutable_type) => { - visitor.visit_lifetime(lifetime); - visitor.visit_ty(mutable_type.ty) + try_visit!(visitor.visit_lifetime(lifetime)); + try_visit!(visitor.visit_ty(mutable_type.ty)); } TyKind::Never => {} TyKind::Tup(tuple_element_types) => { @@ -831,64 +859,71 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { } TyKind::BareFn(ref function_declaration) => { walk_list!(visitor, visit_generic_param, function_declaration.generic_params); - visitor.visit_fn_decl(function_declaration.decl); + try_visit!(visitor.visit_fn_decl(function_declaration.decl)); } TyKind::Path(ref qpath) => { - visitor.visit_qpath(qpath, typ.hir_id, typ.span); + try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span)); } TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { - visitor.visit_nested_item(item_id); + try_visit!(visitor.visit_nested_item(item_id)); walk_list!(visitor, visit_generic_arg, lifetimes); } TyKind::Array(ref ty, ref length) => { - visitor.visit_ty(ty); - visitor.visit_array_length(length) + try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_array_length(length)); } TyKind::TraitObject(bounds, ref lifetime, _syntax) => { - for bound in bounds { - visitor.visit_poly_trait_ref(bound); - } - visitor.visit_lifetime(lifetime); + walk_list!(visitor, visit_poly_trait_ref, bounds); + try_visit!(visitor.visit_lifetime(lifetime)); } - TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), + TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)), TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {} TyKind::AnonAdt(item_id) => { - visitor.visit_nested_item(item_id); + try_visit!(visitor.visit_nested_item(item_id)); } } + V::Result::output() } -pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam<'v>) { - visitor.visit_id(param.hir_id); +pub fn walk_generic_param<'v, V: Visitor<'v>>( + visitor: &mut V, + param: &'v GenericParam<'v>, +) -> V::Result { + try_visit!(visitor.visit_id(param.hir_id)); match param.name { - ParamName::Plain(ident) => visitor.visit_ident(ident), + ParamName::Plain(ident) => try_visit!(visitor.visit_ident(ident)), ParamName::Error | ParamName::Fresh => {} } match param.kind { GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default), + GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default), GenericParamKind::Const { ref ty, ref default, is_host_effect: _ } => { - visitor.visit_ty(ty); + try_visit!(visitor.visit_ty(ty)); if let Some(ref default) = default { visitor.visit_const_param_default(param.hir_id, default); } } } + V::Result::output() } -pub fn walk_const_param_default<'v, V: Visitor<'v>>(visitor: &mut V, ct: &'v AnonConst) { +pub fn walk_const_param_default<'v, V: Visitor<'v>>( + visitor: &mut V, + ct: &'v AnonConst, +) -> V::Result { visitor.visit_anon_const(ct) } -pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) { +pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result { walk_list!(visitor, visit_generic_param, generics.params); walk_list!(visitor, visit_where_predicate, generics.predicates); + V::Result::output() } pub fn walk_where_predicate<'v, V: Visitor<'v>>( visitor: &mut V, predicate: &'v WherePredicate<'v>, -) { +) -> V::Result { match *predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { hir_id, @@ -898,8 +933,8 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( origin: _, span: _, }) => { - visitor.visit_id(hir_id); - visitor.visit_ty(bounded_ty); + try_visit!(visitor.visit_id(hir_id)); + try_visit!(visitor.visit_ty(bounded_ty)); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); } @@ -909,27 +944,30 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( span: _, in_where_clause: _, }) => { - visitor.visit_lifetime(lifetime); + try_visit!(visitor.visit_lifetime(lifetime)); walk_list!(visitor, visit_param_bound, bounds); } WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span: _ }) => { - visitor.visit_ty(lhs_ty); - visitor.visit_ty(rhs_ty); + try_visit!(visitor.visit_ty(lhs_ty)); + try_visit!(visitor.visit_ty(rhs_ty)); } } + V::Result::output() } -pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl<'v>) { - for ty in function_declaration.inputs { - visitor.visit_ty(ty) - } +pub fn walk_fn_decl<'v, V: Visitor<'v>>( + visitor: &mut V, + function_declaration: &'v FnDecl<'v>, +) -> V::Result { + walk_list!(visitor, visit_ty, function_declaration.inputs); visitor.visit_fn_ret_ty(&function_declaration.output) } -pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) { - if let FnRetTy::Return(ref output_ty) = *ret_ty { - visitor.visit_ty(output_ty) +pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) -> V::Result { + if let FnRetTy::Return(output_ty) = *ret_ty { + try_visit!(visitor.visit_ty(output_ty)); } + V::Result::output() } pub fn walk_fn<'v, V: Visitor<'v>>( @@ -938,73 +976,87 @@ pub fn walk_fn<'v, V: Visitor<'v>>( function_declaration: &'v FnDecl<'v>, body_id: BodyId, _: LocalDefId, -) { - visitor.visit_fn_decl(function_declaration); - walk_fn_kind(visitor, function_kind); +) -> V::Result { + try_visit!(visitor.visit_fn_decl(function_declaration)); + try_visit!(walk_fn_kind(visitor, function_kind)); visitor.visit_nested_body(body_id) } -pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) { +pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) -> V::Result { match function_kind { FnKind::ItemFn(_, generics, ..) => { - visitor.visit_generics(generics); + try_visit!(visitor.visit_generics(generics)); } FnKind::Closure | FnKind::Method(..) => {} } + V::Result::output() } -pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v UsePath<'v>, hir_id: HirId) { - visitor.visit_id(hir_id); +pub fn walk_use<'v, V: Visitor<'v>>( + visitor: &mut V, + path: &'v UsePath<'v>, + hir_id: HirId, +) -> V::Result { + try_visit!(visitor.visit_id(hir_id)); let UsePath { segments, ref res, span } = *path; for &res in res { - visitor.visit_path(&Path { segments, res, span }, hir_id); + try_visit!(visitor.visit_path(&Path { segments, res, span }, hir_id)); } + V::Result::output() } -pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) { +pub fn walk_trait_item<'v, V: Visitor<'v>>( + visitor: &mut V, + trait_item: &'v TraitItem<'v>, +) -> V::Result { // N.B., deliberately force a compilation error if/when new fields are added. let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item; let hir_id = trait_item.hir_id(); - visitor.visit_ident(ident); - visitor.visit_generics(&generics); - visitor.visit_defaultness(&defaultness); - visitor.visit_id(hir_id); + try_visit!(visitor.visit_ident(ident)); + try_visit!(visitor.visit_generics(&generics)); + try_visit!(visitor.visit_defaultness(&defaultness)); + try_visit!(visitor.visit_id(hir_id)); match *kind { TraitItemKind::Const(ref ty, default) => { - visitor.visit_ty(ty); - walk_list!(visitor, visit_nested_body, default); + try_visit!(visitor.visit_ty(ty)); + visit_opt!(visitor, visit_nested_body, default); } TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { - visitor.visit_fn_decl(sig.decl); - for ¶m_name in param_names { - visitor.visit_ident(param_name); - } + try_visit!(visitor.visit_fn_decl(sig.decl)); + walk_list!(visitor, visit_ident, param_names.iter().copied()); } TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { - visitor.visit_fn( + try_visit!(visitor.visit_fn( FnKind::Method(ident, sig), sig.decl, body_id, span, trait_item.owner_id.def_id, - ); + )); } TraitItemKind::Type(bounds, ref default) => { walk_list!(visitor, visit_param_bound, bounds); - walk_list!(visitor, visit_ty, default); + visit_opt!(visitor, visit_ty, default); } } + V::Result::output() } -pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) { +pub fn walk_trait_item_ref<'v, V: Visitor<'v>>( + visitor: &mut V, + trait_item_ref: &'v TraitItemRef, +) -> V::Result { // N.B., deliberately force a compilation error if/when new fields are added. let TraitItemRef { id, ident, ref kind, span: _ } = *trait_item_ref; - visitor.visit_nested_trait_item(id); - visitor.visit_ident(ident); - visitor.visit_associated_item_kind(kind); + try_visit!(visitor.visit_nested_trait_item(id)); + try_visit!(visitor.visit_ident(ident)); + visitor.visit_associated_item_kind(kind) } -pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) { +pub fn walk_impl_item<'v, V: Visitor<'v>>( + visitor: &mut V, + impl_item: &'v ImplItem<'v>, +) -> V::Result { // N.B., deliberately force a compilation error if/when new fields are added. let ImplItem { owner_id: _, @@ -1016,106 +1068,118 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt vis_span: _, } = *impl_item; - visitor.visit_ident(ident); - visitor.visit_generics(generics); - visitor.visit_defaultness(defaultness); - visitor.visit_id(impl_item.hir_id()); + try_visit!(visitor.visit_ident(ident)); + try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_defaultness(defaultness)); + try_visit!(visitor.visit_id(impl_item.hir_id())); match *kind { ImplItemKind::Const(ref ty, body) => { - visitor.visit_ty(ty); - visitor.visit_nested_body(body); - } - ImplItemKind::Fn(ref sig, body_id) => { - visitor.visit_fn( - FnKind::Method(impl_item.ident, sig), - sig.decl, - body_id, - impl_item.span, - impl_item.owner_id.def_id, - ); - } - ImplItemKind::Type(ref ty) => { - visitor.visit_ty(ty); - } + try_visit!(visitor.visit_ty(ty)); + visitor.visit_nested_body(body) + } + ImplItemKind::Fn(ref sig, body_id) => visitor.visit_fn( + FnKind::Method(impl_item.ident, sig), + sig.decl, + body_id, + impl_item.span, + impl_item.owner_id.def_id, + ), + ImplItemKind::Type(ref ty) => visitor.visit_ty(ty), } } pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>( visitor: &mut V, foreign_item_ref: &'v ForeignItemRef, -) { +) -> V::Result { // N.B., deliberately force a compilation error if/when new fields are added. let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref; - visitor.visit_nested_foreign_item(id); - visitor.visit_ident(ident); + try_visit!(visitor.visit_nested_foreign_item(id)); + visitor.visit_ident(ident) } -pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) { +pub fn walk_impl_item_ref<'v, V: Visitor<'v>>( + visitor: &mut V, + impl_item_ref: &'v ImplItemRef, +) -> V::Result { // N.B., deliberately force a compilation error if/when new fields are added. let ImplItemRef { id, ident, ref kind, span: _, trait_item_def_id: _ } = *impl_item_ref; - visitor.visit_nested_impl_item(id); - visitor.visit_ident(ident); - visitor.visit_associated_item_kind(kind); + try_visit!(visitor.visit_nested_impl_item(id)); + try_visit!(visitor.visit_ident(ident)); + visitor.visit_associated_item_kind(kind) } -pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) { - visitor.visit_id(trait_ref.hir_ref_id); +pub fn walk_trait_ref<'v, V: Visitor<'v>>( + visitor: &mut V, + trait_ref: &'v TraitRef<'v>, +) -> V::Result { + try_visit!(visitor.visit_id(trait_ref.hir_ref_id)); visitor.visit_path(trait_ref.path, trait_ref.hir_ref_id) } -pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) { +pub fn walk_param_bound<'v, V: Visitor<'v>>( + visitor: &mut V, + bound: &'v GenericBound<'v>, +) -> V::Result { match *bound { - GenericBound::Trait(ref typ, _modifier) => { - visitor.visit_poly_trait_ref(typ); - } + GenericBound::Trait(ref typ, _modifier) => visitor.visit_poly_trait_ref(typ), GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), } } -pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) { +pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>( + visitor: &mut V, + trait_ref: &'v PolyTraitRef<'v>, +) -> V::Result { walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params); - visitor.visit_trait_ref(&trait_ref.trait_ref); + visitor.visit_trait_ref(&trait_ref.trait_ref) } pub fn walk_struct_def<'v, V: Visitor<'v>>( visitor: &mut V, struct_definition: &'v VariantData<'v>, -) { - walk_list!(visitor, visit_id, struct_definition.ctor_hir_id()); +) -> V::Result { + visit_opt!(visitor, visit_id, struct_definition.ctor_hir_id()); walk_list!(visitor, visit_field_def, struct_definition.fields()); + V::Result::output() } -pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) { - visitor.visit_id(field.hir_id); - visitor.visit_ident(field.ident); - visitor.visit_ty(field.ty); +pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) -> V::Result { + try_visit!(visitor.visit_id(field.hir_id)); + try_visit!(visitor.visit_ident(field.ident)); + visitor.visit_ty(field.ty) } pub fn walk_enum_def<'v, V: Visitor<'v>>( visitor: &mut V, enum_definition: &'v EnumDef<'v>, item_id: HirId, -) { - visitor.visit_id(item_id); +) -> V::Result { + try_visit!(visitor.visit_id(item_id)); walk_list!(visitor, visit_variant, enum_definition.variants); + V::Result::output() } -pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) { - visitor.visit_ident(variant.ident); - visitor.visit_id(variant.hir_id); - visitor.visit_variant_data(&variant.data); - walk_list!(visitor, visit_anon_const, &variant.disr_expr); +pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) -> V::Result { + try_visit!(visitor.visit_ident(variant.ident)); + try_visit!(visitor.visit_id(variant.hir_id)); + try_visit!(visitor.visit_variant_data(&variant.data)); + visit_opt!(visitor, visit_anon_const, &variant.disr_expr); + V::Result::output() } -pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) { - visitor.visit_ident(label.ident); +pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) -> V::Result { + visitor.visit_ident(label.ident) } -pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) { - visitor.visit_id(inf.hir_id); +pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) -> V::Result { + visitor.visit_id(inf.hir_id) } -pub fn walk_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v GenericArg<'v>) { +pub fn walk_generic_arg<'v, V: Visitor<'v>>( + visitor: &mut V, + generic_arg: &'v GenericArg<'v>, +) -> V::Result { match generic_arg { GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt), GenericArg::Type(ty) => visitor.visit_ty(ty), @@ -1124,92 +1188,109 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v Ge } } -pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) { - visitor.visit_id(lifetime.hir_id); - visitor.visit_ident(lifetime.ident); +pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) -> V::Result { + try_visit!(visitor.visit_id(lifetime.hir_id)); + visitor.visit_ident(lifetime.ident) } -pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) { +pub fn walk_qpath<'v, V: Visitor<'v>>( + visitor: &mut V, + qpath: &'v QPath<'v>, + id: HirId, +) -> V::Result { match *qpath { QPath::Resolved(ref maybe_qself, ref path) => { - walk_list!(visitor, visit_ty, maybe_qself); + visit_opt!(visitor, visit_ty, maybe_qself); visitor.visit_path(path, id) } QPath::TypeRelative(ref qself, ref segment) => { - visitor.visit_ty(qself); - visitor.visit_path_segment(segment); + try_visit!(visitor.visit_ty(qself)); + visitor.visit_path_segment(segment) } - QPath::LangItem(..) => {} + QPath::LangItem(..) => V::Result::output(), } } -pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) { - for segment in path.segments { - visitor.visit_path_segment(segment); - } +pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) -> V::Result { + walk_list!(visitor, visit_path_segment, path.segments); + V::Result::output() } -pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, segment: &'v PathSegment<'v>) { - visitor.visit_ident(segment.ident); - visitor.visit_id(segment.hir_id); - if let Some(ref args) = segment.args { - visitor.visit_generic_args(args); - } +pub fn walk_path_segment<'v, V: Visitor<'v>>( + visitor: &mut V, + segment: &'v PathSegment<'v>, +) -> V::Result { + try_visit!(visitor.visit_ident(segment.ident)); + try_visit!(visitor.visit_id(segment.hir_id)); + visit_opt!(visitor, visit_generic_args, segment.args); + V::Result::output() } -pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V, generic_args: &'v GenericArgs<'v>) { +pub fn walk_generic_args<'v, V: Visitor<'v>>( + visitor: &mut V, + generic_args: &'v GenericArgs<'v>, +) -> V::Result { walk_list!(visitor, visit_generic_arg, generic_args.args); walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings); + V::Result::output() } pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( visitor: &mut V, type_binding: &'v TypeBinding<'v>, -) { - visitor.visit_id(type_binding.hir_id); - visitor.visit_ident(type_binding.ident); - visitor.visit_generic_args(type_binding.gen_args); +) -> V::Result { + try_visit!(visitor.visit_id(type_binding.hir_id)); + try_visit!(visitor.visit_ident(type_binding.ident)); + try_visit!(visitor.visit_generic_args(type_binding.gen_args)); match type_binding.kind { TypeBindingKind::Equality { ref term } => match term { - Term::Ty(ref ty) => visitor.visit_ty(ty), - Term::Const(ref c) => visitor.visit_anon_const(c), + Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)), + Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)), }, TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds), } + V::Result::output() } -pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) { +pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) -> V::Result { // No visitable content here: this fn exists so you can call it if // the right thing to do, should content be added in the future, // would be to walk it. + V::Result::output() } -pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) { +pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) -> V::Result { // No visitable content here: this fn exists so you can call it if // the right thing to do, should content be added in the future, // would be to walk it. + V::Result::output() } -pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) { +pub fn walk_inline_asm<'v, V: Visitor<'v>>( + visitor: &mut V, + asm: &'v InlineAsm<'v>, + id: HirId, +) -> V::Result { for (op, op_sp) in asm.operands { match op { InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => { - visitor.visit_expr(expr) + try_visit!(visitor.visit_expr(expr)); } InlineAsmOperand::Out { expr, .. } => { - if let Some(expr) = expr { - visitor.visit_expr(expr); - } + visit_opt!(visitor, visit_expr, expr); } InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { - visitor.visit_expr(in_expr); - if let Some(out_expr) = out_expr { - visitor.visit_expr(out_expr); - } + try_visit!(visitor.visit_expr(in_expr)); + visit_opt!(visitor, visit_expr, out_expr); } InlineAsmOperand::Const { anon_const, .. } - | InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const), - InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp), + | InlineAsmOperand::SymFn { anon_const, .. } => { + try_visit!(visitor.visit_anon_const(anon_const)); + } + InlineAsmOperand::SymStatic { path, .. } => { + try_visit!(visitor.visit_qpath(path, id, *op_sp)); + } } } + V::Result::output() } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index e7d9dc04886b8..db27e2bd6301b 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -3,6 +3,8 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; use rustc_ast as ast; +use rustc_ast::visit::VisitorResult; +use rustc_ast::walk_list; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; @@ -431,23 +433,28 @@ impl<'hir> Map<'hir> { } /// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`. - pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) { + pub fn walk_toplevel_module(self, visitor: &mut V) -> V::Result + where + V: Visitor<'hir>, + { let (top_mod, span, hir_id) = self.get_module(LocalModDefId::CRATE_DEF_ID); - visitor.visit_mod(top_mod, span, hir_id); + visitor.visit_mod(top_mod, span, hir_id) } /// Walks the attributes in a crate. - pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) { + pub fn walk_attributes(self, visitor: &mut V) -> V::Result + where + V: Visitor<'hir>, + { let krate = self.krate(); for info in krate.owners.iter() { if let MaybeOwner::Owner(info) = info { for attrs in info.attrs.map.values() { - for a in *attrs { - visitor.visit_attribute(a) - } + walk_list!(visitor, visit_attribute, *attrs); } } } + V::Result::output() } /// Visits all item-likes in the crate in some deterministic (but unspecified) order. If you @@ -460,52 +467,38 @@ impl<'hir> Map<'hir> { /// provided by `tcx.hir_crate_items(())`. /// /// Please see the notes in `intravisit.rs` for more information. - pub fn visit_all_item_likes_in_crate(self, visitor: &mut V) + pub fn visit_all_item_likes_in_crate(self, visitor: &mut V) -> V::Result where V: Visitor<'hir>, { let krate = self.tcx.hir_crate_items(()); - - for id in krate.items() { - visitor.visit_item(self.item(id)); - } - - for id in krate.trait_items() { - visitor.visit_trait_item(self.trait_item(id)); - } - - for id in krate.impl_items() { - visitor.visit_impl_item(self.impl_item(id)); - } - - for id in krate.foreign_items() { - visitor.visit_foreign_item(self.foreign_item(id)); - } + walk_list!(visitor, visit_item, krate.items().map(|id| self.item(id))); + walk_list!(visitor, visit_trait_item, krate.trait_items().map(|id| self.trait_item(id))); + walk_list!(visitor, visit_impl_item, krate.impl_items().map(|id| self.impl_item(id))); + walk_list!( + visitor, + visit_foreign_item, + krate.foreign_items().map(|id| self.foreign_item(id)) + ); + V::Result::output() } /// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to /// item-likes in a single module. - pub fn visit_item_likes_in_module(self, module: LocalModDefId, visitor: &mut V) + pub fn visit_item_likes_in_module(self, module: LocalModDefId, visitor: &mut V) -> V::Result where V: Visitor<'hir>, { let module = self.tcx.hir_module_items(module); - - for id in module.items() { - visitor.visit_item(self.item(id)); - } - - for id in module.trait_items() { - visitor.visit_trait_item(self.trait_item(id)); - } - - for id in module.impl_items() { - visitor.visit_impl_item(self.impl_item(id)); - } - - for id in module.foreign_items() { - visitor.visit_foreign_item(self.foreign_item(id)); - } + walk_list!(visitor, visit_item, module.items().map(|id| self.item(id))); + walk_list!(visitor, visit_trait_item, module.trait_items().map(|id| self.trait_item(id))); + walk_list!(visitor, visit_impl_item, module.impl_items().map(|id| self.impl_item(id))); + walk_list!( + visitor, + visit_foreign_item, + module.foreign_items().map(|id| self.foreign_item(id)) + ); + V::Result::output() } pub fn for_each_module(self, mut f: impl FnMut(LocalModDefId)) { From 7a83e2f30d92748640461edbd5812e7b9229e995 Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Sun, 18 Feb 2024 05:02:03 +0000 Subject: [PATCH 40/40] fmt --- src/tools/miri/tests/pass/overflow_checks_off.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/miri/tests/pass/overflow_checks_off.rs b/src/tools/miri/tests/pass/overflow_checks_off.rs index 7b9d4f8fff5d5..831bffb6c5e8d 100644 --- a/src/tools/miri/tests/pass/overflow_checks_off.rs +++ b/src/tools/miri/tests/pass/overflow_checks_off.rs @@ -7,10 +7,9 @@ // Miri does not implement the codegen-time hack that backs `#[rustc_inherit_overflow_checks]`. // use std::ops::*; - // Disable _compile-time_ overflow linting // so that we can test runtime overflow checks - #![allow(arithmetic_overflow)] +#![allow(arithmetic_overflow)] fn main() { assert_eq!(-{ -0x80i8 }, -0x80);