summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs')
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs115
1 files changed, 105 insertions, 10 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
index 53838cf41..067bdc960 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
@@ -1,3 +1,5 @@
+use std::collections::HashMap;
+
use base_db::fixture::WithFixture;
use chalk_ir::{AdtId, TyKind};
use hir_def::{
@@ -5,20 +7,16 @@ use hir_def::{
layout::{Layout, LayoutError},
};
-use crate::{test_db::TestDB, Interner, Substitution};
+use crate::{db::HirDatabase, test_db::TestDB, Interner, Substitution};
use super::layout_of_ty;
-fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
- // using unstable cargo features failed, fall back to using plain rustc
- let mut cmd = std::process::Command::new("rustc");
- cmd.args(["-Z", "unstable-options", "--print", "target-spec-json"]).env("RUSTC_BOOTSTRAP", "1");
- let output = cmd.output().unwrap();
- assert!(output.status.success(), "{}", output.status);
- let stdout = String::from_utf8(output.stdout).unwrap();
- let target_data_layout =
- stdout.split_once(r#""data-layout": ""#).unwrap().1.split_once('"').unwrap().0.to_owned();
+fn current_machine_data_layout() -> String {
+ project_model::target_data_layout::get(None, None, &HashMap::default()).unwrap()
+}
+fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
+ let target_data_layout = current_machine_data_layout();
let ra_fixture = format!(
"{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\n{ra_fixture}",
);
@@ -45,6 +43,42 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
layout_of_ty(&db, &goal_ty, module_id.krate())
}
+/// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
+fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
+ let target_data_layout = current_machine_data_layout();
+ let ra_fixture = format!(
+ "{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\nfn main(){{let goal = {{{ra_fixture}}};}}",
+ );
+
+ 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 adt_id = scope
+ .declarations()
+ .find_map(|x| match x {
+ hir_def::ModuleDefId::FunctionId(x) => {
+ let name = db.function_data(x).name.to_smol_str();
+ (name == "main").then_some(x)
+ }
+ _ => None,
+ })
+ .unwrap();
+ let hir_body = db.body(adt_id.into());
+ let pat = hir_body
+ .pats
+ .iter()
+ .find(|x| match x.1 {
+ hir_def::expr::Pat::Bind { name, .. } => name.to_smol_str() == "goal",
+ _ => false,
+ })
+ .unwrap()
+ .0;
+ let infer = db.infer(adt_id.into());
+ let goal_ty = infer.type_of_pat[pat].clone();
+ layout_of_ty(&db, &goal_ty, module_id.krate())
+}
+
#[track_caller]
fn check_size_and_align(ra_fixture: &str, minicore: &str, size: u64, align: u64) {
let l = eval_goal(ra_fixture, minicore).unwrap();
@@ -53,6 +87,13 @@ 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);
+}
+
+#[track_caller]
fn check_fail(ra_fixture: &str, e: LayoutError) {
let r = eval_goal(ra_fixture, "");
assert_eq!(r, Err(e));
@@ -85,11 +126,31 @@ macro_rules! size_and_align {
};
}
+macro_rules! size_and_align_expr {
+ ($($t:tt)*) => {
+ {
+ #[allow(dead_code)]
+ {
+ let val = { $($t)* };
+ check_size_and_align_expr(
+ stringify!($($t)*),
+ "",
+ ::std::mem::size_of_val(&val) as u64,
+ ::std::mem::align_of_val(&val) as u64,
+ );
+ }
+ }
+ };
+}
+
#[test]
fn hello_world() {
size_and_align! {
struct Goal(i32);
}
+ size_and_align_expr! {
+ 2i32
+ }
}
#[test]
@@ -144,6 +205,40 @@ fn generic() {
}
#[test]
+fn return_position_impl_trait() {
+ size_and_align_expr! {
+ trait T {}
+ impl T for i32 {}
+ impl T for i64 {}
+ fn foo() -> impl T { 2i64 }
+ foo()
+ }
+ size_and_align_expr! {
+ trait T {}
+ impl T for i32 {}
+ impl T for i64 {}
+ fn foo() -> (impl T, impl T, impl T) { (2i64, 5i32, 7i32) }
+ foo()
+ }
+ size_and_align_expr! {
+ struct Foo<T>(T, T, (T, T));
+ trait T {}
+ impl T for Foo<i32> {}
+ impl T for Foo<i64> {}
+
+ fn foo() -> Foo<impl T> { Foo(
+ Foo(1i64, 2, (3, 4)),
+ Foo(5, 6, (7, 8)),
+ (
+ Foo(1i64, 2, (3, 4)),
+ Foo(5, 6, (7, 8)),
+ ),
+ ) }
+ foo()
+ }
+}
+
+#[test]
fn enums() {
size_and_align! {
enum Goal {