loop_match: suggest extracting to a const item
if the expression cannot be evaluated in a straightforward way
This commit is contained in:
parent
29a58723b0
commit
730d33dd64
5 changed files with 297 additions and 4 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
174
tests/ui/loop-match/suggest-const-item.rs
Normal file
174
tests/ui/loop-match/suggest-const-item.rs
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
#![allow(incomplete_features)]
|
||||
#![feature(loop_match)]
|
||||
#![feature(generic_const_items)]
|
||||
#![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
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
const M: usize = 42;
|
||||
|
||||
fn g() {
|
||||
let mut state = 0;
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
0 => {
|
||||
#[const_continue]
|
||||
break 'blk Self::M;
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait T {
|
||||
const N: usize;
|
||||
|
||||
fn f() {
|
||||
let mut state = 0;
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
0 => {
|
||||
#[const_continue]
|
||||
break 'blk Self::N;
|
||||
//~^ ERROR could not determine the target branch for this `#[const_continue]`
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl T for S {
|
||||
const N: usize = 1;
|
||||
}
|
||||
|
||||
impl S {
|
||||
fn h() {
|
||||
let mut state = 0;
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
0 => {
|
||||
#[const_continue]
|
||||
break 'blk Self::N;
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait T2<U> {
|
||||
const L: u32;
|
||||
|
||||
fn p() {
|
||||
let mut state = 0;
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
0 => {
|
||||
#[const_continue]
|
||||
break 'blk Self::L;
|
||||
//~^ ERROR could not determine the target branch for this `#[const_continue]`
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SIZE_OF<T>: usize = size_of::<T>();
|
||||
|
||||
fn q<T>() {
|
||||
let mut state = 0;
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
0 => {
|
||||
#[const_continue]
|
||||
break 'blk SIZE_OF::<T>;
|
||||
//~^ ERROR could not determine the target branch for this `#[const_continue]`
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Trait<T> {
|
||||
const X: usize = 9000;
|
||||
const Y: usize = size_of::<T>();
|
||||
}
|
||||
|
||||
impl<T> Trait<T> for () {}
|
||||
|
||||
fn r<T>() {
|
||||
let mut state = 0;
|
||||
#[loop_match]
|
||||
loop {
|
||||
state = 'blk: {
|
||||
match state {
|
||||
0 => {
|
||||
#[const_continue]
|
||||
break 'blk <() as Trait<T>>::X;
|
||||
}
|
||||
1 => {
|
||||
#[const_continue]
|
||||
break 'blk <() as Trait<T>>::Y;
|
||||
//~^ ERROR could not determine the target branch for this `#[const_continue]`
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
tests/ui/loop-match/suggest-const-item.stderr
Normal file
58
tests/ui/loop-match/suggest-const-item.stderr
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
error: could not determine the target branch for this `#[const_continue]`
|
||||
--> $DIR/suggest-const-item.rs:19: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:24: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:29: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:34: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: could not determine the target branch for this `#[const_continue]`
|
||||
--> $DIR/suggest-const-item.rs:76:36
|
||||
|
|
||||
LL | break 'blk Self::N;
|
||||
| ^^^^^^^ this value is too generic
|
||||
|
||||
error: could not determine the target branch for this `#[const_continue]`
|
||||
--> $DIR/suggest-const-item.rs:119:36
|
||||
|
|
||||
LL | break 'blk Self::L;
|
||||
| ^^^^^^^ this value is too generic
|
||||
|
||||
error: could not determine the target branch for this `#[const_continue]`
|
||||
--> $DIR/suggest-const-item.rs:139:32
|
||||
|
|
||||
LL | break 'blk SIZE_OF::<T>;
|
||||
| ^^^^^^^^^^^^ this value is too generic
|
||||
|
||||
error: could not determine the target branch for this `#[const_continue]`
|
||||
--> $DIR/suggest-const-item.rs:167:32
|
||||
|
|
||||
LL | break 'blk <() as Trait<T>>::Y;
|
||||
| ^^^^^^^^^^^^^^^^^^^ this value is too generic
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue