]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/transform/qualify_min_const_fn.rs
Reword const fn conditional and loop error text
[rust.git] / src / librustc_mir / transform / qualify_min_const_fn.rs
index e1d41ba4fc509f151800216059972090e7dd1ae9..ff4459dd3577f74504b441af8fff789d2ab7b29c 100644 (file)
@@ -11,7 +11,7 @@
 pub fn is_min_const_fn(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
 ) -> McfResult {
     let mut current = def_id;
     loop {
@@ -130,16 +130,16 @@ fn check_ty(
 
 fn check_rvalue(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     rvalue: &Rvalue<'tcx>,
     span: Span,
 ) -> McfResult {
     match rvalue {
         Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
-            check_operand(tcx, mir, operand, span)
+            check_operand(operand, span)
         }
         Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
-            check_place(tcx, mir, place, span)
+            check_place(place, span)
         }
         Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
             use rustc::ty::cast::CastTy;
@@ -153,11 +153,11 @@ fn check_rvalue(
                 (CastTy::RPtr(_), CastTy::Float) => bug!(),
                 (CastTy::RPtr(_), CastTy::Int(_)) => bug!(),
                 (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(),
-                _ => check_operand(tcx, mir, operand, span),
+                _ => check_operand(operand, span),
             }
         }
         Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), operand, _) => {
-            check_operand(tcx, mir, operand, span)
+            check_operand(operand, span)
         }
         Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), _, _) |
         Rvalue::Cast(CastKind::Pointer(PointerCast::ClosureFnPointer(_)), _, _) |
@@ -171,8 +171,8 @@ fn check_rvalue(
         )),
         // binops are fine on integers
         Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
-            check_operand(tcx, mir, lhs, span)?;
-            check_operand(tcx, mir, rhs, span)?;
+            check_operand(lhs, span)?;
+            check_operand(rhs, span)?;
             let ty = lhs.ty(mir, tcx);
             if ty.is_integral() || ty.is_bool() || ty.is_char() {
                 Ok(())
@@ -191,7 +191,7 @@ fn check_rvalue(
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(mir, tcx);
             if ty.is_integral() || ty.is_bool() {
-                check_operand(tcx, mir, operand, span)
+                check_operand(operand, span)
             } else {
                 Err((
                     span,
@@ -201,7 +201,7 @@ fn check_rvalue(
         }
         Rvalue::Aggregate(_, operands) => {
             for operand in operands {
-                check_operand(tcx, mir, operand, span)?;
+                check_operand(operand, span)?;
             }
             Ok(())
         }
@@ -210,17 +210,17 @@ fn check_rvalue(
 
 fn check_statement(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     statement: &Statement<'tcx>,
 ) -> McfResult {
     let span = statement.source_info.span;
     match &statement.kind {
         StatementKind::Assign(place, rval) => {
-            check_place(tcx, mir, place, span)?;
+            check_place(place, span)?;
             check_rvalue(tcx, mir, rval, span)
         }
 
-        StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span),
+        StatementKind::FakeRead(_, place) => check_place(place, span),
 
         // just an assignment
         StatementKind::SetDiscriminant { .. } => Ok(()),
@@ -239,48 +239,48 @@ fn check_statement(
 }
 
 fn check_operand(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
     operand: &Operand<'tcx>,
     span: Span,
 ) -> McfResult {
     match operand {
         Operand::Move(place) | Operand::Copy(place) => {
-            check_place(tcx, mir, place, span)
+            check_place(place, span)
         }
         Operand::Constant(_) => Ok(()),
     }
 }
 
 fn check_place(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
     place: &Place<'tcx>,
     span: Span,
 ) -> McfResult {
-    match place {
-        Place::Base(PlaceBase::Local(_)) => Ok(()),
-        // promoteds are always fine, they are essentially constants
-        Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => Ok(()),
-        Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })) =>
-            Err((span, "cannot access `static` items in const fn".into())),
-        Place::Projection(proj) => {
+    place.iterate(|place_base, place_projection| {
+        for proj in place_projection {
             match proj.elem {
-                | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
-                | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => {
-                    check_place(tcx, mir, &proj.base, span)
-                }
-                | ProjectionElem::Downcast(..) => {
-                    Err((span, "`match` or `if let` in `const fn` is unstable".into()))
+                ProjectionElem::Downcast(..) => {
+                    return Err((span, "`match` or `if let` in `const fn` is unstable".into()));
                 }
+                ProjectionElem::ConstantIndex { .. }
+                | ProjectionElem::Subslice { .. }
+                | ProjectionElem::Deref
+                | ProjectionElem::Field(..)
+                | ProjectionElem::Index(_) => {}
             }
         }
-    }
+
+        match place_base {
+            PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. }) => {
+                Err((span, "cannot access `static` items in const fn".into()))
+            }
+            PlaceBase::Local(_)
+            | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => Ok(()),
+        }
+    })
 }
 
 fn check_terminator(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
+    mir: &'a Body<'tcx>,
     terminator: &Terminator<'tcx>,
 ) -> McfResult {
     let span = terminator.source_info.span;
@@ -290,16 +290,16 @@ fn check_terminator(
         | TerminatorKind::Resume => Ok(()),
 
         TerminatorKind::Drop { location, .. } => {
-            check_place(tcx, mir, location, span)
+            check_place(location, span)
         }
         TerminatorKind::DropAndReplace { location, value, .. } => {
-            check_place(tcx, mir, location, span)?;
-            check_operand(tcx, mir, value, span)
+            check_place(location, span)?;
+            check_operand(value, span)
         },
 
         TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err((
             span,
-            "`if`, `match`, `&&` and `||` are not stable in const fn".into(),
+            "loops and conditional expressions are not stable in const fn".into(),
         )),
         | TerminatorKind::Abort | TerminatorKind::Unreachable => {
             Err((span, "const fn with unreachable code is not stable".into()))
@@ -346,10 +346,10 @@ fn check_terminator(
                     )),
                 }
 
-                check_operand(tcx, mir, func, span)?;
+                check_operand(func, span)?;
 
                 for arg in args {
-                    check_operand(tcx, mir, arg, span)?;
+                    check_operand(arg, span)?;
                 }
                 Ok(())
             } else {
@@ -363,7 +363,7 @@ fn check_terminator(
             msg: _,
             target: _,
             cleanup: _,
-        } => check_operand(tcx, mir, cond, span),
+        } => check_operand(cond, span),
 
         TerminatorKind::FalseUnwind { .. } => {
             Err((span, "loops are not allowed in const fn".into()))