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)] | #[derive(Debug, Clone, PartialEq, Eq)] | ||||||
| pub struct TraitData { | pub struct TraitData { | ||||||
|     pub name: Name, |     pub name: Name, | ||||||
|     pub items: Vec<(Name, AssocItemId)>, |     pub items: Vec<(Name, AssocItemId)>, | ||||||
|     pub is_auto: bool, |     pub flags: TraitFlags, | ||||||
|     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 visibility: RawVisibility, |     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
 |     // box it as the vec is usually empty anyways
 | ||||||
|     pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, |     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 item_tree = tree_id.item_tree(db); | ||||||
|         let tr_def = &item_tree[tree_id.value]; |         let tr_def = &item_tree[tree_id.value]; | ||||||
|         let name = tr_def.name.clone(); |         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 visibility = item_tree[tr_def.visibility].clone(); | ||||||
|         let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into()); |         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 = |         let mut skip_array_during_method_dispatch = | ||||||
|             attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists(); |             attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists(); | ||||||
|         let mut skip_boxed_slice_during_method_dispatch = false; |         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(); |         if skip_array_during_method_dispatch { | ||||||
|         let fundamental = attrs.by_key(&sym::fundamental).exists(); |             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 = |         let mut collector = | ||||||
|             AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); |             AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); | ||||||
|         collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); |         collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); | ||||||
|         let (items, macro_calls, diagnostics) = collector.finish(); |         let (items, macro_calls, diagnostics) = collector.finish(); | ||||||
| 
 | 
 | ||||||
