Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/eval/tests.rs')
| -rw-r--r-- | crates/hir-ty/src/mir/eval/tests.rs | 253 |
1 files changed, 248 insertions, 5 deletions
diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs index 6a9d3c5b4f..453c93de8e 100644 --- a/crates/hir-ty/src/mir/eval/tests.rs +++ b/crates/hir-ty/src/mir/eval/tests.rs @@ -21,10 +21,15 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr } _ => None, }) - .unwrap(); - let body = - db.mir_body(func_id.into()).map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?; - let (result, stdout, stderr) = interpret_mir(db, &body, Substitution::empty(Interner), false); + .expect("no main function found"); + let body = db + .monomorphized_mir_body( + func_id.into(), + Substitution::empty(Interner), + db.trait_environment(func_id.into()), + ) + .map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?; + let (result, stdout, stderr) = interpret_mir(db, &body, false); result?; Ok((stdout, stderr)) } @@ -34,7 +39,8 @@ fn check_pass(ra_fixture: &str) { } fn check_pass_and_stdio(ra_fixture: &str, expected_stdout: &str, expected_stderr: &str) { - let (db, file_id) = TestDB::with_single_file(ra_fixture); + let (db, file_ids) = TestDB::with_many_files(ra_fixture); + let file_id = *file_ids.last().unwrap(); let x = eval_main(&db, file_id); match x { Err(e) => { @@ -271,6 +277,243 @@ fn main() { } #[test] +fn from_fn() { + check_pass( + r#" +//- minicore: fn, iterator +struct FromFn<F>(F); + +impl<T, F: FnMut() -> Option<T>> Iterator for FromFn<F> { + type Item = T; + + fn next(&mut self) -> Option<Self::Item> { + (self.0)() + } +} + +fn main() { + let mut tokenize = { + FromFn(move || Some(2)) + }; + let s = tokenize.next(); +} + "#, + ); +} + +#[test] +fn for_loop() { + check_pass( + r#" +//- minicore: iterator, add +fn should_not_reach() { + _ // FIXME: replace this function with panic when that works +} + +struct X; +struct XIter(i32); + +impl IntoIterator for X { + type Item = i32; + + type IntoIter = XIter; + + fn into_iter(self) -> Self::IntoIter { + XIter(0) + } +} + +impl Iterator for XIter { + type Item = i32; + + fn next(&mut self) -> Option<Self::Item> { + if self.0 == 5 { + None + } else { + self.0 += 1; + Some(self.0) + } + } +} + +fn main() { + let mut s = 0; + for x in X { + s += x; + } + if s != 15 { + should_not_reach(); + } +} + "#, + ); +} + +#[test] +fn field_with_associated_type() { + check_pass( + r#" +//- /b/mod.rs crate:b +pub trait Tr { + fn f(self); +} + +pub trait Tr2 { + type Ty: Tr; +} + +pub struct S<T: Tr2> { + pub t: T::Ty, +} + +impl<T: Tr2> S<T> { + pub fn g(&self) { + let k = (self.t, self.t); + self.t.f(); + } +} + +//- /a/mod.rs crate:a deps:b +use b::{Tr, Tr2, S}; + +struct A(i32); +struct B(u8); + +impl Tr for A { + fn f(&self) { + } +} + +impl Tr2 for B { + type Ty = A; +} + +#[test] +fn main() { + let s: S<B> = S { t: A(2) }; + s.g(); +} + "#, + ); +} + +#[test] +fn specialization_array_clone() { + check_pass( + r#" +//- minicore: copy, derive, slice, index, coerce_unsized +impl<T: Clone, const N: usize> Clone for [T; N] { + #[inline] + fn clone(&self) -> Self { + SpecArrayClone::clone(self) + } +} + +trait SpecArrayClone: Clone { + fn clone<const N: usize>(array: &[Self; N]) -> [Self; N]; +} + +impl<T: Clone> SpecArrayClone for T { + #[inline] + default fn clone<const N: usize>(array: &[T; N]) -> [T; N] { + // FIXME: panic here when we actually implement specialization. + from_slice(array) + } +} + +fn from_slice<T, const N: usize>(s: &[T]) -> [T; N] { + [s[0]; N] +} + +impl<T: Copy> SpecArrayClone for T { + #[inline] + fn clone<const N: usize>(array: &[T; N]) -> [T; N] { + *array + } +} + +#[derive(Clone, Copy)] +struct X(i32); + +fn main() { + let ar = [X(1), X(2)]; + ar.clone(); +} + "#, + ); +} + +#[test] +fn short_circuit_operator() { + check_pass( + r#" +fn should_not_reach() -> bool { + _ // FIXME: replace this function with panic when that works +} + +fn main() { + if false && should_not_reach() { + should_not_reach(); + } + true || should_not_reach(); + +} + "#, + ); +} + +#[test] +fn closure_state() { + check_pass( + r#" +//- minicore: fn, add, copy +fn should_not_reach() { + _ // FIXME: replace this function with panic when that works +} + +fn main() { + let mut x = 2; + let mut c = move || { + x += 1; + x + }; + c(); + c(); + c(); + if x != 2 { + should_not_reach(); + } + if c() != 6 { + should_not_reach(); + } +} + "#, + ); +} + +#[test] +fn closure_capture_array_const_generic() { + check_pass( + r#" +//- minicore: fn, add, copy +struct X(i32); + +fn f<const N: usize>(mut x: [X; N]) { // -> impl FnOnce() { + let c = || { + x; + }; + c(); +} + +fn main() { + let s = f([X(1)]); + //s(); +} + "#, + ); +} + +#[test] fn posix_tls() { check_pass( r#" |