Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/opaques.rs')
| -rw-r--r-- | crates/hir-ty/src/opaques.rs | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/crates/hir-ty/src/opaques.rs b/crates/hir-ty/src/opaques.rs index 8531f24377..27ae5e39d5 100644 --- a/crates/hir-ty/src/opaques.rs +++ b/crates/hir-ty/src/opaques.rs @@ -7,14 +7,13 @@ use hir_expand::name::Name; use la_arena::ArenaMap; use rustc_type_ir::inherent::Ty as _; use syntax::ast; -use triomphe::Arc; use crate::{ - ImplTraitId, + ImplTraitId, InferenceResult, db::{HirDatabase, InternedOpaqueTyId}, lower::{ImplTraitIdx, ImplTraits}, next_solver::{ - DbInterner, EarlyBinder, ErrorGuaranteed, SolverDefId, Ty, TypingMode, + DbInterner, ErrorGuaranteed, SolverDefId, StoredEarlyBinder, StoredTy, Ty, TypingMode, infer::{DbInternerInferExt, traits::ObligationCause}, obligation_ctxt::ObligationCtxt, }, @@ -29,7 +28,7 @@ pub(crate) fn opaque_types_defined_by( // A function may define its own RPITs. extend_with_opaques( db, - db.return_type_impl_traits(func), + ImplTraits::return_type_impl_traits(db, func), |opaque_idx| ImplTraitId::ReturnTypeImplTrait(func, opaque_idx), result, ); @@ -38,7 +37,7 @@ pub(crate) fn opaque_types_defined_by( let extend_with_taits = |type_alias| { extend_with_opaques( db, - db.type_alias_impl_traits(type_alias), + ImplTraits::type_alias_impl_traits(db, type_alias), |opaque_idx| ImplTraitId::TypeAliasImplTrait(type_alias, opaque_idx), result, ); @@ -73,14 +72,14 @@ pub(crate) fn opaque_types_defined_by( // FIXME: Collect opaques from `#[define_opaque]`. - fn extend_with_opaques<'db>( - db: &'db dyn HirDatabase, - opaques: Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>>, - mut make_impl_trait: impl FnMut(ImplTraitIdx<'db>) -> ImplTraitId<'db>, + fn extend_with_opaques( + db: &dyn HirDatabase, + opaques: &Option<Box<StoredEarlyBinder<ImplTraits>>>, + mut make_impl_trait: impl FnMut(ImplTraitIdx) -> ImplTraitId, result: &mut Vec<SolverDefId>, ) { if let Some(opaques) = opaques { - for (opaque_idx, _) in (*opaques).as_ref().skip_binder().impl_traits.iter() { + for (opaque_idx, _) in (**opaques).as_ref().skip_binder().impl_traits.iter() { let opaque_id = InternedOpaqueTyId::new(db, make_impl_trait(opaque_idx)); result.push(opaque_id.into()); } @@ -90,43 +89,47 @@ pub(crate) fn opaque_types_defined_by( // These are firewall queries to prevent drawing dependencies between infers: -#[salsa::tracked(returns(ref), unsafe(non_update_return_type))] +#[salsa::tracked(returns(ref))] pub(crate) fn rpit_hidden_types<'db>( db: &'db dyn HirDatabase, function: FunctionId, -) -> ArenaMap<ImplTraitIdx<'db>, EarlyBinder<'db, Ty<'db>>> { - let infer = db.infer(function.into()); +) -> ArenaMap<ImplTraitIdx, StoredEarlyBinder<StoredTy>> { + let infer = InferenceResult::for_body(db, function.into()); let mut result = ArenaMap::new(); for (opaque, hidden_type) in infer.return_position_impl_trait_types(db) { - result.insert(opaque, EarlyBinder::bind(hidden_type)); + result.insert(opaque, StoredEarlyBinder::bind(hidden_type.store())); } result.shrink_to_fit(); result } -#[salsa::tracked(returns(ref), unsafe(non_update_return_type))] +#[salsa::tracked(returns(ref))] pub(crate) fn tait_hidden_types<'db>( db: &'db dyn HirDatabase, type_alias: TypeAliasId, -) -> ArenaMap<ImplTraitIdx<'db>, EarlyBinder<'db, Ty<'db>>> { +) -> ArenaMap<ImplTraitIdx, StoredEarlyBinder<StoredTy>> { + // Call this first, to not perform redundant work if there are no TAITs. + let Some(taits_count) = ImplTraits::type_alias_impl_traits(db, type_alias) + .as_deref() + .map(|taits| taits.as_ref().skip_binder().impl_traits.len()) + else { + return ArenaMap::new(); + }; + let loc = type_alias.loc(db); let module = loc.module(db); - let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); + let interner = DbInterner::new_with(db, module.krate(db)); let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); let mut ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy(); - let param_env = db.trait_environment(type_alias.into()).env; + let param_env = db.trait_environment(type_alias.into()); let defining_bodies = tait_defining_bodies(db, &loc); - let taits_count = db - .type_alias_impl_traits(type_alias) - .map_or(0, |taits| (*taits).as_ref().skip_binder().impl_traits.len()); - let mut result = ArenaMap::with_capacity(taits_count); for defining_body in defining_bodies { - let infer = db.infer(defining_body); - for (&opaque, &hidden_type) in &infer.type_of_opaque { + let infer = InferenceResult::for_body(db, defining_body); + for (&opaque, hidden_type) in &infer.type_of_opaque { let ImplTraitId::TypeAliasImplTrait(opaque_owner, opaque_idx) = opaque.loc(db) else { continue; }; @@ -135,13 +138,18 @@ pub(crate) fn tait_hidden_types<'db>( } // In the presence of errors, we attempt to create a unified type from all // types. rustc doesn't do that, but this should improve the experience. - let hidden_type = infcx.insert_type_vars(hidden_type); + let hidden_type = infcx.insert_type_vars(hidden_type.as_ref()); match result.entry(opaque_idx) { la_arena::Entry::Vacant(entry) => { - entry.insert(EarlyBinder::bind(hidden_type)); + entry.insert(StoredEarlyBinder::bind(hidden_type.store())); } la_arena::Entry::Occupied(entry) => { - _ = ocx.eq(&cause, param_env, entry.get().instantiate_identity(), hidden_type); + _ = ocx.eq( + &cause, + param_env, + entry.get().get().instantiate_identity(), + hidden_type, + ); } } } @@ -154,12 +162,15 @@ pub(crate) fn tait_hidden_types<'db>( let idx = la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(idx as u32)); match result.entry(idx) { la_arena::Entry::Vacant(entry) => { - entry.insert(EarlyBinder::bind(Ty::new_error(interner, ErrorGuaranteed))); + entry.insert(StoredEarlyBinder::bind( + Ty::new_error(interner, ErrorGuaranteed).store(), + )); } la_arena::Entry::Occupied(mut entry) => { - *entry.get_mut() = entry.get().map_bound(|hidden_type| { - infcx.resolve_vars_if_possible(hidden_type).replace_infer_with_error(interner) - }); + let hidden_type = entry.get().get().skip_binder(); + let hidden_type = + infcx.resolve_vars_if_possible(hidden_type).replace_infer_with_error(interner); + *entry.get_mut() = StoredEarlyBinder::bind(hidden_type.store()); } } } |