about summary refs log tree commit diff
diff options
context:
space:
mode:
authorhkalbasi <hamidrezakalbasi@protonmail.com>2022-03-24 13:06:27 +0430
committerhkalbasi <hamidrezakalbasi@protonmail.com>2022-03-24 13:20:35 +0430
commit22eaee25b8e8849aedc3454646cf9d9ca7195487 (patch)
tree648f4d84610133afe3601b4762bce939291cebe9
parent0e2989e421b03cb38bed54705783c63e751c3c86 (diff)
downloadrust-22eaee25b8e8849aedc3454646cf9d9ca7195487.tar.gz
rust-22eaee25b8e8849aedc3454646cf9d9ca7195487.zip
organize const eval tests
-rw-r--r--crates/hir/src/lib.rs5
-rw-r--r--crates/hir_ty/src/consteval.rs15
-rw-r--r--crates/hir_ty/src/consteval/tests.rs148
-rw-r--r--crates/hir_ty/src/tests/simple.rs12
-rw-r--r--crates/ide/src/hover/tests.rs168
5 files changed, 180 insertions, 168 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8c3c5fc628e..18de04b16da 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -55,10 +55,7 @@ use hir_def::{
 use hir_expand::{name::name, MacroCallKind};
 use hir_ty::{
     autoderef,
-    consteval::{
-        eval_const, unknown_const_as_generic, ComputedExpr, ConstEvalCtx, ConstEvalError, ConstExt,
-    },
-    could_unify,
+    consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt},
     diagnostics::BodyValidationDiagnostic,
     method_resolution::{self, TyFingerprint},
     primitive::UintTy,
diff --git a/crates/hir_ty/src/consteval.rs b/crates/hir_ty/src/consteval.rs
index 4829482e70b..9e1a856cd02 100644
--- a/crates/hir_ty/src/consteval.rs
+++ b/crates/hir_ty/src/consteval.rs
@@ -87,14 +87,14 @@ impl Display for ComputedExpr {
         match self {
             ComputedExpr::Literal(l) => match l {
                 Literal::Int(x, _) => {
-                    if *x >= 16 {
+                    if *x >= 10 {
                         write!(f, "{} ({:#X})", x, x)
                     } else {
                         x.fmt(f)
                     }
                 }
                 Literal::Uint(x, _) => {
-                    if *x >= 16 {
+                    if *x >= 10 {
                         write!(f, "{} ({:#X})", x, x)
                     } else {
                         x.fmt(f)
@@ -156,6 +156,7 @@ pub fn eval_const(
 ) -> Result<ComputedExpr, ConstEvalError> {
     let expr = &ctx.exprs[expr_id];
     match expr {
+        Expr::Missing => Err(ConstEvalError::IncompleteExpr),
         Expr::Literal(l) => Ok(ComputedExpr::Literal(l.clone())),
         &Expr::UnaryOp { expr, op } => {
             let ty = &ctx.expr_ty(expr);
@@ -339,6 +340,9 @@ pub fn eval_const(
                     Ok(r.clone())
                 }
                 ValueNs::ConstId(id) => ctx.db.const_eval(id),
+                ValueNs::GenericParam(_) => {
+                    Err(ConstEvalError::NotSupported("const generic without substitution"))
+                }
                 _ => Err(ConstEvalError::NotSupported("path that are not const or local")),
             }
         }
@@ -433,7 +437,7 @@ pub(crate) fn const_eval_query(
 ) -> Result<ComputedExpr, ConstEvalError> {
     let def = const_id.into();
     let body = db.body(def);
-    let mut infer = db.infer_query(def);
+    let infer = &db.infer(def);
     let result = eval_const(
         body.body_expr,
         &mut ConstEvalCtx {
@@ -442,7 +446,7 @@ pub(crate) fn const_eval_query(
             exprs: &body.exprs,
             pats: &body.pats,
             local_data: HashMap::default(),
-            infer: &mut infer,
+            infer,
         },
     );
     result
@@ -473,3 +477,6 @@ pub(crate) fn eval_to_const<'a>(
     };
     usize_const(eval_usize(expr, ctx))
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/crates/hir_ty/src/consteval/tests.rs b/crates/hir_ty/src/consteval/tests.rs
new file mode 100644
index 00000000000..4a052851afd
--- /dev/null
+++ b/crates/hir_ty/src/consteval/tests.rs
@@ -0,0 +1,148 @@
+use base_db::fixture::WithFixture;
+use hir_def::{db::DefDatabase, expr::Literal};
+
+use crate::{consteval::ComputedExpr, db::HirDatabase, test_db::TestDB};
+
+use super::ConstEvalError;
+
+fn check_fail(ra_fixture: &str, error: ConstEvalError) {
+    assert_eq!(eval_goal(ra_fixture), Err(error));
+}
+
+fn check_number(ra_fixture: &str, answer: i128) {
+    let r = eval_goal(ra_fixture).unwrap();
+    match r {
+        ComputedExpr::Literal(Literal::Int(r, _)) => assert_eq!(r, answer),
+        ComputedExpr::Literal(Literal::Uint(r, _)) => assert_eq!(r, answer as u128),
+        x => panic!("Expected number but found {:?}", x),
+    }
+}
+
+fn eval_goal(ra_fixture: &str) -> Result<ComputedExpr, ConstEvalError> {
+    let (db, file_id) = TestDB::with_single_file(ra_fixture);
+    let module_id = db.module_for_file(file_id);
+    let def_map = module_id.def_map(&db);
+    let scope = &def_map[module_id.local_id].scope;
+    let const_id = scope
+        .declarations()
+        .into_iter()
+        .find_map(|x| match x {
+            hir_def::ModuleDefId::ConstId(x) => {
+                if db.const_data(x).name.as_ref()?.to_string() == "GOAL" {
+                    Some(x)
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        })
+        .unwrap();
+    db.const_eval(const_id)
+}
+
+#[test]
+fn add() {
+    check_number(r#"const GOAL: usize = 2 + 2;"#, 4);
+}
+
+#[test]
+fn bit_op() {
+    check_number(r#"const GOAL: u8 = !0 & !(!0 >> 1)"#, 128);
+    check_number(r#"const GOAL: i8 = !0 & !(!0 >> 1)"#, 0);
+    // FIXME: rustc evaluate this to -128
+    check_fail(
+        r#"const GOAL: i8 = 1 << 7"#,
+        ConstEvalError::Panic("attempt to run invalid arithmetic operation".to_string()),
+    );
+    check_fail(
+        r#"const GOAL: i8 = 1 << 8"#,
+        ConstEvalError::Panic("attempt to run invalid arithmetic operation".to_string()),
+    );
+}
+
+#[test]
+fn locals() {
+    check_number(
+        r#"
+    const GOAL: usize = {
+        let a = 3 + 2;
+        let b = a * a;
+        b
+    };
+    "#,
+        25,
+    );
+}
+
+#[test]
+fn consts() {
+    check_number(
+        r#"
+    const F1: i32 = 1;
+    const F3: i32 = 3 * F2;
+    const F2: i32 = 2 * F1;
+    const GOAL: i32 = F3;
+    "#,
+        6,
+    );
+}
+
+#[test]
+fn const_loop() {
+    check_fail(
+        r#"
+    const F1: i32 = 1 * F3;
+    const F3: i32 = 3 * F2;
+    const F2: i32 = 2 * F1;
+    const GOAL: i32 = F3;
+    "#,
+        ConstEvalError::Loop,
+    );
+}
+
+#[test]
+fn const_impl_assoc() {
+    check_number(
+        r#"
+    struct U5;
+    impl U5 {
+        const VAL: usize = 5;
+    }
+    const GOAL: usize = U5::VAL;
+    "#,
+        5,
+    );
+}
+
+#[test]
+fn const_generic_subst() {
+    // FIXME: this should evaluate to 5
+    check_fail(
+        r#"
+    struct Adder<const N: usize, const M: usize>;
+    impl<const N: usize, const M: usize> Adder<N, M> {
+        const VAL: usize = N + M;
+    }
+    const GOAL: usize = Adder::<2, 3>::VAL;
+    "#,
+        ConstEvalError::NotSupported("const generic without substitution"),
+    );
+}
+
+#[test]
+fn const_trait_assoc() {
+    // FIXME: this should evaluate to 0
+    check_fail(
+        r#"
+    struct U0;
+    trait ToConst {
+        const VAL: usize;
+    }
+    impl ToConst for U0 {
+        const VAL: usize = 0;
+    }
+    const GOAL: usize = U0::VAL;
+    "#,
+        ConstEvalError::IncompleteExpr,
+    );
+}
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 31045c193c9..675f9038f09 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -1750,6 +1750,18 @@ fn main() {
 }
 
 #[test]
+fn const_eval_array_repeat_expr() {
+    check_types(
+        r#"
+fn main() {
+    const X: usize = 6 - 1;
+    let t = [(); X + 2];
+      //^ [(); 7]
+}"#,
+    );
+}
+
+#[test]
 fn shadowing_primitive_with_inner_items() {
     check_types(
         r#"
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 987e5d15564..67dc9884ed3 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -3399,13 +3399,13 @@ impl<const LEN: usize> Foo<LEN$0> {}
     );
 }
 
-// FIXME: move these tests to consteval module
 #[test]
 fn hover_const_eval() {
+    // show hex for <10
     check(
         r#"
 /// This is a doc
-const FOO$0: usize = !0 & !(!0 >> 1);
+const FOO$0: usize = 1 << 3;
 "#,
         expect![[r#"
             *FOO*
@@ -3415,7 +3415,7 @@ const FOO$0: usize = !0 & !(!0 >> 1);
             ```
 
             ```rust
-            const FOO: usize = 9223372036854775808 (0x8000000000000000)
+            const FOO: usize = 8
             ```
 
             ---
@@ -3423,14 +3423,11 @@ const FOO$0: usize = !0 & !(!0 >> 1);
             This is a doc
         "#]],
     );
+    // show hex for >10
     check(
         r#"
 /// This is a doc
-const FOO$0: usize = {
-    let a = 3 + 2;
-    let b = a * a;
-    b
-};
+const FOO$0: usize = (1 << 3) + (1 << 2);
 "#,
         expect![[r#"
             *FOO*
@@ -3440,53 +3437,7 @@ const FOO$0: usize = {
             ```
 
             ```rust
-            const FOO: usize = 25 (0x19)
-            ```
-
-            ---
-
-            This is a doc
-        "#]],
-    );
-    check(
-        r#"
-/// This is a doc
-const FOO$0: usize = 1 << 10;
-"#,
-        expect![[r#"
-            *FOO*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const FOO: usize = 1024 (0x400)
-            ```
-
-            ---
-
-            This is a doc
-        "#]],
-    );
-    check(
-        r#"
-/// This is a doc
-const FOO$0: usize = {
-    let b = 4;
-    let a = { let b = 2; let a = b; a } + { let a = 1; a + b };
-    a
-};
-"#,
-        expect![[r#"
-            *FOO*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const FOO: usize = 7
+            const FOO: usize = 12 (0xC)
             ```
 
             ---
@@ -3494,6 +3445,7 @@ const FOO$0: usize = {
             This is a doc
         "#]],
     );
+    // show original body when const eval fails
     check(
         r#"
 /// This is a doc
@@ -3515,6 +3467,7 @@ const FOO$0: usize = 2 - 3;
             This is a doc
         "#]],
     );
+    // don't show hex for negatives
     check(
         r#"
 /// This is a doc
@@ -3539,27 +3492,6 @@ const FOO$0: i32 = 2 - 3;
     check(
         r#"
 /// This is a doc
-const FOO$0: usize = 1 << 100;
-"#,
-        expect![[r#"
-            *FOO*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const FOO: usize = 1 << 100
-            ```
-
-            ---
-
-            This is a doc
-        "#]],
-    );
-    check(
-        r#"
-/// This is a doc
 const FOO$0: &str = "bar";
 "#,
         expect![[r#"
@@ -3578,90 +3510,6 @@ const FOO$0: &str = "bar";
             This is a doc
         "#]],
     );
-    check(
-        r#"
-const F1: i32 = 1;
-const F$03: i32 = 3 * F2;
-const F2: i32 = 2 * F1;
-"#,
-        expect![[r#"
-            *F3*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const F3: i32 = 6
-            ```
-        "#]],
-    );
-    check(
-        r#"
-const F1: i32 = 1 * F3;
-const F2: i32 = 2 * F1;
-const F$03: i32 = 3 * F2;
-"#,
-        expect![[r#"
-            *F3*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const F3: i32 = 3 * F2
-            ```
-        "#]],
-    );
-    check(
-        r#"
-struct U5;
-impl U5 {
-    const VAL: usize = 5;
-}
-const X$0X: usize = U5::VAL;
-"#,
-        expect![[r#"
-            *XX*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const XX: usize = 5
-            ```
-        "#]],
-    );
-}
-
-// FIXME: this should evaluate to zero
-#[test]
-fn hover_const_eval_broken() {
-    check(
-        r#"
-struct U0;
-trait ToConst {
-    const VAL: usize;
-}
-impl ToConst for U0 {
-    const VAL: usize = 0;
-}
-const X$0X: usize = U0::VAL;
-"#,
-        expect![[r#"
-            *XX*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const XX: usize = U0::VAL
-            ```
-        "#]],
-    );
 }
 
 #[test]