mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 05:08:52 +00:00
minor: Encode TraitData bools as bitflags
This commit is contained in:
parent
7e639ee3dd
commit
4d66fa797f
7 changed files with 81 additions and 50 deletions
|
@ -227,20 +227,24 @@ impl TypeAliasData {
|
|||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
|
||||
pub struct TraitFlags: u8 {
|
||||
const IS_AUTO = 1 << 0;
|
||||
const IS_UNSAFE = 1 << 1;
|
||||
const IS_FUNDAMENTAL = 1 << 2;
|
||||
const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 3;
|
||||
const SKIP_ARRAY_DURING_METHOD_DISPATCH = 1 << 4;
|
||||
const SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH = 1 << 5;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TraitData {
|
||||
pub name: Name,
|
||||
pub items: Vec<(Name, AssocItemId)>,
|
||||
pub is_auto: bool,
|
||||
pub is_unsafe: bool,
|
||||
pub rustc_has_incoherent_inherent_impls: bool,
|
||||
pub skip_array_during_method_dispatch: bool,
|
||||
pub skip_boxed_slice_during_method_dispatch: bool,
|
||||
pub fundamental: bool,
|
||||
pub flags: TraitFlags,
|
||||
pub visibility: RawVisibility,
|
||||
/// Whether the trait has `#[rust_skip_array_during_method_dispatch]`. `hir_ty` will ignore
|
||||
/// method calls to this trait's methods when the receiver is an array and the crate edition is
|
||||
/// 2015 or 2018.
|
||||
// box it as the vec is usually empty anyways
|
||||
pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||
}
|
||||
|
@ -259,10 +263,24 @@ impl TraitData {
|
|||
let item_tree = tree_id.item_tree(db);
|
||||
let tr_def = &item_tree[tree_id.value];
|
||||
let name = tr_def.name.clone();
|
||||
let is_auto = tr_def.is_auto;
|
||||
let is_unsafe = tr_def.is_unsafe;
|
||||
let visibility = item_tree[tr_def.visibility].clone();
|
||||
let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into());
|
||||
|
||||
let mut flags = TraitFlags::empty();
|
||||
|
||||
if tr_def.is_auto {
|
||||
flags |= TraitFlags::IS_AUTO;
|
||||
}
|
||||
if tr_def.is_unsafe {
|
||||
flags |= TraitFlags::IS_UNSAFE;
|
||||
}
|
||||
if attrs.by_key(&sym::fundamental).exists() {
|
||||
flags |= TraitFlags::IS_FUNDAMENTAL;
|
||||
}
|
||||
if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
|
||||
flags |= TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS;
|
||||
}
|
||||
|
||||
let mut skip_array_during_method_dispatch =
|
||||
attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists();
|
||||
let mut skip_boxed_slice_during_method_dispatch = false;
|
||||
|
@ -274,27 +292,21 @@ impl TraitData {
|
|||
}
|
||||
}
|
||||
}
|
||||
let rustc_has_incoherent_inherent_impls =
|
||||
attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
|
||||
let fundamental = attrs.by_key(&sym::fundamental).exists();
|
||||
|
||||
if skip_array_during_method_dispatch {
|
||||
flags |= TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH;
|
||||
}
|
||||
if skip_boxed_slice_during_method_dispatch {
|
||||
flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH;
|
||||
}
|
||||
|
||||
let mut collector =
|
||||
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
|
||||
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
|
||||
let (items, macro_calls, diagnostics) = collector.finish();
|
||||
|
||||
(
|
||||
Arc::new(TraitData {
|
||||
name,
|
||||
macro_calls,
|
||||
items,
|
||||
is_auto,
|
||||
is_unsafe,
|
||||
visibility,
|
||||
skip_array_during_method_dispatch,
|
||||
skip_boxed_slice_during_method_dispatch,
|
||||
rustc_has_incoherent_inherent_impls,
|
||||
fundamental,
|
||||
}),
|
||||
Arc::new(TraitData { name, macro_calls, items, visibility, flags }),
|
||||
DefDiagnostics::new(diagnostics),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
|
|||
|
||||
use base_db::CrateId;
|
||||
use hir_def::{
|
||||
data::adt::StructFlags,
|
||||
data::{adt::StructFlags, TraitFlags},
|
||||
hir::Movability,
|
||||
lang_item::{LangItem, LangItemTarget},
|
||||
AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
|
||||
|
@ -675,13 +675,13 @@ pub(crate) fn trait_datum_query(
|
|||
let generic_params = generics(db.upcast(), trait_.into());
|
||||
let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
|
||||
let flags = rust_ir::TraitFlags {
|
||||
auto: trait_data.is_auto,
|
||||
auto: trait_data.flags.contains(TraitFlags::IS_AUTO),
|
||||
upstream: trait_.lookup(db.upcast()).container.krate() != krate,
|
||||
non_enumerable: true,
|
||||
coinductive: false, // only relevant for Chalk testing
|
||||
// FIXME: set these flags correctly
|
||||
marker: false,
|
||||
fundamental: trait_data.fundamental,
|
||||
fundamental: trait_data.flags.contains(TraitFlags::IS_FUNDAMENTAL),
|
||||
};
|
||||
let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
|
||||
let associated_ty_ids = trait_data.associated_types().map(to_assoc_type_id).collect();
|
||||
|
|
|
@ -9,8 +9,8 @@ use chalk_ir::{
|
|||
};
|
||||
use chalk_solve::rust_ir::InlineBound;
|
||||
use hir_def::{
|
||||
lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId,
|
||||
TypeAliasId,
|
||||
data::TraitFlags, lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId,
|
||||
HasModule, TraitId, TypeAliasId,
|
||||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -432,7 +432,7 @@ where
|
|||
// Allow `impl AutoTrait` predicates
|
||||
if let WhereClause::Implemented(TraitRef { trait_id, substitution }) = pred {
|
||||
let trait_data = db.trait_data(from_chalk_trait_id(*trait_id));
|
||||
if trait_data.is_auto
|
||||
if trait_data.flags.contains(TraitFlags::IS_AUTO)
|
||||
&& substitution
|
||||
.as_slice(Interner)
|
||||
.first()
|
||||
|
|
|
@ -25,7 +25,7 @@ use either::Either;
|
|||
use hir_def::{
|
||||
body::HygieneId,
|
||||
builtin_type::BuiltinType,
|
||||
data::adt::StructKind,
|
||||
data::{adt::StructKind, TraitFlags},
|
||||
expander::Expander,
|
||||
generics::{
|
||||
GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
|
||||
|
@ -1567,9 +1567,17 @@ impl<'a> TyLoweringContext<'a> {
|
|||
match (lhs.skip_binders(), rhs.skip_binders()) {
|
||||
(WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => {
|
||||
let lhs_id = lhs.trait_id;
|
||||
let lhs_is_auto = ctx.db.trait_data(from_chalk_trait_id(lhs_id)).is_auto;
|
||||
let lhs_is_auto = ctx
|
||||
.db
|
||||
.trait_data(from_chalk_trait_id(lhs_id))
|
||||
.flags
|
||||
.contains(TraitFlags::IS_AUTO);
|
||||
let rhs_id = rhs.trait_id;
|
||||
let rhs_is_auto = ctx.db.trait_data(from_chalk_trait_id(rhs_id)).is_auto;
|
||||
let rhs_is_auto = ctx
|
||||
.db
|
||||
.trait_data(from_chalk_trait_id(rhs_id))
|
||||
.flags
|
||||
.contains(TraitFlags::IS_AUTO);
|
||||
|
||||
if !lhs_is_auto && !rhs_is_auto {
|
||||
multiple_regular_traits = true;
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::ops::ControlFlow;
|
|||
use base_db::CrateId;
|
||||
use chalk_ir::{cast::Cast, UniverseIndex, WithKind};
|
||||
use hir_def::{
|
||||
data::{adt::StructFlags, ImplData},
|
||||
data::{adt::StructFlags, ImplData, TraitFlags},
|
||||
nameres::DefMap,
|
||||
AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup,
|
||||
ModuleId, TraitId,
|
||||
|
@ -419,11 +419,17 @@ pub fn def_crates(
|
|||
}
|
||||
TyKind::Dyn(_) => {
|
||||
let trait_id = ty.dyn_trait()?;
|
||||
Some(if db.trait_data(trait_id).rustc_has_incoherent_inherent_impls {
|
||||
db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id))
|
||||
} else {
|
||||
smallvec![trait_id.module(db.upcast()).krate()]
|
||||
})
|
||||
Some(
|
||||
if db
|
||||
.trait_data(trait_id)
|
||||
.flags
|
||||
.contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
|
||||
{
|
||||
db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id))
|
||||
} else {
|
||||
smallvec![trait_id.module(db.upcast()).krate()]
|
||||
},
|
||||
)
|
||||
}
|
||||
// for primitives, there may be impls in various places (core and alloc
|
||||
// mostly). We just check the whole crate graph for crates with impls
|
||||
|
@ -835,7 +841,9 @@ fn is_inherent_impl_coherent(
|
|||
hir_def::AdtId::EnumId(it) => db.enum_data(it).rustc_has_incoherent_inherent_impls,
|
||||
},
|
||||
TyKind::Dyn(it) => it.principal_id().map_or(false, |trait_id| {
|
||||
db.trait_data(from_chalk_trait_id(trait_id)).rustc_has_incoherent_inherent_impls
|
||||
db.trait_data(from_chalk_trait_id(trait_id))
|
||||
.flags
|
||||
.contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
|
||||
}),
|
||||
|
||||
_ => false,
|
||||
|
@ -1204,7 +1212,7 @@ fn iterate_trait_method_candidates(
|
|||
// 2021.
|
||||
// This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for
|
||||
// arrays.
|
||||
if data.skip_array_during_method_dispatch
|
||||
if data.flags.contains(TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH)
|
||||
&& matches!(self_ty.kind(Interner), TyKind::Array(..))
|
||||
{
|
||||
// FIXME: this should really be using the edition of the method name's span, in case it
|
||||
|
@ -1213,7 +1221,7 @@ fn iterate_trait_method_candidates(
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if data.skip_boxed_slice_during_method_dispatch
|
||||
if data.flags.contains(TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH)
|
||||
&& matches!(
|
||||
self_ty.kind(Interner), TyKind::Adt(AdtId(def), subst)
|
||||
if is_box(table.db, *def)
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
//! HirDisplay implementations for various hir types.
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
data::adt::{StructKind, VariantData},
|
||||
data::{
|
||||
adt::{StructKind, VariantData},
|
||||
TraitFlags,
|
||||
},
|
||||
generics::{
|
||||
GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
|
||||
WherePredicateTypeTarget,
|
||||
|
@ -791,10 +794,10 @@ impl HirDisplay for Trait {
|
|||
fn write_trait_header(trait_: &Trait, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?;
|
||||
let data = f.db.trait_data(trait_.id);
|
||||
if data.is_unsafe {
|
||||
if data.flags.contains(TraitFlags::IS_UNSAFE) {
|
||||
f.write_str("unsafe ")?;
|
||||
}
|
||||
if data.is_auto {
|
||||
if data.flags.contains(TraitFlags::IS_AUTO) {
|
||||
f.write_str("auto ")?;
|
||||
}
|
||||
write!(f, "trait {}", data.name.display(f.db.upcast(), f.edition()))?;
|
||||
|
|
|
@ -43,7 +43,7 @@ use base_db::{CrateDisplayName, CrateId, CrateOrigin};
|
|||
use either::Either;
|
||||
use hir_def::{
|
||||
body::BodyDiagnostic,
|
||||
data::adt::VariantData,
|
||||
data::{adt::VariantData, TraitFlags},
|
||||
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
|
||||
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
|
||||
item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
|
||||
|
@ -2778,11 +2778,11 @@ impl Trait {
|
|||
}
|
||||
|
||||
pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
|
||||
db.trait_data(self.id).is_auto
|
||||
db.trait_data(self.id).flags.contains(TraitFlags::IS_AUTO)
|
||||
}
|
||||
|
||||
pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
|
||||
db.trait_data(self.id).is_unsafe
|
||||
db.trait_data(self.id).flags.contains(TraitFlags::IS_UNSAFE)
|
||||
}
|
||||
|
||||
pub fn type_or_const_param_count(
|
||||
|
|
Loading…
Reference in a new issue