Compute closure captures

This commit is contained in:
hkalbasi 2023-04-06 16:14:38 +03:30
parent 51d5862caf
commit 59b6f2d9f2
42 changed files with 2537 additions and 433 deletions

View file

@ -11,6 +11,8 @@ use crate::{db::HirDatabase, test_db::TestDB, Interner, Substitution};
use super::layout_of_ty;
mod closure;
fn current_machine_data_layout() -> String {
project_model::target_data_layout::get(None, None, &HashMap::default()).unwrap()
}
@ -81,8 +83,8 @@ fn check_size_and_align(ra_fixture: &str, minicore: &str, size: u64, align: u64)
#[track_caller]
fn check_size_and_align_expr(ra_fixture: &str, minicore: &str, size: u64, align: u64) {
let l = eval_expr(ra_fixture, minicore).unwrap();
assert_eq!(l.size.bytes(), size);
assert_eq!(l.align.abi.bytes(), align);
assert_eq!(l.size.bytes(), size, "size mismatch");
assert_eq!(l.align.abi.bytes(), align, "align mismatch");
}
#[track_caller]
@ -118,13 +120,31 @@ macro_rules! size_and_align {
};
}
#[macro_export]
macro_rules! size_and_align_expr {
(minicore: $($x:tt),*; stmts: [$($s:tt)*] $($t:tt)*) => {
{
#[allow(dead_code)]
#[allow(unused_must_use)]
#[allow(path_statements)]
{
$($s)*
let val = { $($t)* };
$crate::layout::tests::check_size_and_align_expr(
&format!("{{ {} let val = {{ {} }}; val }}", stringify!($($s)*), stringify!($($t)*)),
&format!("//- minicore: {}\n", stringify!($($x),*)),
::std::mem::size_of_val(&val) as u64,
::std::mem::align_of_val(&val) as u64,
);
}
}
};
($($t:tt)*) => {
{
#[allow(dead_code)]
{
let val = { $($t)* };
check_size_and_align_expr(
$crate::layout::tests::check_size_and_align_expr(
stringify!($($t)*),
"",
::std::mem::size_of_val(&val) as u64,

View file

@ -0,0 +1,175 @@
use crate::size_and_align_expr;
#[test]
fn zero_capture_simple() {
size_and_align_expr! {
|x: i32| x + 2
}
}
#[test]
fn move_simple() {
size_and_align_expr! {
minicore: copy;
stmts: []
let y: i32 = 5;
move |x: i32| {
x + y
}
}
}
#[test]
fn ref_simple() {
size_and_align_expr! {
minicore: copy;
stmts: [
let y: i32 = 5;
]
|x: i32| {
x + y
}
}
size_and_align_expr! {
minicore: copy;
stmts: [
let mut y: i32 = 5;
]
|x: i32| {
y = y + x;
y
}
}
size_and_align_expr! {
minicore: copy;
stmts: [
struct X(i32, i64);
let x: X = X(2, 6);
]
|| {
x
}
}
}
#[test]
fn ref_then_mut_then_move() {
size_and_align_expr! {
minicore: copy;
stmts: [
struct X(i32, i64);
let mut x: X = X(2, 6);
]
|| {
&x;
&mut x;
x;
}
}
}
#[test]
fn nested_closures() {
size_and_align_expr! {
|| {
|| {
|| {
let x = 2;
move || {
move || {
x
}
}
}
}
}
}
}
#[test]
fn capture_specific_fields() {
size_and_align_expr! {
struct X(i64, i32, (u8, i128));
let y: X = X(2, 5, (7, 3));
move |x: i64| {
y.0 + x + (y.2 .0 as i64)
}
}
size_and_align_expr! {
struct X(i64, i32, (u8, i128));
let y: X = X(2, 5, (7, 3));
move |x: i64| {
let _ = &y;
y.0 + x + (y.2 .0 as i64)
}
}
size_and_align_expr! {
minicore: copy;
stmts: [
struct X(i64, i32, (u8, i128));
let y: X = X(2, 5, (7, 3));
]
let y = &y;
move |x: i64| {
y.0 + x + (y.2 .0 as i64)
}
}
size_and_align_expr! {
struct X(i64, i32, (u8, i128));
let y: X = X(2, 5, (7, 3));
move |x: i64| {
let X(a, _, (b, _)) = y;
a + x + (b as i64)
}
}
size_and_align_expr! {
struct X(i64, i32, (u8, i128));
let y = &&X(2, 5, (7, 3));
move |x: i64| {
let X(a, _, (b, _)) = y;
*a + x + (*b as i64)
}
}
size_and_align_expr! {
struct X(i64, i32, (u8, i128));
let y: X = X(2, 5, (7, 3));
move |x: i64| {
match y {
X(a, _, (b, _)) => a + x + (b as i64),
}
}
}
size_and_align_expr! {
struct X(i64, i32, (u8, i128));
let y: X = X(2, 5, (7, 3));
move |x: i64| {
let X(a @ 2, _, (b, _)) = y else { return 5 };
a + x + (b as i64)
}
}
}
#[test]
fn ellipsis_pattern() {
size_and_align_expr! {
struct X(i8, u16, i32, u64, i128, u8);
let y: X = X(1, 2, 3, 4, 5, 6);
move |_: i64| {
let X(_a, .., _b, _c) = y;
}
}
size_and_align_expr! {
struct X { a: i32, b: u8, c: i128}
let y: X = X { a: 1, b: 2, c: 3 };
move |_: i64| {
let X { a, b, .. } = y;
_ = (a, b);
}
}
size_and_align_expr! {
let y: (&&&(i8, u16, i32, u64, i128, u8), u16, i32, u64, i128, u8) = (&&&(1, 2, 3, 4, 5, 6), 2, 3, 4, 5, 6);
move |_: i64| {
let ((_a, .., _b, _c), .., _e, _f) = y;
}
}
}