From 13890697ebb6d4f566c4236d82daa8deedda7ea1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 6 Apr 2024 13:12:07 +0200 Subject: [PATCH 1/4] Simplify --- crates/base-db/src/input.rs | 1 + crates/hir-def/src/data.rs | 2 +- crates/hir-def/src/expander.rs | 8 ++- crates/hir-ty/src/consteval.rs | 33 ++++----- crates/hir-ty/src/infer.rs | 6 +- crates/hir-ty/src/infer/cast.rs | 4 -- crates/hir-ty/src/infer/closure.rs | 16 ++--- crates/hir-ty/src/infer/expr.rs | 20 ++---- crates/hir-ty/src/infer/pat.rs | 48 +++++++------ crates/hir-ty/src/lower.rs | 104 ++++++++++++----------------- crates/hir-ty/src/utils.rs | 10 ++- crates/limit/Cargo.toml | 3 +- 12 files changed, 120 insertions(+), 135 deletions(-) diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index 27eb05cd4dc5..6ea1e676a13a 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -285,6 +285,7 @@ pub struct CrateData { /// For purposes of analysis, crates are anonymous (only names in /// `Dependency` matters), this name should only be used for UI. pub display_name: Option, + // FIXME: Arc this pub cfg_options: CfgOptions, /// The cfg options that could be used by the crate pub potential_cfg_options: Option, diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index da790f11516d..b5317be288e4 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -737,7 +737,7 @@ impl<'a> AssocItemCollector<'a> { &AstIdWithPath::new(file_id, ast_id, Clone::clone(path)), ctxt, expand_to, - self.expander.module.krate(), + self.expander.krate(), resolver, ) { Ok(Some(call_id)) => { diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs index b0872fcdc0e6..3084e06c1be2 100644 --- a/crates/hir-def/src/expander.rs +++ b/crates/hir-def/src/expander.rs @@ -21,7 +21,6 @@ use crate::{ pub struct Expander { cfg_options: CfgOptions, span_map: OnceCell, - krate: CrateId, current_file_id: HirFileId, pub(crate) module: ModuleId, /// `recursion_depth == usize::MAX` indicates that the recursion limit has been reached. @@ -45,10 +44,13 @@ impl Expander { recursion_limit, cfg_options: db.crate_graph()[module.krate].cfg_options.clone(), span_map: OnceCell::new(), - krate: module.krate, } } + pub fn krate(&self) -> CrateId { + self.module.krate + } + pub fn enter_expand( &mut self, db: &dyn DefDatabase, @@ -112,7 +114,7 @@ impl Expander { pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs { Attrs::filter( db, - self.krate, + self.krate(), RawAttrs::new( db.upcast(), owner, diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index 705609ba68de..eb5c2c55041d 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -77,30 +77,32 @@ pub(crate) fn path_to_const( resolver: &Resolver, path: &Path, mode: ParamLoweringMode, - args_lazy: impl FnOnce() -> Generics, + args: impl FnOnce() -> Option, debruijn: DebruijnIndex, expected_ty: Ty, ) -> Option { match resolver.resolve_path_in_value_ns_fully(db.upcast(), path) { Some(ValueNs::GenericParam(p)) => { let ty = db.const_param_ty(p); - let args = args_lazy(); let value = match mode { ParamLoweringMode::Placeholder => { ConstValue::Placeholder(to_placeholder_idx(db, p.into())) } - ParamLoweringMode::Variable => match args.param_idx(p.into()) { - Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), - None => { - never!( - "Generic list doesn't contain this param: {:?}, {:?}, {:?}", - args, - path, - p - ); - return None; + ParamLoweringMode::Variable => { + let args = args(); + match args.as_ref().and_then(|args| args.param_idx(p.into())) { + Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), + None => { + never!( + "Generic list doesn't contain this param: {:?}, {:?}, {:?}", + args, + path, + p + ); + return None; + } } - }, + } }; Some(ConstData { ty, value }.intern(Interner)) } @@ -285,7 +287,6 @@ pub(crate) fn eval_to_const( expr: ExprId, mode: ParamLoweringMode, ctx: &mut InferenceContext<'_>, - args: impl FnOnce() -> Generics, debruijn: DebruijnIndex, ) -> Const { let db = ctx.db; @@ -304,7 +305,9 @@ pub(crate) fn eval_to_const( } if let Expr::Path(p) = &ctx.body.exprs[expr] { let resolver = &ctx.resolver; - if let Some(c) = path_to_const(db, resolver, p, mode, args, debruijn, infer[expr].clone()) { + if let Some(c) = + path_to_const(db, resolver, p, mode, || ctx.generics(), debruijn, infer[expr].clone()) + { return c; } } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 3b644379fa6e..3aacf7d07f99 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -60,7 +60,7 @@ use crate::{ lower::ImplTraitLoweringMode, to_assoc_type_id, traits::FnTrait, - utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder}, + utils::{Generics, InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder}, AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId, ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, @@ -630,6 +630,10 @@ impl<'a> InferenceContext<'a> { } } + pub(crate) fn generics(&self) -> Option { + Some(crate::utils::generics(self.db.upcast(), self.resolver.generic_def()?)) + } + // FIXME: This function should be private in module. It is currently only used in the consteval, since we need // `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you // used this function for another workaround, mention it here. If you really need this function and believe that diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs index f8c03ee2886b..060b5f36f292 100644 --- a/crates/hir-ty/src/infer/cast.rs +++ b/crates/hir-ty/src/infer/cast.rs @@ -19,10 +19,6 @@ impl CastCheck { let expr_ty = table.resolve_ty_shallow(&self.expr_ty); let cast_ty = table.resolve_ty_shallow(&self.cast_ty); - if expr_ty.contains_unknown() || cast_ty.contains_unknown() { - return; - } - if table.coerce(&expr_ty, &cast_ty).is_ok() { return; } diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 20d24e6fe2ee..f08c0b687163 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -26,7 +26,7 @@ use crate::{ mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, to_chalk_trait_id, traits::FnTrait, - utils::{self, elaborate_clause_supertraits, generics, Generics}, + utils::{self, elaborate_clause_supertraits, Generics}, Adjust, Adjustment, AliasEq, AliasTy, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, DynTyExt, FnAbi, FnPointer, FnSig, Interner, OpaqueTy, ProjectionTyExt, Substitution, Ty, TyExt, WhereClause, @@ -331,14 +331,10 @@ impl CapturedItemWithoutTy { place: self.place, kind: self.kind, span: self.span, - ty: replace_placeholder_with_binder(ctx.db, ctx.owner, ty), + ty: replace_placeholder_with_binder(ctx, ty), }; - fn replace_placeholder_with_binder( - db: &dyn HirDatabase, - owner: DefWithBodyId, - ty: Ty, - ) -> Binders { + fn replace_placeholder_with_binder(ctx: &mut InferenceContext<'_>, ty: Ty) -> Binders { struct Filler<'a> { db: &'a dyn HirDatabase, generics: Generics, @@ -379,12 +375,12 @@ impl CapturedItemWithoutTy { Ok(BoundVar::new(outer_binder, idx).to_ty(Interner)) } } - let Some(generic_def) = owner.as_generic_def_id() else { + let Some(generics) = ctx.generics() else { return Binders::empty(Interner, ty); }; - let filler = &mut Filler { db, generics: generics(db.upcast(), generic_def) }; + let filler = &mut Filler { db: ctx.db, generics }; let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty); - make_binders(db, &filler.generics, result) + make_binders(ctx.db, &filler.generics, result) } } } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 4d3d7376c4de..d011a62e77a3 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1040,18 +1040,12 @@ impl InferenceContext<'_> { ( elem_ty, - if let Some(g_def) = self.owner.as_generic_def_id() { - let generics = generics(self.db.upcast(), g_def); - consteval::eval_to_const( - repeat, - ParamLoweringMode::Placeholder, - self, - || generics, - DebruijnIndex::INNERMOST, - ) - } else { - consteval::usize_const(self.db, None, krate) - }, + consteval::eval_to_const( + repeat, + ParamLoweringMode::Placeholder, + self, + DebruijnIndex::INNERMOST, + ), ) } }; @@ -1852,7 +1846,7 @@ impl InferenceContext<'_> { ty, c, ParamLoweringMode::Placeholder, - || generics(this.db.upcast(), this.resolver.generic_def().unwrap()), + || this.generics(), DebruijnIndex::INNERMOST, ) }, diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs index 440ffa335728..1b354935a5bf 100644 --- a/crates/hir-ty/src/infer/pat.rs +++ b/crates/hir-ty/src/infer/pat.rs @@ -2,13 +2,13 @@ use std::iter::repeat_with; -use chalk_ir::Mutability; use hir_def::{ body::Body, hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, Literal, Pat, PatId}, path::Path, }; use hir_expand::name::Name; +use stdx::TupleExt; use crate::{ consteval::{try_const_usize, usize_const}, @@ -16,8 +16,8 @@ use crate::{ infer::{BindingMode, Expectation, InferenceContext, TypeMismatch}, lower::lower_to_chalk_mutability, primitive::UintTy, - static_lifetime, InferenceDiagnostic, Interner, Scalar, Substitution, Ty, TyBuilder, TyExt, - TyKind, + static_lifetime, InferenceDiagnostic, Interner, Mutability, Scalar, Substitution, Ty, + TyBuilder, TyExt, TyKind, }; /// Used to generalize patterns and assignee expressions. @@ -90,9 +90,6 @@ impl InferenceContext<'_> { self.unify(&ty, expected); - let substs = - ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(Interner)); - match def { _ if subs.is_empty() => {} Some(def) => { @@ -109,8 +106,10 @@ impl InferenceContext<'_> { let pre_iter = pre.iter().enumerate(); let post_iter = (post_idx_offset..).zip(post.iter()); + let substs = ty.as_adt().map(TupleExt::tail); + for (i, &subpat) in pre_iter.chain(post_iter) { - let field_def = { + let expected_ty = { match variant_data.field(&Name::new_tuple_field(i)) { Some(local_id) => { if !visibilities[local_id] @@ -118,17 +117,17 @@ impl InferenceContext<'_> { { // FIXME(DIAGNOSE): private tuple field } - Some(local_id) + let f = field_types[local_id].clone(); + let expected_ty = match substs { + Some(substs) => f.substitute(Interner, substs), + None => f.substitute(Interner, &Substitution::empty(Interner)), + }; + self.normalize_associated_types_in(expected_ty) } - None => None, + None => self.err_ty(), } }; - let expected_ty = field_def.map_or(self.err_ty(), |f| { - field_types[f].clone().substitute(Interner, &substs) - }); - let expected_ty = self.normalize_associated_types_in(expected_ty); - T::infer(self, subpat, &expected_ty, default_bm); } } @@ -159,9 +158,6 @@ impl InferenceContext<'_> { self.unify(&ty, expected); - let substs = - ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(Interner)); - match def { _ if subs.len() == 0 => {} Some(def) => { @@ -169,8 +165,10 @@ impl InferenceContext<'_> { let variant_data = def.variant_data(self.db.upcast()); let visibilities = self.db.field_visibilities(def); + let substs = ty.as_adt().map(TupleExt::tail); + for (name, inner) in subs { - let field_def = { + let expected_ty = { match variant_data.field(&name) { Some(local_id) => { if !visibilities[local_id] @@ -181,23 +179,23 @@ impl InferenceContext<'_> { private: true, }); } - Some(local_id) + let f = field_types[local_id].clone(); + let expected_ty = match substs { + Some(substs) => f.substitute(Interner, substs), + None => f.substitute(Interner, &Substitution::empty(Interner)), + }; + self.normalize_associated_types_in(expected_ty) } None => { self.push_diagnostic(InferenceDiagnostic::NoSuchField { field: inner.into(), private: false, }); - None + self.err_ty() } } }; - let expected_ty = field_def.map_or(self.err_ty(), |f| { - field_types[f].clone().substitute(Interner, &substs) - }); - let expected_ty = self.normalize_associated_types_in(expected_ty); - T::infer(self, inner, &expected_ty, default_bm); } } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 9a468e2a2335..a4ab1ebb8b93 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -62,8 +62,8 @@ use crate::{ mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk}, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, utils::{ - all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics, - InTypeConstIdMetadata, + self, all_super_trait_refs, associated_type_by_name_including_super_traits, generics, + Generics, InTypeConstIdMetadata, }, AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, @@ -245,13 +245,8 @@ impl<'a> TyLoweringContext<'a> { ) } - fn generics(&self) -> Generics { - generics( - self.db.upcast(), - self.resolver - .generic_def() - .expect("there should be generics if there's a generic param"), - ) + fn generics(&self) -> Option { + Some(generics(self.db.upcast(), self.resolver.generic_def()?)) } pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option) { @@ -352,8 +347,7 @@ impl<'a> TyLoweringContext<'a> { let idx = counter.get(); // FIXME we're probably doing something wrong here counter.set(idx + count_impl_traits(type_ref) as u16); - if let Some(def) = self.resolver.generic_def() { - let generics = generics(self.db.upcast(), def); + if let Some(generics) = self.generics() { let param = generics .iter() .filter(|(_, data)| { @@ -388,8 +382,7 @@ impl<'a> TyLoweringContext<'a> { const_params, _impl_trait_params, _lifetime_params, - ) = if let Some(def) = self.resolver.generic_def() { - let generics = generics(self.db.upcast(), def); + ) = if let Some(generics) = self.generics() { generics.provenance_split() } else { (0, 0, 0, 0, 0, 0) @@ -577,44 +570,40 @@ impl<'a> TyLoweringContext<'a> { // FIXME(trait_alias): Implement trait alias. return (TyKind::Error.intern(Interner), None); } - TypeNs::GenericParam(param_id) => { - let generics = generics( - self.db.upcast(), - self.resolver.generic_def().expect("generics in scope"), - ); - match self.type_param_mode { - ParamLoweringMode::Placeholder => { - TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into())) - } - ParamLoweringMode::Variable => { - let idx = match generics.param_idx(param_id.into()) { - None => { - never!("no matching generics"); - return (TyKind::Error.intern(Interner), None); - } - Some(idx) => idx, - }; + TypeNs::GenericParam(param_id) => match self.type_param_mode { + ParamLoweringMode::Placeholder => { + TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into())) + } + ParamLoweringMode::Variable => { + let idx = match self + .generics() + .expect("generics in scope") + .param_idx(param_id.into()) + { + None => { + never!("no matching generics"); + return (TyKind::Error.intern(Interner), None); + } + Some(idx) => idx, + }; - TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) - } + TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) } - .intern(Interner) } + .intern(Interner), TypeNs::SelfType(impl_id) => { - let def = - self.resolver.generic_def().expect("impl should have generic param scope"); - let generics = generics(self.db.upcast(), def); + let generics = self.generics().expect("impl should have generic param scope"); match self.type_param_mode { ParamLoweringMode::Placeholder => { // `def` can be either impl itself or item within, and we need impl itself // now. - let generics = generics.parent_generics().unwrap_or(&generics); + let generics = generics.parent_or_self(); let subst = generics.placeholder_subst(self.db); self.db.impl_self_ty(impl_id).substitute(Interner, &subst) } ParamLoweringMode::Variable => { - let starting_from = match def { + let starting_from = match generics.def() { GenericDefId::ImplId(_) => 0, // `def` is an item within impl. We need to substitute `BoundVar`s but // remember that they are for parent (i.e. impl) generic params so they @@ -682,12 +671,12 @@ impl<'a> TyLoweringContext<'a> { } fn select_associated_type(&self, res: Option, segment: PathSegment<'_>) -> Ty { - let Some((def, res)) = self.resolver.generic_def().zip(res) else { + let Some((generics, res)) = self.generics().zip(res) else { return TyKind::Error.intern(Interner); }; let ty = named_associated_type_shorthand_candidates( self.db, - def, + generics.def(), res, Some(segment.name.clone()), move |name, t, associated_ty| { @@ -699,7 +688,6 @@ impl<'a> TyLoweringContext<'a> { let parent_subst = match self.type_param_mode { ParamLoweringMode::Placeholder => { // if we're lowering to placeholders, we have to put them in now. - let generics = generics(self.db.upcast(), def); let s = generics.placeholder_subst(self.db); s.apply(parent_subst, Interner) } @@ -721,7 +709,7 @@ impl<'a> TyLoweringContext<'a> { None, ); - let len_self = generics(self.db.upcast(), associated_ty.into()).len_self(); + let len_self = utils::generics(self.db.upcast(), associated_ty.into()).len_self(); let substs = Substitution::from_iter( Interner, @@ -1029,18 +1017,17 @@ impl<'a> TyLoweringContext<'a> { | WherePredicate::TypeBound { target, bound } => { let self_ty = match target { WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref), - WherePredicateTypeTarget::TypeOrConstParam(param_id) => { - let generic_def = self.resolver.generic_def().expect("generics in scope"); - let generics = generics(self.db.upcast(), generic_def); - let param_id = hir_def::TypeOrConstParamId { - parent: generic_def, - local_id: *param_id, - }; - let placeholder = to_placeholder_idx(self.db, param_id); + &WherePredicateTypeTarget::TypeOrConstParam(local_id) => { + let def = self.resolver.generic_def().expect("generics in scope"); + let param_id = hir_def::TypeOrConstParamId { parent: def, local_id }; match self.type_param_mode { - ParamLoweringMode::Placeholder => TyKind::Placeholder(placeholder), + ParamLoweringMode::Placeholder => { + TyKind::Placeholder(to_placeholder_idx(self.db, param_id)) + } ParamLoweringMode::Variable => { - let idx = generics.param_idx(param_id).expect("matching generics"); + let idx = generics(self.db.upcast(), def) + .param_idx(param_id) + .expect("matching generics"); TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx)) } } @@ -1218,8 +1205,8 @@ impl<'a> TyLoweringContext<'a> { }); if let Some(target_param_idx) = target_param_idx { let mut counter = 0; - for (idx, data) in self.generics().params.type_or_consts.iter() - { + let generics = self.generics().expect("generics in scope"); + for (idx, data) in generics.params.type_or_consts.iter() { // Count the number of `impl Trait` things that appear before // the target of our `bound`. // Our counter within `impl_trait_mode` should be that number @@ -1409,10 +1396,7 @@ impl<'a> TyLoweringContext<'a> { LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id)) } ParamLoweringMode::Variable => { - let generics = generics( - self.db.upcast(), - self.resolver.generic_def().expect("generics in scope"), - ); + let generics = self.generics().expect("generics in scope"); let idx = match generics.lifetime_idx(id) { None => return error_lifetime(), Some(idx) => idx, @@ -2258,7 +2242,7 @@ pub(crate) fn const_or_path_to_chalk( expected_ty: Ty, value: &ConstRef, mode: ParamLoweringMode, - args: impl FnOnce() -> Generics, + args: impl FnOnce() -> Option, debruijn: DebruijnIndex, ) -> Const { match value { @@ -2277,7 +2261,7 @@ pub(crate) fn const_or_path_to_chalk( .unwrap_or_else(|| unknown_const(expected_ty)) } &ConstRef::Complex(it) => { - let crate_data = &db.crate_graph()[owner.module(db.upcast()).krate()]; + let crate_data = &db.crate_graph()[resolver.krate()]; if crate_data.env.get("__ra_is_test_fixture").is_none() && crate_data.origin.is_local() { // FIXME: current `InTypeConstId` is very unstable, so we only use it in non local crate diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index afd4d1f271df..77c5fd054d1c 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -262,7 +262,7 @@ impl<'a> ClosureSubst<'a> { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub(crate) struct Generics { def: GenericDefId, pub(crate) params: Interned, @@ -274,6 +274,10 @@ impl Generics { self.iter().map(|(id, _)| id) } + pub(crate) fn def(&self) -> GenericDefId { + self.def + } + /// Iterator over types and const params of self, then parent. pub(crate) fn iter<'a>( &'a self, @@ -450,6 +454,10 @@ impl Generics { self.parent_generics.as_deref() } + pub(crate) fn parent_or_self(&self) -> &Generics { + self.parent_generics.as_deref().unwrap_or(self) + } + /// Returns a Substitution that replaces each parameter by a bound variable. pub(crate) fn bound_vars_subst( &self, diff --git a/crates/limit/Cargo.toml b/crates/limit/Cargo.toml index c89722cc40de..c1a768833b99 100644 --- a/crates/limit/Cargo.toml +++ b/crates/limit/Cargo.toml @@ -10,7 +10,6 @@ rust-version.workspace = true [features] tracking = [] -default = ["tracking"] [lints] -workspace = true \ No newline at end of file +workspace = true From 336dee3415d935ad438f1f2e30ad57fa253bd88e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 6 Apr 2024 13:40:15 +0200 Subject: [PATCH 2/4] Remove some allocs --- crates/hir-ty/src/lib.rs | 6 ++++-- crates/hir-ty/src/lower.rs | 26 ++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index ad8202d4d233..14f1fd728dae 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -603,15 +603,17 @@ pub enum ImplTraitId { } impl_intern_value_trivial!(ImplTraitId); -#[derive(Clone, PartialEq, Eq, Debug, Hash)] +#[derive(PartialEq, Eq, Debug, Hash)] pub struct ImplTraits { pub(crate) impl_traits: Arena, } has_interner!(ImplTraits); -#[derive(Clone, PartialEq, Eq, Debug, Hash)] +#[derive(PartialEq, Eq, Debug, Hash)] pub struct ImplTrait { + // FIXME: Should be Arc<[QuantifiedWhereClause]>, but the HasInterner impl for Arc is missing a + // ?Sized bound pub(crate) bounds: Binders>, } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index a4ab1ebb8b93..08cb89d97488 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -316,7 +316,7 @@ impl<'a> TyLoweringContext<'a> { // place even if we encounter more opaque types while // lowering the bounds let idx = opaque_type_data.borrow_mut().alloc(ImplTrait { - bounds: crate::make_single_type_binders(Vec::new()), + bounds: crate::make_single_type_binders(Vec::default()), }); // We don't want to lower the bounds inside the binders // we're currently in, because they don't end up inside @@ -1007,11 +1007,11 @@ impl<'a> TyLoweringContext<'a> { self.substs_from_path_segment(segment, Some(resolved.into()), false, explicit_self_ty) } - pub(crate) fn lower_where_predicate( - &self, - where_predicate: &WherePredicate, + pub(crate) fn lower_where_predicate<'b>( + &'b self, + where_predicate: &'b WherePredicate, ignore_bindings: bool, - ) -> impl Iterator { + ) -> impl Iterator + 'b { match where_predicate { WherePredicate::ForLifetime { target, bound, .. } | WherePredicate::TypeBound { target, bound } => { @@ -1034,18 +1034,16 @@ impl<'a> TyLoweringContext<'a> { .intern(Interner) } }; - self.lower_type_bound(bound, self_ty, ignore_bindings) - .collect::>() - .into_iter() + Either::Left(self.lower_type_bound(bound, self_ty, ignore_bindings)) } - WherePredicate::Lifetime { bound, target } => { - vec![crate::wrap_empty_binders(WhereClause::LifetimeOutlives(LifetimeOutlives { + WherePredicate::Lifetime { bound, target } => Either::Right(iter::once( + crate::wrap_empty_binders(WhereClause::LifetimeOutlives(LifetimeOutlives { a: self.lower_lifetime(bound), b: self.lower_lifetime(target), - }))] - .into_iter() - } + })), + )), } + .into_iter() } pub(crate) fn lower_type_bound( @@ -1380,8 +1378,8 @@ impl<'a> TyLoweringContext<'a> { crate::wrap_empty_binders(clause) }); predicates.extend(sized_clause); - predicates.shrink_to_fit(); } + predicates.shrink_to_fit(); predicates }); ImplTrait { bounds: crate::make_single_type_binders(predicates) } From f3567bb604eef8f05ec14259f2f65a21cc776c97 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 6 Apr 2024 13:55:10 +0200 Subject: [PATCH 3/4] Arc CrateData::cfg_options --- crates/base-db/src/input.rs | 9 ++++----- crates/hir-def/src/data/adt.rs | 11 +++-------- crates/hir-def/src/expander.rs | 3 ++- crates/hir/src/lib.rs | 4 ++-- crates/ide/src/lib.rs | 2 +- crates/project-model/src/workspace.rs | 23 +++++++++++++---------- crates/test-fixture/src/lib.rs | 8 ++++---- 7 files changed, 29 insertions(+), 31 deletions(-) diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index 6ea1e676a13a..1924ce578abd 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -285,10 +285,9 @@ pub struct CrateData { /// For purposes of analysis, crates are anonymous (only names in /// `Dependency` matters), this name should only be used for UI. pub display_name: Option, - // FIXME: Arc this - pub cfg_options: CfgOptions, + pub cfg_options: Arc, /// The cfg options that could be used by the crate - pub potential_cfg_options: Option, + pub potential_cfg_options: Option>, pub env: Env, pub dependencies: Vec, pub origin: CrateOrigin, @@ -329,8 +328,8 @@ impl CrateGraph { edition: Edition, display_name: Option, version: Option, - cfg_options: CfgOptions, - potential_cfg_options: Option, + cfg_options: Arc, + potential_cfg_options: Option>, env: Env, is_proc_macro: bool, origin: CrateOrigin, diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index a7461b78af1c..5330db7c80ce 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -191,8 +191,6 @@ impl StructData { let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); - let cfg_options = db.crate_graph()[krate].cfg_options.clone(); - let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let mut flags = StructFlags::NO_FLAGS; @@ -219,7 +217,7 @@ impl StructData { loc.id.file_id(), loc.container.local_id, &item_tree, - &cfg_options, + &db.crate_graph()[krate].cfg_options, &strukt.fields, None, ); @@ -248,8 +246,6 @@ impl StructData { let krate = loc.container.krate; let item_tree = loc.id.item_tree(db); let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); - let cfg_options = db.crate_graph()[krate].cfg_options.clone(); - let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let mut flags = StructFlags::NO_FLAGS; if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() { @@ -266,7 +262,7 @@ impl StructData { loc.id.file_id(), loc.container.local_id, &item_tree, - &cfg_options, + &db.crate_graph()[krate].cfg_options, &union.fields, None, ); @@ -338,7 +334,6 @@ impl EnumVariantData { let container = loc.parent.lookup(db).container; let krate = container.krate; let item_tree = loc.id.item_tree(db); - let cfg_options = db.crate_graph()[krate].cfg_options.clone(); let variant = &item_tree[loc.id.value]; let (var_data, diagnostics) = lower_fields( @@ -347,7 +342,7 @@ impl EnumVariantData { loc.id.file_id(), container.local_id, &item_tree, - &cfg_options, + &db.crate_graph()[krate].cfg_options, &variant.fields, Some(item_tree[loc.parent.lookup(db).id.value].visibility), ); diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs index 3084e06c1be2..73ce942c5807 100644 --- a/crates/hir-def/src/expander.rs +++ b/crates/hir-def/src/expander.rs @@ -11,6 +11,7 @@ use hir_expand::{ }; use limit::Limit; use syntax::{ast, Parse}; +use triomphe::Arc; use crate::{ attr::Attrs, db::DefDatabase, lower::LowerCtx, path::Path, AsMacroCall, MacroId, ModuleId, @@ -19,7 +20,7 @@ use crate::{ #[derive(Debug)] pub struct Expander { - cfg_options: CfgOptions, + cfg_options: Arc, span_map: OnceCell, current_file_id: HirFileId, pub(crate) module: ModuleId, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 9b9f710d9a12..c4e051bff5e7 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -260,11 +260,11 @@ impl Crate { doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/") } - pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions { + pub fn cfg(&self, db: &dyn HirDatabase) -> Arc { db.crate_graph()[self.id].cfg_options.clone() } - pub fn potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions { + pub fn potential_cfg(&self, db: &dyn HirDatabase) -> Arc { let data = &db.crate_graph()[self.id]; data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone()) } diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index ad48d803895f..e13060e4d79b 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -252,7 +252,7 @@ impl Analysis { Edition::CURRENT, None, None, - cfg_options.clone(), + Arc::new(cfg_options), None, Env::default(), false, diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index b59c0d59e478..00e9c1298801 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -913,12 +913,14 @@ fn project_json_to_crate_graph( *edition, display_name.clone(), version.clone(), - target_cfgs - .iter() - .chain(cfg.iter()) - .chain(iter::once(&r_a_cfg_flag)) - .cloned() - .collect(), + Arc::new( + target_cfgs + .iter() + .chain(cfg.iter()) + .chain(iter::once(&r_a_cfg_flag)) + .cloned() + .collect(), + ), None, env, *is_proc_macro, @@ -1179,6 +1181,7 @@ fn detached_files_to_crate_graph( let mut cfg_options = create_cfg_options(rustc_cfg); cfg_options.insert_atom("rust_analyzer".into()); + let cfg_options = Arc::new(cfg_options); for detached_file in detached_files { let file_id = match load(detached_file) { @@ -1380,8 +1383,8 @@ fn add_target_crate_root( edition, Some(display_name), Some(pkg.version.to_string()), - cfg_options, - potential_cfg_options, + Arc::new(cfg_options), + potential_cfg_options.map(Arc::new), env, matches!(kind, TargetKind::Lib { is_proc_macro: true }), origin, @@ -1437,7 +1440,7 @@ fn sysroot_to_crate_graph( let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag("test".into())]).unwrap(); for (cid, c) in cg.iter_mut() { // uninject `test` flag so `core` keeps working. - c.cfg_options.apply_diff(diff.clone()); + Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone()); // patch the origin if c.origin.is_local() { let lang_crate = LangCrateOrigin::from( @@ -1486,7 +1489,7 @@ fn sysroot_to_crate_graph( (SysrootPublicDeps { deps: pub_deps }, libproc_macro) } SysrootMode::Stitched(stitched) => { - let cfg_options = create_cfg_options(rustc_cfg); + let cfg_options = Arc::new(create_cfg_options(rustc_cfg)); let sysroot_crates: FxHashMap = stitched .crates() .filter_map(|krate| { diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index c8d785f83e8f..7ce83078cb5c 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -189,8 +189,8 @@ impl ChangeFixture { meta.edition, Some(crate_name.clone().into()), version, - meta.cfg.clone(), - Some(meta.cfg), + From::from(meta.cfg.clone()), + Some(From::from(meta.cfg)), meta.env, false, origin, @@ -227,8 +227,8 @@ impl ChangeFixture { Edition::CURRENT, Some(CrateName::new("test").unwrap().into()), None, - default_cfg.clone(), - Some(default_cfg), + From::from(default_cfg.clone()), + Some(From::from(default_cfg)), default_env, false, CrateOrigin::Local { repo: None, name: None }, From a82e028e30ea11481ca3e60c1318b1aa84221ec1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 6 Apr 2024 14:29:40 +0200 Subject: [PATCH 4/4] Cleanup util::Generics method names --- crates/hir-def/src/generics.rs | 30 ++++++--- crates/hir-ty/src/consteval.rs | 2 +- crates/hir-ty/src/display.rs | 6 +- crates/hir-ty/src/infer/closure.rs | 4 +- crates/hir-ty/src/lib.rs | 2 +- crates/hir-ty/src/lower.rs | 6 +- crates/hir-ty/src/mir/lower.rs | 8 ++- crates/hir-ty/src/mir/monomorphization.rs | 4 +- crates/hir-ty/src/utils.rs | 63 +++++++++++-------- crates/hir/src/lib.rs | 2 +- .../rust-analyzer/src/cli/analysis_stats.rs | 4 +- 11 files changed, 82 insertions(+), 49 deletions(-) diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index 118055b605ec..acc60e1d9e4e 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -3,13 +3,15 @@ //! generic parameters. See also the `Generics` type and the `generics_of` query //! in rustc. +use std::ops; + use either::Either; use hir_expand::{ name::{AsName, Name}, ExpandResult, }; use intern::Interned; -use la_arena::{Arena, Idx}; +use la_arena::Arena; use once_cell::unsync::Lazy; use stdx::impl_from; use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds}; @@ -23,7 +25,7 @@ use crate::{ nameres::{DefMap, MacroSubNs}, type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef}, AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId, - LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, + LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, }; /// Data about a generic type parameter (to a function, struct, impl, ...). @@ -158,6 +160,20 @@ pub struct GenericParams { pub where_predicates: Box<[WherePredicate]>, } +impl ops::Index for GenericParams { + type Output = TypeOrConstParamData; + fn index(&self, index: LocalTypeOrConstParamId) -> &TypeOrConstParamData { + &self.type_or_consts[index] + } +} + +impl ops::Index for GenericParams { + type Output = LifetimeParamData; + fn index(&self, index: LocalLifetimeParamId) -> &LifetimeParamData { + &self.lifetimes[index] + } +} + /// A single predicate from a where clause, i.e. `where Type: Trait`. Combined /// where clauses like `where T: Foo + Bar` are turned into multiple of these. /// It might still result in multiple actual predicates though, because of @@ -199,7 +215,7 @@ impl GenericParamsCollector { lower_ctx: &LowerCtx<'_>, node: &dyn HasGenericParams, add_param_attrs: impl FnMut( - Either, Idx>, + Either, ast::GenericParam, ), ) { @@ -227,7 +243,7 @@ impl GenericParamsCollector { lower_ctx: &LowerCtx<'_>, params: ast::GenericParamList, mut add_param_attrs: impl FnMut( - Either, Idx>, + Either, ast::GenericParam, ), ) { @@ -416,16 +432,16 @@ impl GenericParams { } /// Iterator of type_or_consts field - pub fn iter( + pub fn iter_type_or_consts( &self, - ) -> impl DoubleEndedIterator, &TypeOrConstParamData)> { + ) -> impl DoubleEndedIterator { self.type_or_consts.iter() } /// Iterator of lifetimes field pub fn iter_lt( &self, - ) -> impl DoubleEndedIterator, &LifetimeParamData)> { + ) -> impl DoubleEndedIterator { self.lifetimes.iter() } diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs index eb5c2c55041d..f09277a92e66 100644 --- a/crates/hir-ty/src/consteval.rs +++ b/crates/hir-ty/src/consteval.rs @@ -90,7 +90,7 @@ pub(crate) fn path_to_const( } ParamLoweringMode::Variable => { let args = args(); - match args.as_ref().and_then(|args| args.param_idx(p.into())) { + match args.as_ref().and_then(|args| args.type_or_const_param_idx(p.into())) { Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), None => { never!( diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index eb7f106cdfaa..22a52e6a2331 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -453,7 +453,7 @@ impl HirDisplay for Const { ConstValue::Placeholder(idx) => { let id = from_placeholder_idx(f.db, *idx); let generics = generics(f.db.upcast(), id.parent); - let param_data = &generics.params.type_or_consts[id.local_id]; + let param_data = &generics.params[id.local_id]; write!(f, "{}", param_data.name().unwrap().display(f.db.upcast()))?; Ok(()) } @@ -1176,7 +1176,7 @@ impl HirDisplay for Ty { TyKind::Placeholder(idx) => { let id = from_placeholder_idx(db, *idx); let generics = generics(db.upcast(), id.parent); - let param_data = &generics.params.type_or_consts[id.local_id]; + let param_data = &generics.params[id.local_id]; match param_data { TypeOrConstParamData::TypeParamData(p) => match p.provenance { TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { @@ -1724,7 +1724,7 @@ impl HirDisplay for LifetimeData { LifetimeData::Placeholder(idx) => { let id = lt_from_placeholder_idx(f.db, *idx); let generics = generics(f.db.upcast(), id.parent); - let param_data = &generics.params.lifetimes[id.local_id]; + let param_data = &generics.params[id.local_id]; write!(f, "{}", param_data.name.display(f.db.upcast()))?; Ok(()) } diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index f08c0b687163..a25498eff333 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -357,7 +357,7 @@ impl CapturedItemWithoutTy { outer_binder: DebruijnIndex, ) -> Result, Self::Error> { let x = from_placeholder_idx(self.db, idx); - let Some(idx) = self.generics.param_idx(x) else { + let Some(idx) = self.generics.type_or_const_param_idx(x) else { return Err(()); }; Ok(BoundVar::new(outer_binder, idx).to_const(Interner, ty)) @@ -369,7 +369,7 @@ impl CapturedItemWithoutTy { outer_binder: DebruijnIndex, ) -> std::result::Result { let x = from_placeholder_idx(self.db, idx); - let Some(idx) = self.generics.param_idx(x) else { + let Some(idx) = self.generics.type_or_const_param_idx(x) else { return Err(()); }; Ok(BoundVar::new(outer_binder, idx).to_ty(Interner)) diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 14f1fd728dae..b12ccf7c837d 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -288,7 +288,7 @@ impl Hash for ConstScalar { /// Return an index of a parameter in the generic type parameter list by it's id. pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option { - generics(db.upcast(), id.parent).param_idx(id) + generics(db.upcast(), id.parent).type_or_const_param_idx(id) } pub(crate) fn wrap_empty_binders(value: T) -> Binders diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 08cb89d97488..bfc84ee5e304 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -578,7 +578,7 @@ impl<'a> TyLoweringContext<'a> { let idx = match self .generics() .expect("generics in scope") - .param_idx(param_id.into()) + .type_or_const_param_idx(param_id.into()) { None => { never!("no matching generics"); @@ -1026,7 +1026,7 @@ impl<'a> TyLoweringContext<'a> { } ParamLoweringMode::Variable => { let idx = generics(self.db.upcast(), def) - .param_idx(param_id) + .type_or_const_param_idx(param_id) .expect("matching generics"); TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx)) } @@ -1505,7 +1505,7 @@ fn named_associated_type_shorthand_candidates( // Handle `Self::Type` referring to own associated type in trait definitions if let GenericDefId::TraitId(trait_id) = param_id.parent() { let trait_generics = generics(db.upcast(), trait_id.into()); - if trait_generics.params.type_or_consts[param_id.local_id()].is_trait_self() { + if trait_generics.params[param_id.local_id()].is_trait_self() { let def_generics = generics(db.upcast(), def); let starting_idx = match def { GenericDefId::TraitId(_) => 0, diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index ea311cadb727..c65dfd32853c 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -495,9 +495,11 @@ impl<'ctx> MirLowerCtx<'ctx> { ty, value: chalk_ir::ConstValue::BoundVar(BoundVar::new( DebruijnIndex::INNERMOST, - gen.param_idx(p.into()).ok_or(MirLowerError::TypeError( - "fail to lower const generic param", - ))?, + gen.type_or_const_param_idx(p.into()).ok_or( + MirLowerError::TypeError( + "fail to lower const generic param", + ), + )?, )), } .intern(Interner), diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs index d6557c3a8160..a384c9306eee 100644 --- a/crates/hir-ty/src/mir/monomorphization.rs +++ b/crates/hir-ty/src/mir/monomorphization.rs @@ -101,7 +101,7 @@ impl FallibleTypeFolder for Filler<'_> { _outer_binder: DebruijnIndex, ) -> std::result::Result, Self::Error> { let it = from_placeholder_idx(self.db, idx); - let Some(idx) = self.generics.as_ref().and_then(|g| g.param_idx(it)) else { + let Some(idx) = self.generics.as_ref().and_then(|g| g.type_or_const_param_idx(it)) else { not_supported!("missing idx in generics"); }; Ok(self @@ -119,7 +119,7 @@ impl FallibleTypeFolder for Filler<'_> { _outer_binder: DebruijnIndex, ) -> std::result::Result { let it = from_placeholder_idx(self.db, idx); - let Some(idx) = self.generics.as_ref().and_then(|g| g.param_idx(it)) else { + let Some(idx) = self.generics.as_ref().and_then(|g| g.type_or_const_param_idx(it)) else { not_supported!("missing idx in generics"); }; Ok(self diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 77c5fd054d1c..42c7a8403283 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -308,7 +308,11 @@ impl Generics { }; let lt_iter = self.params.iter_lt().map(from_lt_id(self)); - self.params.iter().map(from_toc_id(self)).chain(lt_iter).chain(self.iter_parent()) + self.params + .iter_type_or_consts() + .map(from_toc_id(self)) + .chain(lt_iter) + .chain(self.iter_parent()) } /// Iterate over types and const params without parent params. @@ -340,16 +344,19 @@ impl Generics { } }; - self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self))) + self.params + .iter_type_or_consts() + .map(from_toc_id(self)) + .chain(self.params.iter_lt().map(from_lt_id(self))) } /// Iterator over types and const params of parent. - #[allow(clippy::needless_lifetimes)] - pub(crate) fn iter_parent<'a>( - &'a self, - ) -> impl DoubleEndedIterator)> + 'a { + pub(crate) fn iter_parent( + &self, + ) -> impl DoubleEndedIterator)> + '_ { self.parent_generics().into_iter().flat_map(|it| { - let from_toc_id = move |(local_id, p): (_, &'a TypeOrConstParamData)| { + let from_toc_id = move |(local_id, p)| { + let p: &_ = p; let id = TypeOrConstParamId { parent: it.def, local_id }; match p { TypeOrConstParamData::TypeParamData(p) => ( @@ -363,14 +370,14 @@ impl Generics { } }; - let from_lt_id = move |(local_id, p): (_, &'a LifetimeParamData)| { + let from_lt_id = move |(local_id, p): (_, _)| { ( GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }), GenericParamDataRef::LifetimeParamData(p), ) }; let lt_iter = it.params.iter_lt().map(from_lt_id); - it.params.iter().map(from_toc_id).chain(lt_iter) + it.params.iter_type_or_consts().map(from_toc_id).chain(lt_iter) }) } @@ -387,7 +394,7 @@ impl Generics { } /// Returns number of generic parameter excluding those from parent - fn len_params(&self) -> usize { + fn len_type_and_const_params(&self) -> usize { self.params.type_or_consts.len() } @@ -398,7 +405,7 @@ impl Generics { let mut impl_trait_params = 0; let mut const_params = 0; let mut lifetime_params = 0; - self.params.iter().for_each(|(_, data)| match data { + self.params.iter_type_or_consts().for_each(|(_, data)| match data { TypeOrConstParamData::TypeParamData(p) => match p.provenance { TypeParamProvenance::TypeParamList => type_params += 1, TypeParamProvenance::TraitSelf => self_params += 1, @@ -413,18 +420,23 @@ impl Generics { (parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params) } - pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option { - Some(self.find_param(param)?.0) + pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option { + Some(self.find_type_or_const_param(param)?.0) } - fn find_param(&self, param: TypeOrConstParamId) -> Option<(usize, &TypeOrConstParamData)> { + fn find_type_or_const_param( + &self, + param: TypeOrConstParamId, + ) -> Option<(usize, &TypeOrConstParamData)> { if param.parent == self.def { - let (idx, (_local_id, data)) = - self.params.iter().enumerate().find(|(_, (idx, _))| *idx == param.local_id)?; - Some((idx, data)) + let idx = param.local_id.into_raw().into_u32() as usize; + if idx >= self.params.type_or_consts.len() { + return None; + } + Some((idx, &self.params.type_or_consts[param.local_id])) } else { self.parent_generics() - .and_then(|g| g.find_param(param)) + .and_then(|g| g.find_type_or_const_param(param)) // Remember that parent parameters come after parameters for self. .map(|(idx, data)| (self.len_self() + idx, data)) } @@ -436,13 +448,14 @@ impl Generics { fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> { if lifetime.parent == self.def { - let (idx, (_local_id, data)) = self - .params - .iter_lt() - .enumerate() - .find(|(_, (idx, _))| *idx == lifetime.local_id)?; - - Some((self.len_params() + idx, data)) + let idx = lifetime.local_id.into_raw().into_u32() as usize; + if idx >= self.params.lifetimes.len() { + return None; + } + Some(( + self.len_type_and_const_params() + idx, + &self.params.lifetimes[lifetime.local_id], + )) } else { self.parent_generics() .and_then(|g| g.find_lifetime(lifetime)) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c4e051bff5e7..8556d35a43b3 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -653,7 +653,7 @@ impl Module { GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id }) }); let type_params = generic_params - .iter() + .iter_type_or_consts() .filter(|(_, it)| it.type_param().is_some()) .map(|(local_id, _)| { GenericParamId::TypeParamId(TypeParamId::from_unchecked( diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index fdd77199aa00..a1eea8839ebf 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -280,7 +280,9 @@ impl flags::AnalysisStats { let mut fail = 0; for &a in adts { let generic_params = db.generic_params(a.into()); - if generic_params.iter().next().is_some() || generic_params.iter_lt().next().is_some() { + if generic_params.iter_type_or_consts().next().is_some() + || generic_params.iter_lt().next().is_some() + { // Data types with generics don't have layout. continue; }