mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 21:25:25 +00:00 
			
		
		
		
	Move attribute parsing out of data module
This commit is contained in:
		
							parent
							
								
									12f54eec27
								
							
						
					
					
						commit
						dff1896436
					
				
					 3 changed files with 128 additions and 124 deletions
				
			
		| 
						 | 
				
			
			@ -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)]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue