Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/interner.rs')
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs283
1 files changed, 203 insertions, 80 deletions
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index b72504a19c..3fd8e7b39d 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -1,75 +1,81 @@
//! Things related to the Interner in the next-trait-solver.
-#![allow(unused)]
+#![allow(unused)] // FIXME(next-solver): Remove this.
+
+use std::{fmt, ops::ControlFlow};
+
+pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db};
use base_db::Crate;
use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variances};
-use hir_def::lang_item::LangItem;
-use hir_def::signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags};
-use hir_def::{AdtId, BlockId, GenericDefId, TypeAliasId, VariantId};
-use hir_def::{AttrDefId, Lookup};
-use hir_def::{CallableDefId, EnumVariantId, ItemContainerId, StructId, UnionId};
+use hir_def::{
+ AdtId, AttrDefId, BlockId, CallableDefId, EnumVariantId, GenericDefId, ItemContainerId, Lookup,
+ StructId, TypeAliasId, UnionId, VariantId,
+ lang_item::LangItem,
+ signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags},
+};
use intern::sym::non_exhaustive;
use intern::{Interned, impl_internable, sym};
use la_arena::Idx;
use rustc_abi::{Align, ReprFlags, ReprOptions};
+use rustc_ast_ir::visit::VisitorResult;
use rustc_hash::FxHashSet;
-use rustc_index::bit_set::DenseBitSet;
-use rustc_type_ir::elaborate::elaborate;
-use rustc_type_ir::error::TypeError;
-use rustc_type_ir::inherent::{
- AdtDef as _, GenericArgs as _, GenericsOf, IntoKind, SliceLike as _, Span as _,
-};
-use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem};
-use rustc_type_ir::solve::SizedTraitKind;
+use rustc_index::{IndexVec, bit_set::DenseBitSet};
use rustc_type_ir::{
- AliasTerm, AliasTermKind, AliasTy, AliasTyKind, EarlyBinder, FlagComputation, Flags,
- ImplPolarity, InferTy, ProjectionPredicate, TraitPredicate, TraitRef, Upcast,
+ AliasTerm, AliasTermKind, AliasTy, AliasTyKind, BoundVar, CollectAndApply, DebruijnIndex,
+ EarlyBinder, FlagComputation, Flags, GenericArgKind, ImplPolarity, InferTy,
+ ProjectionPredicate, RegionKind, TermKind, TraitPredicate, TraitRef, TypeVisitableExt,
+ UniverseIndex, Upcast, Variance, WithCachedTypeInfo,
+ elaborate::{self, elaborate},
+ error::TypeError,
+ inherent::{
+ self, AdtDef as _, Const as _, GenericArgs as _, GenericsOf, IntoKind, ParamEnv as _,
+ Region as _, SliceLike as _, Span as _, Ty as _,
+ },
+ ir_print,
+ lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem},
+ relate,
+ solve::SizedTraitKind,
};
use salsa::plumbing::AsId;
use smallvec::{SmallVec, smallvec};
-use std::fmt;
-use std::ops::ControlFlow;
use syntax::ast::SelfParamKind;
+use tracing::debug;
use triomphe::Arc;
-use rustc_ast_ir::visit::VisitorResult;
-use rustc_index::IndexVec;
-use rustc_type_ir::TypeVisitableExt;
-use rustc_type_ir::{
- BoundVar, CollectAndApply, DebruijnIndex, GenericArgKind, RegionKind, TermKind, UniverseIndex,
- Variance, WithCachedTypeInfo, elaborate,
- inherent::{self, Const as _, Region as _, Ty as _},
- ir_print, relate,
-};
-
-use crate::lower_nextsolver::{self, TyLoweringContext};
-use crate::method_resolution::{ALL_FLOAT_FPS, ALL_INT_FPS, TyFingerprint};
-use crate::next_solver::infer::InferCtxt;
-use crate::next_solver::util::{ContainsTypeErrors, explicit_item_bounds, for_trait_impls};
-use crate::next_solver::{
- AdtIdWrapper, BoundConst, CallableIdWrapper, CanonicalVarKind, ClosureIdWrapper,
- CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, ImplIdWrapper, InternedWrapperNoDebug,
- RegionAssumptions, SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper,
+use crate::{
+ ConstScalar, FnAbi, Interner,
+ db::HirDatabase,
+ lower_nextsolver::{self, TyLoweringContext},
+ method_resolution::{ALL_FLOAT_FPS, ALL_INT_FPS, TyFingerprint},
+ next_solver::{
+ AdtIdWrapper, BoundConst, CallableIdWrapper, CanonicalVarKind, ClosureIdWrapper,
+ CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, ImplIdWrapper, InternedWrapperNoDebug,
+ RegionAssumptions, SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper,
+ TypingMode,
+ infer::{
+ DbInternerInferExt, InferCtxt,
+ traits::{Obligation, ObligationCause},
+ },
+ obligation_ctxt::ObligationCtxt,
+ util::{ContainsTypeErrors, explicit_item_bounds, for_trait_impls},
+ },
};
-use crate::{ConstScalar, FnAbi, Interner, db::HirDatabase};
-use super::generics::generics;
-use super::util::sizedness_constraint_for_ty;
use super::{
Binder, BoundExistentialPredicate, BoundExistentialPredicates, BoundTy, BoundTyKind, Clause,
- Clauses, Const, ConstKind, ErrorGuaranteed, ExprConst, ExternalConstraints,
+ ClauseKind, Clauses, Const, ConstKind, ErrorGuaranteed, ExprConst, ExternalConstraints,
ExternalConstraintsData, GenericArg, GenericArgs, InternedClausesWrapper, ParamConst, ParamEnv,
ParamTy, PlaceholderConst, PlaceholderTy, PredefinedOpaques, PredefinedOpaquesData, Predicate,
- PredicateKind, Term, Ty, TyKind, Tys, ValueConst,
+ PredicateKind, SolverDefId, Term, Ty, TyKind, Tys, Valtree, ValueConst,
abi::Safety,
fold::{BoundVarReplacer, BoundVarReplacerDelegate, FnMutDelegate},
- generics::Generics,
+ generics::{Generics, generics},
mapping::ChalkToNextSolver,
region::{
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, PlaceholderRegion, Region,
},
+ util::sizedness_constraint_for_ty,
};
-use super::{ClauseKind, SolverDefId, Valtree};
#[macro_export]
#[doc(hidden)]
@@ -127,11 +133,10 @@ macro_rules! _interned_vec_nolifetime_salsa {
pub fn inner(&self) -> &smallvec::SmallVec<[$ty; 2]> {
// SAFETY: ¯\_(ツ)_/¯
- salsa::with_attached_database(|db| {
+ $crate::with_attached_db(|db| {
let inner = self.inner_(db);
unsafe { std::mem::transmute(inner) }
})
- .unwrap()
}
}
@@ -230,11 +235,10 @@ macro_rules! _interned_vec_db {
pub fn inner(&self) -> &smallvec::SmallVec<[$ty<'db>; 2]> {
// SAFETY: ¯\_(ツ)_/¯
- salsa::with_attached_database(|db| {
+ $crate::with_attached_db(|db| {
let inner = self.inner_(db);
unsafe { std::mem::transmute(inner) }
})
- .unwrap()
}
}
@@ -285,14 +289,11 @@ unsafe impl Sync for DbInterner<'_> {}
impl<'db> DbInterner<'db> {
// FIXME(next-solver): remove this method
pub fn conjure() -> DbInterner<'db> {
- salsa::with_attached_database(|db| DbInterner {
- db: unsafe {
- std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db.as_view())
- },
+ crate::with_attached_db(|db| DbInterner {
+ db: unsafe { std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db) },
krate: None,
block: None,
})
- .expect("db is expected to be attached")
}
pub fn new_with(
@@ -303,6 +304,7 @@ impl<'db> DbInterner<'db> {
DbInterner { db, krate, block }
}
+ #[inline]
pub fn db(&self) -> &'db dyn HirDatabase {
self.db
}
@@ -585,12 +587,11 @@ impl AdtDef {
}
pub fn inner(&self) -> &AdtDefInner {
- salsa::with_attached_database(|db| {
+ crate::with_attached_db(|db| {
let inner = self.data_(db);
// SAFETY: ¯\_(ツ)_/¯
unsafe { std::mem::transmute(inner) }
})
- .unwrap()
}
pub fn is_enum(&self) -> bool {
@@ -708,21 +709,20 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
impl fmt::Debug for AdtDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- salsa::with_attached_database(|db| match self.inner().id {
+ crate::with_attached_db(|db| match self.inner().id {
AdtId::StructId(struct_id) => {
- let data = db.as_view::<dyn HirDatabase>().struct_signature(struct_id);
+ let data = db.struct_signature(struct_id);
f.write_str(data.name.as_str())
}
AdtId::UnionId(union_id) => {
- let data = db.as_view::<dyn HirDatabase>().union_signature(union_id);
+ let data = db.union_signature(union_id);
f.write_str(data.name.as_str())
}
AdtId::EnumId(enum_id) => {
- let data = db.as_view::<dyn HirDatabase>().enum_signature(enum_id);
+ let data = db.enum_signature(enum_id);
f.write_str(data.name.as_str())
}
})
- .unwrap_or_else(|| f.write_str(&format!("AdtDef({:?})", self.inner().id)))
}
}
@@ -778,13 +778,12 @@ impl<'db> Pattern<'db> {
}
pub fn inner(&self) -> &PatternKind<'db> {
- salsa::with_attached_database(|db| {
+ crate::with_attached_db(|db| {
let inner = &self.kind_(db).0;
// SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will
// make sure that our returned value is valid for the lifetime `'db`.
unsafe { std::mem::transmute(inner) }
})
- .unwrap()
}
}
@@ -1020,17 +1019,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
self,
f: impl FnOnce(&mut rustc_type_ir::search_graph::GlobalCache<Self>) -> R,
) -> R {
- salsa::with_attached_database(|db| {
- tls_cache::with_cache(
- unsafe {
- std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(
- db.as_view::<dyn HirDatabase>(),
- )
- },
- f,
- )
- })
- .unwrap()
+ tls_cache::with_cache(self.db, f)
}
fn canonical_param_env_cache_get_or_insert<R>(
@@ -1118,7 +1107,15 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
fn alias_ty_kind(self, alias: rustc_type_ir::AliasTy<Self>) -> AliasTyKind {
match alias.def_id {
SolverDefId::InternedOpaqueTyId(_) => AliasTyKind::Opaque,
- SolverDefId::TypeAliasId(_) => AliasTyKind::Projection,
+ SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
+ ItemContainerId::ImplId(impl_)
+ if self.db.impl_signature(impl_).target_trait.is_none() =>
+ {
+ AliasTyKind::Inherent
+ }
+ ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => AliasTyKind::Projection,
+ _ => AliasTyKind::Free,
+ },
_ => unimplemented!("Unexpected alias: {:?}", alias.def_id),
}
}
@@ -1129,7 +1126,19 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
) -> rustc_type_ir::AliasTermKind {
match alias.def_id {
SolverDefId::InternedOpaqueTyId(_) => AliasTermKind::OpaqueTy,
- SolverDefId::TypeAliasId(_) => AliasTermKind::ProjectionTy,
+ SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
+ ItemContainerId::ImplId(impl_)
+ if self.db.impl_signature(impl_).target_trait.is_none() =>
+ {
+ AliasTermKind::InherentTy
+ }
+ ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => {
+ AliasTermKind::ProjectionTy
+ }
+ _ => AliasTermKind::FreeTy,
+ },
+ // rustc creates an `AnonConst` for consts, and evaluates them with CTFE (normalizing projections
+ // via selection, similar to ours `find_matching_impl()`, and not with the trait solver), so mimic it.
SolverDefId::ConstId(_) => AliasTermKind::UnevaluatedConst,
_ => unimplemented!("Unexpected alias: {:?}", alias.def_id),
}
@@ -1616,7 +1625,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
mut f: impl FnMut(Self::ImplId),
) {
let trait_ = trait_.0;
- let self_ty_fp = TyFingerprint::for_trait_impl_ns(&self_ty);
+ let self_ty_fp = TyFingerprint::for_trait_impl(self_ty);
let fps: &[TyFingerprint] = match self_ty.kind() {
TyKind::Infer(InferTy::IntVar(..)) => &ALL_INT_FPS,
TyKind::Infer(InferTy::FloatVar(..)) => &ALL_FLOAT_FPS,
@@ -1692,8 +1701,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
}
fn impl_is_default(self, impl_def_id: Self::ImplId) -> bool {
- // FIXME
- false
+ self.db.impl_signature(impl_def_id.0).is_default()
}
#[tracing::instrument(skip(self), ret)]
@@ -1747,7 +1755,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
}
fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed {
- panic!("Bug encountered in next-trait-solver.")
+ panic!("Bug encountered in next-trait-solver: {}", msg.to_string())
}
fn is_general_coroutine(self, coroutine_def_id: Self::CoroutineId) -> bool {
@@ -1907,7 +1915,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
match impl_trait_id {
crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
let infer = self.db().infer(func.into());
- EarlyBinder::bind(infer.type_of_rpit[idx].to_nextsolver(self))
+ EarlyBinder::bind(infer.type_of_rpit[idx.to_nextsolver(self)])
}
crate::ImplTraitId::TypeAliasImplTrait(..)
| crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
@@ -1945,7 +1953,11 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
false
}
- fn impl_specializes(self, impl_def_id: Self::ImplId, victim_def_id: Self::ImplId) -> bool {
+ fn impl_specializes(
+ self,
+ specializing_impl_def_id: Self::ImplId,
+ parent_impl_def_id: Self::ImplId,
+ ) -> bool {
false
}
@@ -2106,6 +2118,117 @@ TrivialTypeTraversalImpls! {
Placeholder<BoundVar>,
}
+mod tls_db {
+ use std::{cell::Cell, ptr::NonNull};
+
+ use crate::db::HirDatabase;
+
+ struct Attached {
+ database: Cell<Option<NonNull<dyn HirDatabase>>>,
+ }
+
+ impl Attached {
+ #[inline]
+ fn attach<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
+ struct DbGuard<'s> {
+ state: Option<&'s Attached>,
+ }
+
+ impl<'s> DbGuard<'s> {
+ #[inline]
+ fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
+ match attached.database.get() {
+ Some(current_db) => {
+ let new_db = NonNull::from(db);
+ if !std::ptr::addr_eq(current_db.as_ptr(), new_db.as_ptr()) {
+ panic!(
+ "Cannot change attached database. This is likely a bug.\n\
+ If this is not a bug, you can use `attach_db_allow_change()`."
+ );
+ }
+ Self { state: None }
+ }
+ None => {
+ // Otherwise, set the database.
+ attached.database.set(Some(NonNull::from(db)));
+ Self { state: Some(attached) }
+ }
+ }
+ }
+ }
+
+ impl Drop for DbGuard<'_> {
+ #[inline]
+ fn drop(&mut self) {
+ // Reset database to null if we did anything in `DbGuard::new`.
+ if let Some(attached) = self.state {
+ attached.database.set(None);
+ }
+ }
+ }
+
+ let _guard = DbGuard::new(self, db);
+ op()
+ }
+
+ #[inline]
+ fn attach_allow_change<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
+ struct DbGuard<'s> {
+ state: &'s Attached,
+ prev: Option<NonNull<dyn HirDatabase>>,
+ }
+
+ impl<'s> DbGuard<'s> {
+ #[inline]
+ fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
+ let prev = attached.database.replace(Some(NonNull::from(db)));
+ Self { state: attached, prev }
+ }
+ }
+
+ impl Drop for DbGuard<'_> {
+ #[inline]
+ fn drop(&mut self) {
+ self.state.database.set(self.prev);
+ }
+ }
+
+ let _guard = DbGuard::new(self, db);
+ op()
+ }
+
+ #[inline]
+ fn with<R>(&self, op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
+ let db = self.database.get().expect("Try to use attached db, but not db is attached");
+
+ // SAFETY: The db is attached, so it must be valid.
+ op(unsafe { db.as_ref() })
+ }
+ }
+
+ thread_local! {
+ static GLOBAL_DB: Attached = const { Attached { database: Cell::new(None) } };
+ }
+
+ #[inline]
+ pub fn attach_db<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
+ GLOBAL_DB.with(|global_db| global_db.attach(db, op))
+ }
+
+ #[inline]
+ pub fn attach_db_allow_change<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
+ GLOBAL_DB.with(|global_db| global_db.attach_allow_change(db, op))
+ }
+
+ #[inline]
+ pub fn with_attached_db<R>(op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
+ GLOBAL_DB.with(
+ #[inline]
+ |a| a.with(op),
+ )
+ }
+}
+
mod tls_cache {
use crate::db::HirDatabase;