diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 4dc8f27955358..1eecebad0e23a 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -568,6 +568,7 @@ pub struct Arm<'tcx> { pub lint_level: LintLevel, pub scope: region::Scope, pub span: Span, + pub is_cold: bool, } #[derive(Copy, Clone, Debug, HashStable)] diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index a2f92a93ec544..44a5c3c5dcee5 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -14,7 +14,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::{self, *}; use rustc_middle::thir::{self, *}; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty}; -use rustc_span::{BytePos, Pos, Span, Symbol}; +use rustc_span::{BytePos, Pos, Span, Symbol, sym}; use tracing::{debug, instrument}; use crate::builder::ForGuard::{self, OutsideGuard, RefWithinGuard}; @@ -458,7 +458,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { opt_scrutinee_place, ); - let arm_block = this.bind_pattern( + let mut arm_block = this.bind_pattern( outer_source_info, branch, &built_match_tree.fake_borrow_temps, @@ -467,6 +467,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { EmitStorageLive::Yes, ); + if arm.is_cold + && let Some(cold_path_def) = this.tcx.get_diagnostic_item(sym::cold_path) + { + let cold_path_ty = this.tcx.type_of(cold_path_def).instantiate_identity(); + let cold_path = Operand::Constant(Box::new(ConstOperand { + span: arm.span, + user_ty: None, + const_: Const::from_value(ConstValue::ZeroSized, cold_path_ty), + })); + let new_arm_block = this.cfg.start_new_block(); + let cold_path_result = + this.local_decls.push(LocalDecl::new(this.tcx.types.unit, arm.span)); + this.cfg.terminate( + arm_block, + this.source_info(arm.span), + TerminatorKind::Call { + func: cold_path, + args: Box::new([]), + destination: Place::from(cold_path_result), + target: Some(new_arm_block), + unwind: UnwindAction::Unreachable, + call_source: CallSource::Misc, + fn_span: arm.span, + }, + ); + arm_block = new_arm_block; + } + this.fixed_temps_scope = old_dedup_scope; if let Some(source_scope) = scope { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 54da6924db444..7e3ada4196df4 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -1005,6 +1005,7 @@ impl<'tcx> ThirBuildCx<'tcx> { } fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId { + let attrs = self.tcx.hir().attrs(arm.hir_id); let arm = Arm { pattern: self.pattern_from_hir(&arm.pat), guard: arm.guard.as_ref().map(|g| self.mirror_expr(g)), @@ -1012,6 +1013,7 @@ impl<'tcx> ThirBuildCx<'tcx> { lint_level: LintLevel::Explicit(arm.hir_id), scope: region::Scope { local_id: arm.hir_id.local_id, data: region::ScopeData::Node }, span: arm.span, + is_cold: attrs.iter().any(|a| a.name_or_empty() == sym::cold), }; self.thir.arms.push(arm) } diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 9ab87dd99ffc0..b41525918cc5d 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -623,7 +623,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "Arm {", depth_lvl); let arm = &self.thir.arms[arm_id]; - let Arm { pattern, guard, body, lint_level, scope, span } = arm; + let Arm { pattern, guard, body, lint_level, scope, span, is_cold } = arm; print_indented!(self, "pattern: ", depth_lvl + 1); self.print_pat(pattern, depth_lvl + 2); @@ -640,6 +640,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 1); print_indented!(self, format!("scope: {:?}", scope), depth_lvl + 1); print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, format!("is_cold: {:?}", is_cold), depth_lvl + 1); print_indented!(self, "}", depth_lvl); } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 3b249c835f237..8eb1d0b175429 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1475,6 +1475,7 @@ pub const unsafe fn assume(b: bool) { /// This intrinsic does not have a stable counterpart. #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] +#[rustc_diagnostic_item = "cold_path"] #[rustc_nounwind] #[miri::intrinsic_fallback_is_spec] #[cold] diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout index 910582ae4d9e9..708a085341bd9 100644 --- a/tests/ui/thir-print/thir-tree-match.stdout +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -143,6 +143,7 @@ body: lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).14)) scope: Node(14) span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0) + is_cold: false } Arm { pattern: @@ -195,6 +196,7 @@ body: lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).20)) scope: Node(20) span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0) + is_cold: false } Arm { pattern: @@ -239,6 +241,7 @@ body: lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26)) scope: Node(26) span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0) + is_cold: false } ] }