Skip to content

loop_match: suggest extracting to a const item #143585

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion compiler/rustc_mir_build/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
29 changes: 26 additions & 3 deletions compiler/rustc_mir_build/src/builder/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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());
Expand All @@ -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
Expand Down
32 changes: 32 additions & 0 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
40 changes: 40 additions & 0 deletions tests/ui/loop-match/suggest-const-item.rs
Original file line number Diff line number Diff line change
@@ -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<const N: i32>() -> 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
}
34 changes: 34 additions & 0 deletions tests/ui/loop-match/suggest-const-item.stderr
Original file line number Diff line number Diff line change
@@ -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

Loading