From 4d66fa797fb76fe37720ca44da579e9076a58de0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 3 Jan 2025 12:46:07 +0100 Subject: [PATCH] minor: Encode TraitData bools as bitflags --- crates/hir-def/src/data.rs | 64 +++++++++++++++----------- crates/hir-ty/src/chalk_db.rs | 6 +-- crates/hir-ty/src/dyn_compatibility.rs | 6 +-- crates/hir-ty/src/lower.rs | 14 ++++-- crates/hir-ty/src/method_resolution.rs | 26 +++++++---- crates/hir/src/display.rs | 9 ++-- crates/hir/src/lib.rs | 6 +-- 7 files changed, 81 insertions(+), 50 deletions(-) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 15dd6aba31..92b841f711 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -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, 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), ) } diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 0a2612219a..9f01f1eb25 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -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(); diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs index fadf8aca99..6a01579bcc 100644 --- a/crates/hir-ty/src/dyn_compatibility.rs +++ b/crates/hir-ty/src/dyn_compatibility.rs @@ -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() diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 7a74694887..b88caea8d3 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -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; diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index dd6104aec8..4ed88c75ce 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -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) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index a5a6bebe6d..e09ded32fb 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -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()))?; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 8289c9006c..fe4b255d3c 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -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(