Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 02ea92f

Browse files
committed
Auto merge of rust-lang#14445 - Veykril:adt-flags, r=Veykril
internal: Introduce StructFlags
2 parents fc8c513 + 33b6012 commit 02ea92f

File tree

8 files changed

+91
-56
lines changed

8 files changed

+91
-56
lines changed

crates/hir-def/src/adt.rs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::sync::Arc;
44

55
use base_db::CrateId;
6+
use bitflags::bitflags;
67
use cfg::CfgOptions;
78
use either::Either;
89

@@ -20,6 +21,7 @@ use crate::{
2021
builtin_type::{BuiltinInt, BuiltinUint},
2122
db::DefDatabase,
2223
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
24+
lang_item::LangItem,
2325
layout::{Align, ReprFlags, ReprOptions},
2426
nameres::diagnostics::DefDiagnostic,
2527
src::HasChildSource,
@@ -39,8 +41,26 @@ pub struct StructData {
3941
pub variant_data: Arc<VariantData>,
4042
pub repr: Option<ReprOptions>,
4143
pub visibility: RawVisibility,
42-
pub rustc_has_incoherent_inherent_impls: bool,
43-
pub fundamental: bool,
44+
pub flags: StructFlags,
45+
}
46+
47+
bitflags! {
48+
pub struct StructFlags: u8 {
49+
const NO_FLAGS = 0;
50+
/// Indicates whether the struct is `PhantomData`.
51+
const IS_PHANTOM_DATA = 1 << 2;
52+
/// Indicates whether the struct has a `#[fundamental]` attribute.
53+
const IS_FUNDAMENTAL = 1 << 3;
54+
// FIXME: should this be a flag?
55+
/// Indicates whether the struct has a `#[rustc_has_incoherent_inherent_impls]` attribute.
56+
const IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL = 1 << 4;
57+
/// Indicates whether this struct is `Box`.
58+
const IS_BOX = 1 << 5;
59+
/// Indicates whether this struct is `ManuallyDrop`.
60+
const IS_MANUALLY_DROP = 1 << 6;
61+
/// Indicates whether this struct is `UnsafeCell`.
62+
const IS_UNSAFE_CELL = 1 << 6;
63+
}
4464
}
4565

4666
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -174,10 +194,25 @@ impl StructData {
174194
let item_tree = loc.id.item_tree(db);
175195
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
176196
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
197+
177198
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
178-
let rustc_has_incoherent_inherent_impls =
179-
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
180-
let fundamental = attrs.by_key("fundamental").exists();
199+
200+
let mut flags = StructFlags::NO_FLAGS;
201+
if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
202+
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
203+
}
204+
if attrs.by_key("fundamental").exists() {
205+
flags |= StructFlags::IS_FUNDAMENTAL;
206+
}
207+
if let Some(lang) = attrs.lang_item() {
208+
match lang {
209+
LangItem::PhantomData => flags |= StructFlags::IS_PHANTOM_DATA,
210+
LangItem::OwnedBox => flags |= StructFlags::IS_BOX,
211+
LangItem::ManuallyDrop => flags |= StructFlags::IS_MANUALLY_DROP,
212+
LangItem::UnsafeCell => flags |= StructFlags::IS_UNSAFE_CELL,
213+
_ => (),
214+
}
215+
}
181216

182217
let strukt = &item_tree[loc.id.value];
183218
let (variant_data, diagnostics) = lower_fields(
@@ -196,8 +231,7 @@ impl StructData {
196231
variant_data: Arc::new(variant_data),
197232
repr,
198233
visibility: item_tree[strukt.visibility].clone(),
199-
rustc_has_incoherent_inherent_impls,
200-
fundamental,
234+
flags,
201235
}),
202236
diagnostics.into(),
203237
)
@@ -218,9 +252,13 @@ impl StructData {
218252
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
219253

220254
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
221-
let rustc_has_incoherent_inherent_impls =
222-
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
223-
let fundamental = attrs.by_key("fundamental").exists();
255+
let mut flags = StructFlags::NO_FLAGS;
256+
if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
257+
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
258+
}
259+
if attrs.by_key("fundamental").exists() {
260+
flags |= StructFlags::IS_FUNDAMENTAL;
261+
}
224262

225263
let union = &item_tree[loc.id.value];
226264
let (variant_data, diagnostics) = lower_fields(
@@ -239,8 +277,7 @@ impl StructData {
239277
variant_data: Arc::new(variant_data),
240278
repr,
241279
visibility: item_tree[union.visibility].clone(),
242-
rustc_has_incoherent_inherent_impls,
243-
fundamental,
280+
flags,
244281
}),
245282
diagnostics.into(),
246283
)

crates/hir-def/src/attr.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use syntax::{
2020
use crate::{
2121
db::DefDatabase,
2222
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
23+
lang_item::LangItem,
2324
nameres::{ModuleOrigin, ModuleSource},
2425
src::{HasChildSource, HasSource},
2526
AdtId, AttrDefId, EnumId, GenericParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroId,
@@ -177,13 +178,13 @@ impl Attrs {
177178

178179
Arc::new(res)
179180
}
181+
}
180182

183+
impl Attrs {
181184
pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
182185
AttrQuery { attrs: self, key }
183186
}
184-
}
185187

186-
impl Attrs {
187188
pub fn cfg(&self) -> Option<CfgExpr> {
188189
let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse);
189190
let first = cfgs.next()?;
@@ -206,6 +207,10 @@ impl Attrs {
206207
self.by_key("lang").string_value()
207208
}
208209

210+
pub fn lang_item(&self) -> Option<LangItem> {
211+
self.by_key("lang").string_value().and_then(|it| LangItem::from_str(it))
212+
}
213+
209214
pub fn docs(&self) -> Option<Documentation> {
210215
let docs = self.by_key("doc").attrs().filter_map(|attr| attr.string_value());
211216
let indent = doc_indent(self);

crates/hir-ty/src/autoderef.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
//! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs).
55
66
use chalk_ir::cast::Cast;
7-
use hir_def::{
8-
lang_item::{LangItem, LangItemTarget},
9-
AdtId,
10-
};
7+
use hir_def::lang_item::LangItem;
118
use hir_expand::name::name;
129
use limit::Limit;
1310

@@ -90,13 +87,8 @@ pub(crate) fn builtin_deref<'ty>(
9087
TyKind::Ref(.., ty) => Some(ty),
9188
// FIXME: Maybe accept this but diagnose if its not explicit?
9289
TyKind::Raw(.., ty) if explicit => Some(ty),
93-
&TyKind::Adt(chalk_ir::AdtId(AdtId::StructId(strukt)), ref substs) => {
94-
if Some(strukt)
95-
== table
96-
.db
97-
.lang_item(table.trait_env.krate, LangItem::OwnedBox)
98-
.and_then(LangItemTarget::as_struct)
99-
{
90+
&TyKind::Adt(chalk_ir::AdtId(adt), ref substs) => {
91+
if crate::lang_items::is_box(table.db, adt) {
10092
substs.at(Interner, 0).ty(Interner)
10193
} else {
10294
None

crates/hir-ty/src/diagnostics/match_check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ impl HirDisplay for Pat {
379379
}
380380
PatKind::Deref { subpattern } => {
381381
match self.ty.kind(Interner) {
382-
TyKind::Adt(adt, _) if is_box(adt.0, f.db) => write!(f, "box ")?,
382+
TyKind::Adt(adt, _) if is_box(f.db, adt.0) => write!(f, "box ")?,
383383
&TyKind::Ref(mutbl, ..) => {
384384
write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })?
385385
}

crates/hir-ty/src/diagnostics/match_check/deconstruct_pat.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ impl Constructor {
384384
TyKind::Tuple(arity, ..) => arity,
385385
TyKind::Ref(..) => 1,
386386
TyKind::Adt(adt, ..) => {
387-
if is_box(adt.0, pcx.cx.db) {
387+
if is_box(pcx.cx.db, adt.0) {
388388
// The only legal patterns of type `Box` (outside `std`) are `_` and box
389389
// patterns. If we're here we can assume this is a box pattern.
390390
1
@@ -800,7 +800,7 @@ impl<'p> Fields<'p> {
800800
}
801801
TyKind::Ref(.., rty) => Fields::wildcards_from_tys(cx, once(rty.clone())),
802802
&TyKind::Adt(AdtId(adt), ref substs) => {
803-
if is_box(adt, cx.db) {
803+
if is_box(cx.db, adt) {
804804
// The only legal patterns of type `Box` (outside `std`) are `_` and box
805805
// patterns. If we're here we can assume this is a box pattern.
806806
let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
@@ -905,7 +905,7 @@ impl<'p> DeconstructedPat<'p> {
905905
}
906906
fields = Fields::from_iter(cx, wilds)
907907
}
908-
TyKind::Adt(adt, substs) if is_box(adt.0, cx.db) => {
908+
TyKind::Adt(adt, substs) if is_box(cx.db, adt.0) => {
909909
// The only legal patterns of type `Box` (outside `std`) are `_` and box
910910
// patterns. If we're here we can assume this is a box pattern.
911911
// FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
@@ -992,7 +992,7 @@ impl<'p> DeconstructedPat<'p> {
992992
})
993993
.collect(),
994994
},
995-
TyKind::Adt(adt, _) if is_box(adt.0, cx.db) => {
995+
TyKind::Adt(adt, _) if is_box(cx.db, adt.0) => {
996996
// Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
997997
// of `std`). So this branch is only reachable when the feature is enabled and
998998
// the pattern is a box pattern.

crates/hir-ty/src/lang_items.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
11
//! Functions to detect special lang items
22
3-
use hir_def::{lang_item::LangItem, AdtId, HasModule};
3+
use hir_def::{adt::StructFlags, lang_item::LangItem, AdtId};
44
use hir_expand::name::Name;
55

66
use crate::db::HirDatabase;
77

8-
pub fn is_box(adt: AdtId, db: &dyn HirDatabase) -> bool {
9-
let krate = adt.module(db.upcast()).krate();
10-
let box_adt =
11-
db.lang_item(krate, LangItem::OwnedBox).and_then(|it| it.as_struct()).map(AdtId::from);
12-
Some(adt) == box_adt
8+
pub fn is_box(db: &dyn HirDatabase, adt: AdtId) -> bool {
9+
let AdtId::StructId(id) = adt else { return false };
10+
db.struct_data(id).flags.contains(StructFlags::IS_UNSAFE_CELL)
1311
}
1412

15-
pub fn is_unsafe_cell(adt: AdtId, db: &dyn HirDatabase) -> bool {
16-
let krate = adt.module(db.upcast()).krate();
17-
let box_adt =
18-
db.lang_item(krate, LangItem::UnsafeCell).and_then(|it| it.as_struct()).map(AdtId::from);
19-
Some(adt) == box_adt
13+
pub fn is_unsafe_cell(db: &dyn HirDatabase, adt: AdtId) -> bool {
14+
let AdtId::StructId(id) = adt else { return false };
15+
db.struct_data(id).flags.contains(StructFlags::IS_UNSAFE_CELL)
2016
}
2117

2218
pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, LangItem)> {

crates/hir-ty/src/layout/adt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub fn layout_of_adt_query(
7171
&repr,
7272
&variants,
7373
is_enum,
74-
is_unsafe_cell(def, db),
74+
is_unsafe_cell(db, def),
7575
layout_scalar_valid_range(db, def),
7676
|min, max| Integer::repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)),
7777
variants.iter_enumerated().filter_map(|(id, _)| {

crates/hir-ty/src/method_resolution.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use std::{ops::ControlFlow, sync::Arc};
77
use base_db::{CrateId, Edition};
88
use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause};
99
use hir_def::{
10-
data::ImplData, item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId,
11-
FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
10+
adt::StructFlags, data::ImplData, item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId,
11+
ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId,
12+
TraitId,
1213
};
1314
use hir_expand::name::Name;
1415
use rustc_hash::{FxHashMap, FxHashSet};
@@ -405,12 +406,14 @@ pub fn def_crates(
405406
match ty.kind(Interner) {
406407
&TyKind::Adt(AdtId(def_id), _) => {
407408
let rustc_has_incoherent_inherent_impls = match def_id {
408-
hir_def::AdtId::StructId(id) => {
409-
db.struct_data(id).rustc_has_incoherent_inherent_impls
410-
}
411-
hir_def::AdtId::UnionId(id) => {
412-
db.union_data(id).rustc_has_incoherent_inherent_impls
413-
}
409+
hir_def::AdtId::StructId(id) => db
410+
.struct_data(id)
411+
.flags
412+
.contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
413+
hir_def::AdtId::UnionId(id) => db
414+
.union_data(id)
415+
.flags
416+
.contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
414417
hir_def::AdtId::EnumId(id) => db.enum_data(id).rustc_has_incoherent_inherent_impls,
415418
};
416419
Some(if rustc_has_incoherent_inherent_impls {
@@ -808,12 +811,14 @@ fn is_inherent_impl_coherent(
808811
| TyKind::Scalar(_) => true,
809812

810813
&TyKind::Adt(AdtId(adt), _) => match adt {
811-
hir_def::AdtId::StructId(it) => {
812-
db.struct_data(it).rustc_has_incoherent_inherent_impls
813-
}
814-
hir_def::AdtId::UnionId(it) => {
815-
db.union_data(it).rustc_has_incoherent_inherent_impls
816-
}
814+
hir_def::AdtId::StructId(id) => db
815+
.struct_data(id)
816+
.flags
817+
.contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
818+
hir_def::AdtId::UnionId(id) => db
819+
.union_data(id)
820+
.flags
821+
.contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
817822
hir_def::AdtId::EnumId(it) => db.enum_data(it).rustc_has_incoherent_inherent_impls,
818823
},
819824
TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| {

0 commit comments

Comments
 (0)