Skip to content

Commit

Permalink
Feature gate or patterns in const contexts
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed Dec 25, 2019
1 parent 58a6a20 commit f1758a0
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 5 deletions.
22 changes: 17 additions & 5 deletions src/librustc_passes/check_const.rs
Expand Up @@ -27,13 +27,15 @@ use std::fmt;
enum NonConstExpr {
Loop(hir::LoopSource),
Match(hir::MatchSource),
OrPattern,
}

impl NonConstExpr {
fn name(self) -> &'static str {
fn name(self) -> String {
match self {
Self::Loop(src) => src.name(),
Self::Match(src) => src.name(),
Self::Loop(src) => format!("`{}`", src.name()),
Self::Match(src) => format!("`{}`", src.name()),
Self::OrPattern => format!("or-pattern"),
}
}

Expand All @@ -44,7 +46,8 @@ impl NonConstExpr {
let gates: &[_] = match self {
Self::Match(Normal)
| Self::Match(IfDesugar { .. })
| Self::Match(IfLetDesugar { .. }) => &[sym::const_if_match],
| Self::Match(IfLetDesugar { .. })
| Self::OrPattern => &[sym::const_if_match],

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

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

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

fn visit_pat(&mut self, p: &'tcx hir::Pat) {
if self.const_kind.is_some() {
if let hir::PatKind::Or { .. } = p.kind {
self.const_check_violated(NonConstExpr::OrPattern, p.span);
}
}
hir::intravisit::walk_pat(self, p)
}

fn visit_expr(&mut self, e: &'tcx hir::Expr) {
match &e.kind {
// Skip the following checks if we are not currently in a const context.
Expand Down
36 changes: 36 additions & 0 deletions src/test/ui/or-patterns/feature-gate-const-fn.rs
@@ -0,0 +1,36 @@
#![feature(or_patterns)]
#![allow(incomplete_features)]

const fn foo((Ok(a) | Err(a)): Result<i32, i32>) {
//~^ ERROR or-pattern is not allowed in a `const fn`
let x = Ok(3);
let Ok(y) | Err(y) = x;
//~^ ERROR or-pattern is not allowed in a `const fn`
}

const X: () = {
let x = Ok(3);
let Ok(y) | Err(y) = x;
//~^ ERROR or-pattern is not allowed in a `const`
};

static Y: () = {
let x = Ok(3);
let Ok(y) | Err(y) = x;
//~^ ERROR or-pattern is not allowed in a `static`
};

static mut Z: () = {
let x = Ok(3);
let Ok(y) | Err(y) = x;
//~^ ERROR or-pattern is not allowed in a `static mut`
};

fn main() {
let _: [(); {
let x = Ok(3);
let Ok(y) | Err(y) = x;
//~^ ERROR or-pattern is not allowed in a `const`
2
}];
}
57 changes: 57 additions & 0 deletions src/test/ui/or-patterns/feature-gate-const-fn.stderr
@@ -0,0 +1,57 @@
error[E0658]: or-pattern is not allowed in a `const fn`
--> $DIR/feature-gate-const-fn.rs:4:15
|
LL | const fn foo((Ok(a) | Err(a)): Result<i32, i32>) {
| ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: or-pattern is not allowed in a `const fn`
--> $DIR/feature-gate-const-fn.rs:7:9
|
LL | let Ok(y) | Err(y) = x;
| ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: or-pattern is not allowed in a `const`
--> $DIR/feature-gate-const-fn.rs:13:9
|
LL | let Ok(y) | Err(y) = x;
| ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: or-pattern is not allowed in a `static`
--> $DIR/feature-gate-const-fn.rs:19:9
|
LL | let Ok(y) | Err(y) = x;
| ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: or-pattern is not allowed in a `static mut`
--> $DIR/feature-gate-const-fn.rs:25:9
|
LL | let Ok(y) | Err(y) = x;
| ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: or-pattern is not allowed in a `const`
--> $DIR/feature-gate-const-fn.rs:32:13
|
LL | let Ok(y) | Err(y) = x;
| ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49146
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0658`.

0 comments on commit f1758a0

Please sign in to comment.