about summary refs log tree commit diff
diff options
context:
space:
mode:
-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 145cf8ddd40..abd84c6a46d 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 c8c3cebb88e..ecc8b407a9c 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 50eabc867b8..f4fbace19e3 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 2b74f1a1a1d..a3ced2bac0a 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 774383d50d6..b621a8dda7e 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 ebde017686d..c765f42447a 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 {