1 use base_db::fixture::WithFixture;
2 use hir_def::{db::DefDatabase, expr::Literal};
4 use crate::{consteval::ComputedExpr, db::HirDatabase, test_db::TestDB};
6 use super::ConstEvalError;
8 fn check_fail(ra_fixture: &str, error: ConstEvalError) {
9 assert_eq!(eval_goal(ra_fixture), Err(error));
12 fn check_number(ra_fixture: &str, answer: i128) {
13 let r = eval_goal(ra_fixture).unwrap();
15 ComputedExpr::Literal(Literal::Int(r, _)) => assert_eq!(r, answer),
16 ComputedExpr::Literal(Literal::Uint(r, _)) => assert_eq!(r, answer as u128),
17 x => panic!("Expected number but found {x:?}"),
21 fn eval_goal(ra_fixture: &str) -> Result<ComputedExpr, ConstEvalError> {
22 let (db, file_id) = TestDB::with_single_file(ra_fixture);
23 let module_id = db.module_for_file(file_id);
24 let def_map = module_id.def_map(&db);
25 let scope = &def_map[module_id.local_id].scope;
28 .find_map(|x| match x {
29 hir_def::ModuleDefId::ConstId(x) => {
30 if db.const_data(x).name.as_ref()?.to_string() == "GOAL" {
39 db.const_eval(const_id)
44 check_number(r#"const GOAL: usize = 2 + 2;"#, 4);
49 check_number(r#"const GOAL: u8 = !0 & !(!0 >> 1)"#, 128);
50 check_number(r#"const GOAL: i8 = !0 & !(!0 >> 1)"#, 0);
51 // FIXME: rustc evaluate this to -128
53 r#"const GOAL: i8 = 1 << 7"#,
54 ConstEvalError::Panic("attempt to run invalid arithmetic operation".to_string()),
57 r#"const GOAL: i8 = 1 << 8"#,
58 ConstEvalError::Panic("attempt to run invalid arithmetic operation".to_string()),
81 const F3: i32 = 3 * F2;
82 const F2: i32 = 2 * F1;
98 const GOAL: i32 = E::F3 as u8;
104 enum E { F1 = 1, F2, }
105 const GOAL: i32 = E::F2 as u8;
112 const GOAL: i32 = E::F1 as u8;
119 const GOAL: E = E::A;
124 ComputedExpr::Enum(name, _, Literal::Uint(val, _)) => {
125 assert_eq!(name, "E::A");
128 x => panic!("Expected enum but found {x:?}"),
136 const F1: i32 = 1 * F3;
137 const F3: i32 = 3 * F2;
138 const F2: i32 = 2 * F1;
139 const GOAL: i32 = F3;
141 ConstEvalError::Loop,
146 fn const_impl_assoc() {
151 const VAL: usize = 5;
153 const GOAL: usize = U5::VAL;
160 fn const_generic_subst() {
161 // FIXME: this should evaluate to 5
164 struct Adder<const N: usize, const M: usize>;
165 impl<const N: usize, const M: usize> Adder<N, M> {
166 const VAL: usize = N + M;
168 const GOAL: usize = Adder::<2, 3>::VAL;
170 ConstEvalError::NotSupported("const generic without substitution"),
175 fn const_trait_assoc() {
176 // FIXME: this should evaluate to 0
183 impl ToConst for U0 {
184 const VAL: usize = 0;
186 const GOAL: usize = U0::VAL;
188 ConstEvalError::IncompleteExpr,