about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/ops.rs24
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs31
-rw-r--r--compiler/rustc_span/src/symbol.rs1
4 files changed, 50 insertions, 9 deletions
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 6452bda293e..17b9e1ee7e8 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -584,6 +584,9 @@ declare_features! (
     /// Allows non trivial generic constants which have to be manually propageted upwards.
     (active, const_evaluatable_checked, "1.48.0", Some(76560), None),
 
+    /// Allows basic arithmetic on floating point types in a `const fn`.
+    (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index 496e620dd9d..1d741085853 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -113,6 +113,30 @@ impl NonConstOp for Abort {
 }
 
 #[derive(Debug)]
+pub struct FloatingPointOp;
+impl NonConstOp for FloatingPointOp {
+    const STOPS_CONST_CHECKING: bool = true;
+
+    fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
+        if ccx.const_kind() == hir::ConstContext::ConstFn {
+            Status::Unstable(sym::const_fn_floating_point_arithmetic)
+        } else {
+            Status::Allowed
+        }
+    }
+
+    fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
+        feature_err(
+            &ccx.tcx.sess.parse_sess,
+            sym::const_fn_floating_point_arithmetic,
+            span,
+            &format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()),
+        )
+        .emit();
+    }
+}
+
+#[derive(Debug)]
 pub struct NonPrimitiveOp;
 impl NonConstOp for NonPrimitiveOp {
     const STOPS_CONST_CHECKING: bool = true;
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index dc28ba46d7c..73725c7b98e 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -540,8 +540,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
 
             Rvalue::UnaryOp(_, ref operand) => {
                 let ty = operand.ty(self.body, self.tcx);
-                if !(ty.is_integral() || ty.is_bool()) {
-                    self.check_op(ops::NonPrimitiveOp)
+                if is_int_bool_or_char(ty) {
+                    // Int, bool, and char operations are fine.
+                } else if ty.is_floating_point() {
+                    self.check_op(ops::FloatingPointOp);
+                } else {
+                    span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty);
                 }
             }
 
@@ -550,7 +554,9 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                 let lhs_ty = lhs.ty(self.body, self.tcx);
                 let rhs_ty = rhs.ty(self.body, self.tcx);
 
-                if let ty::RawPtr(_) | ty::FnPtr(..) = lhs_ty.kind() {
+                if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) {
+                    // Int, bool, and char operations are fine.
+                } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() {
                     assert_eq!(lhs_ty, rhs_ty);
                     assert!(
                         op == BinOp::Eq
@@ -563,12 +569,15 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                     );
 
                     self.check_op(ops::RawPtrComparison);
-                }
-
-                if !(lhs_ty.is_integral() || lhs_ty.is_bool() || lhs_ty.is_char())
-                    || !(rhs_ty.is_integral() || rhs_ty.is_bool() || rhs_ty.is_char())
-                {
-                    self.check_op(ops::NonPrimitiveOp)
+                } else if lhs_ty.is_floating_point() || rhs_ty.is_floating_point() {
+                    self.check_op(ops::FloatingPointOp);
+                } else {
+                    span_bug!(
+                        self.span,
+                        "non-primitive type in `Rvalue::BinaryOp`: {:?} ⚬ {:?}",
+                        lhs_ty,
+                        rhs_ty
+                    );
                 }
             }
         }
@@ -867,3 +876,7 @@ fn place_as_reborrow(
         }
     })
 }
+
+fn is_int_bool_or_char(ty: Ty<'_>) -> bool {
+    ty.is_bool() || ty.is_integral() || ty.is_char()
+}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 602bb4a44a9..12134a85f45 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -352,6 +352,7 @@ symbols! {
         const_evaluatable_checked,
         const_extern_fn,
         const_fn,
+        const_fn_floating_point_arithmetic,
         const_fn_transmute,
         const_fn_union,
         const_generics,