Skip to content

Commit 8e5f944

Browse files
committed
Auto merge of #15282 - HKalbasi:mir, r=HKalbasi
Give real discriminant_type to chalk
2 parents c7ce8ad + 5055911 commit 8e5f944

File tree

13 files changed

+293
-80
lines changed

13 files changed

+293
-80
lines changed

crates/base-db/src/fixture.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
2626
let fixture = ChangeFixture::parse(ra_fixture);
2727
let mut db = Self::default();
2828
fixture.change.apply(&mut db);
29-
assert_eq!(fixture.files.len(), 1);
29+
assert_eq!(fixture.files.len(), 1, "Multiple file found in the fixture");
3030
(db, fixture.files[0])
3131
}
3232

crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,44 @@ fn test_hash_expand() {
416416
//- minicore: derive, hash
417417
use core::hash::Hash;
418418
419+
#[derive(Hash)]
420+
struct Foo {
421+
x: i32,
422+
y: u64,
423+
z: (i32, u64),
424+
}
425+
"#,
426+
expect![[r#"
427+
use core::hash::Hash;
428+
429+
#[derive(Hash)]
430+
struct Foo {
431+
x: i32,
432+
y: u64,
433+
z: (i32, u64),
434+
}
435+
436+
impl < > core::hash::Hash for Foo< > where {
437+
fn hash<H: core::hash::Hasher>(&self , ra_expand_state: &mut H) {
438+
match self {
439+
Foo {
440+
x: x, y: y, z: z,
441+
}
442+
=> {
443+
x.hash(ra_expand_state);
444+
y.hash(ra_expand_state);
445+
z.hash(ra_expand_state);
446+
}
447+
,
448+
}
449+
}
450+
}"#]],
451+
);
452+
check(
453+
r#"
454+
//- minicore: derive, hash
455+
use core::hash::Hash;
456+
419457
#[derive(Hash)]
420458
enum Command {
421459
Move { x: i32, y: i32 },

crates/hir-expand/src/builtin_derive_macro.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -624,9 +624,14 @@ fn hash_expand(
624624
}
625625
},
626626
);
627+
let check_discriminant = if matches!(&adt.shape, AdtShape::Enum { .. }) {
628+
quote! { #krate::mem::discriminant(self).hash(ra_expand_state); }
629+
} else {
630+
quote! {}
631+
};
627632
quote! {
628633
fn hash<H: #krate::hash::Hasher>(&self, ra_expand_state: &mut H) {
629-
#krate::mem::discriminant(self).hash(ra_expand_state);
634+
#check_discriminant
630635
match self {
631636
##arms
632637
}
@@ -742,9 +747,6 @@ fn ord_expand(
742747
// FIXME: Return expand error here
743748
return quote!();
744749
}
745-
let left = quote!(#krate::intrinsics::discriminant_value(self));
746-
let right = quote!(#krate::intrinsics::discriminant_value(other));
747-
748750
let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name);
749751
let arms = izip!(self_patterns, other_patterns, adt.shape.field_names()).map(
750752
|(pat1, pat2, fields)| {
@@ -759,17 +761,17 @@ fn ord_expand(
759761
},
760762
);
761763
let fat_arrow = fat_arrow();
762-
let body = compare(
763-
krate,
764-
left,
765-
right,
766-
quote! {
767-
match (self, other) {
768-
##arms
769-
_unused #fat_arrow #krate::cmp::Ordering::Equal
770-
}
771-
},
772-
);
764+
let mut body = quote! {
765+
match (self, other) {
766+
##arms
767+
_unused #fat_arrow #krate::cmp::Ordering::Equal
768+
}
769+
};
770+
if matches!(&adt.shape, AdtShape::Enum { .. }) {
771+
let left = quote!(#krate::intrinsics::discriminant_value(self));
772+
let right = quote!(#krate::intrinsics::discriminant_value(other));
773+
body = compare(krate, left, right, body);
774+
}
773775
quote! {
774776
fn cmp(&self, other: &Self) -> #krate::cmp::Ordering {
775777
#body

crates/hir-ty/src/chalk_db.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,37 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
6060
// FIXME: keep track of these
6161
Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None })
6262
}
63-
fn discriminant_type(&self, _ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> {
64-
// FIXME: keep track of this
65-
chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(Interner)
63+
fn discriminant_type(&self, ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> {
64+
if let chalk_ir::TyKind::Adt(id, _) = ty.kind(Interner) {
65+
if let hir_def::AdtId::EnumId(e) = id.0 {
66+
let enum_data = self.db.enum_data(e);
67+
let ty = enum_data.repr.unwrap_or_default().discr_type();
68+
return chalk_ir::TyKind::Scalar(match ty {
69+
hir_def::layout::IntegerType::Pointer(is_signed) => match is_signed {
70+
true => chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize),
71+
false => chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize),
72+
},
73+
hir_def::layout::IntegerType::Fixed(size, is_signed) => match is_signed {
74+
true => chalk_ir::Scalar::Int(match size {
75+
hir_def::layout::Integer::I8 => chalk_ir::IntTy::I8,
76+
hir_def::layout::Integer::I16 => chalk_ir::IntTy::I16,
77+
hir_def::layout::Integer::I32 => chalk_ir::IntTy::I32,
78+
hir_def::layout::Integer::I64 => chalk_ir::IntTy::I64,
79+
hir_def::layout::Integer::I128 => chalk_ir::IntTy::I128,
80+
}),
81+
false => chalk_ir::Scalar::Uint(match size {
82+
hir_def::layout::Integer::I8 => chalk_ir::UintTy::U8,
83+
hir_def::layout::Integer::I16 => chalk_ir::UintTy::U16,
84+
hir_def::layout::Integer::I32 => chalk_ir::UintTy::U32,
85+
hir_def::layout::Integer::I64 => chalk_ir::UintTy::U64,
86+
hir_def::layout::Integer::I128 => chalk_ir::UintTy::U128,
87+
}),
88+
},
89+
})
90+
.intern(Interner);
91+
}
92+
}
93+
chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U8)).intern(Interner)
6694
}
6795
fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
6896
self.db.impl_datum(self.krate, impl_id)

crates/hir-ty/src/consteval/tests.rs

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use test_utils::skip_slow_tests;
55

66
use crate::{
77
consteval::try_const_usize, db::HirDatabase, mir::pad16, test_db::TestDB, Const, ConstScalar,
8-
Interner,
8+
Interner, MemoryMap,
99
};
1010

1111
use super::{
@@ -37,7 +37,7 @@ fn check_fail(ra_fixture: &str, error: impl FnOnce(ConstEvalError) -> bool) {
3737

3838
#[track_caller]
3939
fn check_number(ra_fixture: &str, answer: i128) {
40-
check_answer(ra_fixture, |b| {
40+
check_answer(ra_fixture, |b, _| {
4141
assert_eq!(
4242
b,
4343
&answer.to_le_bytes()[0..b.len()],
@@ -48,8 +48,26 @@ fn check_number(ra_fixture: &str, answer: i128) {
4848
}
4949

5050
#[track_caller]
51-
fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8])) {
52-
let (db, file_id) = TestDB::with_single_file(ra_fixture);
51+
fn check_str(ra_fixture: &str, answer: &str) {
52+
check_answer(ra_fixture, |b, mm| {
53+
let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
54+
let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
55+
let Some(bytes) = mm.get(addr, size) else {
56+
panic!("string data missed in the memory map");
57+
};
58+
assert_eq!(
59+
bytes,
60+
answer.as_bytes(),
61+
"Bytes differ. In string form: actual = {}, expected = {answer}",
62+
String::from_utf8_lossy(bytes)
63+
);
64+
});
65+
}
66+
67+
#[track_caller]
68+
fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8], &MemoryMap)) {
69+
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
70+
let file_id = *file_ids.last().unwrap();
5371
let r = match eval_goal(&db, file_id) {
5472
Ok(t) => t,
5573
Err(e) => {
@@ -59,8 +77,8 @@ fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8])) {
5977
};
6078
match &r.data(Interner).value {
6179
chalk_ir::ConstValue::Concrete(c) => match &c.interned {
62-
ConstScalar::Bytes(b, _) => {
63-
check(b);
80+
ConstScalar::Bytes(b, mm) => {
81+
check(b, mm);
6482
}
6583
x => panic!("Expected number but found {:?}", x),
6684
},
@@ -225,7 +243,7 @@ const GOAL: usize = {
225243
transmute(&x)
226244
}
227245
"#,
228-
|b| assert_eq!(b[0] % 8, 0),
246+
|b, _| assert_eq!(b[0] % 8, 0),
229247
);
230248
check_answer(
231249
r#"
@@ -234,7 +252,7 @@ use core::mem::transmute;
234252
static X: i64 = 12;
235253
const GOAL: usize = transmute(&X);
236254
"#,
237-
|b| assert_eq!(b[0] % 8, 0),
255+
|b, _| assert_eq!(b[0] % 8, 0),
238256
);
239257
}
240258

@@ -2068,6 +2086,17 @@ fn array_and_index() {
20682086
);
20692087
}
20702088

2089+
#[test]
2090+
fn string() {
2091+
check_str(
2092+
r#"
2093+
//- minicore: coerce_unsized, index, slice
2094+
const GOAL: &str = "hello";
2095+
"#,
2096+
"hello",
2097+
);
2098+
}
2099+
20712100
#[test]
20722101
fn byte_string() {
20732102
check_number(
@@ -2444,6 +2473,25 @@ fn const_trait_assoc() {
24442473
"#,
24452474
32,
24462475
);
2476+
check_number(
2477+
r#"
2478+
//- /a/lib.rs crate:a
2479+
pub trait ToConst {
2480+
const VAL: usize;
2481+
}
2482+
pub const fn to_const<T: ToConst>() -> usize {
2483+
T::VAL
2484+
}
2485+
//- /main.rs crate:main deps:a
2486+
use a::{ToConst, to_const};
2487+
struct U0;
2488+
impl ToConst for U0 {
2489+
const VAL: usize = 5;
2490+
}
2491+
const GOAL: usize = to_const::<U0>();
2492+
"#,
2493+
5,
2494+
);
24472495
check_number(
24482496
r#"
24492497
struct S<T>(*mut T);

crates/hir-ty/src/consteval/tests/intrinsics.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,36 @@ fn min_align_of_val() {
149149
);
150150
}
151151

152+
#[test]
153+
fn type_name() {
154+
check_str(
155+
r#"
156+
extern "rust-intrinsic" {
157+
pub fn type_name<T: ?Sized>() -> &'static str;
158+
}
159+
160+
const GOAL: &str = type_name::<i32>();
161+
"#,
162+
"i32",
163+
);
164+
check_str(
165+
r#"
166+
extern "rust-intrinsic" {
167+
pub fn type_name<T: ?Sized>() -> &'static str;
168+
}
169+
170+
mod mod1 {
171+
pub mod mod2 {
172+
pub struct Ty;
173+
}
174+
}
175+
176+
const GOAL: &str = type_name::<mod1::mod2::Ty>();
177+
"#,
178+
"mod1::mod2::Ty",
179+
);
180+
}
181+
152182
#[test]
153183
fn transmute() {
154184
check_number(

crates/hir-ty/src/layout/tests.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,3 +464,41 @@ fn enums_with_discriminants() {
464464
}
465465
}
466466
}
467+
468+
#[test]
469+
fn core_mem_discriminant() {
470+
size_and_align! {
471+
minicore: discriminant;
472+
struct S(i32, u64);
473+
struct Goal(core::mem::Discriminant<S>);
474+
}
475+
size_and_align! {
476+
minicore: discriminant;
477+
#[repr(u32)]
478+
enum S {
479+
A,
480+
B,
481+
C,
482+
}
483+
struct Goal(core::mem::Discriminant<S>);
484+
}
485+
size_and_align! {
486+
minicore: discriminant;
487+
enum S {
488+
A(i32),
489+
B(i64),
490+
C(u8),
491+
}
492+
struct Goal(core::mem::Discriminant<S>);
493+
}
494+
size_and_align! {
495+
minicore: discriminant;
496+
#[repr(C, u16)]
497+
enum S {
498+
A(i32),
499+
B(i64) = 200,
500+
C = 1000,
501+
}
502+
struct Goal(core::mem::Discriminant<S>);
503+
}
504+
}

0 commit comments

Comments
 (0)