Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs38
-rw-r--r--crates/hir-expand/src/builtin_derive_macro.rs32
-rw-r--r--crates/hir-ty/src/chalk_db.rs34
-rw-r--r--crates/hir-ty/src/layout/tests.rs38
-rw-r--r--crates/ide/src/inlay_hints/chaining.rs12
-rw-r--r--crates/test-utils/src/minicore.rs5
6 files changed, 135 insertions, 24 deletions
diff --git a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
index 145cf8ddd4..abd84c6a46 100644
--- a/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
+++ b/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
@@ -417,6 +417,44 @@ fn test_hash_expand() {
use core::hash::Hash;
#[derive(Hash)]
+struct Foo {
+ x: i32,
+ y: u64,
+ z: (i32, u64),
+}
+"#,
+ expect![[r#"
+use core::hash::Hash;
+
+#[derive(Hash)]
+struct Foo {
+ x: i32,
+ y: u64,
+ z: (i32, u64),
+}
+
+impl < > core::hash::Hash for Foo< > where {
+ fn hash<H: core::hash::Hasher>(&self , ra_expand_state: &mut H) {
+ match self {
+ Foo {
+ x: x, y: y, z: z,
+ }
+ => {
+ x.hash(ra_expand_state);
+ y.hash(ra_expand_state);
+ z.hash(ra_expand_state);
+ }
+ ,
+ }
+ }
+}"#]],
+ );
+ check(
+ r#"
+//- minicore: derive, hash
+use core::hash::Hash;
+
+#[derive(Hash)]
enum Command {
Move { x: i32, y: i32 },
Do(&'static str),
diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs
index c8c3cebb88..ecc8b407a9 100644
--- a/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/crates/hir-expand/src/builtin_derive_macro.rs
@@ -624,9 +624,14 @@ fn hash_expand(
}
},
);
+ let check_discriminant = if matches!(&adt.shape, AdtShape::Enum { .. }) {
+ quote! { #krate::mem::discriminant(self).hash(ra_expand_state); }
+ } else {
+ quote! {}
+ };
quote! {
fn hash<H: #krate::hash::Hasher>(&self, ra_expand_state: &mut H) {
- #krate::mem::discriminant(self).hash(ra_expand_state);
+ #check_discriminant
match self {
##arms
}
@@ -742,9 +747,6 @@ fn ord_expand(
// FIXME: Return expand error here
return quote!();
}
- let left = quote!(#krate::intrinsics::discriminant_value(self));
- let right = quote!(#krate::intrinsics::discriminant_value(other));
-
let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name);
let arms = izip!(self_patterns, other_patterns, adt.shape.field_names()).map(
|(pat1, pat2, fields)| {
@@ -759,17 +761,17 @@ fn ord_expand(
},
);
let fat_arrow = fat_arrow();
- let body = compare(
- krate,
- left,
- right,
- quote! {
- match (self, other) {
- ##arms
- _unused #fat_arrow #krate::cmp::Ordering::Equal
- }
- },
- );
+ let mut body = quote! {
+ match (self, other) {
+ ##arms
+ _unused #fat_arrow #krate::cmp::Ordering::Equal
+ }
+ };
+ if matches!(&adt.shape, AdtShape::Enum { .. }) {
+ let left = quote!(#krate::intrinsics::discriminant_value(self));
+ let right = quote!(#krate::intrinsics::discriminant_value(other));
+ body = compare(krate, left, right, body);
+ }
quote! {
fn cmp(&self, other: &Self) -> #krate::cmp::Ordering {
#body
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index 50eabc867b..f4fbace19e 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -60,9 +60,37 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
// FIXME: keep track of these
Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None })
}
- fn discriminant_type(&self, _ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> {
- // FIXME: keep track of this
- chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(Interner)
+ fn discriminant_type(&self, ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> {
+ if let chalk_ir::TyKind::Adt(id, _) = ty.kind(Interner) {
+ if let hir_def::AdtId::EnumId(e) = id.0 {
+ let enum_data = self.db.enum_data(e);
+ let ty = enum_data.repr.unwrap_or_default().discr_type();
+ return chalk_ir::TyKind::Scalar(match ty {
+ hir_def::layout::IntegerType::Pointer(is_signed) => match is_signed {
+ true => chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize),
+ false => chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize),
+ },
+ hir_def::layout::IntegerType::Fixed(size, is_signed) => match is_signed {
+ true => chalk_ir::Scalar::Int(match size {
+ hir_def::layout::Integer::I8 => chalk_ir::IntTy::I8,
+ hir_def::layout::Integer::I16 => chalk_ir::IntTy::I16,
+ hir_def::layout::Integer::I32 => chalk_ir::IntTy::I32,
+ hir_def::layout::Integer::I64 => chalk_ir::IntTy::I64,
+ hir_def::layout::Integer::I128 => chalk_ir::IntTy::I128,
+ }),
+ false => chalk_ir::Scalar::Uint(match size {
+ hir_def::layout::Integer::I8 => chalk_ir::UintTy::U8,
+ hir_def::layout::Integer::I16 => chalk_ir::UintTy::U16,
+ hir_def::layout::Integer::I32 => chalk_ir::UintTy::U32,
+ hir_def::layout::Integer::I64 => chalk_ir::UintTy::U64,
+ hir_def::layout::Integer::I128 => chalk_ir::UintTy::U128,
+ }),
+ },
+ })
+ .intern(Interner);
+ }
+ }
+ chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U8)).intern(Interner)
}
fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
self.db.impl_datum(self.krate, impl_id)
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index 2b74f1a1a1..a3ced2bac0 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -464,3 +464,41 @@ fn enums_with_discriminants() {
}
}
}
+
+#[test]
+fn core_mem_discriminant() {
+ size_and_align! {
+ minicore: discriminant;
+ struct S(i32, u64);
+ struct Goal(core::mem::Discriminant<S>);
+ }
+ size_and_align! {
+ minicore: discriminant;
+ #[repr(u32)]
+ enum S {
+ A,
+ B,
+ C,
+ }
+ struct Goal(core::mem::Discriminant<S>);
+ }
+ size_and_align! {
+ minicore: discriminant;
+ enum S {
+ A(i32),
+ B(i64),
+ C(u8),
+ }
+ struct Goal(core::mem::Discriminant<S>);
+ }
+ size_and_align! {
+ minicore: discriminant;
+ #[repr(C, u16)]
+ enum S {
+ A(i32),
+ B(i64) = 200,
+ C = 1000,
+ }
+ struct Goal(core::mem::Discriminant<S>);
+ }
+}
diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index 774383d50d..b621a8dda7 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/crates/ide/src/inlay_hints/chaining.rs
@@ -474,7 +474,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9288..9296,
+ range: 9289..9297,
},
),
tooltip: "",
@@ -487,7 +487,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9320..9324,
+ range: 9321..9325,
},
),
tooltip: "",
@@ -511,7 +511,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9288..9296,
+ range: 9289..9297,
},
),
tooltip: "",
@@ -524,7 +524,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9320..9324,
+ range: 9321..9325,
},
),
tooltip: "",
@@ -548,7 +548,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9288..9296,
+ range: 9289..9297,
},
),
tooltip: "",
@@ -561,7 +561,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9320..9324,
+ range: 9321..9325,
},
),
tooltip: "",
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index ebde017686..c765f42447 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -364,6 +364,11 @@ pub mod mem {
pub fn size_of<T>() -> usize;
}
// endregion:size_of
+
+ // region:discriminant
+ use crate::marker::DiscriminantKind;
+ pub struct Discriminant<T>(<T as DiscriminantKind>::Discriminant);
+ // endregion:discriminant
}
pub mod ptr {