about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs64
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs6
7 files changed, 81 insertions, 50 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 15dd6aba311..92b841f7117 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/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<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),
         )
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 0a2612219a4..9f01f1eb259 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index fadf8aca998..6a01579bccc 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 7a746948877..b88caea8d34 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index dd6104aec89..4ed88c75ce1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index a5a6bebe6d1..e09ded32fbd 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 8289c9006c9..fe4b255d3c5 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/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(