Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/adt.rs')
-rw-r--r--crates/hir-def/src/adt.rs95
1 files changed, 54 insertions, 41 deletions
diff --git a/crates/hir-def/src/adt.rs b/crates/hir-def/src/adt.rs
index e5ab7bf3f6..db3b419488 100644
--- a/crates/hir-def/src/adt.rs
+++ b/crates/hir-def/src/adt.rs
@@ -1,6 +1,6 @@
//! Defines hir-level representation of structs, enums and unions
-use std::{num::NonZeroU32, sync::Arc};
+use std::sync::Arc;
use base_db::CrateId;
use either::Either;
@@ -9,6 +9,7 @@ use hir_expand::{
HirFileId, InFile,
};
use la_arena::{Arena, ArenaMap};
+use rustc_abi::{Integer, IntegerType};
use syntax::ast::{self, HasName, HasVisibility};
use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
@@ -18,6 +19,7 @@ use crate::{
db::DefDatabase,
intern::Interned,
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
+ layout::{Align, ReprFlags, ReprOptions},
nameres::diagnostics::DefDiagnostic,
src::HasChildSource,
src::HasSource,
@@ -34,7 +36,7 @@ use cfg::CfgOptions;
pub struct StructData {
pub name: Name,
pub variant_data: Arc<VariantData>,
- pub repr: Option<ReprData>,
+ pub repr: Option<ReprOptions>,
pub visibility: RawVisibility,
pub rustc_has_incoherent_inherent_impls: bool,
}
@@ -43,7 +45,7 @@ pub struct StructData {
pub struct EnumData {
pub name: Name,
pub variants: Arena<EnumVariantData>,
- pub repr: Option<ReprData>,
+ pub repr: Option<ReprOptions>,
pub visibility: RawVisibility,
pub rustc_has_incoherent_inherent_impls: bool,
}
@@ -69,80 +71,91 @@ pub struct FieldData {
pub visibility: RawVisibility,
}
-#[derive(Copy, Debug, Clone, PartialEq, Eq)]
-pub enum ReprKind {
- C,
- BuiltinInt { builtin: Either<BuiltinInt, BuiltinUint>, is_c: bool },
- Transparent,
- Default,
-}
-
-#[derive(Copy, Debug, Clone, PartialEq, Eq)]
-pub struct ReprData {
- pub kind: ReprKind,
- pub packed: bool,
- pub align: Option<NonZeroU32>,
-}
-
fn repr_from_value(
db: &dyn DefDatabase,
krate: CrateId,
item_tree: &ItemTree,
of: AttrOwner,
-) -> Option<ReprData> {
+) -> Option<ReprOptions> {
item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
}
-fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
+fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
match tt.delimiter {
Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {}
_ => return None,
}
- let mut data = ReprData { kind: ReprKind::Default, packed: false, align: None };
+ let mut flags = ReprFlags::empty();
+ let mut int = None;
+ let mut max_align: Option<Align> = None;
+ let mut min_pack: Option<Align> = None;
let mut tts = tt.token_trees.iter().peekable();
while let Some(tt) = tts.next() {
if let TokenTree::Leaf(Leaf::Ident(ident)) = tt {
- match &*ident.text {
+ flags.insert(match &*ident.text {
"packed" => {
- data.packed = true;
- if let Some(TokenTree::Subtree(_)) = tts.peek() {
+ let pack = if let Some(TokenTree::Subtree(tt)) = tts.peek() {
tts.next();
- }
+ if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
+ lit.text.parse().unwrap_or_default()
+ } else {
+ 0
+ }
+ } else {
+ 0
+ };
+ let pack = Align::from_bytes(pack).unwrap();
+ min_pack =
+ Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack });
+ ReprFlags::empty()
}
"align" => {
if let Some(TokenTree::Subtree(tt)) = tts.peek() {
tts.next();
if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
if let Ok(align) = lit.text.parse() {
- data.align = Some(align);
+ let align = Align::from_bytes(align).ok();
+ max_align = max_align.max(align);
}
}
}
+ ReprFlags::empty()
}
- "C" => {
- if let ReprKind::BuiltinInt { is_c, .. } = &mut data.kind {
- *is_c = true;
- } else {
- data.kind = ReprKind::C;
- }
- }
- "transparent" => data.kind = ReprKind::Transparent,
+ "C" => ReprFlags::IS_C,
+ "transparent" => ReprFlags::IS_TRANSPARENT,
repr => {
- let is_c = matches!(data.kind, ReprKind::C);
if let Some(builtin) = BuiltinInt::from_suffix(repr)
.map(Either::Left)
.or_else(|| BuiltinUint::from_suffix(repr).map(Either::Right))
{
- data.kind = ReprKind::BuiltinInt { builtin, is_c };
+ int = Some(match builtin {
+ Either::Left(bi) => match bi {
+ BuiltinInt::Isize => IntegerType::Pointer(true),
+ BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true),
+ BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true),
+ BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true),
+ BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true),
+ BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true),
+ },
+ Either::Right(bu) => match bu {
+ BuiltinUint::Usize => IntegerType::Pointer(false),
+ BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false),
+ BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false),
+ BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false),
+ BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false),
+ BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false),
+ },
+ });
}
+ ReprFlags::empty()
}
- }
+ })
}
}
- Some(data)
+ Some(ReprOptions { int, align: max_align, pack: min_pack, flags, field_shuffle_seed: 0 })
}
impl StructData {
@@ -299,10 +312,10 @@ impl EnumData {
Some(id)
}
- pub fn variant_body_type(&self) -> Either<BuiltinInt, BuiltinUint> {
+ pub fn variant_body_type(&self) -> IntegerType {
match self.repr {
- Some(ReprData { kind: ReprKind::BuiltinInt { builtin, .. }, .. }) => builtin,
- _ => Either::Left(BuiltinInt::Isize),
+ Some(ReprOptions { int: Some(builtin), .. }) => builtin,
+ _ => IntegerType::Pointer(true),
}
}
}