Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/data/adt.rs')
| -rw-r--r-- | crates/hir-def/src/data/adt.rs | 201 |
1 files changed, 60 insertions, 141 deletions
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index 0fe73418e5..a70710e565 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -5,24 +5,20 @@ use bitflags::bitflags; use cfg::CfgOptions; use either::Either; -use hir_expand::{ - name::{AsName, Name}, - HirFileId, InFile, -}; -use intern::Interned; +use hir_expand::name::Name; +use intern::{sym, Interned}; use la_arena::Arena; use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; -use syntax::ast::{self, HasName, HasVisibility}; use triomphe::Arc; use crate::{ builtin_type::{BuiltinInt, BuiltinUint}, db::DefDatabase, - item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId}, + item_tree::{ + AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId, + }, lang_item::LangItem, - lower::LowerCtx, nameres::diagnostics::{DefDiagnostic, DefDiagnostics}, - trace::Trace, tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree}, type_ref::TypeRef, visibility::RawVisibility, @@ -95,7 +91,7 @@ fn repr_from_value( item_tree: &ItemTree, of: AttrOwner, ) -> Option<ReprOptions> { - item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt) + item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt) } fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> { @@ -112,12 +108,12 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> { let mut tts = tt.token_trees.iter().peekable(); while let Some(tt) = tts.next() { if let TokenTree::Leaf(Leaf::Ident(ident)) = tt { - flags.insert(match &*ident.text { - "packed" => { + flags.insert(match &ident.sym { + s if *s == sym::packed => { 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() + lit.symbol.as_str().parse().unwrap_or_default() } else { 0 } @@ -129,11 +125,11 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> { Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); ReprFlags::empty() } - "align" => { + s if *s == sym::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() { + if let Ok(align) = lit.symbol.as_str().parse() { let align = Align::from_bytes(align).ok(); max_align = max_align.max(align); } @@ -141,13 +137,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> { } ReprFlags::empty() } - "C" => ReprFlags::IS_C, - "transparent" => ReprFlags::IS_TRANSPARENT, - "simd" => ReprFlags::IS_SIMD, + 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(repr) + if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) .map(Either::Left) - .or_else(|| BuiltinUint::from_suffix(repr).map(Either::Right)) + .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) { int = Some(match builtin { Either::Left(bi) => match bi { @@ -194,10 +190,10 @@ impl StructData { let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let mut flags = StructFlags::NO_FLAGS; - if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() { + if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL; } - if attrs.by_key("fundamental").exists() { + if attrs.by_key(&sym::fundamental).exists() { flags |= StructFlags::IS_FUNDAMENTAL; } if let Some(lang) = attrs.lang_item() { @@ -211,20 +207,25 @@ impl StructData { } let strukt = &item_tree[loc.id.value]; - let (variant_data, diagnostics) = lower_fields( + let (data, diagnostics) = lower_fields( db, krate, - loc.id.file_id(), loc.container.local_id, + loc.id.tree_id(), &item_tree, &db.crate_graph()[krate].cfg_options, + FieldParent::Struct(loc.id.value), &strukt.fields, None, ); ( Arc::new(StructData { name: strukt.name.clone(), - variant_data: Arc::new(variant_data), + variant_data: Arc::new(match strukt.shape { + FieldsShape::Record => VariantData::Record(data), + FieldsShape::Tuple => VariantData::Tuple(data), + FieldsShape::Unit => VariantData::Unit, + }), repr, visibility: item_tree[strukt.visibility].clone(), flags, @@ -248,28 +249,29 @@ impl StructData { let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let mut flags = StructFlags::NO_FLAGS; - if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() { + if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL; } - if attrs.by_key("fundamental").exists() { + if attrs.by_key(&sym::fundamental).exists() { flags |= StructFlags::IS_FUNDAMENTAL; } let union = &item_tree[loc.id.value]; - let (variant_data, diagnostics) = lower_fields( + let (data, diagnostics) = lower_fields( db, krate, - loc.id.file_id(), loc.container.local_id, + loc.id.tree_id(), &item_tree, &db.crate_graph()[krate].cfg_options, + FieldParent::Union(loc.id.value), &union.fields, None, ); ( Arc::new(StructData { name: union.name.clone(), - variant_data: Arc::new(variant_data), + variant_data: Arc::new(VariantData::Record(data)), repr, visibility: item_tree[union.visibility].clone(), flags, @@ -287,7 +289,7 @@ impl EnumData { let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let rustc_has_incoherent_inherent_impls = item_tree .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) - .by_key("rustc_has_incoherent_inherent_impls") + .by_key(&sym::rustc_has_incoherent_inherent_impls) .exists(); let enum_ = &item_tree[loc.id.value]; @@ -336,13 +338,14 @@ impl EnumVariantData { let item_tree = loc.id.item_tree(db); let variant = &item_tree[loc.id.value]; - let (var_data, diagnostics) = lower_fields( + let (data, diagnostics) = lower_fields( db, krate, - loc.id.file_id(), container.local_id, + loc.id.tree_id(), &item_tree, &db.crate_graph()[krate].cfg_options, + FieldParent::Variant(loc.id.value), &variant.fields, Some(item_tree[loc.parent.lookup(db).id.value].visibility), ); @@ -350,7 +353,11 @@ impl EnumVariantData { ( Arc::new(EnumVariantData { name: variant.name.clone(), - variant_data: Arc::new(var_data), + variant_data: Arc::new(match variant.shape { + FieldsShape::Record => VariantData::Record(data), + FieldsShape::Tuple => VariantData::Tuple(data), + FieldsShape::Unit => VariantData::Unit, + }), }), DefDiagnostics::new(diagnostics), ) @@ -396,123 +403,35 @@ pub enum StructKind { Unit, } -pub(crate) fn lower_struct( - db: &dyn DefDatabase, - trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>, - ast: &InFile<ast::StructKind>, - krate: CrateId, - item_tree: &ItemTree, - fields: &Fields, -) -> StructKind { - let ctx = LowerCtx::new(db, ast.file_id); - - match (&ast.value, fields) { - (ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => { - let cfg_options = &db.crate_graph()[krate].cfg_options; - for ((i, fd), item_tree_id) in fl.fields().enumerate().zip(fields.clone()) { - if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) { - continue; - } - - trace.alloc( - || Either::Left(fd.clone()), - || FieldData { - name: Name::new_tuple_field(i), - type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())), - visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| { - ctx.span_map().span_for_range(range).ctx - }), - }, - ); - } - StructKind::Tuple - } - (ast::StructKind::Record(fl), Fields::Record(fields)) => { - let cfg_options = &db.crate_graph()[krate].cfg_options; - for (fd, item_tree_id) in fl.fields().zip(fields.clone()) { - if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) { - continue; - } - - trace.alloc( - || Either::Right(fd.clone()), - || FieldData { - name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), - type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())), - visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| { - ctx.span_map().span_for_range(range).ctx - }), - }, - ); - } - StructKind::Record - } - _ => StructKind::Unit, - } -} - fn lower_fields( db: &dyn DefDatabase, krate: CrateId, - current_file_id: HirFileId, container: LocalModuleId, + tree_id: TreeId, item_tree: &ItemTree, cfg_options: &CfgOptions, - fields: &Fields, + parent: FieldParent, + fields: &[Field], override_visibility: Option<RawVisibilityId>, -) -> (VariantData, Vec<DefDiagnostic>) { +) -> (Arena<FieldData>, Vec<DefDiagnostic>) { let mut diagnostics = Vec::new(); - match fields { - Fields::Record(flds) => { - let mut arena = Arena::new(); - for field_id in flds.clone() { - let attrs = item_tree.attrs(db, krate, field_id.into()); - let field = &item_tree[field_id]; - if attrs.is_cfg_enabled(cfg_options) { - arena.alloc(lower_field(item_tree, field, override_visibility)); - } else { - diagnostics.push(DefDiagnostic::unconfigured_code( - container, - InFile::new( - current_file_id, - match field.ast_id { - FieldAstId::Record(it) => it.erase(), - FieldAstId::Tuple(it) => it.erase(), - }, - ), - attrs.cfg().unwrap(), - cfg_options.clone(), - )) - } - } - (VariantData::Record(arena), diagnostics) - } - Fields::Tuple(flds) => { - let mut arena = Arena::new(); - for field_id in flds.clone() { - let attrs = item_tree.attrs(db, krate, field_id.into()); - let field = &item_tree[field_id]; - if attrs.is_cfg_enabled(cfg_options) { - arena.alloc(lower_field(item_tree, field, override_visibility)); - } else { - diagnostics.push(DefDiagnostic::unconfigured_code( - container, - InFile::new( - current_file_id, - match field.ast_id { - FieldAstId::Record(it) => it.erase(), - FieldAstId::Tuple(it) => it.erase(), - }, - ), - attrs.cfg().unwrap(), - cfg_options.clone(), - )) - } - } - (VariantData::Tuple(arena), diagnostics) + let mut arena = Arena::new(); + for (idx, field) in fields.iter().enumerate() { + let attr_owner = AttrOwner::make_field_indexed(parent, idx); + let attrs = item_tree.attrs(db, krate, attr_owner); + if attrs.is_cfg_enabled(cfg_options) { + arena.alloc(lower_field(item_tree, field, override_visibility)); + } else { + diagnostics.push(DefDiagnostic::unconfigured_code( + container, + tree_id, + attr_owner, + attrs.cfg().unwrap(), + cfg_options.clone(), + )) } - Fields::Unit => (VariantData::Unit, diagnostics), } + (arena, diagnostics) } fn lower_field( |