Lazy generics

This commit is contained in:
Lukas Wirth 2024-06-21 18:38:37 +02:00
parent c01f4cf902
commit 7a16e06009
4 changed files with 26 additions and 11 deletions

View file

@ -71,12 +71,12 @@ impl From<MirEvalError> for ConstEvalError {
} }
} }
pub(crate) fn path_to_const( pub(crate) fn path_to_const<'g>(
db: &dyn HirDatabase, db: &dyn HirDatabase,
resolver: &Resolver, resolver: &Resolver,
path: &Path, path: &Path,
mode: ParamLoweringMode, mode: ParamLoweringMode,
args: impl FnOnce() -> Option<Generics>, args: impl FnOnce() -> Option<&'g Generics>,
debruijn: DebruijnIndex, debruijn: DebruijnIndex,
expected_ty: Ty, expected_ty: Ty,
) -> Option<Const> { ) -> Option<Const> {
@ -89,7 +89,7 @@ pub(crate) fn path_to_const(
} }
ParamLoweringMode::Variable => { ParamLoweringMode::Variable => {
let args = args(); let args = args();
match args.as_ref().and_then(|args| args.type_or_const_param_idx(p.into())) { match args.and_then(|args| args.type_or_const_param_idx(p.into())) {
Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
None => { None => {
never!( never!(

View file

@ -49,6 +49,7 @@ use hir_def::{
use hir_expand::name::{name, Name}; use hir_expand::name::{name, Name};
use indexmap::IndexSet; use indexmap::IndexSet;
use la_arena::{ArenaMap, Entry}; use la_arena::{ArenaMap, Entry};
use once_cell::unsync::OnceCell;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use stdx::{always, never}; use stdx::{always, never};
use triomphe::Arc; use triomphe::Arc;
@ -527,6 +528,7 @@ pub(crate) struct InferenceContext<'a> {
pub(crate) owner: DefWithBodyId, pub(crate) owner: DefWithBodyId,
pub(crate) body: &'a Body, pub(crate) body: &'a Body,
pub(crate) resolver: Resolver, pub(crate) resolver: Resolver,
generics: OnceCell<Option<Generics>>,
table: unify::InferenceTable<'a>, table: unify::InferenceTable<'a>,
/// The traits in scope, disregarding block modules. This is used for caching purposes. /// The traits in scope, disregarding block modules. This is used for caching purposes.
traits_in_scope: FxHashSet<TraitId>, traits_in_scope: FxHashSet<TraitId>,
@ -612,6 +614,7 @@ impl<'a> InferenceContext<'a> {
) -> Self { ) -> Self {
let trait_env = db.trait_environment_for_body(owner); let trait_env = db.trait_environment_for_body(owner);
InferenceContext { InferenceContext {
generics: OnceCell::new(),
result: InferenceResult::default(), result: InferenceResult::default(),
table: unify::InferenceTable::new(db, trait_env), table: unify::InferenceTable::new(db, trait_env),
tuple_field_accesses_rev: Default::default(), tuple_field_accesses_rev: Default::default(),
@ -633,8 +636,14 @@ impl<'a> InferenceContext<'a> {
} }
} }
pub(crate) fn generics(&self) -> Option<Generics> { pub(crate) fn generics(&self) -> Option<&Generics> {
Some(crate::generics::generics(self.db.upcast(), self.resolver.generic_def()?)) self.generics
.get_or_init(|| {
self.resolver
.generic_def()
.map(|def| crate::generics::generics(self.db.upcast(), def))
})
.as_ref()
} }
// FIXME: This function should be private in module. It is currently only used in the consteval, since we need // FIXME: This function should be private in module. It is currently only used in the consteval, since we need

View file

@ -339,7 +339,7 @@ impl CapturedItemWithoutTy {
fn replace_placeholder_with_binder(ctx: &mut InferenceContext<'_>, ty: Ty) -> Binders<Ty> { fn replace_placeholder_with_binder(ctx: &mut InferenceContext<'_>, ty: Ty) -> Binders<Ty> {
struct Filler<'a> { struct Filler<'a> {
db: &'a dyn HirDatabase, db: &'a dyn HirDatabase,
generics: Generics, generics: &'a Generics,
} }
impl FallibleTypeFolder<Interner> for Filler<'_> { impl FallibleTypeFolder<Interner> for Filler<'_> {
type Error = (); type Error = ();
@ -382,7 +382,7 @@ impl CapturedItemWithoutTy {
}; };
let filler = &mut Filler { db: ctx.db, generics }; let filler = &mut Filler { db: ctx.db, generics };
let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty); let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty);
make_binders(ctx.db, &filler.generics, result) make_binders(ctx.db, filler.generics, result)
} }
} }
} }

View file

@ -45,6 +45,7 @@ use hir_def::{
use hir_expand::{name::Name, ExpandResult}; use hir_expand::{name::Name, ExpandResult};
use intern::Interned; use intern::Interned;
use la_arena::{Arena, ArenaMap}; use la_arena::{Arena, ArenaMap};
use once_cell::unsync::OnceCell;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use smallvec::SmallVec; use smallvec::SmallVec;
use stdx::{impl_from, never}; use stdx::{impl_from, never};
@ -122,6 +123,7 @@ impl ImplTraitLoweringState {
pub struct TyLoweringContext<'a> { pub struct TyLoweringContext<'a> {
pub db: &'a dyn HirDatabase, pub db: &'a dyn HirDatabase,
resolver: &'a Resolver, resolver: &'a Resolver,
generics: OnceCell<Option<Generics>>,
in_binders: DebruijnIndex, in_binders: DebruijnIndex,
// FIXME: Should not be an `Option` but `Resolver` currently does not return owners in all cases // FIXME: Should not be an `Option` but `Resolver` currently does not return owners in all cases
// where expected // where expected
@ -153,6 +155,7 @@ impl<'a> TyLoweringContext<'a> {
Self { Self {
db, db,
resolver, resolver,
generics: OnceCell::new(),
owner, owner,
in_binders, in_binders,
impl_trait_mode, impl_trait_mode,
@ -175,6 +178,7 @@ impl<'a> TyLoweringContext<'a> {
impl_trait_mode, impl_trait_mode,
expander: RefCell::new(expander), expander: RefCell::new(expander),
unsized_types: RefCell::new(unsized_types), unsized_types: RefCell::new(unsized_types),
generics: self.generics.clone(),
..*self ..*self
}; };
let result = f(&new_ctx); let result = f(&new_ctx);
@ -246,8 +250,10 @@ impl<'a> TyLoweringContext<'a> {
) )
} }
fn generics(&self) -> Option<Generics> { fn generics(&self) -> Option<&Generics> {
Some(generics(self.db.upcast(), self.resolver.generic_def()?)) self.generics
.get_or_init(|| self.resolver.generic_def().map(|def| generics(self.db.upcast(), def)))
.as_ref()
} }
pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) { pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
@ -2207,14 +2213,14 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
} }
} }
pub(crate) fn const_or_path_to_chalk( pub(crate) fn const_or_path_to_chalk<'g>(
db: &dyn HirDatabase, db: &dyn HirDatabase,
resolver: &Resolver, resolver: &Resolver,
owner: TypeOwnerId, owner: TypeOwnerId,
expected_ty: Ty, expected_ty: Ty,
value: &ConstRef, value: &ConstRef,
mode: ParamLoweringMode, mode: ParamLoweringMode,
args: impl FnOnce() -> Option<Generics>, args: impl FnOnce() -> Option<&'g Generics>,
debruijn: DebruijnIndex, debruijn: DebruijnIndex,
) -> Const { ) -> Const {
match value { match value {