Unnamed repository; edit this file 'description' to name the repository.
Move attribute parsing out of data module
Lukas Wirth 2025-03-14
parent 12f54ee · commit dff1896
-rw-r--r--crates/hir-def/src/attr.rs125
-rw-r--r--crates/hir-def/src/data.rs33
-rw-r--r--crates/hir-def/src/data/adt.rs94
3 files changed, 128 insertions, 124 deletions
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index 579ea12e6a..030d064584 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,
@@ -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)]
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index 8a1f07c92e..1a6bed6cab 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -7,7 +7,6 @@ use hir_expand::name::Name;
use intern::{sym, Symbol};
use la_arena::{Idx, RawIdx};
use triomphe::Arc;
-use tt::iter::TtElement;
use crate::{
db::DefDatabase,
@@ -73,13 +72,6 @@ impl FunctionData {
}
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
- let legacy_const_generics_indices = attrs
- .by_key(&sym::rustc_legacy_const_generics)
- .tt_values()
- .next()
- .map(parse_rustc_legacy_const_generics)
- .filter(|it| !it.is_empty())
- .map(Box::new);
let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
if flags.contains(FnFlags::HAS_UNSAFE_KW)
&& attrs.by_key(&sym::rustc_deprecated_safe_2024).exists()
@@ -106,7 +98,7 @@ impl FunctionData {
ret_type: func.ret_type,
visibility,
abi: func.abi.clone(),
- legacy_const_generics_indices,
+ legacy_const_generics_indices: attrs.rustc_legacy_const_generics(),
types_map: func.types_map.clone(),
flags,
rustc_allow_incoherent_impl,
@@ -156,29 +148,6 @@ impl FunctionData {
}
}
-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()
-}
-
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TypeAliasData {
pub name: Name,
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index bf8f5024c2..161b205c80 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -3,18 +3,14 @@
use base_db::Crate;
use bitflags::bitflags;
use cfg::CfgOptions;
-use either::Either;
use hir_expand::name::Name;
use intern::sym;
use la_arena::Arena;
-use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
-use rustc_hashes::Hash64;
+use rustc_abi::{IntegerType, ReprOptions};
use triomphe::Arc;
-use tt::iter::TtElement;
use crate::{
- builtin_type::{BuiltinInt, BuiltinUint},
db::DefDatabase,
hir::Expr,
item_tree::{
@@ -22,7 +18,6 @@ use crate::{
},
lang_item::LangItem,
nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
- tt::{Delimiter, DelimiterKind, Leaf, TopSubtree},
type_ref::{TypeRefId, TypesMap},
visibility::RawVisibility,
EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
@@ -94,92 +89,7 @@ fn repr_from_value(
item_tree: &ItemTree,
of: AttrOwner,
) -> Option<ReprOptions> {
- item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt)
-}
-
-fn parse_repr_tt(tt: &TopSubtree) -> Option<ReprOptions> {
- match tt.top_subtree().delimiter {
- 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(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(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(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: Hash64::ZERO,
- })
+ item_tree.attrs(db, krate, of).repr()
}
impl StructData {