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.rs113
1 files changed, 72 insertions, 41 deletions
diff --git a/crates/hir-def/src/adt.rs b/crates/hir-def/src/adt.rs
index 938db032fb..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,16 +36,18 @@ 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,
}
#[derive(Debug, Clone, PartialEq, Eq)]
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,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -67,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 {
@@ -157,6 +172,10 @@ impl StructData {
let item_tree = loc.id.item_tree(db);
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
+ 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")
+ .exists();
let strukt = &item_tree[loc.id.value];
let (variant_data, diagnostics) = lower_fields(
@@ -175,6 +194,7 @@ impl StructData {
variant_data: Arc::new(variant_data),
repr,
visibility: item_tree[strukt.visibility].clone(),
+ rustc_has_incoherent_inherent_impls,
}),
diagnostics.into(),
)
@@ -194,6 +214,11 @@ impl StructData {
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
+ 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")
+ .exists();
+
let union = &item_tree[loc.id.value];
let (variant_data, diagnostics) = lower_fields(
db,
@@ -211,6 +236,7 @@ impl StructData {
variant_data: Arc::new(variant_data),
repr,
visibility: item_tree[union.visibility].clone(),
+ rustc_has_incoherent_inherent_impls,
}),
diagnostics.into(),
)
@@ -231,6 +257,10 @@ impl EnumData {
let item_tree = loc.id.item_tree(db);
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
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")
+ .exists();
let enum_ = &item_tree[loc.id.value];
let mut variants = Arena::new();
@@ -271,6 +301,7 @@ impl EnumData {
variants,
repr,
visibility: item_tree[enum_.visibility].clone(),
+ rustc_has_incoherent_inherent_impls,
}),
diagnostics.into(),
)
@@ -281,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),
}
}
}