diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 38265cfa77295..a0aead9891101 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -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"), } } @@ -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], @@ -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<_> = @@ -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. diff --git a/src/test/ui/or-patterns/feature-gate-const-fn.rs b/src/test/ui/or-patterns/feature-gate-const-fn.rs new file mode 100644 index 0000000000000..d73dcf2666648 --- /dev/null +++ b/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) { + //~^ 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 + }]; +} diff --git a/src/test/ui/or-patterns/feature-gate-const-fn.stderr b/src/test/ui/or-patterns/feature-gate-const-fn.stderr new file mode 100644 index 0000000000000..26143d2f19d33 --- /dev/null +++ b/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) { + | ^^^^^^^^^^^^^^ + | + = 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`.