Skip to content

Commit 069f5cb

Browse files
committed
loop_match: suggest extracting to a const item
if the expression cannot be evaluated in a straightforward way
1 parent c720f49 commit 069f5cb

File tree

5 files changed

+139
-4
lines changed

5 files changed

+139
-4
lines changed

compiler/rustc_mir_build/messages.ftl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,16 @@ mir_build_confused = missing patterns are not covered because `{$variable}` is i
8686
8787
mir_build_const_continue_bad_const = could not determine the target branch for this `#[const_continue]`
8888
.label = this value is too generic
89-
.note = the value must be a literal or a monomorphic const
9089
9190
mir_build_const_continue_missing_value = a `#[const_continue]` must break to a label with a value
9291
92+
mir_build_const_continue_not_const = could not determine the target branch for this `#[const_continue]`
93+
.help = try extracting the expression into a `const` item
94+
95+
mir_build_const_continue_not_const_const_block = `const` blocks may use generics, and are not evaluated early enough
96+
mir_build_const_continue_not_const_const_other = this value must be a literal or a monomorphic const
97+
mir_build_const_continue_not_const_constant_parameter = constant parameters may use generics, and are not evaluated early enough
98+
9399
mir_build_const_continue_unknown_jump_target = the target of this `#[const_continue]` is not statically known
94100
.label = this value must be a literal or a monomorphic const
95101

compiler/rustc_mir_build/src/builder/scope.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ use tracing::{debug, instrument};
100100

101101
use super::matches::BuiltMatchTree;
102102
use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
103-
use crate::errors::{ConstContinueBadConst, ConstContinueUnknownJumpTarget};
103+
use crate::errors::{
104+
ConstContinueBadConst, ConstContinueNotMonomorphicConst, ConstContinueUnknownJumpTarget,
105+
};
104106

105107
#[derive(Debug)]
106108
pub(crate) struct Scopes<'tcx> {
@@ -867,7 +869,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
867869
span_bug!(span, "break value must be a scope")
868870
};
869871

870-
let constant = match &self.thir[value].kind {
872+
let expr = &self.thir[value];
873+
let constant = match &expr.kind {
871874
ExprKind::Adt(box AdtExpr { variant_index, fields, base, .. }) => {
872875
assert!(matches!(base, AdtExprBase::None));
873876
assert!(fields.is_empty());
@@ -887,7 +890,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
887890
),
888891
}
889892
}
890-
_ => self.as_constant(&self.thir[value]),
893+
894+
ExprKind::Literal { .. }
895+
| ExprKind::NonHirLiteral { .. }
896+
| ExprKind::ZstLiteral { .. }
897+
| ExprKind::NamedConst { .. } => self.as_constant(&self.thir[value]),
898+
899+
other => {
900+
use crate::errors::ConstContinueNotMonomorphicConstReason as Reason;
901+
902+
let span = expr.span;
903+
let reason = match other {
904+
ExprKind::ConstParam { .. } => Reason::ConstantParameter { span },
905+
ExprKind::ConstBlock { .. } => Reason::ConstBlock { span },
906+
_ => Reason::Other { span },
907+
};
908+
909+
self.tcx
910+
.dcx()
911+
.emit_err(ConstContinueNotMonomorphicConst { span: expr.span, reason });
912+
return block.unit();
913+
}
891914
};
892915

893916
let break_index = self

compiler/rustc_mir_build/src/errors.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,38 @@ pub(crate) struct LoopMatchArmWithGuard {
12131213
pub span: Span,
12141214
}
12151215

1216+
#[derive(Diagnostic)]
1217+
#[diag(mir_build_const_continue_not_const)]
1218+
#[help]
1219+
pub(crate) struct ConstContinueNotMonomorphicConst {
1220+
#[primary_span]
1221+
pub span: Span,
1222+
1223+
#[subdiagnostic]
1224+
pub reason: ConstContinueNotMonomorphicConstReason,
1225+
}
1226+
1227+
#[derive(Subdiagnostic)]
1228+
pub(crate) enum ConstContinueNotMonomorphicConstReason {
1229+
#[label(mir_build_const_continue_not_const_constant_parameter)]
1230+
ConstantParameter {
1231+
#[primary_span]
1232+
span: Span,
1233+
},
1234+
1235+
#[label(mir_build_const_continue_not_const_const_block)]
1236+
ConstBlock {
1237+
#[primary_span]
1238+
span: Span,
1239+
},
1240+
1241+
#[label(mir_build_const_continue_not_const_const_other)]
1242+
Other {
1243+
#[primary_span]
1244+
span: Span,
1245+
},
1246+
}
1247+
12161248
#[derive(Diagnostic)]
12171249
#[diag(mir_build_const_continue_bad_const)]
12181250
pub(crate) struct ConstContinueBadConst {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#![allow(incomplete_features)]
2+
#![feature(loop_match)]
3+
#![crate_type = "lib"]
4+
5+
const fn const_fn() -> i32 {
6+
1
7+
}
8+
9+
#[unsafe(no_mangle)]
10+
fn suggest_const_block<const N: i32>() -> i32 {
11+
let mut state = 0;
12+
#[loop_match]
13+
loop {
14+
state = 'blk: {
15+
match state {
16+
0 => {
17+
#[const_continue]
18+
break 'blk const_fn();
19+
//~^ ERROR could not determine the target branch for this `#[const_continue]`
20+
}
21+
1 => {
22+
#[const_continue]
23+
break 'blk const { const_fn() };
24+
//~^ ERROR could not determine the target branch for this `#[const_continue]`
25+
}
26+
2 => {
27+
#[const_continue]
28+
break 'blk N;
29+
//~^ ERROR could not determine the target branch for this `#[const_continue]`
30+
}
31+
_ => {
32+
#[const_continue]
33+
break 'blk 1 + 1;
34+
//~^ ERROR could not determine the target branch for this `#[const_continue]`
35+
}
36+
}
37+
}
38+
}
39+
state
40+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
error: could not determine the target branch for this `#[const_continue]`
2+
--> $DIR/suggest-const-item.rs:18:32
3+
|
4+
LL | break 'blk const_fn();
5+
| ^^^^^^^^^^ this value must be a literal or a monomorphic const
6+
|
7+
= help: try extracting the expression into a `const` item
8+
9+
error: could not determine the target branch for this `#[const_continue]`
10+
--> $DIR/suggest-const-item.rs:23:32
11+
|
12+
LL | break 'blk const { const_fn() };
13+
| ^^^^^^^^^^^^^^^^^^^^ `const` blocks may use generics, and are not evaluated early enough
14+
|
15+
= help: try extracting the expression into a `const` item
16+
17+
error: could not determine the target branch for this `#[const_continue]`
18+
--> $DIR/suggest-const-item.rs:28:32
19+
|
20+
LL | break 'blk N;
21+
| ^ constant parameters may use generics, and are not evaluated early enough
22+
|
23+
= help: try extracting the expression into a `const` item
24+
25+
error: could not determine the target branch for this `#[const_continue]`
26+
--> $DIR/suggest-const-item.rs:33:32
27+
|
28+
LL | break 'blk 1 + 1;
29+
| ^^^^^ this value must be a literal or a monomorphic const
30+
|
31+
= help: try extracting the expression into a `const` item
32+
33+
error: aborting due to 4 previous errors
34+

0 commit comments

Comments
 (0)