fix: Support unstable `UnsafePinned` struct in type layout calc
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index e7784f3..5431ec9 100644
--- a/crates/hir-def/src/lang_item.rs
+++ b/crates/hir-def/src/lang_item.rs
@@ -345,6 +345,7 @@
     IndexMut,                sym::index_mut,           index_mut_trait,            Target::Trait,          GenericRequirement::Exact(1);
 
     UnsafeCell,              sym::unsafe_cell,         unsafe_cell_type,           Target::Struct,         GenericRequirement::None;
+    UnsafePinned,            sym::unsafe_pinned,       unsafe_pinned_type,         Target::Struct,         GenericRequirement::None;
     VaList,                  sym::va_list,             va_list,                    Target::Struct,         GenericRequirement::None;
 
     Deref,                   sym::deref,               deref_trait,                Target::Trait,          GenericRequirement::Exact(0);
diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs
index 4800a1c..d1d250a 100644
--- a/crates/hir-def/src/signatures.rs
+++ b/crates/hir-def/src/signatures.rs
@@ -62,6 +62,8 @@
         const IS_MANUALLY_DROP = 1 << 5;
         /// Indicates whether this struct is `UnsafeCell`.
         const IS_UNSAFE_CELL   = 1 << 6;
+        /// Indicates whether this struct is `UnsafePinned`.
+        const IS_UNSAFE_PINNED = 1 << 7;
     }
 }
 
@@ -84,6 +86,7 @@
                 LangItem::OwnedBox => flags |= StructFlags::IS_BOX,
                 LangItem::ManuallyDrop => flags |= StructFlags::IS_MANUALLY_DROP,
                 LangItem::UnsafeCell => flags |= StructFlags::IS_UNSAFE_CELL,
+                LangItem::UnsafePinned => flags |= StructFlags::IS_UNSAFE_PINNED,
                 _ => (),
             }
         }
diff --git a/crates/hir-ty/src/lang_items.rs b/crates/hir-ty/src/lang_items.rs
index 8ec3aee..10e880d 100644
--- a/crates/hir-ty/src/lang_items.rs
+++ b/crates/hir-ty/src/lang_items.rs
@@ -11,12 +11,6 @@
     db.struct_signature(id).flags.contains(StructFlags::IS_BOX)
 }
 
-pub fn is_unsafe_cell(db: &dyn HirDatabase, adt: AdtId) -> bool {
-    let AdtId::StructId(id) = adt else { return false };
-
-    db.struct_signature(id).flags.contains(StructFlags::IS_UNSAFE_CELL)
-}
-
 pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, LangItem)> {
     use syntax::ast::{ArithOp, BinaryOp, CmpOp, Ordering};
     Some(match op {
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index de6a82a..67e0e37 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -5,7 +5,7 @@
 use hir_def::{
     AdtId, VariantId,
     layout::{Integer, ReprOptions, TargetDataLayout},
-    signatures::VariantFields,
+    signatures::{StructFlags, VariantFields},
 };
 use intern::sym;
 use rustc_index::IndexVec;
@@ -16,7 +16,6 @@
 use crate::{
     Substitution, TraitEnvironment,
     db::HirDatabase,
-    lang_items::is_unsafe_cell,
     layout::{Layout, LayoutError, field_ty},
 };
 
@@ -40,18 +39,22 @@
             .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), trait_env.clone()))
             .collect::<Result<Vec<_>, _>>()
     };
-    let (variants, repr) = match def {
+    let (variants, repr, is_special_no_niche) = match def {
         AdtId::StructId(s) => {
-            let data = db.struct_signature(s);
+            let sig = db.struct_signature(s);
             let mut r = SmallVec::<[_; 1]>::new();
             r.push(handle_variant(s.into(), &db.variant_fields(s.into()))?);
-            (r, data.repr.unwrap_or_default())
+            (
+                r,
+                sig.repr.unwrap_or_default(),
+                sig.flags.intersects(StructFlags::IS_UNSAFE_CELL | StructFlags::IS_UNSAFE_PINNED),
+            )
         }
         AdtId::UnionId(id) => {
             let data = db.union_signature(id);
             let mut r = SmallVec::new();
             r.push(handle_variant(id.into(), &db.variant_fields(id.into()))?);
-            (r, data.repr.unwrap_or_default())
+            (r, data.repr.unwrap_or_default(), false)
         }
         AdtId::EnumId(e) => {
             let variants = db.enum_variants(e);
@@ -60,7 +63,7 @@
                 .iter()
                 .map(|&(v, _)| handle_variant(v.into(), &db.variant_fields(v.into())))
                 .collect::<Result<SmallVec<_>, _>>()?;
-            (r, db.enum_signature(e).repr.unwrap_or_default())
+            (r, db.enum_signature(e).repr.unwrap_or_default(), false)
         }
     };
     let variants = variants
@@ -75,7 +78,7 @@
             &repr,
             &variants,
             matches!(def, AdtId::EnumId(..)),
-            is_unsafe_cell(db, def),
+            is_special_no_niche,
             layout_scalar_valid_range(db, def),
             |min, max| repr_discr(dl, &repr, min, max).unwrap_or((Integer::I8, false)),
             variants.iter_enumerated().filter_map(|(id, _)| {
diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs
index a9ed185..49c1c95 100644
--- a/crates/intern/src/symbol/symbols.rs
+++ b/crates/intern/src/symbol/symbols.rs
@@ -512,6 +512,7 @@
     unreachable_2021,
     unreachable,
     unsafe_cell,
+    unsafe_pinned,
     unsize,
     unstable,
     usize,