Skip to content

Commit f1758a0

Browse files
committed
Feature gate or patterns in const contexts
1 parent 58a6a20 commit f1758a0

File tree

3 files changed

+110
-5
lines changed

3 files changed

+110
-5
lines changed

src/librustc_passes/check_const.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ use std::fmt;
2727
enum NonConstExpr {
2828
Loop(hir::LoopSource),
2929
Match(hir::MatchSource),
30+
OrPattern,
3031
}
3132

3233
impl NonConstExpr {
33-
fn name(self) -> &'static str {
34+
fn name(self) -> String {
3435
match self {
35-
Self::Loop(src) => src.name(),
36-
Self::Match(src) => src.name(),
36+
Self::Loop(src) => format!("`{}`", src.name()),
37+
Self::Match(src) => format!("`{}`", src.name()),
38+
Self::OrPattern => format!("or-pattern"),
3739
}
3840
}
3941

@@ -44,7 +46,8 @@ impl NonConstExpr {
4446
let gates: &[_] = match self {
4547
Self::Match(Normal)
4648
| Self::Match(IfDesugar { .. })
47-
| Self::Match(IfLetDesugar { .. }) => &[sym::const_if_match],
49+
| Self::Match(IfLetDesugar { .. })
50+
| Self::OrPattern => &[sym::const_if_match],
4851

4952
Self::Loop(Loop) => &[sym::const_loop],
5053

@@ -144,7 +147,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
144147
let const_kind = self
145148
.const_kind
146149
.expect("`const_check_violated` may only be called inside a const context");
147-
let msg = format!("`{}` is not allowed in a `{}`", expr.name(), const_kind);
150+
let msg = format!("{} is not allowed in a `{}`", expr.name(), const_kind);
148151

149152
let required_gates = required_gates.unwrap_or(&[]);
150153
let missing_gates: Vec<_> =
@@ -211,6 +214,15 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
211214
self.recurse_into(kind, |this| hir::intravisit::walk_body(this, body));
212215
}
213216

217+
fn visit_pat(&mut self, p: &'tcx hir::Pat) {
218+
if self.const_kind.is_some() {
219+
if let hir::PatKind::Or { .. } = p.kind {
220+
self.const_check_violated(NonConstExpr::OrPattern, p.span);
221+
}
222+
}
223+
hir::intravisit::walk_pat(self, p)
224+
}
225+
214226
fn visit_expr(&mut self, e: &'tcx hir::Expr) {
215227
match &e.kind {
216228
// Skip the following checks if we are not currently in a const context.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#![feature(or_patterns)]
2+
#![allow(incomplete_features)]
3+
4+
const fn foo((Ok(a) | Err(a)): Result<i32, i32>) {
5+
//~^ ERROR or-pattern is not allowed in a `const fn`
6+
let x = Ok(3);
7+
let Ok(y) | Err(y) = x;
8+
//~^ ERROR or-pattern is not allowed in a `const fn`
9+
}
10+
11+
const X: () = {
12+
let x = Ok(3);
13+
let Ok(y) | Err(y) = x;
14+
//~^ ERROR or-pattern is not allowed in a `const`
15+
};
16+
17+
static Y: () = {
18+
let x = Ok(3);
19+
let Ok(y) | Err(y) = x;
20+
//~^ ERROR or-pattern is not allowed in a `static`
21+
};
22+
23+
static mut Z: () = {
24+
let x = Ok(3);
25+
let Ok(y) | Err(y) = x;
26+
//~^ ERROR or-pattern is not allowed in a `static mut`
27+
};
28+
29+
fn main() {
30+
let _: [(); {
31+
let x = Ok(3);
32+
let Ok(y) | Err(y) = x;
33+
//~^ ERROR or-pattern is not allowed in a `const`
34+
2
35+
}];
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
error[E0658]: or-pattern is not allowed in a `const fn`
2+
--> $DIR/feature-gate-const-fn.rs:4:15
3+
|
4+
LL | const fn foo((Ok(a) | Err(a)): Result<i32, i32>) {
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
8+
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
9+
10+
error[E0658]: or-pattern is not allowed in a `const fn`
11+
--> $DIR/feature-gate-const-fn.rs:7:9
12+
|
13+
LL | let Ok(y) | Err(y) = x;
14+
| ^^^^^^^^^^^^^^
15+
|
16+
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
17+
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
18+
19+
error[E0658]: or-pattern is not allowed in a `const`
20+
--> $DIR/feature-gate-const-fn.rs:13:9
21+
|
22+
LL | let Ok(y) | Err(y) = x;
23+
| ^^^^^^^^^^^^^^
24+
|
25+
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
26+
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
27+
28+
error[E0658]: or-pattern is not allowed in a `static`
29+
--> $DIR/feature-gate-const-fn.rs:19:9
30+
|
31+
LL | let Ok(y) | Err(y) = x;
32+
| ^^^^^^^^^^^^^^
33+
|
34+
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
35+
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
36+
37+
error[E0658]: or-pattern is not allowed in a `static mut`
38+
--> $DIR/feature-gate-const-fn.rs:25:9
39+
|
40+
LL | let Ok(y) | Err(y) = x;
41+
| ^^^^^^^^^^^^^^
42+
|
43+
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
44+
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
45+
46+
error[E0658]: or-pattern is not allowed in a `const`
47+
--> $DIR/feature-gate-const-fn.rs:32:13
48+
|
49+
LL | let Ok(y) | Err(y) = x;
50+
| ^^^^^^^^^^^^^^
51+
|
52+
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
53+
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
54+
55+
error: aborting due to 6 previous errors
56+
57+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)