Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #17474 - Veykril:ty-perf-stuff, r=Veykril
internal: Remove some allocations from hir-ty
| -rw-r--r-- | crates/hir-ty/src/chalk_db.rs | 1 | ||||
| -rw-r--r-- | crates/hir-ty/src/db.rs | 11 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 8 | ||||
| -rw-r--r-- | crates/hir-ty/src/lib.rs | 26 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 204 |
5 files changed, 140 insertions, 110 deletions
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 0d8ceb68b2..debae1fe12 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -604,7 +604,6 @@ pub(crate) fn associated_ty_data_query( // Lower bounds -- we could/should maybe move this to a separate query in `lower` let type_alias_data = db.type_alias_data(type_alias); let generic_params = generics(db.upcast(), type_alias.into()); - // let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); let ctx = crate::TyLoweringContext::new(db, &resolver, type_alias.into()) .with_type_param_mode(crate::lower::ParamLoweringMode::Variable); diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs index 000871ed52..e951048021 100644 --- a/crates/hir-ty/src/db.rs +++ b/crates/hir-ty/src/db.rs @@ -21,11 +21,12 @@ use crate::{ chalk_db, consteval::ConstEvalError, layout::{Layout, LayoutError}, + lower::{GenericDefaults, GenericPredicates}, method_resolution::{InherentImpls, TraitImpls, TyFingerprint}, mir::{BorrowckResult, MirBody, MirLowerError}, - Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, ImplTraits, - InferenceResult, Interner, PolyFnSig, QuantifiedWhereClause, Substitution, TraitEnvironment, - TraitRef, Ty, TyDefId, ValueTyDefId, + Binders, CallableDefId, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, + Interner, PolyFnSig, QuantifiedWhereClause, Substitution, TraitEnvironment, TraitRef, Ty, + TyDefId, ValueTyDefId, }; use hir_expand::name::Name; @@ -147,7 +148,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { ) -> Arc<[Binders<QuantifiedWhereClause>]>; #[salsa::invoke(crate::lower::generic_predicates_query)] - fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<QuantifiedWhereClause>]>; + fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates; #[salsa::invoke(crate::lower::trait_environment_for_body_query)] #[salsa::transparent] @@ -158,7 +159,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { #[salsa::invoke(crate::lower::generic_defaults_query)] #[salsa::cycle(crate::lower::generic_defaults_recover)] - fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<GenericArg>]>; + fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults; #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>; diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index aeb6e69ce7..96431ba4ce 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -64,8 +64,8 @@ use crate::{ traits::FnTrait, utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder}, AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId, - ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution, - TraitEnvironment, Ty, TyBuilder, TyExt, + ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ParamLoweringMode, ProjectionTy, + Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, }; // This lint has a false positive here. See the link below for details. @@ -791,7 +791,8 @@ impl<'a> InferenceContext<'a> { fn collect_fn(&mut self, func: FunctionId) { let data = self.db.function_data(func); - let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, func.into()) + let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into()) + .with_type_param_mode(ParamLoweringMode::Placeholder) .with_impl_trait_mode(ImplTraitLoweringMode::Param); let mut param_tys = data.params.iter().map(|type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>(); @@ -826,6 +827,7 @@ impl<'a> InferenceContext<'a> { let return_ty = &*data.ret_type; let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into()) + .with_type_param_mode(ParamLoweringMode::Placeholder) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); let return_ty = ctx.lower_ty(return_ty); let return_ty = self.insert_type_vars(return_ty); diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 685aceb233..5e33e1285e 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -330,18 +330,15 @@ pub(crate) fn make_single_type_binders<T: HasInterner<Interner = Interner>>( ) } -pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>( +pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>( db: &dyn HirDatabase, - count: usize, generics: &Generics, value: T, ) -> Binders<T> { - let it = generics.iter_id().take(count); - Binders::new( VariableKinds::from_iter( Interner, - it.map(|x| match x { + generics.iter_id().map(|x| match x { hir_def::GenericParamId::ConstParamId(id) => { chalk_ir::VariableKind::Const(db.const_param_ty(id)) } @@ -355,14 +352,6 @@ pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>( ) } -pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>( - db: &dyn HirDatabase, - generics: &Generics, - value: T, -) -> Binders<T> { - make_binders_with_count(db, usize::MAX, generics, value) -} - // FIXME: get rid of this, just replace it by FnPointer /// A function signature as seen by type inference: Several parameter types and /// one return type. @@ -524,14 +513,16 @@ pub type PolyFnSig = Binders<CallableSig>; impl CallableSig { pub fn from_params_and_return( - mut params: Vec<Ty>, + params: impl ExactSizeIterator<Item = Ty>, ret: Ty, is_varargs: bool, safety: Safety, abi: FnAbi, ) -> CallableSig { - params.push(ret); - CallableSig { params_and_return: params.into(), is_varargs, safety, abi } + let mut params_and_return = Vec::with_capacity(params.len() + 1); + params_and_return.extend(params); + params_and_return.push(ret); + CallableSig { params_and_return: params_and_return.into(), is_varargs, safety, abi } } pub fn from_def(db: &dyn HirDatabase, def: FnDefId, substs: &Substitution) -> CallableSig { @@ -946,8 +937,7 @@ pub fn callable_sig_from_fn_trait( .as_tuple()? .iter(Interner) .map(|it| it.assert_ty_ref(Interner)) - .cloned() - .collect(); + .cloned(); return Some(( fn_x, diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 30d6b2f664..96f545415e 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -8,6 +8,7 @@ use std::{ cell::{Cell, RefCell, RefMut}, iter, + ops::{self, Not as _}, }; use base_db::{ @@ -47,6 +48,7 @@ use intern::Interned; use la_arena::{Arena, ArenaMap}; use once_cell::unsync::OnceCell; use rustc_hash::FxHashSet; +use rustc_pattern_analysis::Captures; use smallvec::SmallVec; use stdx::{impl_from, never}; use syntax::ast; @@ -1594,14 +1596,20 @@ pub(crate) fn generic_predicates_for_param_query( .collect(); let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); - let explicitly_unsized_tys = ctx.unsized_types.into_inner(); - if let Some(implicitly_sized_predicates) = - implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &subst, &resolver) - { - predicates.extend( - implicitly_sized_predicates - .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))), - ); + if !subst.is_empty(Interner) { + let explicitly_unsized_tys = ctx.unsized_types.into_inner(); + if let Some(implicitly_sized_predicates) = implicitly_sized_clauses( + db, + param_id.parent, + &explicitly_unsized_tys, + &subst, + &resolver, + ) { + predicates.extend( + implicitly_sized_predicates + .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))), + ); + }; } predicates.into() } @@ -1664,14 +1672,17 @@ pub(crate) fn trait_environment_query( } let subst = generics(db.upcast(), def).placeholder_subst(db); - let explicitly_unsized_tys = ctx.unsized_types.into_inner(); - if let Some(implicitly_sized_clauses) = - implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver) - { - clauses.extend( - implicitly_sized_clauses - .map(|pred| pred.cast::<ProgramClause>(Interner).into_from_env_clause(Interner)), - ); + if !subst.is_empty(Interner) { + let explicitly_unsized_tys = ctx.unsized_types.into_inner(); + if let Some(implicitly_sized_clauses) = + implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver) + { + clauses.extend( + implicitly_sized_clauses.map(|pred| { + pred.cast::<ProgramClause>(Interner).into_from_env_clause(Interner) + }), + ); + }; } let env = chalk_ir::Environment::new(Interner).add_clauses(Interner, clauses); @@ -1679,20 +1690,32 @@ pub(crate) fn trait_environment_query( TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env) } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GenericPredicates(Option<Arc<[Binders<QuantifiedWhereClause>]>>); + +impl ops::Deref for GenericPredicates { + type Target = [Binders<crate::QuantifiedWhereClause>]; + + fn deref(&self) -> &Self::Target { + self.0.as_deref().unwrap_or(&[]) + } +} + /// Resolve the where clause(s) of an item with generics. pub(crate) fn generic_predicates_query( db: &dyn HirDatabase, def: GenericDefId, -) -> Arc<[Binders<QuantifiedWhereClause>]> { +) -> GenericPredicates { let resolver = def.resolver(db.upcast()); - let ctx = if let GenericDefId::FunctionId(_) = def { - TyLoweringContext::new(db, &resolver, def.into()) - .with_impl_trait_mode(ImplTraitLoweringMode::Variable) - .with_type_param_mode(ParamLoweringMode::Variable) - } else { - TyLoweringContext::new(db, &resolver, def.into()) - .with_type_param_mode(ParamLoweringMode::Variable) + let (impl_trait_lowering, param_lowering) = match def { + GenericDefId::FunctionId(_) => { + (ImplTraitLoweringMode::Variable, ParamLoweringMode::Variable) + } + _ => (ImplTraitLoweringMode::Disallowed, ParamLoweringMode::Variable), }; + let ctx = TyLoweringContext::new(db, &resolver, def.into()) + .with_impl_trait_mode(impl_trait_lowering) + .with_type_param_mode(param_lowering); let generics = generics(db.upcast(), def); let mut predicates = resolver @@ -1703,27 +1726,29 @@ pub(crate) fn generic_predicates_query( .collect::<Vec<_>>(); let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); - let explicitly_unsized_tys = ctx.unsized_types.into_inner(); - if let Some(implicitly_sized_predicates) = - implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver) - { - predicates.extend( - implicitly_sized_predicates - .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))), - ); + if !subst.is_empty(Interner) { + let explicitly_unsized_tys = ctx.unsized_types.into_inner(); + if let Some(implicitly_sized_predicates) = + implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver) + { + predicates.extend( + implicitly_sized_predicates + .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))), + ); + }; } - predicates.into() + GenericPredicates(predicates.is_empty().not().then(|| predicates.into())) } /// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound. /// Exception is Self of a trait def. -fn implicitly_sized_clauses<'a>( +fn implicitly_sized_clauses<'a, 'subst: 'a>( db: &dyn HirDatabase, def: GenericDefId, explicitly_unsized_tys: &'a FxHashSet<Ty>, - substitution: &'a Substitution, + substitution: &'subst Substitution, resolver: &Resolver, -) -> Option<impl Iterator<Item = WhereClause> + 'a> { +) -> Option<impl Iterator<Item = WhereClause> + Captures<'a> + Captures<'subst>> { let is_trait_def = matches!(def, GenericDefId::TraitId(..)); let generic_args = &substitution.as_slice(Interner)[is_trait_def as usize..]; let sized_trait = db @@ -1744,71 +1769,84 @@ fn implicitly_sized_clauses<'a>( }) } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GenericDefaults(Option<Arc<[Binders<crate::GenericArg>]>>); + +impl ops::Deref for GenericDefaults { + type Target = [Binders<crate::GenericArg>]; + + fn deref(&self) -> &Self::Target { + self.0.as_deref().unwrap_or(&[]) + } +} + /// Resolve the default type params from generics -pub(crate) fn generic_defaults_query( - db: &dyn HirDatabase, - def: GenericDefId, -) -> Arc<[Binders<crate::GenericArg>]> { - let resolver = def.resolver(db.upcast()); - let ctx = TyLoweringContext::new(db, &resolver, def.into()) - .with_type_param_mode(ParamLoweringMode::Variable); +pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults { let generic_params = generics(db.upcast(), def); + if generic_params.len() == 0 { + return GenericDefaults(None); + } + let resolver = def.resolver(db.upcast()); let parent_start_idx = generic_params.len_self(); - let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| { - match p { - GenericParamDataRef::TypeParamData(p) => { - let mut ty = - p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t)); - // Each default can only refer to previous parameters. - // Type variable default referring to parameter coming - // after it is forbidden (FIXME: report diagnostic) - ty = fallback_bound_vars(ty, idx, parent_start_idx); - crate::make_binders(db, &generic_params, ty.cast(Interner)) - } - GenericParamDataRef::ConstParamData(p) => { - let GenericParamId::ConstParamId(id) = id else { - unreachable!("Unexpected lifetime or type argument") - }; + let ctx = TyLoweringContext::new(db, &resolver, def.into()) + .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed) + .with_type_param_mode(ParamLoweringMode::Variable); + GenericDefaults(Some(Arc::from_iter(generic_params.iter().enumerate().map( + |(idx, (id, p))| { + match p { + GenericParamDataRef::TypeParamData(p) => { + let ty = p.default.as_ref().map_or(TyKind::Error.intern(Interner), |ty| { + // Each default can only refer to previous parameters. + // Type variable default referring to parameter coming + // after it is forbidden (FIXME: report diagnostic) + fallback_bound_vars(ctx.lower_ty(ty), idx, parent_start_idx) + }); + crate::make_binders(db, &generic_params, ty.cast(Interner)) + } + GenericParamDataRef::ConstParamData(p) => { + let GenericParamId::ConstParamId(id) = id else { + unreachable!("Unexpected lifetime or type argument") + }; - let mut val = p.default.as_ref().map_or_else( - || unknown_const_as_generic(db.const_param_ty(id)), - |c| { - let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); - c.cast(Interner) - }, - ); - // Each default can only refer to previous parameters, see above. - val = fallback_bound_vars(val, idx, parent_start_idx); - make_binders(db, &generic_params, val) - } - GenericParamDataRef::LifetimeParamData(_) => { - make_binders(db, &generic_params, error_lifetime().cast(Interner)) + let mut val = p.default.as_ref().map_or_else( + || unknown_const_as_generic(db.const_param_ty(id)), + |c| { + let c = ctx.lower_const(c, ctx.lower_ty(&p.ty)); + c.cast(Interner) + }, + ); + // Each default can only refer to previous parameters, see above. + val = fallback_bound_vars(val, idx, parent_start_idx); + make_binders(db, &generic_params, val) + } + GenericParamDataRef::LifetimeParamData(_) => { + make_binders(db, &generic_params, error_lifetime().cast(Interner)) + } } - } - })); - - defaults + }, + )))) } pub(crate) fn generic_defaults_recover( db: &dyn HirDatabase, _cycle: &Cycle, def: &GenericDefId, -) -> Arc<[Binders<crate::GenericArg>]> { +) -> GenericDefaults { let generic_params = generics(db.upcast(), *def); + if generic_params.len() == 0 { + return GenericDefaults(None); + } // FIXME: this code is not covered in tests. // we still need one default per parameter - let defaults = Arc::from_iter(generic_params.iter_id().map(|id| { + GenericDefaults(Some(Arc::from_iter(generic_params.iter_id().map(|id| { let val = match id { GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner), GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)), GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), }; crate::make_binders(db, &generic_params, val) - })); - - defaults + })))) } fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { @@ -1817,7 +1855,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { let ctx_params = TyLoweringContext::new(db, &resolver, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Variable) .with_type_param_mode(ParamLoweringMode::Variable); - let params = data.params.iter().map(|tr| ctx_params.lower_ty(tr)).collect::<Vec<_>>(); + let params = data.params.iter().map(|tr| ctx_params.lower_ty(tr)); let ctx_ret = TyLoweringContext::new(db, &resolver, def.into()) .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) .with_type_param_mode(ParamLoweringMode::Variable); @@ -1871,7 +1909,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS let resolver = def.resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver, AdtId::from(def).into()) .with_type_param_mode(ParamLoweringMode::Variable); - let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>(); + let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)); let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders(); Binders::new( binders, @@ -1903,7 +1941,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) let resolver = def.resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into()) .with_type_param_mode(ParamLoweringMode::Variable); - let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>(); + let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)); let (ret, binders) = type_for_adt(db, def.lookup(db.upcast()).parent.into()).into_value_and_skipped_binders(); Binders::new( |