Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/attr.rs')
| -rw-r--r-- | crates/hir-def/src/attr.rs | 127 |
1 files changed, 126 insertions, 1 deletions
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 579ea12e6a..2775e1398c 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -12,6 +12,7 @@ use hir_expand::{ use intern::{sym, Symbol}; use la_arena::{ArenaMap, Idx, RawIdx}; use mbe::DelimiterKind; +use rustc_abi::ReprOptions; use syntax::{ ast::{self, HasAttrs}, AstPtr, @@ -83,7 +84,7 @@ impl Attrs { let krate = loc.parent.lookup(db).container.krate; item_tree = loc.id.item_tree(db); let variant = &item_tree[loc.id.value]; - (FieldParent::Variant(loc.id.value), &variant.fields, krate) + (FieldParent::EnumVariant(loc.id.value), &variant.fields, krate) } VariantId::StructId(it) => { let loc = it.lookup(db); @@ -221,6 +222,130 @@ impl Attrs { pub fn is_unstable(&self) -> bool { self.by_key(&sym::unstable).exists() } + + pub fn rustc_legacy_const_generics(&self) -> Option<Box<Box<[u32]>>> { + self.by_key(&sym::rustc_legacy_const_generics) + .tt_values() + .next() + .map(parse_rustc_legacy_const_generics) + .filter(|it| !it.is_empty()) + .map(Box::new) + } + + pub fn repr(&self) -> Option<ReprOptions> { + self.by_key(&sym::repr).tt_values().find_map(parse_repr_tt) + } +} + +fn parse_rustc_legacy_const_generics(tt: &crate::tt::TopSubtree) -> Box<[u32]> { + let mut indices = Vec::new(); + let mut iter = tt.iter(); + while let (Some(first), second) = (iter.next(), iter.next()) { + match first { + TtElement::Leaf(tt::Leaf::Literal(lit)) => match lit.symbol.as_str().parse() { + Ok(index) => indices.push(index), + Err(_) => break, + }, + _ => break, + } + + if let Some(comma) = second { + match comma { + TtElement::Leaf(tt::Leaf::Punct(punct)) if punct.char == ',' => {} + _ => break, + } + } + } + + indices.into_boxed_slice() +} + +fn parse_repr_tt(tt: &crate::tt::TopSubtree) -> Option<ReprOptions> { + use crate::builtin_type::{BuiltinInt, BuiltinUint}; + use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; + + match tt.top_subtree().delimiter { + tt::Delimiter { kind: DelimiterKind::Parenthesis, .. } => {} + _ => return 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.iter(); + while let Some(tt) = tts.next() { + if let TtElement::Leaf(tt::Leaf::Ident(ident)) = tt { + flags.insert(match &ident.sym { + s if *s == sym::packed => { + let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { + tts.next(); + if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { + lit.symbol.as_str().parse().unwrap_or_default() + } else { + 0 + } + } else { + 0 + }; + let pack = Align::from_bytes(pack).unwrap_or(Align::ONE); + min_pack = + Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); + ReprFlags::empty() + } + s if *s == sym::align => { + if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() { + tts.next(); + if let Some(TtElement::Leaf(tt::Leaf::Literal(lit))) = tt_iter.next() { + if let Ok(align) = lit.symbol.as_str().parse() { + let align = Align::from_bytes(align).ok(); + max_align = max_align.max(align); + } + } + } + ReprFlags::empty() + } + s if *s == sym::C => ReprFlags::IS_C, + s if *s == sym::transparent => ReprFlags::IS_TRANSPARENT, + s if *s == sym::simd => ReprFlags::IS_SIMD, + repr => { + if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) + .map(Either::Left) + .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) + { + 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(ReprOptions { + int, + align: max_align, + pack: min_pack, + flags, + field_shuffle_seed: rustc_hashes::Hash64::ZERO, + }) } #[derive(Debug, Clone, PartialEq, Eq, Hash)] |