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.rs73
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());
}
}
}