|         ( |         ( | ||||||
|             Arc::new(TraitData { |             Arc::new(TraitData { name, macro_calls, items, visibility, flags }), | ||||||
|                 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, |  | ||||||
|             }), |  | ||||||
|             DefDiagnostics::new(diagnostics), |             DefDiagnostics::new(diagnostics), | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; | ||||||
| 
 | 
 | ||||||
| use base_db::CrateId; | use base_db::CrateId; | ||||||
| use hir_def::{ | use hir_def::{ | ||||||
|     data::adt::StructFlags, |     data::{adt::StructFlags, TraitFlags}, | ||||||
|     hir::Movability, |     hir::Movability, | ||||||
|     lang_item::{LangItem, LangItemTarget}, |     lang_item::{LangItem, LangItemTarget}, | ||||||
|     AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup, |     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 generic_params = generics(db.upcast(), trait_.into()); | ||||||
|     let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST); |     let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST); | ||||||
|     let flags = rust_ir::TraitFlags { |     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, |         upstream: trait_.lookup(db.upcast()).container.krate() != krate, | ||||||
|         non_enumerable: true, |         non_enumerable: true, | ||||||
|         coinductive: false, // only relevant for Chalk testing
 |         coinductive: false, // only relevant for Chalk testing
 | ||||||
|         // FIXME: set these flags correctly
 |         // FIXME: set these flags correctly
 | ||||||
|         marker: false, |         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 where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); | ||||||
|     let associated_ty_ids = trait_data.associated_types().map(to_assoc_type_id).collect(); |     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 chalk_solve::rust_ir::InlineBound; | ||||||
| use hir_def::{ | use hir_def::{ | ||||||
|     lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, |     data::TraitFlags, lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, | ||||||
|     TypeAliasId, |     HasModule, TraitId, TypeAliasId, | ||||||
| }; | }; | ||||||
| use rustc_hash::FxHashSet; | use rustc_hash::FxHashSet; | ||||||
| use smallvec::SmallVec; | use smallvec::SmallVec; | ||||||
|  | @ -432,7 +432,7 @@ where | ||||||
|         // Allow `impl AutoTrait` predicates
 |         // Allow `impl AutoTrait` predicates
 | ||||||
|         if let WhereClause::Implemented(TraitRef { trait_id, substitution }) = pred { |         if let WhereClause::Implemented(TraitRef { trait_id, substitution }) = pred { | ||||||
|             let trait_data = db.trait_data(from_chalk_trait_id(*trait_id)); |             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 |                 && substitution | ||||||
|                     .as_slice(Interner) |                     .as_slice(Interner) | ||||||
|                     .first() |                     .first() | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ use either::Either; | ||||||
| use hir_def::{ | use hir_def::{ | ||||||
|     body::HygieneId, |     body::HygieneId, | ||||||
|     builtin_type::BuiltinType, |     builtin_type::BuiltinType, | ||||||
|     data::adt::StructKind, |     data::{adt::StructKind, TraitFlags}, | ||||||
|     expander::Expander, |     expander::Expander, | ||||||
|     generics::{ |     generics::{ | ||||||
|         GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, |         GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, | ||||||
|  | @ -1567,9 +1567,17 @@ impl<'a> TyLoweringContext<'a> { | ||||||
|                 match (lhs.skip_binders(), rhs.skip_binders()) { |                 match (lhs.skip_binders(), rhs.skip_binders()) { | ||||||
|                     (WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => { |                     (WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => { | ||||||
|                         let lhs_id = lhs.trait_id; |                         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_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 { |                         if !lhs_is_auto && !rhs_is_auto { | ||||||
|                             multiple_regular_traits = true; |                             multiple_regular_traits = true; | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ use std::ops::ControlFlow; | ||||||
| use base_db::CrateId; | use base_db::CrateId; | ||||||
| use chalk_ir::{cast::Cast, UniverseIndex, WithKind}; | use chalk_ir::{cast::Cast, UniverseIndex, WithKind}; | ||||||
| use hir_def::{ | use hir_def::{ | ||||||
|     data::{adt::StructFlags, ImplData}, |     data::{adt::StructFlags, ImplData, TraitFlags}, | ||||||
|     nameres::DefMap, |     nameres::DefMap, | ||||||
|     AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, |     AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, | ||||||
|     ModuleId, TraitId, |     ModuleId, TraitId, | ||||||
|  | @ -419,11 +419,17 @@ pub fn def_crates( | ||||||
|         } |         } | ||||||
|         TyKind::Dyn(_) => { |         TyKind::Dyn(_) => { | ||||||
|             let trait_id = ty.dyn_trait()?; |             let trait_id = ty.dyn_trait()?; | ||||||
|             Some(if db.trait_data(trait_id).rustc_has_incoherent_inherent_impls { |             Some( | ||||||
|                 db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id)) |                 if db | ||||||
|             } else { |                     .trait_data(trait_id) | ||||||
|                 smallvec![trait_id.module(db.upcast()).krate()] |                     .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
 |         // for primitives, there may be impls in various places (core and alloc
 | ||||||
|         // mostly). We just check the whole crate graph for crates with impls
 |         // 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, |                 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| { |             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, |             _ => false, | ||||||
|  | @ -1204,7 +1212,7 @@ fn iterate_trait_method_candidates( | ||||||
|         // 2021.
 |         // 2021.
 | ||||||
|         // This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for
 |         // This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for
 | ||||||
|         // arrays.
 |         // 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(..)) |             && matches!(self_ty.kind(Interner), TyKind::Array(..)) | ||||||
|         { |         { | ||||||
|             // FIXME: this should really be using the edition of the method name's span, in case it
 |             // 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; |                 continue; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if data.skip_boxed_slice_during_method_dispatch |         if data.flags.contains(TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH) | ||||||
|             && matches!( |             && matches!( | ||||||
|                 self_ty.kind(Interner), TyKind::Adt(AdtId(def), subst) |                 self_ty.kind(Interner), TyKind::Adt(AdtId(def), subst) | ||||||
|                 if is_box(table.db, *def) |                 if is_box(table.db, *def) | ||||||
|  |  | ||||||
|  | @ -1,7 +1,10 @@ | ||||||
| //! HirDisplay implementations for various hir types.
 | //! HirDisplay implementations for various hir types.
 | ||||||
| use either::Either; | use either::Either; | ||||||
| use hir_def::{ | use hir_def::{ | ||||||
|     data::adt::{StructKind, VariantData}, |     data::{ | ||||||
|  |         adt::{StructKind, VariantData}, | ||||||
|  |         TraitFlags, | ||||||
|  |     }, | ||||||
|     generics::{ |     generics::{ | ||||||
|         GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate, |         GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate, | ||||||
|         WherePredicateTypeTarget, |         WherePredicateTypeTarget, | ||||||
|  | @ -791,10 +794,10 @@ impl HirDisplay for Trait { | ||||||
| fn write_trait_header(trait_: &Trait, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { | fn write_trait_header(trait_: &Trait, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { | ||||||
|     write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?; |     write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?; | ||||||
|     let data = f.db.trait_data(trait_.id); |     let data = f.db.trait_data(trait_.id); | ||||||
|     if data.is_unsafe { |     if data.flags.contains(TraitFlags::IS_UNSAFE) { | ||||||
|         f.write_str("unsafe ")?; |         f.write_str("unsafe ")?; | ||||||
|     } |     } | ||||||
|     if data.is_auto { |     if data.flags.contains(TraitFlags::IS_AUTO) { | ||||||
|         f.write_str("auto ")?; |         f.write_str("auto ")?; | ||||||
|     } |     } | ||||||
|     write!(f, "trait {}", data.name.display(f.db.upcast(), f.edition()))?; |     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 either::Either; | ||||||
| use hir_def::{ | use hir_def::{ | ||||||
|     body::BodyDiagnostic, |     body::BodyDiagnostic, | ||||||
|     data::adt::VariantData, |     data::{adt::VariantData, TraitFlags}, | ||||||
|     generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, |     generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, | ||||||
|     hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat}, |     hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat}, | ||||||
|     item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode}, |     item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode}, | ||||||
|  | @ -2778,11 +2778,11 @@ impl Trait { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn is_auto(self, db: &dyn HirDatabase) -> bool { |     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 { |     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( |     pub fn type_or_const_param_count( | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth