mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +00:00
⬆️ rust-analyzer
This commit is contained in:
parent
3e0e51c108
commit
bc45c7659a
321 changed files with 11210 additions and 9720 deletions
|
@ -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();
|
||||
|
@ -52,6 +86,13 @@ fn check_size_and_align(ra_fixture: &str, minicore: &str, size: u64, align: u64)
|
|||
assert_eq!(l.align.abi.bytes(), align);
|
||||
}
|
||||
|
||||
#[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, "");
|
||||
|
@ -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]
|
||||
|
@ -143,6 +204,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! {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue