Skip to content

Commit 9f233cd

Browse files
committed
Parse more repr options
1 parent 6d0d051 commit 9f233cd

File tree

5 files changed

+74
-19
lines changed

5 files changed

+74
-19
lines changed

crates/hir-def/src/adt.rs

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Defines hir-level representation of structs, enums and unions
22
3-
use std::sync::Arc;
3+
use std::{num::NonZeroU32, sync::Arc};
44

55
use base_db::CrateId;
66
use either::Either;
@@ -14,6 +14,7 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
1414

1515
use crate::{
1616
body::{CfgExpander, LowerCtx},
17+
builtin_type::{BuiltinInt, BuiltinUint},
1718
db::DefDatabase,
1819
intern::Interned,
1920
item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
@@ -31,14 +32,15 @@ use cfg::CfgOptions;
3132
pub struct StructData {
3233
pub name: Name,
3334
pub variant_data: Arc<VariantData>,
34-
pub repr: Option<ReprKind>,
35+
pub repr: Option<ReprData>,
3536
pub visibility: RawVisibility,
3637
}
3738

3839
#[derive(Debug, Clone, PartialEq, Eq)]
3940
pub struct EnumData {
4041
pub name: Name,
4142
pub variants: Arena<EnumVariantData>,
43+
pub repr: Option<ReprData>,
4244
pub visibility: RawVisibility,
4345
}
4446

@@ -63,32 +65,80 @@ pub struct FieldData {
6365
pub visibility: RawVisibility,
6466
}
6567

66-
#[derive(Debug, Clone, PartialEq, Eq)]
68+
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
6769
pub enum ReprKind {
68-
Packed,
69-
Other,
70+
C,
71+
BuiltinInt { builtin: Either<BuiltinInt, BuiltinUint>, is_c: bool },
72+
Transparent,
73+
Default,
74+
}
75+
76+
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
77+
pub struct ReprData {
78+
pub kind: ReprKind,
79+
pub packed: bool,
80+
pub align: Option<NonZeroU32>,
7081
}
7182

7283
fn repr_from_value(
7384
db: &dyn DefDatabase,
7485
krate: CrateId,
7586
item_tree: &ItemTree,
7687
of: AttrOwner,
77-
) -> Option<ReprKind> {
88+
) -> Option<ReprData> {
7889
item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
7990
}
8091

81-
fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
92+
fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
8293
match tt.delimiter {
8394
Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {}
8495
_ => return None,
8596
}
8697

87-
let mut it = tt.token_trees.iter();
88-
match it.next()? {
89-
TokenTree::Leaf(Leaf::Ident(ident)) if ident.text == "packed" => Some(ReprKind::Packed),
90-
_ => Some(ReprKind::Other),
98+
let mut data = ReprData { kind: ReprKind::Default, packed: false, align: None };
99+
100+
let mut tts = tt.token_trees.iter().peekable();
101+
while let Some(tt) = tts.next() {
102+
if let TokenTree::Leaf(Leaf::Ident(ident)) = tt {
103+
match &*ident.text {
104+
"packed" => {
105+
data.packed = true;
106+
if let Some(TokenTree::Subtree(_)) = tts.peek() {
107+
tts.next();
108+
}
109+
}
110+
"align" => {
111+
if let Some(TokenTree::Subtree(tt)) = tts.peek() {
112+
tts.next();
113+
if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
114+
if let Ok(align) = lit.text.parse() {
115+
data.align = Some(align);
116+
}
117+
}
118+
}
119+
}
120+
"C" => {
121+
if let ReprKind::BuiltinInt { is_c, .. } = &mut data.kind {
122+
*is_c = true;
123+
} else {
124+
data.kind = ReprKind::C;
125+
}
126+
}
127+
"transparent" => data.kind = ReprKind::Transparent,
128+
repr => {
129+
let is_c = matches!(data.kind, ReprKind::C);
130+
if let Some(builtin) = BuiltinInt::from_suffix(repr)
131+
.map(Either::Left)
132+
.or_else(|| BuiltinUint::from_suffix(repr).map(Either::Right))
133+
{
134+
data.kind = ReprKind::BuiltinInt { builtin, is_c };
135+
}
136+
}
137+
}
138+
}
91139
}
140+
141+
Some(data)
92142
}
93143

94144
impl StructData {
@@ -108,6 +158,7 @@ impl StructData {
108158
visibility: item_tree[strukt.visibility].clone(),
109159
})
110160
}
161+
111162
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
112163
let loc = id.lookup(db);
113164
let krate = loc.container.krate;
@@ -133,6 +184,7 @@ impl EnumData {
133184
let krate = loc.container.krate;
134185
let item_tree = loc.id.item_tree(db);
135186
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
187+
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
136188

137189
let enum_ = &item_tree[loc.id.value];
138190
let mut variants = Arena::new();
@@ -158,6 +210,7 @@ impl EnumData {
158210
Arc::new(EnumData {
159211
name: enum_.name.clone(),
160212
variants,
213+
repr,
161214
visibility: item_tree[enum_.visibility].clone(),
162215
})
163216
}

crates/hir-def/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,6 @@ pub enum DefWithBodyId {
479479

480480
impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
481481

482-
// FIXME: Rename EnumVariantId to VariantId so that the macro above can be used
483482
impl From<EnumVariantId> for DefWithBodyId {
484483
fn from(id: EnumVariantId) -> Self {
485484
DefWithBodyId::VariantId(id)

crates/hir-ty/src/db.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
4444
#[salsa::invoke(crate::lower::const_param_ty_query)]
4545
fn const_param_ty(&self, def: ConstParamId) -> Ty;
4646

47-
#[salsa::invoke(crate::consteval::const_eval_query)]
47+
#[salsa::invoke(crate::consteval::const_eval_variant_query)]
4848
#[salsa::cycle(crate::consteval::const_eval_recover)]
4949
fn const_eval(&self, def: ConstId) -> Result<ComputedExpr, ConstEvalError>;
5050

5151
#[salsa::invoke(crate::consteval::const_eval_query_variant)]
52-
#[salsa::cycle(crate::consteval::const_eval_recover_variant)]
52+
#[salsa::cycle(crate::consteval::const_eval_variant_recover)]
5353
fn const_eval_variant(&self, def: EnumVariantId) -> Result<ComputedExpr, ConstEvalError>;
5454

5555
#[salsa::invoke(crate::lower::impl_trait_query)]

crates/hir-ty/src/infer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,12 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
6767
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
6868
DefWithBodyId::FunctionId(f) => ctx.collect_fn(f),
6969
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
70-
DefWithBodyId::VariantId(v) => {
70+
DefWithBodyId::VariantId(_v) => {
71+
// db.enum_data(v.parent)
7172
// FIXME: This should return the `repr(...)` type of the enum
72-
ctx.return_ty = TyBuilder::def_ty(db, v.parent.into()).fill_with_unknown().build()
73+
ctx.return_ty = TyBuilder::builtin(hir_def::builtin_type::BuiltinType::Uint(
74+
hir_def::builtin_type::BuiltinUint::U32,
75+
));
7376
}
7477
}
7578

crates/hir/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use arrayvec::ArrayVec;
3939
use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind};
4040
use either::Either;
4141
use hir_def::{
42-
adt::{ReprKind, VariantData},
42+
adt::{ReprData, VariantData},
4343
body::{BodyDiagnostic, SyntheticSyntax},
4444
expr::{BindingAnnotation, LabelId, Pat, PatId},
4545
generics::{TypeOrConstParamData, TypeParamProvenance},
@@ -874,7 +874,7 @@ impl Struct {
874874
Type::from_def(db, self.id)
875875
}
876876

877-
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
877+
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprData> {
878878
db.struct_data(self.id).repr.clone()
879879
}
880880

@@ -2964,7 +2964,7 @@ impl Type {
29642964

29652965
let adt = adt_id.into();
29662966
match adt {
2967-
Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)),
2967+
Adt::Struct(s) => matches!(s.repr(db), Some(ReprData { packed: true, .. })),
29682968
_ => false,
29692969
}
29702970
}

0 commit comments

Comments
 (0)