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.rs1255
1 files changed, 789 insertions, 466 deletions
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index 9cf56bef95..2e52dcea6c 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -1,75 +1,64 @@
//! Things related to the Interner in the next-trait-solver.
-#![allow(unused)]
+
+use std::fmt;
+
+use rustc_ast_ir::{FloatTy, IntTy, UintTy};
+pub use tls_cache::clear_tls_solver_cache;
+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 intern::sym::non_exhaustive;
-use intern::{Interned, impl_internable, sym};
+use hir_def::{
+ AdtId, CallableDefId, DefWithBodyId, EnumVariantId, HasModule, ItemContainerId, StructId,
+ UnionId, VariantId,
+ attrs::AttrFlags,
+ lang_item::LangItems,
+ signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags},
+};
use la_arena::Idx;
-use rustc_abi::{Align, ReprFlags, ReprOptions};
+use rustc_abi::{ReprFlags, ReprOptions};
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_type_ir::{
- AliasTerm, AliasTermKind, AliasTy, AliasTyKind, EarlyBinder, FlagComputation, Flags,
- ImplPolarity, InferTy, ProjectionPredicate, TraitPredicate, TraitRef, Upcast,
+ AliasTermKind, AliasTyKind, BoundVar, CollectAndApply, CoroutineWitnessTypes, DebruijnIndex,
+ EarlyBinder, FlagComputation, Flags, GenericArgKind, ImplPolarity, InferTy, Interner, TraitRef,
+ TypeFlags, TypeVisitableExt, UniverseIndex, Upcast, Variance,
+ elaborate::elaborate,
+ error::TypeError,
+ fast_reject,
+ inherent::{self, GenericsOf, IntoKind, SliceLike as _, Span as _, Ty as _},
+ lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem},
+ solve::SizedTraitKind,
};
-use salsa::plumbing::AsId;
-use smallvec::{SmallVec, smallvec};
-use std::fmt;
-use std::ops::ControlFlow;
-use syntax::ast::SelfParamKind;
-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::{
+ FnAbi,
+ db::{HirDatabase, InternedCoroutine, InternedCoroutineId},
+ lower::GenericPredicates,
+ method_resolution::TraitImpls,
+ next_solver::{
+ AdtIdWrapper, BoundConst, CallableIdWrapper, CanonicalVarKind, ClosureIdWrapper,
+ CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, GeneralConstIdWrapper, ImplIdWrapper,
+ OpaqueTypeKey, RegionAssumptions, SimplifiedType, SolverContext, SolverDefIds,
+ TraitIdWrapper, TypeAliasIdWrapper, util::explicit_item_bounds,
+ },
};
-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,
- ExternalConstraintsData, GenericArg, GenericArgs, InternedClausesWrapper, ParamConst, ParamEnv,
- ParamTy, PlaceholderConst, PlaceholderTy, PredefinedOpaques, PredefinedOpaquesData, Predicate,
- PredicateKind, Term, Ty, TyKind, Tys, ValueConst,
+ Binder, BoundExistentialPredicates, BoundTy, BoundTyKind, Clause, ClauseKind, Clauses, Const,
+ ErrorGuaranteed, ExprConst, ExternalConstraints, GenericArg, GenericArgs, ParamConst, ParamEnv,
+ ParamTy, PlaceholderConst, PlaceholderTy, PredefinedOpaques, Predicate, SolverDefId, Term, Ty,
+ TyKind, Tys, Valtree, ValueConst,
abi::Safety,
fold::{BoundVarReplacer, BoundVarReplacerDelegate, FnMutDelegate},
- generics::Generics,
- mapping::ChalkToNextSolver,
+ generics::{Generics, generics},
region::{
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, PlaceholderRegion, Region,
},
+ util::sizedness_constraint_for_ty,
};
-use super::{ClauseKind, SolverDefId, Valtree};
+
+#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
+pub struct InternedWrapperNoDebug<T>(pub(crate) T);
#[macro_export]
#[doc(hidden)]
@@ -77,7 +66,7 @@ macro_rules! _interned_vec_nolifetime_salsa {
($name:ident, $ty:ty) => {
interned_vec_nolifetime_salsa!($name, $ty, nofold);
- impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $name {
+ impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $name<'db> {
fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
self,
folder: &mut F,
@@ -98,7 +87,7 @@ macro_rules! _interned_vec_nolifetime_salsa {
}
}
- impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for $name {
+ impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for $name<'db> {
fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
&self,
visitor: &mut V,
@@ -111,14 +100,14 @@ macro_rules! _interned_vec_nolifetime_salsa {
}
};
($name:ident, $ty:ty, nofold) => {
- #[salsa::interned(no_lifetime, constructor = new_, debug)]
+ #[salsa::interned(constructor = new_)]
pub struct $name {
#[returns(ref)]
inner_: smallvec::SmallVec<[$ty; 2]>,
}
- impl $name {
- pub fn new_from_iter<'db>(
+ impl<'db> $name<'db> {
+ pub fn new_from_iter(
interner: DbInterner<'db>,
data: impl IntoIterator<Item = $ty>,
) -> Self {
@@ -127,15 +116,20 @@ 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()
}
}
- impl rustc_type_ir::inherent::SliceLike for $name {
+ impl<'db> std::fmt::Debug for $name<'db> {
+ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.as_slice().fmt(fmt)
+ }
+ }
+
+ impl<'db> rustc_type_ir::inherent::SliceLike for $name<'db> {
type Item = $ty;
type IntoIter = <smallvec::SmallVec<[$ty; 2]> as IntoIterator>::IntoIter;
@@ -149,7 +143,7 @@ macro_rules! _interned_vec_nolifetime_salsa {
}
}
- impl IntoIterator for $name {
+ impl<'db> IntoIterator for $name<'db> {
type Item = $ty;
type IntoIter = <Self as rustc_type_ir::inherent::SliceLike>::IntoIter;
@@ -158,7 +152,7 @@ macro_rules! _interned_vec_nolifetime_salsa {
}
}
- impl Default for $name {
+ impl<'db> Default for $name<'db> {
fn default() -> Self {
$name::new_from_iter(DbInterner::conjure(), [])
}
@@ -221,6 +215,10 @@ macro_rules! _interned_vec_db {
}
impl<'db> $name<'db> {
+ pub fn empty(interner: DbInterner<'db>) -> Self {
+ $name::new_(interner.db(), smallvec::SmallVec::new())
+ }
+
pub fn new_from_iter(
interner: DbInterner<'db>,
data: impl IntoIterator<Item = $ty<'db>>,
@@ -230,11 +228,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()
}
}
@@ -274,8 +271,8 @@ pub use crate::_interned_vec_db as interned_vec_db;
#[derive(Debug, Copy, Clone)]
pub struct DbInterner<'db> {
pub(crate) db: &'db dyn HirDatabase,
- pub(crate) krate: Option<Crate>,
- pub(crate) block: Option<BlockId>,
+ krate: Option<Crate>,
+ lang_items: Option<&'db LangItems>,
}
// FIXME: very wrong, see https://github.com/rust-lang/rust/pull/144808
@@ -285,27 +282,45 @@ 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,
+ lang_items: None,
})
- .expect("db is expected to be attached")
}
- pub fn new_with(
- db: &'db dyn HirDatabase,
- krate: Option<Crate>,
- block: Option<BlockId>,
- ) -> DbInterner<'db> {
- DbInterner { db, krate, block }
+ /// Creates a new interner without an active crate. Good only for interning things, not for trait solving etc..
+ /// As a rule of thumb, when you create an `InferCtxt`, you need to provide the crate (and the block).
+ ///
+ /// Elaboration is a special kind: it needs lang items (for `Sized`), therefore it needs `new_with()`.
+ pub fn new_no_crate(db: &'db dyn HirDatabase) -> Self {
+ DbInterner { db, krate: None, lang_items: None }
+ }
+
+ pub fn new_with(db: &'db dyn HirDatabase, krate: Crate) -> DbInterner<'db> {
+ DbInterner {
+ db,
+ krate: Some(krate),
+ // As an approximation, when we call `new_with` we're trait solving, therefore we need the lang items.
+ // This is also convenient since here we have a starting crate but not in `new_no_crate`.
+ lang_items: Some(hir_def::lang_item::lang_items(db, krate)),
+ }
}
+ #[inline]
pub fn db(&self) -> &'db dyn HirDatabase {
self.db
}
+
+ #[inline]
+ #[track_caller]
+ pub fn lang_items(&self) -> &'db LangItems {
+ self.lang_items.expect(
+ "Must have `DbInterner::lang_items`.\n\n\
+ Note: you might have called `DbInterner::new_no_crate()` \
+ where you should've called `DbInterner::new_with()`",
+ )
+ }
}
// This is intentionally left as `()`
@@ -485,28 +500,28 @@ impl AdtDef {
let variants = vec![(VariantIdx(0), VariantDef::Struct(struct_id))];
- let mut repr = ReprOptions::default();
- repr.align = data.repr.and_then(|r| r.align);
- repr.pack = data.repr.and_then(|r| r.pack);
- repr.int = data.repr.and_then(|r| r.int);
-
+ let data_repr = data.repr(db, struct_id);
let mut repr_flags = ReprFlags::empty();
if flags.is_box {
repr_flags.insert(ReprFlags::IS_LINEAR);
}
- if data.repr.is_some_and(|r| r.c()) {
+ if data_repr.is_some_and(|r| r.c()) {
repr_flags.insert(ReprFlags::IS_C);
}
- if data.repr.is_some_and(|r| r.simd()) {
+ if data_repr.is_some_and(|r| r.simd()) {
repr_flags.insert(ReprFlags::IS_SIMD);
}
- repr.flags = repr_flags;
+ let repr = ReprOptions {
+ align: data_repr.and_then(|r| r.align),
+ pack: data_repr.and_then(|r| r.pack),
+ int: data_repr.and_then(|r| r.int),
+ flags: repr_flags,
+ ..ReprOptions::default()
+ };
(flags, variants, repr)
}
AdtId::UnionId(union_id) => {
- let data = db.union_signature(union_id);
-
let flags = AdtFlags {
is_enum: false,
is_union: true,
@@ -519,22 +534,24 @@ impl AdtDef {
let variants = vec![(VariantIdx(0), VariantDef::Union(union_id))];
- let mut repr = ReprOptions::default();
- repr.align = data.repr.and_then(|r| r.align);
- repr.pack = data.repr.and_then(|r| r.pack);
- repr.int = data.repr.and_then(|r| r.int);
-
+ let data_repr = AttrFlags::repr(db, union_id.into());
let mut repr_flags = ReprFlags::empty();
if flags.is_box {
repr_flags.insert(ReprFlags::IS_LINEAR);
}
- if data.repr.is_some_and(|r| r.c()) {
+ if data_repr.is_some_and(|r| r.c()) {
repr_flags.insert(ReprFlags::IS_C);
}
- if data.repr.is_some_and(|r| r.simd()) {
+ if data_repr.is_some_and(|r| r.simd()) {
repr_flags.insert(ReprFlags::IS_SIMD);
}
- repr.flags = repr_flags;
+ let repr = ReprOptions {
+ align: data_repr.and_then(|r| r.align),
+ pack: data_repr.and_then(|r| r.pack),
+ int: data_repr.and_then(|r| r.int),
+ flags: repr_flags,
+ ..ReprOptions::default()
+ };
(flags, variants, repr)
}
@@ -558,24 +575,26 @@ impl AdtDef {
.map(|(idx, v)| (idx, VariantDef::Enum(v.0)))
.collect();
- let data = db.enum_signature(enum_id);
-
- let mut repr = ReprOptions::default();
- repr.align = data.repr.and_then(|r| r.align);
- repr.pack = data.repr.and_then(|r| r.pack);
- repr.int = data.repr.and_then(|r| r.int);
+ let data_repr = AttrFlags::repr(db, enum_id.into());
let mut repr_flags = ReprFlags::empty();
if flags.is_box {
repr_flags.insert(ReprFlags::IS_LINEAR);
}
- if data.repr.is_some_and(|r| r.c()) {
+ if data_repr.is_some_and(|r| r.c()) {
repr_flags.insert(ReprFlags::IS_C);
}
- if data.repr.is_some_and(|r| r.simd()) {
+ if data_repr.is_some_and(|r| r.simd()) {
repr_flags.insert(ReprFlags::IS_SIMD);
}
- repr.flags = repr_flags;
+
+ let repr = ReprOptions {
+ align: data_repr.and_then(|r| r.align),
+ pack: data_repr.and_then(|r| r.pack),
+ int: data_repr.and_then(|r| r.int),
+ flags: repr_flags,
+ ..ReprOptions::default()
+ };
(flags, variants, repr)
}
@@ -585,18 +604,21 @@ 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 {
self.inner().flags.is_enum
}
+ pub fn is_box(&self) -> bool {
+ self.inner().flags.is_box
+ }
+
#[inline]
pub fn repr(self) -> ReprOptions {
self.inner().repr
@@ -630,12 +652,11 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
self,
interner: DbInterner<'db>,
) -> Option<EarlyBinder<DbInterner<'db>, Ty<'db>>> {
- let db = interner.db();
let hir_def::AdtId::StructId(struct_id) = self.inner().id else {
return None;
};
let id: VariantId = struct_id.into();
- let field_types = interner.db().field_types_ns(id);
+ let field_types = interner.db().field_types(id);
field_types.iter().last().map(|f| *f.1)
}
@@ -646,23 +667,10 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
) -> EarlyBinder<DbInterner<'db>, impl IntoIterator<Item = Ty<'db>>> {
let db = interner.db();
// FIXME: this is disabled just to match the behavior with chalk right now
- let field_tys = |id: VariantId| {
- let variant_data = id.fields(db);
- let fields = if variant_data.fields().is_empty() {
- vec![]
- } else {
- let field_types = db.field_types_ns(id);
- variant_data
- .fields()
- .iter()
- .map(|(idx, _)| {
- let ty = field_types[idx];
- ty.skip_binder()
- })
- .collect()
- };
+ let _field_tys = |id: VariantId| {
+ db.field_types(id).iter().map(|(_, ty)| ty.skip_binder()).collect::<Vec<_>>()
};
- let field_tys = |id: VariantId| vec![];
+ let field_tys = |_id: VariantId| vec![];
let tys: Vec<_> = match self.inner().id {
hir_def::AdtId::StructId(id) => field_tys(id.into()),
hir_def::AdtId::UnionId(id) => field_tys(id.into()),
@@ -695,7 +703,7 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
fn destructor(
self,
- interner: DbInterner<'db>,
+ _interner: DbInterner<'db>,
) -> Option<rustc_type_ir::solve::AdtDestructorKind> {
// FIXME(next-solver)
None
@@ -708,21 +716,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)))
}
}
@@ -742,7 +749,7 @@ impl<'db> inherent::Features<DbInterner<'db>> for Features {
false
}
- fn feature_bound_holds_in_crate(self, symbol: ()) -> bool {
+ fn feature_bound_holds_in_crate(self, _symbol: ()) -> bool {
false
}
}
@@ -778,18 +785,17 @@ 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()
}
}
impl<'db> Flags for Pattern<'db> {
- fn flags(&self) -> rustc_type_ir::TypeFlags {
+ fn flags(&self) -> TypeFlags {
match self.inner() {
PatternKind::Range { start, end } => {
FlagComputation::for_const_kind(&start.kind()).flags
@@ -802,6 +808,7 @@ impl<'db> Flags for Pattern<'db> {
}
flags
}
+ PatternKind::NotNull => TypeFlags::empty(),
}
}
@@ -817,6 +824,7 @@ impl<'db> Flags for Pattern<'db> {
}
idx
}
+ PatternKind::NotNull => rustc_type_ir::INNERMOST,
}
}
}
@@ -854,7 +862,10 @@ impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for Pattern<'db> {
)?;
Ok(Pattern::new(tcx, PatternKind::Or(pats)))
}
- (PatternKind::Range { .. } | PatternKind::Or(_), _) => Err(TypeError::Mismatch),
+ (PatternKind::NotNull, PatternKind::NotNull) => Ok(a),
+ (PatternKind::Range { .. } | PatternKind::Or(_) | PatternKind::NotNull, _) => {
+ Err(TypeError::Mismatch)
+ }
}
}
}
@@ -863,7 +874,7 @@ interned_vec_db!(PatList, Pattern);
macro_rules! as_lang_item {
(
- $solver_enum:ident, $var:ident;
+ $solver_enum:ident, $self:ident, $def_id:expr;
ignore = {
$( $ignore:ident ),* $(,)?
@@ -871,6 +882,7 @@ macro_rules! as_lang_item {
$( $variant:ident ),* $(,)?
) => {{
+ let lang_items = $self.lang_items();
// Ensure exhaustiveness.
if let Some(it) = None::<$solver_enum> {
match it {
@@ -878,17 +890,36 @@ macro_rules! as_lang_item {
$( $solver_enum::$ignore => {} )*
}
}
- match $var {
- $( LangItem::$variant => Some($solver_enum::$variant), )*
+ match $def_id {
+ $( def_id if lang_items.$variant.is_some_and(|it| it == def_id) => Some($solver_enum::$variant), )*
_ => None
}
}};
}
-impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
+macro_rules! is_lang_item {
+ (
+ $solver_enum:ident, $self:ident, $def_id:expr, $expected_variant:ident;
+
+ ignore = {
+ $( $ignore:ident ),* $(,)?
+ }
+
+ $( $variant:ident ),* $(,)?
+ ) => {{
+ let lang_items = $self.lang_items();
+ let def_id = $def_id;
+ match $expected_variant {
+ $( $solver_enum::$variant => lang_items.$variant.is_some_and(|it| it == def_id), )*
+ $( $solver_enum::$ignore => false, )*
+ }
+ }};
+}
+
+impl<'db> Interner for DbInterner<'db> {
type DefId = SolverDefId;
type LocalDefId = SolverDefId;
- type LocalDefIds = SolverDefIds;
+ type LocalDefIds = SolverDefIds<'db>;
type TraitId = TraitIdWrapper;
type ForeignId = TypeAliasIdWrapper;
type FunctionId = CallableIdWrapper;
@@ -897,6 +928,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
type CoroutineId = CoroutineIdWrapper;
type AdtId = AdtIdWrapper;
type ImplId = ImplIdWrapper;
+ type UnevaluatedConstId = GeneralConstIdWrapper;
type Span = Span;
type GenericArgs = GenericArgs<'db>;
@@ -905,16 +937,16 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
type Term = Term<'db>;
- type BoundVarKinds = BoundVarKinds;
+ type BoundVarKinds = BoundVarKinds<'db>;
type BoundVarKind = BoundVarKind;
type PredefinedOpaques = PredefinedOpaques<'db>;
fn mk_predefined_opaques_in_body(
self,
- data: rustc_type_ir::solve::PredefinedOpaquesData<Self>,
+ data: &[(OpaqueTypeKey<'db>, Self::Ty)],
) -> Self::PredefinedOpaques {
- PredefinedOpaques::new(self, data)
+ PredefinedOpaques::new_from_iter(self, data.iter().cloned())
}
type CanonicalVarKinds = CanonicalVars<'db>;
@@ -978,7 +1010,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
type GenericsOf = Generics;
- type VariancesOf = VariancesOf;
+ type VariancesOf = VariancesOf<'db>;
type AdtDef = AdtDef;
@@ -1003,7 +1035,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
fn mk_tracked<T: fmt::Debug + Clone>(
self,
data: T,
- dep_node: Self::DepNodeIndex,
+ _dep_node: Self::DepNodeIndex,
) -> Self::Tracked<T> {
Tracked(data)
}
@@ -1020,30 +1052,20 @@ 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>(
self,
- param_env: Self::ParamEnv,
+ _param_env: Self::ParamEnv,
f: impl FnOnce() -> rustc_type_ir::CanonicalParamEnvCacheEntry<Self>,
from_entry: impl FnOnce(&rustc_type_ir::CanonicalParamEnvCacheEntry<Self>) -> R,
) -> R {
from_entry(&f())
}
- fn evaluation_is_concurrent(&self) -> bool {
- false
+ fn assert_evaluation_is_concurrent(&self) {
+ panic!("evaluation shouldn't be concurrent yet")
}
fn expand_abstract_consts<T: rustc_type_ir::TypeFoldable<Self>>(self, _: T) -> T {
@@ -1056,10 +1078,9 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
let generic_def = match def_id {
- SolverDefId::FunctionId(def_id) => def_id.into(),
- SolverDefId::AdtId(def_id) => def_id.into(),
- SolverDefId::Ctor(Ctor::Struct(def_id)) => def_id.into(),
- SolverDefId::Ctor(Ctor::Enum(def_id)) => def_id.loc(self.db).parent.into(),
+ SolverDefId::Ctor(Ctor::Enum(def_id)) | SolverDefId::EnumVariantId(def_id) => {
+ def_id.loc(self.db).parent.into()
+ }
SolverDefId::InternedOpaqueTyId(_def_id) => {
// FIXME(next-solver): track variances
//
@@ -1070,17 +1091,20 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
(0..self.generics_of(def_id).count()).map(|_| Variance::Invariant),
);
}
- _ => return VariancesOf::new_from_iter(self, []),
+ SolverDefId::Ctor(Ctor::Struct(def_id)) => def_id.into(),
+ SolverDefId::AdtId(def_id) => def_id.into(),
+ SolverDefId::FunctionId(def_id) => def_id.into(),
+ SolverDefId::ConstId(_)
+ | SolverDefId::StaticId(_)
+ | SolverDefId::TraitId(_)
+ | SolverDefId::TypeAliasId(_)
+ | SolverDefId::ImplId(_)
+ | SolverDefId::InternedClosureId(_)
+ | SolverDefId::InternedCoroutineId(_) => {
+ return VariancesOf::new_from_iter(self, []);
+ }
};
- VariancesOf::new_from_iter(
- self,
- self.db()
- .variances_of(generic_def)
- .as_deref()
- .unwrap_or_default()
- .iter()
- .map(|v| v.to_nextsolver(self)),
- )
+ self.db.variances_of(generic_def)
}
fn type_of(self, def_id: Self::DefId) -> EarlyBinder<Self, Self::Ty> {
@@ -1091,23 +1115,21 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
ItemContainerId::ImplId(it) => it,
_ => panic!("assoc ty value should be in impl"),
};
- self.db().ty_ns(id.into())
+ self.db().ty(id.into())
}
- SolverDefId::AdtId(id) => self.db().ty_ns(id.into()),
+ SolverDefId::AdtId(id) => self.db().ty(id.into()),
// FIXME(next-solver): This uses the types of `query mir_borrowck` in rustc.
//
// We currently always use the type from HIR typeck which ignores regions. This
// should be fine.
SolverDefId::InternedOpaqueTyId(_) => self.type_of_opaque_hir_typeck(def_id),
- SolverDefId::FunctionId(id) => self.db.value_ty_ns(id.into()).unwrap(),
+ SolverDefId::FunctionId(id) => self.db.value_ty(id.into()).unwrap(),
SolverDefId::Ctor(id) => {
let id = match id {
Ctor::Struct(id) => id.into(),
Ctor::Enum(id) => id.into(),
};
- self.db
- .value_ty_ns(id)
- .expect("`SolverDefId::Ctor` should have a function-like ctor")
+ self.db.value_ty(id).expect("`SolverDefId::Ctor` should have a function-like ctor")
}
_ => panic!("Unexpected def_id `{def_id:?}` provided for `type_of`"),
}
@@ -1120,7 +1142,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),
}
}
@@ -1131,7 +1161,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),
}
@@ -1153,17 +1195,17 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
(TraitRef::new_from_args(self, trait_def_id.try_into().unwrap(), trait_args), alias_args)
}
- fn check_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs) -> bool {
+ fn check_args_compatible(self, _def_id: Self::DefId, _args: Self::GenericArgs) -> bool {
// FIXME
true
}
- fn debug_assert_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs) {}
+ fn debug_assert_args_compatible(self, _def_id: Self::DefId, _args: Self::GenericArgs) {}
fn debug_assert_existential_args_compatible(
self,
- def_id: Self::DefId,
- args: Self::GenericArgs,
+ _def_id: Self::DefId,
+ _args: Self::GenericArgs,
) {
}
@@ -1204,6 +1246,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
| SolverDefId::AdtId(_)
| SolverDefId::TraitId(_)
| SolverDefId::ImplId(_)
+ | SolverDefId::EnumVariantId(..)
| SolverDefId::Ctor(..)
| SolverDefId::InternedOpaqueTyId(..) => panic!(),
};
@@ -1227,20 +1270,35 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
self,
def_id: Self::FunctionId,
) -> EarlyBinder<Self, rustc_type_ir::Binder<Self, rustc_type_ir::FnSig<Self>>> {
- self.db().callable_item_signature_ns(def_id.0)
+ self.db().callable_item_signature(def_id.0)
}
fn coroutine_movability(self, def_id: Self::CoroutineId) -> rustc_ast_ir::Movability {
- unimplemented!()
+ // FIXME: Make this a query? I don't believe this can be accessed from bodies other than
+ // the current infer query, except with revealed opaques - is it rare enough to not matter?
+ let InternedCoroutine(owner, expr_id) = def_id.0.loc(self.db);
+ let body = self.db.body(owner);
+ let expr = &body[expr_id];
+ match *expr {
+ hir_def::hir::Expr::Closure { closure_kind, .. } => match closure_kind {
+ hir_def::hir::ClosureKind::Coroutine(movability) => match movability {
+ hir_def::hir::Movability::Static => rustc_ast_ir::Movability::Static,
+ hir_def::hir::Movability::Movable => rustc_ast_ir::Movability::Movable,
+ },
+ hir_def::hir::ClosureKind::Async => rustc_ast_ir::Movability::Static,
+ _ => panic!("unexpected expression for a coroutine: {expr:?}"),
+ },
+ hir_def::hir::Expr::Async { .. } => rustc_ast_ir::Movability::Static,
+ _ => panic!("unexpected expression for a coroutine: {expr:?}"),
+ }
}
- fn coroutine_for_closure(self, def_id: Self::CoroutineId) -> Self::CoroutineId {
- unimplemented!()
+ fn coroutine_for_closure(self, def_id: Self::CoroutineClosureId) -> Self::CoroutineId {
+ def_id
}
fn generics_require_sized_self(self, def_id: Self::DefId) -> bool {
- let sized_trait =
- LangItem::Sized.resolve_trait(self.db(), self.krate.expect("Must have self.krate"));
+ let sized_trait = self.lang_items().Sized;
let Some(sized_id) = sized_trait else {
return false; /* No Sized trait, can't require it! */
};
@@ -1267,27 +1325,21 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
})
}
- #[tracing::instrument(skip(self), ret)]
+ #[tracing::instrument(skip(self))]
fn item_bounds(
self,
def_id: Self::DefId,
) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
- explicit_item_bounds(self, def_id).map_bound(|bounds| {
- Clauses::new_from_iter(self, elaborate(self, bounds).collect::<Vec<_>>())
- })
+ explicit_item_bounds(self, def_id).map_bound(|bounds| elaborate(self, bounds))
}
- #[tracing::instrument(skip(self), ret)]
+ #[tracing::instrument(skip(self))]
fn item_self_bounds(
self,
def_id: Self::DefId,
) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
- explicit_item_bounds(self, def_id).map_bound(|bounds| {
- Clauses::new_from_iter(
- self,
- elaborate(self, bounds).filter_only_self().collect::<Vec<_>>(),
- )
- })
+ explicit_item_bounds(self, def_id)
+ .map_bound(|bounds| elaborate(self, bounds).filter_only_self())
}
fn item_non_self_bounds(
@@ -1312,9 +1364,8 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
self,
def_id: Self::DefId,
) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
- let predicates = self.db().generic_predicates_ns(def_id.try_into().unwrap());
- let predicates: Vec<_> = predicates.iter().cloned().collect();
- EarlyBinder::bind(predicates.into_iter())
+ GenericPredicates::query_all(self.db, def_id.try_into().unwrap())
+ .map_bound(|it| it.iter().copied())
}
#[tracing::instrument(level = "debug", skip(self), ret)]
@@ -1322,9 +1373,8 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
self,
def_id: Self::DefId,
) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
- let predicates = self.db().generic_predicates_without_parent_ns(def_id.try_into().unwrap());
- let predicates: Vec<_> = predicates.iter().cloned().collect();
- EarlyBinder::bind(predicates.into_iter())
+ GenericPredicates::query_own(self.db, def_id.try_into().unwrap())
+ .map_bound(|it| it.iter().copied())
}
#[tracing::instrument(skip(self), ret)]
@@ -1337,23 +1387,21 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
_ => false,
};
- let predicates: Vec<(Clause<'db>, Span)> = self
- .db()
- .generic_predicates_ns(def_id.0.into())
- .iter()
- .filter(|p| match p.kind().skip_binder() {
- // rustc has the following assertion:
- // https://github.com/rust-lang/rust/blob/52618eb338609df44978b0ca4451ab7941fd1c7a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs#L525-L608
- rustc_type_ir::ClauseKind::Trait(it) => is_self(it.self_ty()),
- rustc_type_ir::ClauseKind::TypeOutlives(it) => is_self(it.0),
- rustc_type_ir::ClauseKind::Projection(it) => is_self(it.self_ty()),
- rustc_type_ir::ClauseKind::HostEffect(it) => is_self(it.self_ty()),
- _ => false,
- })
- .cloned()
- .map(|p| (p, Span::dummy()))
- .collect();
- EarlyBinder::bind(predicates)
+ GenericPredicates::query_explicit(self.db, def_id.0.into()).map_bound(move |predicates| {
+ predicates
+ .iter()
+ .copied()
+ .filter(move |p| match p.kind().skip_binder() {
+ // rustc has the following assertion:
+ // https://github.com/rust-lang/rust/blob/52618eb338609df44978b0ca4451ab7941fd1c7a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs#L525-L608
+ ClauseKind::Trait(it) => is_self(it.self_ty()),
+ ClauseKind::TypeOutlives(it) => is_self(it.0),
+ ClauseKind::Projection(it) => is_self(it.self_ty()),
+ ClauseKind::HostEffect(it) => is_self(it.self_ty()),
+ _ => false,
+ })
+ .map(|p| (p, Span::dummy()))
+ })
}
#[tracing::instrument(skip(self), ret)]
@@ -1371,49 +1419,47 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
}
}
- let predicates: Vec<(Clause<'db>, Span)> = self
- .db()
- .generic_predicates_ns(def_id.try_into().unwrap())
- .iter()
- .filter(|p| match p.kind().skip_binder() {
- rustc_type_ir::ClauseKind::Trait(it) => is_self_or_assoc(it.self_ty()),
- rustc_type_ir::ClauseKind::TypeOutlives(it) => is_self_or_assoc(it.0),
- rustc_type_ir::ClauseKind::Projection(it) => is_self_or_assoc(it.self_ty()),
- rustc_type_ir::ClauseKind::HostEffect(it) => is_self_or_assoc(it.self_ty()),
- // FIXME: Not sure is this correct to allow other clauses but we might replace
- // `generic_predicates_ns` query here with something closer to rustc's
- // `implied_bounds_with_filter`, which is more granular lowering than this
- // "lower at once and then filter" implementation.
- _ => true,
- })
- .cloned()
- .map(|p| (p, Span::dummy()))
- .collect();
- EarlyBinder::bind(predicates)
+ GenericPredicates::query_explicit(self.db, def_id.try_into().unwrap()).map_bound(
+ |predicates| {
+ predicates
+ .iter()
+ .copied()
+ .filter(|p| match p.kind().skip_binder() {
+ ClauseKind::Trait(it) => is_self_or_assoc(it.self_ty()),
+ ClauseKind::TypeOutlives(it) => is_self_or_assoc(it.0),
+ ClauseKind::Projection(it) => is_self_or_assoc(it.self_ty()),
+ ClauseKind::HostEffect(it) => is_self_or_assoc(it.self_ty()),
+ // FIXME: Not sure is this correct to allow other clauses but we might replace
+ // `generic_predicates_ns` query here with something closer to rustc's
+ // `implied_bounds_with_filter`, which is more granular lowering than this
+ // "lower at once and then filter" implementation.
+ _ => true,
+ })
+ .map(|p| (p, Span::dummy()))
+ },
+ )
}
fn impl_super_outlives(
self,
impl_id: Self::ImplId,
) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
- let trait_ref = self.db().impl_trait_ns(impl_id.0).expect("expected an impl of trait");
+ let trait_ref = self.db().impl_trait(impl_id.0).expect("expected an impl of trait");
trait_ref.map_bound(|trait_ref| {
let clause: Clause<'_> = trait_ref.upcast(self);
- Clauses::new_from_iter(
- self,
- rustc_type_ir::elaborate::elaborate(self, [clause]).filter(|clause| {
- matches!(
- clause.kind().skip_binder(),
- ClauseKind::TypeOutlives(_) | ClauseKind::RegionOutlives(_)
- )
- }),
- )
+ elaborate(self, [clause]).filter(|clause| {
+ matches!(
+ clause.kind().skip_binder(),
+ ClauseKind::TypeOutlives(_) | ClauseKind::RegionOutlives(_)
+ )
+ })
})
}
+ #[expect(unreachable_code)]
fn const_conditions(
self,
- def_id: Self::DefId,
+ _def_id: Self::DefId,
) -> EarlyBinder<
Self,
impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
@@ -1421,89 +1467,74 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
EarlyBinder::bind([unimplemented!()])
}
- fn has_target_features(self, def_id: Self::FunctionId) -> bool {
+ fn has_target_features(self, _def_id: Self::FunctionId) -> bool {
false
}
fn require_lang_item(self, lang_item: SolverLangItem) -> Self::DefId {
+ let lang_items = self.lang_items();
let lang_item = match lang_item {
SolverLangItem::AsyncFnKindUpvars => unimplemented!(),
- SolverLangItem::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput,
- SolverLangItem::CallOnceFuture => LangItem::CallOnceFuture,
- SolverLangItem::CallRefFuture => LangItem::CallRefFuture,
- SolverLangItem::CoroutineReturn => LangItem::CoroutineReturn,
- SolverLangItem::CoroutineYield => LangItem::CoroutineYield,
- SolverLangItem::DynMetadata => LangItem::DynMetadata,
- SolverLangItem::FutureOutput => LangItem::FutureOutput,
- SolverLangItem::Metadata => LangItem::Metadata,
+ SolverLangItem::AsyncFnOnceOutput => lang_items.AsyncFnOnceOutput,
+ SolverLangItem::CallOnceFuture => lang_items.CallOnceFuture,
+ SolverLangItem::CallRefFuture => lang_items.CallRefFuture,
+ SolverLangItem::CoroutineReturn => lang_items.CoroutineReturn,
+ SolverLangItem::CoroutineYield => lang_items.CoroutineYield,
+ SolverLangItem::FutureOutput => lang_items.FutureOutput,
+ SolverLangItem::Metadata => lang_items.Metadata,
+ SolverLangItem::DynMetadata => {
+ return lang_items.DynMetadata.expect("Lang item required but not found.").into();
+ }
};
- let target = hir_def::lang_item::lang_item(
- self.db(),
- self.krate.expect("Must have self.krate"),
- lang_item,
- )
- .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found."));
- match target {
- hir_def::lang_item::LangItemTarget::EnumId(enum_id) => enum_id.into(),
- hir_def::lang_item::LangItemTarget::Function(function_id) => function_id.into(),
- hir_def::lang_item::LangItemTarget::ImplDef(impl_id) => impl_id.into(),
- hir_def::lang_item::LangItemTarget::Static(static_id) => static_id.into(),
- hir_def::lang_item::LangItemTarget::Struct(struct_id) => struct_id.into(),
- hir_def::lang_item::LangItemTarget::Union(union_id) => union_id.into(),
- hir_def::lang_item::LangItemTarget::TypeAlias(type_alias_id) => type_alias_id.into(),
- hir_def::lang_item::LangItemTarget::Trait(trait_id) => trait_id.into(),
- hir_def::lang_item::LangItemTarget::EnumVariant(enum_variant_id) => unimplemented!(),
- }
+ lang_item.expect("Lang item required but not found.").into()
}
fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> TraitIdWrapper {
+ let lang_items = self.lang_items();
let lang_item = match lang_item {
- SolverTraitLangItem::AsyncFn => LangItem::AsyncFn,
+ SolverTraitLangItem::AsyncFn => lang_items.AsyncFn,
SolverTraitLangItem::AsyncFnKindHelper => unimplemented!(),
- SolverTraitLangItem::AsyncFnMut => LangItem::AsyncFnMut,
- SolverTraitLangItem::AsyncFnOnce => LangItem::AsyncFnOnce,
- SolverTraitLangItem::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput,
+ SolverTraitLangItem::AsyncFnMut => lang_items.AsyncFnMut,
+ SolverTraitLangItem::AsyncFnOnce => lang_items.AsyncFnOnce,
+ SolverTraitLangItem::AsyncFnOnceOutput => unimplemented!(
+ "This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver."
+ ),
SolverTraitLangItem::AsyncIterator => unimplemented!(),
- SolverTraitLangItem::Clone => LangItem::Clone,
- SolverTraitLangItem::Copy => LangItem::Copy,
- SolverTraitLangItem::Coroutine => LangItem::Coroutine,
- SolverTraitLangItem::Destruct => LangItem::Destruct,
- SolverTraitLangItem::DiscriminantKind => LangItem::DiscriminantKind,
- SolverTraitLangItem::Drop => LangItem::Drop,
- SolverTraitLangItem::Fn => LangItem::Fn,
- SolverTraitLangItem::FnMut => LangItem::FnMut,
- SolverTraitLangItem::FnOnce => LangItem::FnOnce,
- SolverTraitLangItem::FnPtrTrait => LangItem::FnPtrTrait,
+ SolverTraitLangItem::Clone => lang_items.Clone,
+ SolverTraitLangItem::Copy => lang_items.Copy,
+ SolverTraitLangItem::Coroutine => lang_items.Coroutine,
+ SolverTraitLangItem::Destruct => lang_items.Destruct,
+ SolverTraitLangItem::DiscriminantKind => lang_items.DiscriminantKind,
+ SolverTraitLangItem::Drop => lang_items.Drop,
+ SolverTraitLangItem::Fn => lang_items.Fn,
+ SolverTraitLangItem::FnMut => lang_items.FnMut,
+ SolverTraitLangItem::FnOnce => lang_items.FnOnce,
+ SolverTraitLangItem::FnPtrTrait => lang_items.FnPtrTrait,
SolverTraitLangItem::FusedIterator => unimplemented!(),
- SolverTraitLangItem::Future => LangItem::Future,
- SolverTraitLangItem::Iterator => LangItem::Iterator,
- SolverTraitLangItem::PointeeTrait => LangItem::PointeeTrait,
- SolverTraitLangItem::Sized => LangItem::Sized,
- SolverTraitLangItem::MetaSized => LangItem::MetaSized,
- SolverTraitLangItem::PointeeSized => LangItem::PointeeSized,
- SolverTraitLangItem::TransmuteTrait => LangItem::TransmuteTrait,
- SolverTraitLangItem::Tuple => LangItem::Tuple,
- SolverTraitLangItem::Unpin => LangItem::Unpin,
- SolverTraitLangItem::Unsize => LangItem::Unsize,
+ SolverTraitLangItem::Future => lang_items.Future,
+ SolverTraitLangItem::Iterator => lang_items.Iterator,
+ SolverTraitLangItem::PointeeTrait => lang_items.PointeeTrait,
+ SolverTraitLangItem::Sized => lang_items.Sized,
+ SolverTraitLangItem::MetaSized => lang_items.MetaSized,
+ SolverTraitLangItem::PointeeSized => lang_items.PointeeSized,
+ SolverTraitLangItem::TransmuteTrait => lang_items.TransmuteTrait,
+ SolverTraitLangItem::Tuple => lang_items.Tuple,
+ SolverTraitLangItem::Unpin => lang_items.Unpin,
+ SolverTraitLangItem::Unsize => lang_items.Unsize,
SolverTraitLangItem::BikeshedGuaranteedNoDrop => {
unimplemented!()
}
};
- lang_item
- .resolve_trait(self.db(), self.krate.expect("Must have self.krate"))
- .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found."))
- .into()
+ lang_item.expect("Lang item required but not found.").into()
}
fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> AdtIdWrapper {
+ let lang_items = self.lang_items();
let lang_item = match lang_item {
- SolverAdtLangItem::Option => LangItem::Option,
- SolverAdtLangItem::Poll => LangItem::Poll,
+ SolverAdtLangItem::Option => lang_items.Option,
+ SolverAdtLangItem::Poll => lang_items.Poll,
};
- lang_item
- .resolve_adt(self.db(), self.krate.expect("Must have self.krate"))
- .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found."))
- .into()
+ AdtIdWrapper(lang_item.expect("Lang item required but not found.").into())
}
fn is_lang_item(self, def_id: Self::DefId, lang_item: SolverLangItem) -> bool {
@@ -1512,8 +1543,41 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
}
fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool {
- self.as_trait_lang_item(def_id)
- .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item))
+ is_lang_item!(
+ SolverTraitLangItem, self, def_id.0, lang_item;
+
+ ignore = {
+ AsyncFnKindHelper,
+ AsyncIterator,
+ BikeshedGuaranteedNoDrop,
+ FusedIterator,
+ AsyncFnOnceOutput, // This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver.
+ }
+
+ Sized,
+ MetaSized,
+ PointeeSized,
+ Unsize,
+ Copy,
+ Clone,
+ DiscriminantKind,
+ PointeeTrait,
+ FnPtrTrait,
+ Drop,
+ Destruct,
+ TransmuteTrait,
+ Fn,
+ FnMut,
+ FnOnce,
+ Future,
+ Coroutine,
+ Unpin,
+ Tuple,
+ Iterator,
+ AsyncFn,
+ AsyncFnMut,
+ AsyncFnOnce,
+ )
}
fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool {
@@ -1523,43 +1587,57 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
}
fn as_lang_item(self, def_id: Self::DefId) -> Option<SolverLangItem> {
- let def_id: AttrDefId = match def_id {
- SolverDefId::TraitId(id) => id.into(),
- SolverDefId::TypeAliasId(id) => id.into(),
- SolverDefId::AdtId(id) => id.into(),
- _ => panic!("Unexpected SolverDefId in as_lang_item"),
- };
- let lang_item = self.db().lang_attr(def_id)?;
- as_lang_item!(
- SolverLangItem, lang_item;
+ match def_id {
+ SolverDefId::TypeAliasId(id) => {
+ as_lang_item!(
+ SolverLangItem, self, id;
- ignore = {
- AsyncFnKindUpvars,
- }
-
- Metadata,
- DynMetadata,
- CoroutineReturn,
- CoroutineYield,
- FutureOutput,
- AsyncFnOnceOutput,
- CallRefFuture,
- CallOnceFuture,
- AsyncFnOnceOutput,
- )
+ ignore = {
+ AsyncFnKindUpvars,
+ DynMetadata,
+ }
+
+ Metadata,
+ CoroutineReturn,
+ CoroutineYield,
+ FutureOutput,
+ CallRefFuture,
+ CallOnceFuture,
+ AsyncFnOnceOutput,
+ )
+ }
+ SolverDefId::AdtId(AdtId::StructId(id)) => {
+ as_lang_item!(
+ SolverLangItem, self, id;
+
+ ignore = {
+ AsyncFnKindUpvars,
+ Metadata,
+ CoroutineReturn,
+ CoroutineYield,
+ FutureOutput,
+ CallRefFuture,
+ CallOnceFuture,
+ AsyncFnOnceOutput,
+ }
+
+ DynMetadata,
+ )
+ }
+ _ => panic!("Unexpected SolverDefId in as_lang_item"),
+ }
}
fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem> {
- let def_id: AttrDefId = def_id.0.into();
- let lang_item = self.db().lang_attr(def_id)?;
as_lang_item!(
- SolverTraitLangItem, lang_item;
+ SolverTraitLangItem, self, def_id.0;
ignore = {
AsyncFnKindHelper,
AsyncIterator,
BikeshedGuaranteedNoDrop,
FusedIterator,
+ AsyncFnOnceOutput, // This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver.
}
Sized,
@@ -1585,16 +1663,15 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
AsyncFn,
AsyncFnMut,
AsyncFnOnce,
- AsyncFnOnceOutput,
- AsyncFnOnceOutput,
)
}
fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option<SolverAdtLangItem> {
- let def_id: AttrDefId = def_id.0.into();
- let lang_item = self.db().lang_attr(def_id)?;
+ let AdtId::EnumId(def_id) = def_id.0 else {
+ panic!("Unexpected SolverDefId in as_adt_lang_item");
+ };
as_lang_item!(
- SolverAdtLangItem, lang_item;
+ SolverAdtLangItem, self, def_id;
ignore = {}
@@ -1603,99 +1680,170 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
)
}
- fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator<Item = Self::DefId> {
- let trait_ = match def_id {
- SolverDefId::TraitId(id) => id,
- _ => unreachable!(),
- };
- trait_.trait_items(self.db()).associated_types().map(|id| id.into())
+ fn associated_type_def_ids(
+ self,
+ def_id: Self::TraitId,
+ ) -> impl IntoIterator<Item = Self::DefId> {
+ def_id.0.trait_items(self.db()).associated_types().map(|id| id.into())
}
fn for_each_relevant_impl(
self,
- trait_: Self::TraitId,
+ trait_def_id: Self::TraitId,
self_ty: Self::Ty,
mut f: impl FnMut(Self::ImplId),
) {
- let trait_ = trait_.0;
- let self_ty_fp = TyFingerprint::for_trait_impl_ns(&self_ty);
- let fps: &[TyFingerprint] = match self_ty.kind() {
- TyKind::Infer(InferTy::IntVar(..)) => &ALL_INT_FPS,
- TyKind::Infer(InferTy::FloatVar(..)) => &ALL_FLOAT_FPS,
- _ => self_ty_fp.as_slice(),
- };
-
- if fps.is_empty() {
- for_trait_impls(
- self.db(),
- self.krate.expect("Must have self.krate"),
- self.block,
- trait_,
- self_ty_fp,
- |impls| {
- for i in impls.for_trait(trait_) {
- use rustc_type_ir::TypeVisitable;
- let contains_errors = self.db().impl_trait_ns(i).map_or(false, |b| {
- b.skip_binder().visit_with(&mut ContainsTypeErrors).is_break()
- });
- if contains_errors {
- continue;
- }
-
- f(i.into());
+ let krate = self.krate.expect("trait solving requires setting `DbInterner::krate`");
+ let trait_block = trait_def_id.0.loc(self.db).container.containing_block();
+ let mut consider_impls_for_simplified_type = |simp: SimplifiedType| {
+ let type_block = simp.def().and_then(|def_id| {
+ let module = match def_id {
+ SolverDefId::AdtId(AdtId::StructId(id)) => id.module(self.db),
+ SolverDefId::AdtId(AdtId::EnumId(id)) => id.module(self.db),
+ SolverDefId::AdtId(AdtId::UnionId(id)) => id.module(self.db),
+ SolverDefId::TraitId(id) => id.module(self.db),
+ SolverDefId::TypeAliasId(id) => id.module(self.db),
+ SolverDefId::ConstId(_)
+ | SolverDefId::FunctionId(_)
+ | SolverDefId::ImplId(_)
+ | SolverDefId::StaticId(_)
+ | SolverDefId::InternedClosureId(_)
+ | SolverDefId::InternedCoroutineId(_)
+ | SolverDefId::InternedOpaqueTyId(_)
+ | SolverDefId::EnumVariantId(_)
+ | SolverDefId::Ctor(_) => return None,
+ };
+ module.containing_block()
+ });
+ TraitImpls::for_each_crate_and_block_trait_and_type(
+ self.db,
+ krate,
+ type_block,
+ trait_block,
+ &mut |impls| {
+ for &impl_ in impls.for_trait_and_self_ty(trait_def_id.0, &simp) {
+ f(impl_.into());
}
- ControlFlow::Continue(())
},
);
- } else {
- for_trait_impls(
- self.db(),
- self.krate.expect("Must have self.krate"),
- self.block,
- trait_,
- self_ty_fp,
- |impls| {
- for fp in fps {
- for i in impls.for_trait_and_self_ty(trait_, *fp) {
- use rustc_type_ir::TypeVisitable;
- let contains_errors = self.db().impl_trait_ns(i).map_or(false, |b| {
- b.skip_binder().visit_with(&mut ContainsTypeErrors).is_break()
- });
- if contains_errors {
- continue;
- }
+ };
- f(i.into());
- }
- }
- ControlFlow::Continue(())
- },
- );
+ match self_ty.kind() {
+ TyKind::Bool
+ | TyKind::Char
+ | TyKind::Int(_)
+ | TyKind::Uint(_)
+ | TyKind::Float(_)
+ | TyKind::Adt(_, _)
+ | TyKind::Foreign(_)
+ | TyKind::Str
+ | TyKind::Array(_, _)
+ | TyKind::Pat(_, _)
+ | TyKind::Slice(_)
+ | TyKind::RawPtr(_, _)
+ | TyKind::Ref(_, _, _)
+ | TyKind::FnDef(_, _)
+ | TyKind::FnPtr(..)
+ | TyKind::Dynamic(_, _)
+ | TyKind::Closure(..)
+ | TyKind::CoroutineClosure(..)
+ | TyKind::Coroutine(_, _)
+ | TyKind::Never
+ | TyKind::Tuple(_)
+ | TyKind::UnsafeBinder(_) => {
+ let simp =
+ fast_reject::simplify_type(self, self_ty, fast_reject::TreatParams::AsRigid)
+ .unwrap();
+ consider_impls_for_simplified_type(simp);
+ }
+
+ // HACK: For integer and float variables we have to manually look at all impls
+ // which have some integer or float as a self type.
+ TyKind::Infer(InferTy::IntVar(_)) => {
+ use IntTy::*;
+ use UintTy::*;
+ // This causes a compiler error if any new integer kinds are added.
+ let (I8 | I16 | I32 | I64 | I128 | Isize): IntTy;
+ let (U8 | U16 | U32 | U64 | U128 | Usize): UintTy;
+ let possible_integers = [
+ // signed integers
+ SimplifiedType::Int(I8),
+ SimplifiedType::Int(I16),
+ SimplifiedType::Int(I32),
+ SimplifiedType::Int(I64),
+ SimplifiedType::Int(I128),
+ SimplifiedType::Int(Isize),
+ // unsigned integers
+ SimplifiedType::Uint(U8),
+ SimplifiedType::Uint(U16),
+ SimplifiedType::Uint(U32),
+ SimplifiedType::Uint(U64),
+ SimplifiedType::Uint(U128),
+ SimplifiedType::Uint(Usize),
+ ];
+ for simp in possible_integers {
+ consider_impls_for_simplified_type(simp);
+ }
+ }
+
+ TyKind::Infer(InferTy::FloatVar(_)) => {
+ // This causes a compiler error if any new float kinds are added.
+ let (FloatTy::F16 | FloatTy::F32 | FloatTy::F64 | FloatTy::F128);
+ let possible_floats = [
+ SimplifiedType::Float(FloatTy::F16),
+ SimplifiedType::Float(FloatTy::F32),
+ SimplifiedType::Float(FloatTy::F64),
+ SimplifiedType::Float(FloatTy::F128),
+ ];
+
+ for simp in possible_floats {
+ consider_impls_for_simplified_type(simp);
+ }
+ }
+
+ // The only traits applying to aliases and placeholders are blanket impls.
+ //
+ // Impls which apply to an alias after normalization are handled by
+ // `assemble_candidates_after_normalizing_self_ty`.
+ TyKind::Alias(_, _) | TyKind::Placeholder(..) | TyKind::Error(_) => (),
+
+ // FIXME: These should ideally not exist as a self type. It would be nice for
+ // the builtin auto trait impls of coroutines to instead directly recurse
+ // into the witness.
+ TyKind::CoroutineWitness(..) => (),
+
+ // These variants should not exist as a self type.
+ TyKind::Infer(
+ InferTy::TyVar(_)
+ | InferTy::FreshTy(_)
+ | InferTy::FreshIntTy(_)
+ | InferTy::FreshFloatTy(_),
+ )
+ | TyKind::Param(_)
+ | TyKind::Bound(_, _) => panic!("unexpected self type: {self_ty:?}"),
}
+
+ self.for_each_blanket_impl(trait_def_id, f)
}
fn for_each_blanket_impl(self, trait_def_id: Self::TraitId, mut f: impl FnMut(Self::ImplId)) {
let Some(krate) = self.krate else { return };
+ let block = trait_def_id.0.loc(self.db).container.containing_block();
- for impls in self.db.trait_impls_in_deps(krate).iter() {
- for impl_id in impls.for_trait(trait_def_id.0) {
- let impl_data = self.db.impl_signature(impl_id);
- let self_ty_ref = &impl_data.store[impl_data.self_ty];
- if matches!(self_ty_ref, hir_def::type_ref::TypeRef::TypeParam(_)) {
- f(impl_id.into());
- }
+ TraitImpls::for_each_crate_and_block(self.db, krate, block, &mut |impls| {
+ for &impl_ in impls.blanket_impls(trait_def_id.0) {
+ f(impl_.into());
}
- }
+ });
}
- fn has_item_definition(self, def_id: Self::DefId) -> bool {
+ fn has_item_definition(self, _def_id: Self::DefId) -> bool {
// FIXME(next-solver): should check if the associated item has a value.
true
}
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)]
@@ -1704,7 +1852,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
impl_id: Self::ImplId,
) -> EarlyBinder<Self, rustc_type_ir::TraitRef<Self>> {
let db = self.db();
- db.impl_trait_ns(impl_id.0)
+ db.impl_trait(impl_id.0)
// ImplIds for impls where the trait ref can't be resolved should never reach trait solving
.expect("invalid impl passed to trait solver")
}
@@ -1737,38 +1885,54 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
trait_data.flags.contains(TraitFlags::FUNDAMENTAL)
}
- fn trait_may_be_implemented_via_object(self, trait_def_id: Self::TraitId) -> bool {
+ fn trait_may_be_implemented_via_object(self, _trait_def_id: Self::TraitId) -> bool {
// FIXME(next-solver): should check the `TraitFlags` for
// the `#[rustc_do_not_implement_via_object]` flag
true
}
- fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool {
+ fn is_impl_trait_in_trait(self, _def_id: Self::DefId) -> bool {
// FIXME(next-solver)
false
}
fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed {
- panic!("Bug encountered in next-trait-solver.")
- }
-
- fn is_general_coroutine(self, coroutine_def_id: Self::CoroutineId) -> bool {
- // FIXME(next-solver)
- true
+ panic!("Bug encountered in next-trait-solver: {}", msg.to_string())
+ }
+
+ fn is_general_coroutine(self, def_id: Self::CoroutineId) -> bool {
+ // FIXME: Make this a query? I don't believe this can be accessed from bodies other than
+ // the current infer query, except with revealed opaques - is it rare enough to not matter?
+ let InternedCoroutine(owner, expr_id) = def_id.0.loc(self.db);
+ let body = self.db.body(owner);
+ matches!(
+ body[expr_id],
+ hir_def::hir::Expr::Closure {
+ closure_kind: hir_def::hir::ClosureKind::Coroutine(_),
+ ..
+ }
+ )
}
- fn coroutine_is_async(self, coroutine_def_id: Self::CoroutineId) -> bool {
- // FIXME(next-solver)
- true
+ fn coroutine_is_async(self, def_id: Self::CoroutineId) -> bool {
+ // FIXME: Make this a query? I don't believe this can be accessed from bodies other than
+ // the current infer query, except with revealed opaques - is it rare enough to not matter?
+ let InternedCoroutine(owner, expr_id) = def_id.0.loc(self.db);
+ let body = self.db.body(owner);
+ matches!(
+ body[expr_id],
+ hir_def::hir::Expr::Closure { closure_kind: hir_def::hir::ClosureKind::Async, .. }
+ | hir_def::hir::Expr::Async { .. }
+ )
}
- fn coroutine_is_gen(self, coroutine_def_id: Self::CoroutineId) -> bool {
- // FIXME(next-solver)
+ fn coroutine_is_gen(self, _coroutine_def_id: Self::CoroutineId) -> bool {
+ // We don't handle gen coroutines yet.
false
}
- fn coroutine_is_async_gen(self, coroutine_def_id: Self::CoroutineId) -> bool {
- // FIXME(next-solver)
+ fn coroutine_is_async_gen(self, _coroutine_def_id: Self::CoroutineId) -> bool {
+ // We don't handle gen coroutines yet.
false
}
@@ -1795,7 +1959,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
return UnsizingParams(DenseBitSet::new_empty(num_params));
};
- let field_types = self.db().field_types_ns(variant.id());
+ let field_types = self.db().field_types(variant.id());
let mut unsizing_params = DenseBitSet::new_empty(num_params);
let ty = field_types[tail_field.0];
for arg in ty.instantiate_identity().walk() {
@@ -1861,19 +2025,52 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
Binder::bind_with_vars(inner, bound_vars)
}
- fn opaque_types_defined_by(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds {
- // FIXME(next-solver)
- SolverDefIds::new_from_iter(self, [])
+ fn opaque_types_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
+ let Ok(def_id) = DefWithBodyId::try_from(def_id) else {
+ return SolverDefIds::default();
+ };
+ let mut result = Vec::new();
+ crate::opaques::opaque_types_defined_by(self.db, def_id, &mut result);
+ SolverDefIds::new_from_iter(self, result)
}
- fn alias_has_const_conditions(self, def_id: Self::DefId) -> bool {
+ fn opaque_types_and_coroutines_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
+ let Ok(def_id) = DefWithBodyId::try_from(def_id) else {
+ return SolverDefIds::default();
+ };
+ let mut result = Vec::new();
+
+ crate::opaques::opaque_types_defined_by(self.db, def_id, &mut result);
+
+ // Collect coroutines.
+ let body = self.db.body(def_id);
+ body.exprs().for_each(|(expr_id, expr)| {
+ if matches!(
+ expr,
+ hir_def::hir::Expr::Async { .. }
+ | hir_def::hir::Expr::Closure {
+ closure_kind: hir_def::hir::ClosureKind::Async
+ | hir_def::hir::ClosureKind::Coroutine(_),
+ ..
+ }
+ ) {
+ let coroutine =
+ InternedCoroutineId::new(self.db, InternedCoroutine(def_id, expr_id));
+ result.push(coroutine.into());
+ }
+ });
+
+ SolverDefIds::new_from_iter(self, result)
+ }
+
+ fn alias_has_const_conditions(self, _def_id: Self::DefId) -> bool {
// FIXME(next-solver)
false
}
fn explicit_implied_const_bounds(
self,
- def_id: Self::DefId,
+ _def_id: Self::DefId,
) -> EarlyBinder<
Self,
impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
@@ -1890,14 +2087,14 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
self.db().function_signature(id).flags.contains(FnFlags::CONST)
}
- fn impl_is_const(self, def_id: Self::ImplId) -> bool {
+ fn impl_is_const(self, _def_id: Self::ImplId) -> bool {
false
}
fn opt_alias_variances(
self,
- kind: impl Into<rustc_type_ir::AliasTermKind>,
- def_id: Self::DefId,
+ _kind: impl Into<rustc_type_ir::AliasTermKind>,
+ _def_id: Self::DefId,
) -> Option<Self::VariancesOf> {
None
}
@@ -1908,13 +2105,10 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
let impl_trait_id = self.db().lookup_intern_impl_trait_id(opaque);
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))
+ crate::opaques::rpit_hidden_types(self.db, func)[idx]
}
- crate::ImplTraitId::TypeAliasImplTrait(..)
- | crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
- // FIXME(next-solver)
- EarlyBinder::bind(Ty::new_error(self, ErrorGuaranteed))
+ crate::ImplTraitId::TypeAliasImplTrait(type_alias, idx) => {
+ crate::opaques::tait_hidden_types(self.db, type_alias)[idx]
}
}
}
@@ -1924,11 +2118,13 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
fn coroutine_hidden_types(
self,
- def_id: Self::CoroutineId,
- ) -> EarlyBinder<Self, rustc_type_ir::Binder<Self, rustc_type_ir::CoroutineWitnessTypes<Self>>>
- {
- // FIXME(next-solver)
- unimplemented!()
+ _def_id: Self::CoroutineId,
+ ) -> EarlyBinder<Self, Binder<'db, CoroutineWitnessTypes<Self>>> {
+ // FIXME: Actually implement this.
+ EarlyBinder::bind(Binder::dummy(CoroutineWitnessTypes {
+ types: Tys::default(),
+ assumptions: RegionAssumptions::default(),
+ }))
}
fn is_default_trait(self, def_id: Self::TraitId) -> bool {
@@ -1943,26 +2139,26 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
self.db().trait_signature(trait_.0).flags.contains(TraitFlags::UNSAFE)
}
- fn impl_self_is_guaranteed_unsized(self, def_id: Self::ImplId) -> bool {
+ fn impl_self_is_guaranteed_unsized(self, _def_id: Self::ImplId) -> bool {
false
}
- fn impl_specializes(self, impl_def_id: Self::ImplId, victim_def_id: Self::ImplId) -> bool {
- false
+ fn impl_specializes(
+ self,
+ specializing_impl_def_id: Self::ImplId,
+ parent_impl_def_id: Self::ImplId,
+ ) -> bool {
+ crate::specialization::specializes(
+ self.db,
+ specializing_impl_def_id.0,
+ parent_impl_def_id.0,
+ )
}
fn next_trait_solver_globally(self) -> bool {
true
}
- fn opaque_types_and_coroutines_defined_by(
- self,
- defining_anchor: Self::LocalDefId,
- ) -> Self::LocalDefIds {
- // FIXME(next-solver)
- unimplemented!()
- }
-
type Probe = rustc_type_ir::solve::inspect::Probe<DbInterner<'db>>;
fn mk_probe(self, probe: rustc_type_ir::solve::inspect::Probe<Self>) -> Self::Probe {
probe
@@ -1976,6 +2172,13 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
Self,
>(self, canonical_goal)
}
+
+ fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool {
+ matches!(
+ self.as_trait_lang_item(def_id),
+ Some(SolverTraitLangItem::Sized | SolverTraitLangItem::MetaSized)
+ )
+ }
}
impl<'db> DbInterner<'db> {
@@ -2095,6 +2298,7 @@ TrivialTypeTraversalImpls! {
CoroutineIdWrapper,
AdtIdWrapper,
ImplIdWrapper,
+ GeneralConstIdWrapper,
Pattern<'db>,
Safety,
FnAbi,
@@ -2108,6 +2312,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;
@@ -2152,4 +2467,12 @@ mod tls_cache {
})
})
}
+
+ /// Clears the thread-local trait solver cache.
+ ///
+ /// Should be called before getting memory usage estimations, as the solver cache
+ /// is per-revision and usually should be excluded from estimations.
+ pub fn clear_tls_solver_cache() {
+ GLOBAL_CACHE.with_borrow_mut(|handle| *handle = None);
+ }
}