mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +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 { | ||||
|             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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth