diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index e339520cd86b8..abfe8eb66dda8 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -86,10 +86,16 @@ mir_build_confused = missing patterns are not covered because `{$variable}` is i mir_build_const_continue_bad_const = could not determine the target branch for this `#[const_continue]` .label = this value is too generic - .note = the value must be a literal or a monomorphic const mir_build_const_continue_missing_value = a `#[const_continue]` must break to a label with a value +mir_build_const_continue_not_const = could not determine the target branch for this `#[const_continue]` + .help = try extracting the expression into a `const` item + +mir_build_const_continue_not_const_const_block = `const` blocks may use generics, and are not evaluated early enough +mir_build_const_continue_not_const_const_other = this value must be a literal or a monomorphic const +mir_build_const_continue_not_const_constant_parameter = constant parameters may use generics, and are not evaluated early enough + mir_build_const_continue_unknown_jump_target = the target of this `#[const_continue]` is not statically known .label = this value must be a literal or a monomorphic const diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 405d47c7c79cb..18fe084e7c4c7 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -100,7 +100,9 @@ use tracing::{debug, instrument}; use super::matches::BuiltMatchTree; use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; -use crate::errors::{ConstContinueBadConst, ConstContinueUnknownJumpTarget}; +use crate::errors::{ + ConstContinueBadConst, ConstContinueNotMonomorphicConst, ConstContinueUnknownJumpTarget, +}; #[derive(Debug)] pub(crate) struct Scopes<'tcx> { @@ -867,7 +869,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span_bug!(span, "break value must be a scope") }; - let constant = match &self.thir[value].kind { + let expr = &self.thir[value]; + let constant = match &expr.kind { ExprKind::Adt(box AdtExpr { variant_index, fields, base, .. }) => { assert!(matches!(base, AdtExprBase::None)); assert!(fields.is_empty()); @@ -887,7 +890,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ), } } - _ => self.as_constant(&self.thir[value]), + + ExprKind::Literal { .. } + | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } + | ExprKind::NamedConst { .. } => self.as_constant(&self.thir[value]), + + other => { + use crate::errors::ConstContinueNotMonomorphicConstReason as Reason; + + let span = expr.span; + let reason = match other { + ExprKind::ConstParam { .. } => Reason::ConstantParameter { span }, + ExprKind::ConstBlock { .. } => Reason::ConstBlock { span }, + _ => Reason::Other { span }, + }; + + self.tcx + .dcx() + .emit_err(ConstContinueNotMonomorphicConst { span: expr.span, reason }); + return block.unit(); + } }; let break_index = self diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 16b49bf384c52..f1fbd5c4a4994 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1213,6 +1213,38 @@ pub(crate) struct LoopMatchArmWithGuard { pub span: Span, } +#[derive(Diagnostic)] +#[diag(mir_build_const_continue_not_const)] +#[help] +pub(crate) struct ConstContinueNotMonomorphicConst { + #[primary_span] + pub span: Span, + + #[subdiagnostic] + pub reason: ConstContinueNotMonomorphicConstReason, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ConstContinueNotMonomorphicConstReason { + #[label(mir_build_const_continue_not_const_constant_parameter)] + ConstantParameter { + #[primary_span] + span: Span, + }, + + #[label(mir_build_const_continue_not_const_const_block)] + ConstBlock { + #[primary_span] + span: Span, + }, + + #[label(mir_build_const_continue_not_const_const_other)] + Other { + #[primary_span] + span: Span, + }, +} + #[derive(Diagnostic)] #[diag(mir_build_const_continue_bad_const)] pub(crate) struct ConstContinueBadConst { diff --git a/tests/ui/loop-match/suggest-const-item.rs b/tests/ui/loop-match/suggest-const-item.rs new file mode 100644 index 0000000000000..761879a6d3c14 --- /dev/null +++ b/tests/ui/loop-match/suggest-const-item.rs @@ -0,0 +1,40 @@ +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +const fn const_fn() -> i32 { + 1 +} + +#[unsafe(no_mangle)] +fn suggest_const_block() -> i32 { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk const_fn(); + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + 1 => { + #[const_continue] + break 'blk const { const_fn() }; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + 2 => { + #[const_continue] + break 'blk N; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + _ => { + #[const_continue] + break 'blk 1 + 1; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + } + } + } + state +} diff --git a/tests/ui/loop-match/suggest-const-item.stderr b/tests/ui/loop-match/suggest-const-item.stderr new file mode 100644 index 0000000000000..b66d9e2618f05 --- /dev/null +++ b/tests/ui/loop-match/suggest-const-item.stderr @@ -0,0 +1,34 @@ +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:18:32 + | +LL | break 'blk const_fn(); + | ^^^^^^^^^^ this value must be a literal or a monomorphic const + | + = help: try extracting the expression into a `const` item + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:23:32 + | +LL | break 'blk const { const_fn() }; + | ^^^^^^^^^^^^^^^^^^^^ `const` blocks may use generics, and are not evaluated early enough + | + = help: try extracting the expression into a `const` item + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:28:32 + | +LL | break 'blk N; + | ^ constant parameters may use generics, and are not evaluated early enough + | + = help: try extracting the expression into a `const` item + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:33:32 + | +LL | break 'blk 1 + 1; + | ^^^^^ this value must be a literal or a monomorphic const + | + = help: try extracting the expression into a `const` item + +error: aborting due to 4 previous errors +