HIR const-checking
This commit is contained in:
parent
4c2383810b
commit
696084c764
@ -23,7 +23,6 @@
|
||||
enum NonConstExpr {
|
||||
Loop(hir::LoopSource),
|
||||
Match(hir::MatchSource),
|
||||
OrPattern,
|
||||
}
|
||||
|
||||
impl NonConstExpr {
|
||||
@ -31,7 +30,6 @@ fn name(self) -> String {
|
||||
match self {
|
||||
Self::Loop(src) => format!("`{}`", src.name()),
|
||||
Self::Match(src) => format!("`{}`", src.name()),
|
||||
Self::OrPattern => "or-pattern".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,22 +38,19 @@ fn required_feature_gates(self) -> Option<&'static [Symbol]> {
|
||||
use hir::MatchSource::*;
|
||||
|
||||
let gates: &[_] = match self {
|
||||
Self::Match(Normal)
|
||||
| Self::Match(IfDesugar { .. })
|
||||
| Self::Match(IfLetDesugar { .. })
|
||||
| Self::OrPattern => &[sym::const_if_match],
|
||||
|
||||
Self::Loop(Loop) => &[sym::const_loop],
|
||||
|
||||
Self::Loop(While)
|
||||
| Self::Loop(WhileLet)
|
||||
| Self::Match(WhileDesugar | WhileLetDesugar) => {
|
||||
&[sym::const_loop, sym::const_if_match]
|
||||
}
|
||||
|
||||
// A `for` loop's desugaring contains a call to `IntoIterator::into_iter`,
|
||||
// so they are not yet allowed with `#![feature(const_loop)]`.
|
||||
_ => return None,
|
||||
// Likewise, `?` desugars to a call to `Try::into_result`.
|
||||
Self::Loop(ForLoop) | Self::Match(ForLoopDesugar | TryDesugar | AwaitDesugar) => {
|
||||
return None;
|
||||
}
|
||||
|
||||
Self::Loop(Loop | While | WhileLet) | Self::Match(WhileDesugar | WhileLetDesugar) => {
|
||||
&[sym::const_loop]
|
||||
}
|
||||
|
||||
// All other matches are allowed.
|
||||
Self::Match(Normal | IfDesugar { .. } | IfLetDesugar { .. }) => &[],
|
||||
};
|
||||
|
||||
Some(gates)
|
||||
@ -114,17 +109,6 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
|
||||
match missing_gates.as_slice() {
|
||||
&[] => struct_span_err!(self.tcx.sess, span, E0744, "{}", msg).emit(),
|
||||
|
||||
// If the user enabled `#![feature(const_loop)]` but not `#![feature(const_if_match)]`,
|
||||
// explain why their `while` loop is being rejected.
|
||||
&[gate @ sym::const_if_match] if required_gates.contains(&sym::const_loop) => {
|
||||
feature_err(&self.tcx.sess.parse_sess, gate, span, &msg)
|
||||
.note(
|
||||
"`#![feature(const_loop)]` alone is not sufficient, \
|
||||
since this loop expression contains an implicit conditional",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
&[missing_primary, ref missing_secondary @ ..] => {
|
||||
let mut err = feature_err(&self.tcx.sess.parse_sess, missing_primary, span, &msg);
|
||||
|
||||
@ -175,15 +159,6 @@ fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
|
||||
self.recurse_into(kind, |this| intravisit::walk_body(this, body));
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
|
||||
if self.const_kind.is_some() {
|
||||
if let hir::PatKind::Or { .. } = p.kind {
|
||||
self.const_check_violated(NonConstExpr::OrPattern, p.span);
|
||||
}
|
||||
}
|
||||
intravisit::walk_pat(self, p)
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
|
||||
match &e.kind {
|
||||
// Skip the following checks if we are not currently in a const context.
|
||||
|
Loading…
Reference in New Issue
Block a user