Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower.rs')
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 211 |
1 files changed, 79 insertions, 132 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index bdb882b70b..098a43a876 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -10,7 +10,6 @@ pub(crate) mod path; use std::{cell::OnceCell, iter, mem, sync::OnceLock}; -use base_db::salsa::update_fallback_db; use either::Either; use hir_def::{ AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, EnumId, EnumVariantId, @@ -80,13 +79,14 @@ use crate::{ pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId); #[derive(PartialEq, Eq, Debug, Hash)] -pub struct ImplTraits { - pub(crate) impl_traits: Arena<ImplTrait>, +pub struct WithDefinedOpaques<T> { + value: T, + impl_traits: Option<Box<Arena<ImplTrait>>>, } #[derive(PartialEq, Eq, Debug, Hash)] pub struct ImplTrait { - pub(crate) predicates: StoredClauses, + pub(crate) predicates: StoredEarlyBinder<StoredClauses>, pub(crate) assoc_ty_bounds_start: u32, } @@ -417,6 +417,15 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { BoundVarKinds::new_from_iter(interner, args) } + + fn take_defined_opaques(&mut self) -> Option<Box<Arena<ImplTrait>>> { + if self.impl_trait_mode.opaque_type_data.is_empty() { + None + } else { + self.impl_trait_mode.opaque_type_data.shrink_to_fit(); + Some(Box::new(mem::take(&mut self.impl_trait_mode.opaque_type_data))) + } + } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] @@ -631,7 +640,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { // place even if we encounter more opaque types while // lowering the bounds let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait { - predicates: Clauses::empty(interner).store(), + predicates: StoredEarlyBinder::bind(Clauses::empty(interner).store()), assoc_ty_bounds_start: 0, }); @@ -1319,7 +1328,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { self.is_lowering_impl_trait_bounds = prev_is_lowering_impl_trait_bounds; ImplTrait { - predicates: Clauses::new_from_slice(&predicates).store(), + predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&predicates).store()), assoc_ty_bounds_start, } } @@ -1365,7 +1374,6 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { pub struct TyLoweringResult<'db, T> { #[update(fallback)] pub value: T, - #[update(bounds(TyLoweringResultInfo<'db>: Update), unsafe(with(update_fallback_db::<'db, _>)))] info: Option<Box<TyLoweringResultInfo<'db>>>, } @@ -1497,19 +1505,21 @@ pub(crate) fn impl_trait_with_diagnostics_cycle_result<'db>( impl ImplTraitId { #[inline] - pub fn predicates<'db>(self, db: &'db dyn HirDatabase) -> EarlyBinder<'db, &'db [Clause<'db>]> { + fn data(self, db: &dyn HirDatabase) -> &ImplTrait { let (impl_traits, idx) = match self { ImplTraitId::ReturnTypeImplTrait(owner, idx) => { - (ImplTraits::return_type_impl_traits(db, owner), idx) + (ImplTrait::return_type_impl_traits(db, owner), idx) } ImplTraitId::TypeAliasImplTrait(owner, idx) => { - (ImplTraits::type_alias_impl_traits(db, owner), idx) + (ImplTrait::type_alias_impl_traits(db, owner), idx) } }; - impl_traits - .as_deref() - .expect("owner should have opaque type") - .get_with(|it| it.impl_traits[idx].predicates.as_ref().as_slice()) + &impl_traits[idx] + } + + #[inline] + pub fn predicates<'db>(self, db: &'db dyn HirDatabase) -> EarlyBinder<'db, &'db [Clause<'db>]> { + self.data(db).predicates.get().map_bound(|it| it.as_slice()) } #[inline] @@ -1517,24 +1527,8 @@ impl ImplTraitId { self, db: &'db dyn HirDatabase, ) -> EarlyBinder<'db, &'db [Clause<'db>]> { - let (impl_traits, idx) = match self { - ImplTraitId::ReturnTypeImplTrait(owner, idx) => { - (ImplTraits::return_type_impl_traits(db, owner), idx) - } - ImplTraitId::TypeAliasImplTrait(owner, idx) => { - (ImplTraits::type_alias_impl_traits(db, owner), idx) - } - }; - let predicates = - impl_traits.as_deref().expect("owner should have opaque type").get_with(|it| { - let impl_trait = &it.impl_traits[idx]; - ( - impl_trait.predicates.as_ref().as_slice(), - impl_trait.assoc_ty_bounds_start as usize, - ) - }); - - predicates.map_bound(|(preds, len)| &preds[..len]) + let data = self.data(db); + data.predicates.get().map_bound(|it| &it.as_slice()[..data.assoc_ty_bounds_start as usize]) } } @@ -1553,71 +1547,25 @@ impl InternedOpaqueTyId<'_> { } } -#[salsa::tracked] -impl ImplTraits { - #[salsa::tracked(returns(ref))] +impl ImplTrait { + #[inline] pub(crate) fn return_type_impl_traits( db: &dyn HirDatabase, - def: hir_def::FunctionId, - ) -> Option<Box<StoredEarlyBinder<ImplTraits>>> { - // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe - let data = FunctionSignature::of(db, def); - let resolver = def.resolver(db); - let generics = OnceCell::new(); - let mut ctx_ret = TyLoweringContext::new( - db, - &resolver, - &data.store, - ExpressionStoreOwnerId::Signature(def.into()), - def.into(), - &generics, - LifetimeElisionKind::Infer, - LifetimeLoweringMode::Bound, - ) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); - if let Some(ret_type) = data.ret_type { - let _ret = ctx_ret.lower_ty(ret_type); - } - let mut return_type_impl_traits = - ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data }; - if return_type_impl_traits.impl_traits.is_empty() { - None - } else { - return_type_impl_traits.impl_traits.shrink_to_fit(); - Some(Box::new(StoredEarlyBinder::bind(return_type_impl_traits))) - } + def: FunctionId, + ) -> &Arena<ImplTrait> { + fn_sig_for_fn(db, def).value.impl_traits.as_deref().unwrap_or(const { &Arena::new() }) } - #[salsa::tracked(returns(ref))] + #[inline] pub(crate) fn type_alias_impl_traits( db: &dyn HirDatabase, - def: hir_def::TypeAliasId, - ) -> Option<Box<StoredEarlyBinder<ImplTraits>>> { - let data = TypeAliasSignature::of(db, def); - let resolver = def.resolver(db); - let generics = OnceCell::new(); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &data.store, - ExpressionStoreOwnerId::Signature(def.into()), - def.into(), - &generics, - LifetimeElisionKind::AnonymousReportError, - LifetimeLoweringMode::Bound, - ) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); - if let Some(type_ref) = data.ty { - let _ty = ctx.lower_ty(type_ref); - } - let mut type_alias_impl_traits = - ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data }; - if type_alias_impl_traits.impl_traits.is_empty() { - None - } else { - type_alias_impl_traits.impl_traits.shrink_to_fit(); - Some(Box::new(StoredEarlyBinder::bind(type_alias_impl_traits))) - } + def: TypeAliasId, + ) -> &Arena<ImplTrait> { + type_for_type_alias_with_diagnostics(db, def) + .value + .impl_traits + .as_deref() + .unwrap_or(const { &Arena::new() }) } } @@ -1666,7 +1614,7 @@ pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBind it, GenericArgs::identity_for_item(interner, it.into()), )), - TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).value.get(), + TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).value.value.get(), } } @@ -1804,13 +1752,14 @@ pub(crate) fn value_ty<'db>( pub(crate) fn type_for_type_alias_with_diagnostics<'db>( db: &'db dyn HirDatabase, t: TypeAliasId, -) -> TyLoweringResult<'db, StoredEarlyBinder<StoredTy>> { +) -> TyLoweringResult<'db, WithDefinedOpaques<StoredEarlyBinder<StoredTy>>> { let type_alias_data = TypeAliasSignature::of(db, t); let interner = DbInterner::new_no_crate(db); if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) { - TyLoweringResult::empty(StoredEarlyBinder::bind( - Ty::new_foreign(interner, t.into()).store(), - )) + TyLoweringResult::empty(WithDefinedOpaques { + value: StoredEarlyBinder::bind(Ty::new_foreign(interner, t.into()).store()), + impl_traits: None, + }) } else { let resolver = t.resolver(db); let generics = OnceCell::new(); @@ -1832,7 +1781,10 @@ pub(crate) fn type_for_type_alias_with_diagnostics<'db>( .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)) .store(), ); - TyLoweringResult::from_ctx(res, ctx) + TyLoweringResult::from_ctx( + WithDefinedOpaques { value: res, impl_traits: ctx.take_defined_opaques() }, + ctx, + ) } } @@ -1840,10 +1792,13 @@ pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>( db: &'db dyn HirDatabase, _: salsa::Id, _adt: TypeAliasId, -) -> TyLoweringResult<'db, StoredEarlyBinder<StoredTy>> { - TyLoweringResult::empty(StoredEarlyBinder::bind( - Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed).store(), - )) +) -> TyLoweringResult<'db, WithDefinedOpaques<StoredEarlyBinder<StoredTy>>> { + TyLoweringResult::empty(WithDefinedOpaques { + value: StoredEarlyBinder::bind( + Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed).store(), + ), + impl_traits: None, + }) } pub(crate) fn impl_self_ty_query<'db>( @@ -2822,27 +2777,18 @@ pub(crate) fn callable_item_signature<'db>( db: &'db dyn HirDatabase, def: CallableDefId, ) -> EarlyBinder<'db, PolyFnSig<'db>> { - callable_item_signature_with_diagnostics(db, def).value.get() -} - -#[salsa::tracked(returns(ref))] -pub(crate) fn callable_item_signature_with_diagnostics<'db>( - db: &'db dyn HirDatabase, - def: CallableDefId, -) -> TyLoweringResult<'db, StoredEarlyBinder<StoredPolyFnSig>> { match def { - CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f), - CallableDefId::StructId(s) => TyLoweringResult::empty(fn_sig_for_struct_constructor(db, s)), - CallableDefId::EnumVariantId(e) => { - TyLoweringResult::empty(fn_sig_for_enum_variant_constructor(db, e)) - } + CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f).value.value.get(), + CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s).get(), + CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e).get(), } } -fn fn_sig_for_fn<'db>( +#[salsa::tracked(returns(ref))] +pub(crate) fn fn_sig_for_fn<'db>( db: &'db dyn HirDatabase, def: FunctionId, -) -> TyLoweringResult<'db, StoredEarlyBinder<StoredPolyFnSig>> { +) -> TyLoweringResult<'db, WithDefinedOpaques<StoredEarlyBinder<StoredPolyFnSig>>> { let data = FunctionSignature::of(db, def); let resolver = def.resolver(db); let interner = DbInterner::new_no_crate(db); @@ -2874,6 +2820,7 @@ fn fn_sig_for_fn<'db>( Some(ret_type) => ctx_ret.lower_ty(ret_type), None => Ty::new_unit(interner), }; + let impl_traits = ctx_ret.take_defined_opaques(); let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret))); ctx_params.diagnostics.extend(ctx_ret.diagnostics); @@ -2891,7 +2838,7 @@ fn fn_sig_for_fn<'db>( }, binder, ))); - TyLoweringResult::from_ctx(result, ctx_params) + TyLoweringResult::from_ctx(WithDefinedOpaques { value: result, impl_traits }, ctx_params) } fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> { @@ -2901,13 +2848,14 @@ fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, T EarlyBinder::bind(ty) } -fn fn_sig_for_struct_constructor( +fn ctor_signature( db: &dyn HirDatabase, - def: StructId, + variant: VariantId, + adt: AdtId, ) -> StoredEarlyBinder<StoredPolyFnSig> { - let field_tys = db.field_types(def.into()); + let field_tys = db.field_types(variant); let params = field_tys.iter().map(|(_, field)| field.ty().skip_binder()); - let ret = type_for_adt(db, def.into()).skip_binder(); + let ret = type_for_adt(db, adt).skip_binder(); let inputs_and_output = Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret))); @@ -2917,21 +2865,20 @@ fn fn_sig_for_struct_constructor( }))) } +#[salsa::tracked(returns(ref))] +fn fn_sig_for_struct_constructor( + db: &dyn HirDatabase, + def: StructId, +) -> StoredEarlyBinder<StoredPolyFnSig> { + ctor_signature(db, def.into(), def.into()) +} + +#[salsa::tracked(returns(ref))] fn fn_sig_for_enum_variant_constructor( db: &dyn HirDatabase, def: EnumVariantId, ) -> StoredEarlyBinder<StoredPolyFnSig> { - let field_tys = db.field_types(def.into()); - let params = field_tys.iter().map(|(_, field)| field.ty().skip_binder()); - let parent = def.lookup(db).parent; - let ret = type_for_adt(db, parent.into()).skip_binder(); - - let inputs_and_output = - Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret))); - StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig { - fn_sig_kind: FnSigKind::new(ExternAbi::Rust, Safety::Safe, false), - inputs_and_output, - }))) + ctor_signature(db, def.into(), def.lookup(db).parent.into()) } // FIXME: Remove this. |