Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock24
-rw-r--r--Cargo.toml4
-rw-r--r--crates/hir-ty/Cargo.toml2
-rw-r--r--crates/hir-ty/src/builder.rs211
-rw-r--r--crates/hir-ty/src/chalk_db.rs9
-rw-r--r--crates/hir-ty/src/chalk_ext.rs46
-rw-r--r--crates/hir-ty/src/consteval_chalk.rs108
-rw-r--r--crates/hir-ty/src/db.rs233
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs2
-rw-r--r--crates/hir-ty/src/display.rs22
-rw-r--r--crates/hir-ty/src/drop.rs4
-rw-r--r--crates/hir-ty/src/dyn_compatibility.rs52
-rw-r--r--crates/hir-ty/src/generics.rs47
-rw-r--r--crates/hir-ty/src/infer.rs14
-rw-r--r--crates/hir-ty/src/infer/cast.rs2
-rw-r--r--crates/hir-ty/src/infer/diagnostics.rs4
-rw-r--r--crates/hir-ty/src/infer/expr.rs10
-rw-r--r--crates/hir-ty/src/infer/mutability.rs2
-rw-r--r--crates/hir-ty/src/infer/pat.rs6
-rw-r--r--crates/hir-ty/src/infer/path.rs4
-rw-r--r--crates/hir-ty/src/infer/unify.rs2
-rw-r--r--crates/hir-ty/src/inhabitedness.rs2
-rw-r--r--crates/hir-ty/src/interner.rs403
-rw-r--r--crates/hir-ty/src/layout.rs4
-rw-r--r--crates/hir-ty/src/lib.rs408
-rw-r--r--crates/hir-ty/src/lower.rs2073
-rw-r--r--crates/hir-ty/src/lower/path.rs769
-rw-r--r--crates/hir-ty/src/lower_nextsolver.rs2138
-rw-r--r--crates/hir-ty/src/lower_nextsolver/path.rs1327
-rw-r--r--crates/hir-ty/src/mapping.rs169
-rw-r--r--crates/hir-ty/src/method_resolution.rs15
-rw-r--r--crates/hir-ty/src/mir.rs2
-rw-r--r--crates/hir-ty/src/mir/eval.rs16
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs2
-rw-r--r--crates/hir-ty/src/mir/eval/shim/simd.rs2
-rw-r--r--crates/hir-ty/src/next_solver.rs2
-rw-r--r--crates/hir-ty/src/next_solver/consts.rs3
-rw-r--r--crates/hir-ty/src/next_solver/generic_arg.rs4
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs19
-rw-r--r--crates/hir-ty/src/next_solver/mapping.rs1733
-rw-r--r--crates/hir-ty/src/next_solver/predicate.rs5
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs8
-rw-r--r--crates/hir-ty/src/next_solver/util.rs197
-rw-r--r--crates/hir-ty/src/tests/incremental.rs28
-rw-r--r--crates/hir-ty/src/tls.rs155
-rw-r--r--crates/hir-ty/src/traits.rs199
-rw-r--r--crates/hir-ty/src/utils.rs137
-rw-r--r--crates/hir-ty/src/variance.rs2
-rw-r--r--crates/hir/src/display.rs2
-rw-r--r--crates/hir/src/lib.rs18
-rw-r--r--crates/hir/src/source_analyzer.rs10
-rw-r--r--crates/ide/src/hover/tests.rs2
52 files changed, 2210 insertions, 8452 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 50ceab6c3a..ea8d1a781d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -259,28 +259,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
-name = "chalk-derive"
-version = "0.104.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ea9b1e80910f66ae87c772247591432032ef3f6a67367ff17f8343db05beafa"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "chalk-ir"
-version = "0.104.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7047a516de16226cd17344d41a319d0ea1064bf9e60bd612ab341ab4a34bbfa8"
-dependencies = [
- "bitflags 2.9.4",
- "chalk-derive",
-]
-
-[[package]]
name = "clap"
version = "4.5.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -777,8 +755,6 @@ dependencies = [
"arrayvec",
"base-db",
"bitflags 2.9.4",
- "chalk-derive",
- "chalk-ir",
"cov-mark",
"either",
"ena",
diff --git a/Cargo.toml b/Cargo.toml
index f94fd37e52..8a10897468 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -37,8 +37,6 @@ debug = 2
[patch.'crates-io']
# rowan = { path = "../rowan" }
-# chalk-ir = { path = "../chalk/chalk-ir" }
-# chalk-derive = { path = "../chalk/chalk-derive" }
# line-index = { path = "lib/line-index" }
# la-arena = { path = "lib/la-arena" }
# lsp-server = { path = "lib/lsp-server" }
@@ -110,8 +108,6 @@ arrayvec = "0.7.6"
bitflags = "2.9.1"
cargo_metadata = "0.21.0"
camino = "1.1.10"
-chalk-ir = "0.104.0"
-chalk-derive = "0.104.0"
crossbeam-channel = "0.5.15"
dissimilar = "1.0.10"
dot = "0.1.4"
diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml
index ec65633154..378a0f0382 100644
--- a/crates/hir-ty/Cargo.toml
+++ b/crates/hir-ty/Cargo.toml
@@ -24,8 +24,6 @@ oorandom = "11.1.5"
tracing.workspace = true
rustc-hash.workspace = true
scoped-tls = "1.0.1"
-chalk-ir.workspace = true
-chalk-derive.workspace = true
la-arena.workspace = true
triomphe.workspace = true
typed-arena = "2.0.2"
diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs
deleted file mode 100644
index 4cd0af28f3..0000000000
--- a/crates/hir-ty/src/builder.rs
+++ /dev/null
@@ -1,211 +0,0 @@
-//! `TyBuilder`, a helper for building instances of `Ty` and related types.
-
-use chalk_ir::{
- DebruijnIndex,
- cast::{Cast, Caster},
-};
-use hir_def::{GenericDefId, GenericParamId, TraitId};
-use smallvec::SmallVec;
-
-use crate::{
- BoundVar, GenericArg, GenericArgData, Interner, Substitution, TraitRef, Ty, TyKind,
- consteval::unknown_const_as_generic,
- db::HirDatabase,
- error_lifetime,
- generics::generics,
- infer::unify::InferenceTable,
- next_solver::{
- DbInterner, EarlyBinder,
- mapping::{ChalkToNextSolver, NextSolverToChalk},
- },
- to_chalk_trait_id,
-};
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub(crate) enum ParamKind {
- Type,
- Lifetime,
- Const(Ty),
-}
-
-/// This is a builder for `Ty` or anything that needs a `Substitution`.
-pub(crate) struct TyBuilder<D> {
- /// The `data` field is used to keep track of what we're building (e.g. an
- /// ADT, a `TraitRef`, ...).
- data: D,
- vec: SmallVec<[GenericArg; 2]>,
- param_kinds: SmallVec<[ParamKind; 2]>,
- parent_subst: Substitution,
-}
-
-impl<A> TyBuilder<A> {
- fn with_data<B>(self, data: B) -> TyBuilder<B> {
- TyBuilder {
- data,
- vec: self.vec,
- param_kinds: self.param_kinds,
- parent_subst: self.parent_subst,
- }
- }
-}
-
-impl<D> TyBuilder<D> {
- fn new(
- data: D,
- param_kinds: SmallVec<[ParamKind; 2]>,
- parent_subst: Option<Substitution>,
- ) -> Self {
- let parent_subst = parent_subst.unwrap_or_else(|| Substitution::empty(Interner));
- Self { data, vec: SmallVec::with_capacity(param_kinds.len()), param_kinds, parent_subst }
- }
-
- fn build_internal(self) -> (D, Substitution) {
- assert_eq!(
- self.vec.len(),
- self.param_kinds.len(),
- "{} args received, {} expected ({:?})",
- self.vec.len(),
- self.param_kinds.len(),
- &self.param_kinds
- );
- for (a, e) in self.vec.iter().zip(self.param_kinds.iter()) {
- self.assert_match_kind(a, e);
- }
- let subst = Substitution::from_iter(
- Interner,
- self.parent_subst.iter(Interner).cloned().chain(self.vec),
- );
- (self.data, subst)
- }
-
- pub(crate) fn remaining(&self) -> usize {
- self.param_kinds.len() - self.vec.len()
- }
-
- pub(crate) fn fill_with_bound_vars(
- self,
- debruijn: DebruijnIndex,
- starting_from: usize,
- ) -> Self {
- // self.fill is inlined to make borrow checker happy
- let mut this = self;
- let other = &this.param_kinds[this.vec.len()..];
- let filler = (starting_from..).zip(other).map(|(idx, kind)| match kind {
- ParamKind::Type => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner),
- ParamKind::Const(ty) => {
- BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner)
- }
- ParamKind::Lifetime => {
- BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
- }
- });
- this.vec.extend(filler.take(this.remaining()).casted(Interner));
- assert_eq!(this.remaining(), 0);
- this
- }
-
- #[tracing::instrument(skip_all)]
- pub(crate) fn fill_with_inference_vars(self, table: &mut InferenceTable<'_>) -> Self {
- self.fill(|x| {
- match x {
- ParamKind::Type => crate::next_solver::GenericArg::Ty(table.next_ty_var()),
- ParamKind::Const(_) => table.next_const_var().into(),
- ParamKind::Lifetime => table.next_region_var().into(),
- }
- .to_chalk(table.interner())
- })
- }
-
- pub(crate) fn fill(mut self, filler: impl FnMut(&ParamKind) -> GenericArg) -> Self {
- self.vec.extend(self.param_kinds[self.vec.len()..].iter().map(filler));
- assert_eq!(self.remaining(), 0);
- self
- }
-
- fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
- match (a.data(Interner), e) {
- (GenericArgData::Ty(_), ParamKind::Type)
- | (GenericArgData::Const(_), ParamKind::Const(_))
- | (GenericArgData::Lifetime(_), ParamKind::Lifetime) => (),
- _ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds),
- }
- }
-}
-
-impl TyBuilder<()> {
- pub(crate) fn usize() -> Ty {
- TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(Interner)
- }
-
- pub(crate) fn unknown_subst(
- db: &dyn HirDatabase,
- def: impl Into<GenericDefId>,
- ) -> Substitution {
- let interner = DbInterner::conjure();
- let params = generics(db, def.into());
- Substitution::from_iter(
- Interner,
- params.iter_id().map(|id| match id {
- GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
- GenericParamId::ConstParamId(id) => {
- unknown_const_as_generic(db.const_param_ty_ns(id))
- .to_chalk(interner)
- .cast(Interner)
- }
- GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
- }),
- )
- }
-
- #[tracing::instrument(skip_all)]
- pub(crate) fn subst_for_def(
- db: &dyn HirDatabase,
- def: impl Into<GenericDefId>,
- parent_subst: Option<Substitution>,
- ) -> TyBuilder<()> {
- let generics = generics(db, def.into());
- assert!(generics.parent_generics().is_some() == parent_subst.is_some());
- let params = generics
- .iter_self()
- .map(|(id, _data)| match id {
- GenericParamId::TypeParamId(_) => ParamKind::Type,
- GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)),
- GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
- })
- .collect();
- TyBuilder::new((), params, parent_subst)
- }
-
- pub(crate) fn build(self) -> Substitution {
- let ((), subst) = self.build_internal();
- subst
- }
-}
-
-impl TyBuilder<TraitId> {
- pub(crate) fn trait_ref(db: &dyn HirDatabase, def: TraitId) -> TyBuilder<TraitId> {
- TyBuilder::subst_for_def(db, def, None).with_data(def)
- }
-
- pub(crate) fn build(self) -> TraitRef {
- let (trait_id, substitution) = self.build_internal();
- TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
- }
-}
-
-impl<'db, T: rustc_type_ir::TypeFoldable<DbInterner<'db>>> TyBuilder<EarlyBinder<'db, T>> {
- pub(crate) fn build(self, interner: DbInterner<'db>) -> T {
- let (b, subst) = self.build_internal();
- let args: crate::next_solver::GenericArgs<'db> = subst.to_nextsolver(interner);
- b.instantiate(interner, args)
- }
-}
-
-impl<'db> TyBuilder<EarlyBinder<'db, crate::next_solver::Ty<'db>>> {
- pub(crate) fn impl_self_ty(
- db: &'db dyn HirDatabase,
- def: hir_def::ImplId,
- ) -> TyBuilder<EarlyBinder<'db, crate::next_solver::Ty<'db>>> {
- TyBuilder::subst_for_def(db, def, None).with_data(db.impl_self_ty(def))
- }
-}
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
deleted file mode 100644
index a6b859b372..0000000000
--- a/crates/hir-ty/src/chalk_db.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//! The implementation of `RustIrDatabase` for Chalk, which provides information
-//! about the code that Chalk needs.
-
-use crate::Interner;
-
-pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
-pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
-pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
-pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs
deleted file mode 100644
index 4ea563d46e..0000000000
--- a/crates/hir-ty/src/chalk_ext.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-//! Various extensions traits for Chalk types.
-
-use hir_def::{ItemContainerId, Lookup, TraitId};
-
-use crate::{
- Interner, ProjectionTy, Substitution, TraitRef, Ty, db::HirDatabase, from_assoc_type_id,
- from_chalk_trait_id, generics::generics, to_chalk_trait_id,
-};
-
-pub(crate) trait ProjectionTyExt {
- fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef;
- fn trait_(&self, db: &dyn HirDatabase) -> TraitId;
- fn self_type_parameter(&self, db: &dyn HirDatabase) -> Ty;
-}
-
-impl ProjectionTyExt for ProjectionTy {
- fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
- // FIXME: something like `Split` trait from chalk-solve might be nice.
- let generics = generics(db, from_assoc_type_id(self.associated_ty_id).into());
- let parent_len = generics.parent_generics().map_or(0, |g| g.len_self());
- let substitution =
- Substitution::from_iter(Interner, self.substitution.iter(Interner).take(parent_len));
- TraitRef { trait_id: to_chalk_trait_id(self.trait_(db)), substitution }
- }
-
- fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
- match from_assoc_type_id(self.associated_ty_id).lookup(db).container {
- ItemContainerId::TraitId(it) => it,
- _ => panic!("projection ty without parent trait"),
- }
- }
-
- fn self_type_parameter(&self, db: &dyn HirDatabase) -> Ty {
- self.trait_ref(db).self_type_parameter(Interner)
- }
-}
-
-pub(crate) trait TraitRefExt {
- fn hir_trait_id(&self) -> TraitId;
-}
-
-impl TraitRefExt for TraitRef {
- fn hir_trait_id(&self) -> TraitId {
- from_chalk_trait_id(self.trait_id)
- }
-}
diff --git a/crates/hir-ty/src/consteval_chalk.rs b/crates/hir-ty/src/consteval_chalk.rs
deleted file mode 100644
index 07b783ea92..0000000000
--- a/crates/hir-ty/src/consteval_chalk.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-//! Constant evaluation details
-
-use base_db::Crate;
-use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast};
-use hir_def::{
- expr_store::{HygieneId, path::Path},
- resolver::{Resolver, ValueNs},
- type_ref::LiteralConstRef,
-};
-use stdx::never;
-
-use crate::{
- Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution,
- TraitEnvironment, Ty,
- db::HirDatabase,
- generics::Generics,
- lower::ParamLoweringMode,
- next_solver::{DbInterner, mapping::ChalkToNextSolver},
- to_placeholder_idx,
-};
-
-pub(crate) fn path_to_const<'g>(
- db: &dyn HirDatabase,
- resolver: &Resolver<'_>,
- path: &Path,
- mode: ParamLoweringMode,
- args: impl FnOnce() -> &'g Generics,
- debruijn: DebruijnIndex,
- expected_ty: Ty,
-) -> Option<Const> {
- match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) {
- Some(ValueNs::GenericParam(p)) => {
- let ty = db.const_param_ty(p);
- let args = args();
- let value = match mode {
- ParamLoweringMode::Placeholder => {
- let idx = args.type_or_const_param_idx(p.into()).unwrap();
- ConstValue::Placeholder(to_placeholder_idx(db, p.into(), idx as u32))
- }
- ParamLoweringMode::Variable => match args.type_or_const_param_idx(p.into()) {
- Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
- None => {
- never!(
- "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
- args,
- path,
- p
- );
- return None;
- }
- },
- };
- Some(ConstData { ty, value }.intern(Interner))
- }
- Some(ValueNs::ConstId(c)) => Some(intern_const_scalar(
- ConstScalar::UnevaluatedConst(c.into(), Substitution::empty(Interner)),
- expected_ty,
- )),
- // FIXME: With feature(adt_const_params), we also need to consider other things here, e.g. struct constructors.
- _ => None,
- }
-}
-
-pub(crate) fn unknown_const(ty: Ty) -> Const {
- ConstData {
- ty,
- value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: ConstScalar::Unknown }),
- }
- .intern(Interner)
-}
-
-pub(crate) fn unknown_const_as_generic(ty: Ty) -> GenericArg {
- unknown_const(ty).cast(Interner)
-}
-
-/// Interns a constant scalar with the given type
-pub(crate) fn intern_const_scalar(value: ConstScalar, ty: Ty) -> Const {
- ConstData { ty, value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: value }) }
- .intern(Interner)
-}
-
-/// Interns a constant scalar with the given type
-pub(crate) fn intern_const_ref(
- db: &dyn HirDatabase,
- value: &LiteralConstRef,
- ty: Ty,
- krate: Crate,
-) -> Const {
- let interner = DbInterner::new_with(db, Some(krate), None);
- let layout = || db.layout_of_ty(ty.to_nextsolver(interner), TraitEnvironment::empty(krate));
- let bytes = match value {
- LiteralConstRef::Int(i) => {
- // FIXME: We should handle failure of layout better.
- let size = layout().map(|it| it.size.bytes_usize()).unwrap_or(16);
- ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default())
- }
- LiteralConstRef::UInt(i) => {
- let size = layout().map(|it| it.size.bytes_usize()).unwrap_or(16);
- ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default())
- }
- LiteralConstRef::Bool(b) => ConstScalar::Bytes(Box::new([*b as u8]), MemoryMap::default()),
- LiteralConstRef::Char(c) => {
- ConstScalar::Bytes((*c as u32).to_le_bytes().into(), MemoryMap::default())
- }
- LiteralConstRef::Unknown => ConstScalar::Unknown,
- };
- intern_const_scalar(bytes, ty)
-}
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index a4c19eea16..c79ff98578 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -1,8 +1,7 @@
//! The home of `HirDatabase`, which is the Salsa database containing all the
//! type inference-related queries.
-use base_db::Crate;
-use base_db::target::TargetLoadError;
+use base_db::{Crate, target::TargetLoadError};
use hir_def::{
AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId,
GeneralConstId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId,
@@ -16,13 +15,14 @@ use smallvec::SmallVec;
use triomphe::Arc;
use crate::{
- Binders, ImplTraitId, ImplTraits, InferenceResult, TraitEnvironment, Ty, TyDefId, ValueTyDefId,
+ ImplTraitId, InferenceResult, TraitEnvironment, TyDefId, ValueTyDefId,
consteval::ConstEvalError,
dyn_compatibility::DynCompatibilityViolation,
layout::{Layout, LayoutError},
- lower::{Diagnostics, GenericDefaults, GenericPredicates},
+ lower::{Diagnostics, GenericDefaults, GenericPredicates, ImplTraits},
method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
mir::{BorrowckResult, MirBody, MirLowerError},
+ next_solver::{Const, EarlyBinder, GenericArgs, PolyFnSig, TraitRef, Ty, VariancesOf},
};
#[query_group::query_group]
@@ -51,7 +51,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
fn monomorphized_mir_body<'db>(
&'db self,
def: DefWithBodyId,
- subst: crate::next_solver::GenericArgs<'db>,
+ subst: GenericArgs<'db>,
env: Arc<TraitEnvironment<'db>>,
) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>;
@@ -59,7 +59,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
fn monomorphized_mir_body_for_closure<'db>(
&'db self,
def: InternedClosureId,
- subst: crate::next_solver::GenericArgs<'db>,
+ subst: GenericArgs<'db>,
env: Arc<TraitEnvironment<'db>>,
) -> Result<Arc<MirBody<'db>>, MirLowerError<'db>>;
@@ -75,16 +75,13 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
fn const_eval<'db>(
&'db self,
def: GeneralConstId,
- subst: crate::next_solver::GenericArgs<'db>,
+ subst: GenericArgs<'db>,
trait_env: Option<Arc<TraitEnvironment<'db>>>,
- ) -> Result<crate::next_solver::Const<'db>, ConstEvalError<'db>>;
+ ) -> Result<Const<'db>, ConstEvalError<'db>>;
#[salsa::invoke(crate::consteval::const_eval_static_query)]
#[salsa::cycle(cycle_result = crate::consteval::const_eval_static_cycle_result)]
- fn const_eval_static<'db>(
- &'db self,
- def: StaticId,
- ) -> Result<crate::next_solver::Const<'db>, ConstEvalError<'db>>;
+ fn const_eval_static<'db>(&'db self, def: StaticId) -> Result<Const<'db>, ConstEvalError<'db>>;
#[salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
#[salsa::cycle(cycle_result = crate::consteval::const_eval_discriminant_cycle_result)]
@@ -99,8 +96,8 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
&'db self,
env: Arc<TraitEnvironment<'db>>,
func: FunctionId,
- fn_subst: crate::next_solver::GenericArgs<'db>,
- ) -> (FunctionId, crate::next_solver::GenericArgs<'db>);
+ fn_subst: GenericArgs<'db>,
+ ) -> (FunctionId, GenericArgs<'db>);
// endregion:mir
@@ -109,7 +106,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
fn layout_of_adt<'db>(
&'db self,
def: AdtId,
- args: crate::next_solver::GenericArgs<'db>,
+ args: GenericArgs<'db>,
trait_env: Arc<TraitEnvironment<'db>>,
) -> Result<Arc<Layout>, LayoutError>;
@@ -117,7 +114,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::cycle(cycle_result = crate::layout::layout_of_ty_cycle_result)]
fn layout_of_ty<'db>(
&'db self,
- ty: crate::next_solver::Ty<'db>,
+ ty: Ty<'db>,
env: Arc<TraitEnvironment<'db>>,
) -> Result<Arc<Layout>, LayoutError>;
@@ -127,149 +124,130 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>;
- #[salsa::invoke(crate::lower_nextsolver::ty_query)]
+ #[salsa::invoke(crate::lower::ty_query)]
#[salsa::transparent]
- fn ty<'db>(
- &'db self,
- def: TyDefId,
- ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>;
+ fn ty<'db>(&'db self, def: TyDefId) -> EarlyBinder<'db, Ty<'db>>;
- #[salsa::invoke(crate::lower_nextsolver::type_for_type_alias_with_diagnostics_query)]
- #[salsa::cycle(cycle_result = crate::lower_nextsolver::type_for_type_alias_with_diagnostics_cycle_result)]
+ #[salsa::invoke(crate::lower::type_for_type_alias_with_diagnostics_query)]
+ #[salsa::cycle(cycle_result = crate::lower::type_for_type_alias_with_diagnostics_cycle_result)]
fn type_for_type_alias_with_diagnostics<'db>(
&'db self,
def: TypeAliasId,
- ) -> (crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>, Diagnostics);
+ ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics);
/// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is
/// a `StructId` or `EnumVariantId` with a record constructor.
- #[salsa::invoke(crate::lower_nextsolver::value_ty_query)]
- fn value_ty<'db>(
- &'db self,
- def: ValueTyDefId,
- ) -> Option<crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>>;
+ #[salsa::invoke(crate::lower::value_ty_query)]
+ fn value_ty<'db>(&'db self, def: ValueTyDefId) -> Option<EarlyBinder<'db, Ty<'db>>>;
- #[salsa::invoke(crate::lower_nextsolver::impl_self_ty_with_diagnostics_query)]
- #[salsa::cycle(cycle_result = crate::lower_nextsolver::impl_self_ty_with_diagnostics_cycle_result)]
+ #[salsa::invoke(crate::lower::impl_self_ty_with_diagnostics_query)]
+ #[salsa::cycle(cycle_result = crate::lower::impl_self_ty_with_diagnostics_cycle_result)]
fn impl_self_ty_with_diagnostics<'db>(
&'db self,
def: ImplId,
- ) -> (crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>, Diagnostics);
+ ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics);
- #[salsa::invoke(crate::lower_nextsolver::impl_self_ty_query)]
+ #[salsa::invoke(crate::lower::impl_self_ty_query)]
#[salsa::transparent]
- fn impl_self_ty<'db>(
- &'db self,
- def: ImplId,
- ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>;
+ fn impl_self_ty<'db>(&'db self, def: ImplId) -> EarlyBinder<'db, Ty<'db>>;
// FIXME: Make this a non-interned query.
- #[salsa::invoke_interned(crate::lower_nextsolver::const_param_ty_with_diagnostics_query)]
- #[salsa::cycle(cycle_result = crate::lower_nextsolver::const_param_ty_with_diagnostics_cycle_result)]
- fn const_param_ty_with_diagnostics<'db>(
- &'db self,
- def: ConstParamId,
- ) -> (crate::next_solver::Ty<'db>, Diagnostics);
+ #[salsa::invoke_interned(crate::lower::const_param_ty_with_diagnostics_query)]
+ #[salsa::cycle(cycle_result = crate::lower::const_param_ty_with_diagnostics_cycle_result)]
+ fn const_param_ty_with_diagnostics<'db>(&'db self, def: ConstParamId)
+ -> (Ty<'db>, Diagnostics);
- // FIXME: Make this a non-interned query.
- #[salsa::invoke_interned(crate::lower::const_param_ty_query)]
- #[salsa::cycle(cycle_result = crate::lower::const_param_ty_cycle_result)]
- fn const_param_ty(&self, def: ConstParamId) -> Ty;
+ #[salsa::invoke(crate::lower::const_param_ty_query)]
+ #[salsa::transparent]
+ fn const_param_ty_ns<'db>(&'db self, def: ConstParamId) -> Ty<'db>;
- #[salsa::invoke(crate::lower_nextsolver::impl_trait_with_diagnostics_query)]
+ #[salsa::invoke(crate::lower::impl_trait_with_diagnostics_query)]
fn impl_trait_with_diagnostics<'db>(
&'db self,
def: ImplId,
- ) -> Option<(
- crate::next_solver::EarlyBinder<'db, crate::next_solver::TraitRef<'db>>,
- Diagnostics,
- )>;
+ ) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)>;
- #[salsa::invoke(crate::lower_nextsolver::impl_trait_query)]
+ #[salsa::invoke(crate::lower::impl_trait_query)]
#[salsa::transparent]
- fn impl_trait<'db>(
- &'db self,
- def: ImplId,
- ) -> Option<crate::next_solver::EarlyBinder<'db, crate::next_solver::TraitRef<'db>>>;
+ fn impl_trait<'db>(&'db self, def: ImplId) -> Option<EarlyBinder<'db, TraitRef<'db>>>;
- #[salsa::invoke(crate::lower_nextsolver::field_types_with_diagnostics_query)]
+ #[salsa::invoke(crate::lower::field_types_with_diagnostics_query)]
fn field_types_with_diagnostics<'db>(
&'db self,
var: VariantId,
- ) -> (
- Arc<
- ArenaMap<
- LocalFieldId,
- crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>,
- >,
- >,
- Diagnostics,
- );
+ ) -> (Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>>, Diagnostics);
#[salsa::invoke(crate::lower::field_types_query)]
#[salsa::transparent]
- fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>;
+ fn field_types<'db>(
+ &'db self,
+ var: VariantId,
+ ) -> Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>>;
- #[salsa::invoke(crate::lower_nextsolver::callable_item_signature_query)]
+ #[salsa::invoke(crate::lower::callable_item_signature_query)]
fn callable_item_signature<'db>(
&'db self,
def: CallableDefId,
- ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::PolyFnSig<'db>>;
+ ) -> EarlyBinder<'db, PolyFnSig<'db>>;
#[salsa::invoke(crate::lower::return_type_impl_traits)]
- fn return_type_impl_traits(&self, def: FunctionId) -> Option<Arc<Binders<ImplTraits>>>;
+ fn return_type_impl_traits<'db>(
+ &'db self,
+ def: FunctionId,
+ ) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>>;
#[salsa::invoke(crate::lower::type_alias_impl_traits)]
- fn type_alias_impl_traits(&self, def: TypeAliasId) -> Option<Arc<Binders<ImplTraits>>>;
-
- #[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
- #[salsa::cycle(cycle_result = crate::lower::generic_predicates_for_param_cycle_result)]
- fn generic_predicates_for_param(
- &self,
- def: GenericDefId,
- param_id: TypeOrConstParamId,
- assoc_name: Option<Name>,
- ) -> GenericPredicates;
-
- #[salsa::invoke(crate::lower::generic_predicates_query)]
- fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates;
+ fn type_alias_impl_traits<'db>(
+ &'db self,
+ def: TypeAliasId,
+ ) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>>;
- #[salsa::invoke(
- crate::lower_nextsolver::generic_predicates_without_parent_with_diagnostics_query
- )]
+ #[salsa::invoke(crate::lower::generic_predicates_without_parent_with_diagnostics_query)]
fn generic_predicates_without_parent_with_diagnostics<'db>(
&'db self,
def: GenericDefId,
- ) -> (crate::lower_nextsolver::GenericPredicates<'db>, Diagnostics);
+ ) -> (GenericPredicates<'db>, Diagnostics);
- #[salsa::invoke(crate::lower_nextsolver::generic_predicates_without_parent_query)]
+ #[salsa::invoke(crate::lower::generic_predicates_without_parent_query)]
#[salsa::transparent]
fn generic_predicates_without_parent<'db>(
&'db self,
def: GenericDefId,
- ) -> crate::lower_nextsolver::GenericPredicates<'db>;
+ ) -> GenericPredicates<'db>;
+
+ #[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
+ #[salsa::cycle(cycle_result = crate::lower::generic_predicates_for_param_cycle_result)]
+ fn generic_predicates_for_param<'db>(
+ &'db self,
+ def: GenericDefId,
+ param_id: TypeOrConstParamId,
+ assoc_name: Option<Name>,
+ ) -> GenericPredicates<'db>;
+
+ #[salsa::invoke(crate::lower::generic_predicates_query)]
+ fn generic_predicates<'db>(&'db self, def: GenericDefId) -> GenericPredicates<'db>;
- #[salsa::invoke(crate::lower_nextsolver::trait_environment_for_body_query)]
+ #[salsa::invoke(crate::lower::trait_environment_for_body_query)]
#[salsa::transparent]
fn trait_environment_for_body<'db>(&'db self, def: DefWithBodyId)
-> Arc<TraitEnvironment<'db>>;
- #[salsa::invoke(crate::lower_nextsolver::trait_environment_query)]
+ #[salsa::invoke(crate::lower::trait_environment_query)]
fn trait_environment<'db>(&'db self, def: GenericDefId) -> Arc<TraitEnvironment<'db>>;
#[salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)]
#[salsa::cycle(cycle_result = crate::lower::generic_defaults_with_diagnostics_cycle_result)]
- fn generic_defaults_with_diagnostics(
- &self,
+ fn generic_defaults_with_diagnostics<'db>(
+ &'db self,
def: GenericDefId,
- ) -> (GenericDefaults, Diagnostics);
+ ) -> (GenericDefaults<'db>, Diagnostics);
/// This returns an empty list if no parameter has default.
///
/// The binders of the returned defaults are only up to (not including) this parameter.
#[salsa::invoke(crate::lower::generic_defaults_query)]
#[salsa::transparent]
- fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults;
+ fn generic_defaults<'db>(&'db self, def: GenericDefId) -> GenericDefaults<'db>;
#[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
fn inherent_impls_in_crate(&self, krate: Crate) -> Arc<InherentImpls>;
@@ -297,7 +275,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(TraitImpls::trait_impls_in_deps_query)]
fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc<TraitImpls>]>;
- // Interned IDs for Chalk integration
+ // Interned IDs for solver integration
#[salsa::interned]
fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
@@ -313,66 +291,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
// cycle_initial = crate::variance::variances_of_cycle_initial,
cycle_result = crate::variance::variances_of_cycle_initial,
)]
- fn variances_of(&self, def: GenericDefId) -> crate::next_solver::VariancesOf<'_>;
-
- // next trait solver
-
- #[salsa::invoke(crate::lower_nextsolver::const_param_ty_query)]
- #[salsa::transparent]
- fn const_param_ty_ns<'db>(&'db self, def: ConstParamId) -> crate::next_solver::Ty<'db>;
-
- #[salsa::invoke(crate::lower_nextsolver::field_types_query)]
- #[salsa::transparent]
- fn field_types_ns<'db>(
- &'db self,
- var: VariantId,
- ) -> Arc<
- ArenaMap<LocalFieldId, crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>>,
- >;
-
- #[salsa::invoke(crate::lower_nextsolver::return_type_impl_traits)]
- fn return_type_impl_traits_ns<'db>(
- &'db self,
- def: FunctionId,
- ) -> Option<Arc<crate::next_solver::EarlyBinder<'db, crate::lower_nextsolver::ImplTraits<'db>>>>;
-
- #[salsa::invoke(crate::lower_nextsolver::type_alias_impl_traits)]
- fn type_alias_impl_traits_ns<'db>(
- &'db self,
- def: TypeAliasId,
- ) -> Option<Arc<crate::next_solver::EarlyBinder<'db, crate::lower_nextsolver::ImplTraits<'db>>>>;
-
- #[salsa::invoke(crate::lower_nextsolver::generic_predicates_for_param_query)]
- #[salsa::cycle(cycle_result = crate::lower_nextsolver::generic_predicates_for_param_cycle_result)]
- fn generic_predicates_for_param_ns<'db>(
- &'db self,
- def: GenericDefId,
- param_id: TypeOrConstParamId,
- assoc_name: Option<Name>,
- ) -> crate::lower_nextsolver::GenericPredicates<'db>;
-
- #[salsa::invoke(crate::lower_nextsolver::generic_predicates_query)]
- fn generic_predicates_ns<'db>(
- &'db self,
- def: GenericDefId,
- ) -> crate::lower_nextsolver::GenericPredicates<'db>;
-
- #[salsa::invoke(crate::lower_nextsolver::generic_defaults_with_diagnostics_query)]
- #[salsa::cycle(cycle_result = crate::lower_nextsolver::generic_defaults_with_diagnostics_cycle_result)]
- fn generic_defaults_ns_with_diagnostics<'db>(
- &'db self,
- def: GenericDefId,
- ) -> (crate::lower_nextsolver::GenericDefaults<'db>, Diagnostics);
-
- /// This returns an empty list if no parameter has default.
- ///
- /// The binders of the returned defaults are only up to (not including) this parameter.
- #[salsa::invoke(crate::lower_nextsolver::generic_defaults_query)]
- #[salsa::transparent]
- fn generic_defaults_ns<'db>(
- &'db self,
- def: GenericDefId,
- ) -> crate::lower_nextsolver::GenericDefaults<'db>;
+ fn variances_of(&self, def: GenericDefId) -> VariancesOf<'_>;
}
#[test]
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index f0efadeafc..fb942e336e 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -150,7 +150,7 @@ impl<'a, 'db> MatchCheckCtx<'a, 'db> {
) -> impl Iterator<Item = (LocalFieldId, Ty<'db>)> {
let (_, substs) = ty.as_adt().unwrap();
- let field_tys = self.db.field_types_ns(variant);
+ let field_tys = self.db.field_types(variant);
let fields_len = variant.fields(self.db).fields().len() as u32;
(0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| {
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 2c6cbdd03f..2b92408f0f 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -626,7 +626,7 @@ fn write_projection<'db>(
// FIXME: We shouldn't use `param.id`, it should be removed. We should know the
// `GenericDefId` from the formatted type (store it inside the `HirFormatter`).
let bounds =
- f.db.generic_predicates_ns(param.id.parent())
+ f.db.generic_predicates(param.id.parent())
.instantiate_identity()
.into_iter()
.flatten()
@@ -902,7 +902,7 @@ fn render_const_scalar_inner<'db>(
hir_def::AdtId::StructId(s) => {
let data = f.db.struct_signature(s);
write!(f, "{}", data.name.display(f.db, f.edition()))?;
- let field_types = f.db.field_types_ns(s.into());
+ let field_types = f.db.field_types(s.into());
render_variant_after_name(
s.fields(f.db),
f,
@@ -934,7 +934,7 @@ fn render_const_scalar_inner<'db>(
.1
.display(f.db, f.edition())
)?;
- let field_types = f.db.field_types_ns(var_id.into());
+ let field_types = f.db.field_types(var_id.into());
render_variant_after_name(
var_id.fields(f.db),
f,
@@ -1121,7 +1121,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id);
if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
let datas = db
- .return_type_impl_traits_ns(func)
+ .return_type_impl_traits(func)
.expect("impl trait id without data");
let data = (*datas).as_ref().map_bound(|rpit| {
&rpit.impl_traits[idx.to_nextsolver(interner)].predicates
@@ -1353,9 +1353,8 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id);
match impl_trait_id {
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
- let datas = db
- .return_type_impl_traits_ns(func)
- .expect("impl trait id without data");
+ let datas =
+ db.return_type_impl_traits(func).expect("impl trait id without data");
let data = (*datas).as_ref().map_bound(|rpit| {
&rpit.impl_traits[idx.to_nextsolver(interner)].predicates
});
@@ -1373,9 +1372,8 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
}
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
- let datas = db
- .type_alias_impl_traits_ns(alias)
- .expect("impl trait id without data");
+ let datas =
+ db.type_alias_impl_traits(alias).expect("impl trait id without data");
let data = (*datas).as_ref().map_bound(|rpit| {
&rpit.impl_traits[idx.to_nextsolver(interner)].predicates
});
@@ -1501,7 +1499,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
}
TypeParamProvenance::ArgumentImplTrait => {
let bounds = db
- .generic_predicates_ns(param.id.parent())
+ .generic_predicates(param.id.parent())
.instantiate_identity()
.into_iter()
.flatten()
@@ -1621,7 +1619,7 @@ fn generic_args_sans_defaults<'ga, 'db>(
parameters: &'ga [GenericArg<'db>],
) -> &'ga [GenericArg<'db>] {
if f.display_kind.is_source_code() || f.omit_verbose_types() {
- match generic_def.map(|generic_def_id| f.db.generic_defaults_ns(generic_def_id)) {
+ match generic_def.map(|generic_def_id| f.db.generic_defaults(generic_def_id)) {
None => parameters,
Some(default_parameters) => {
let should_show = |arg: GenericArg<'db>, i: usize| match default_parameters.get(i) {
diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs
index aaf274799c..b09d1fb196 100644
--- a/crates/hir-ty/src/drop.rs
+++ b/crates/hir-ty/src/drop.rs
@@ -85,7 +85,7 @@ fn has_drop_glue_impl<'db>(
{
return DropGlue::None;
}
- db.field_types_ns(id.into())
+ db.field_types(id.into())
.iter()
.map(|(_, field_ty)| {
has_drop_glue_impl(
@@ -105,7 +105,7 @@ fn has_drop_glue_impl<'db>(
.variants
.iter()
.map(|&(variant, _, _)| {
- db.field_types_ns(variant.into())
+ db.field_types(variant.into())
.iter()
.map(|(_, field_ty)| {
has_drop_glue_impl(
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index e35a798703..437141e41d 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/dyn_compatibility.rs
@@ -18,10 +18,10 @@ use smallvec::SmallVec;
use crate::{
ImplTraitId,
db::{HirDatabase, InternedOpaqueTyId},
- lower_nextsolver::associated_ty_item_bounds,
+ lower::associated_ty_item_bounds,
next_solver::{
- Clause, Clauses, DbInterner, GenericArgs, ParamEnv, SolverDefId, TraitPredicate, TraitRef,
- TypingMode, infer::DbInternerInferExt, mk_param,
+ Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, Goal, ParamEnv, ParamTy,
+ SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, infer::DbInternerInferExt, mk_param,
},
traits::next_trait_solve_in_ctxt,
};
@@ -136,7 +136,7 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
};
let interner = DbInterner::new_with(db, Some(krate), None);
- let predicates = db.generic_predicates_ns(def);
+ let predicates = db.generic_predicates(def);
// FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to
// rust-analyzer yet
// https://github.com/rust-lang/rust/blob/ddaf12390d3ffb7d5ba74491a48f3cd528e5d777/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L490
@@ -162,7 +162,7 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b
// but we don't have good way to render such locations.
// So, just return single boolean value for existence of such `Self` reference
fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
- db.generic_predicates_ns(trait_.into())
+ db.generic_predicates(trait_.into())
.iter()
.any(|pred| predicate_references_self(db, trait_, pred, AllowSelfProjection::No))
}
@@ -378,7 +378,7 @@ where
}) = pred
&& let trait_data = db.trait_signature(pred_trait_ref.def_id.0)
&& trait_data.flags.contains(TraitFlags::AUTO)
- && let rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0, .. }) =
+ && let rustc_type_ir::TyKind::Param(ParamTy { index: 0, .. }) =
pred_trait_ref.self_ty().kind()
{
continue;
@@ -397,10 +397,7 @@ fn receiver_is_dispatchable<'db>(
db: &dyn HirDatabase,
trait_: TraitId,
func: FunctionId,
- sig: &crate::next_solver::EarlyBinder<
- 'db,
- crate::next_solver::Binder<'db, rustc_type_ir::FnSig<DbInterner<'db>>>,
- >,
+ sig: &EarlyBinder<'db, Binder<'db, rustc_type_ir::FnSig<DbInterner<'db>>>>,
) -> bool {
let sig = sig.instantiate_identity();
@@ -409,10 +406,8 @@ fn receiver_is_dispatchable<'db>(
parent: trait_.into(),
local_id: LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)),
});
- let self_param_ty = crate::next_solver::Ty::new(
- interner,
- rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0, id: self_param_id }),
- );
+ let self_param_ty =
+ Ty::new(interner, rustc_type_ir::TyKind::Param(ParamTy { index: 0, id: self_param_id }));
// `self: Self` can't be dispatched on, but this is already considered dyn-compatible
// See rustc's comment on https://github.com/rust-lang/rust/blob/3f121b9461cce02a703a0e7e450568849dfaa074/compiler/rustc_trait_selection/src/traits/object_safety.rs#L433-L437
@@ -440,12 +435,12 @@ fn receiver_is_dispatchable<'db>(
// Type `U`
// FIXME: That seems problematic to fake a generic param like that?
- let unsized_self_ty = crate::next_solver::Ty::new_param(interner, self_param_id, u32::MAX);
+ let unsized_self_ty = Ty::new_param(interner, self_param_id, u32::MAX);
// `Receiver[Self => U]`
let unsized_receiver_ty = receiver_for_self_ty(interner, func, receiver_ty, unsized_self_ty);
let param_env = {
- let generic_predicates = &*db.generic_predicates_ns(func.into());
+ let generic_predicates = &*db.generic_predicates(func.into());
// Self: Unsize<U>
let unsize_predicate =
@@ -475,7 +470,7 @@ fn receiver_is_dispatchable<'db>(
// Receiver: DispatchFromDyn<Receiver[Self => U]>
let predicate =
TraitRef::new(interner, dispatch_from_dyn_did.into(), [receiver_ty, unsized_receiver_ty]);
- let goal = crate::next_solver::Goal::new(interner, param_env, predicate);
+ let goal = Goal::new(interner, param_env, predicate);
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
// the receiver is dispatchable iff the obligation holds
@@ -486,26 +481,19 @@ fn receiver_is_dispatchable<'db>(
fn receiver_for_self_ty<'db>(
interner: DbInterner<'db>,
func: FunctionId,
- receiver_ty: crate::next_solver::Ty<'db>,
- self_ty: crate::next_solver::Ty<'db>,
-) -> crate::next_solver::Ty<'db> {
- let args = crate::next_solver::GenericArgs::for_item(
- interner,
- SolverDefId::FunctionId(func),
- |index, kind, _| {
- if index == 0 { self_ty.into() } else { mk_param(interner, index, kind) }
- },
- );
+ receiver_ty: Ty<'db>,
+ self_ty: Ty<'db>,
+) -> Ty<'db> {
+ let args = GenericArgs::for_item(interner, SolverDefId::FunctionId(func), |index, kind, _| {
+ if index == 0 { self_ty.into() } else { mk_param(interner, index, kind) }
+ });
- crate::next_solver::EarlyBinder::bind(receiver_ty).instantiate(interner, args)
+ EarlyBinder::bind(receiver_ty).instantiate(interner, args)
}
fn contains_illegal_impl_trait_in_trait<'db>(
db: &'db dyn HirDatabase,
- sig: &crate::next_solver::EarlyBinder<
- 'db,
- crate::next_solver::Binder<'db, rustc_type_ir::FnSig<DbInterner<'db>>>,
- >,
+ sig: &EarlyBinder<'db, Binder<'db, rustc_type_ir::FnSig<DbInterner<'db>>>>,
) -> Option<MethodViolationCode> {
struct OpaqueTypeCollector(FxHashSet<InternedOpaqueTyId>);
diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
index 3ca5f0dcb2..26e03aa01a 100644
--- a/crates/hir-ty/src/generics.rs
+++ b/crates/hir-ty/src/generics.rs
@@ -9,7 +9,6 @@
//! where parent follows the same scheme.
use std::ops;
-use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast as _};
use hir_def::{
ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, Lookup,
TypeOrConstParamId, TypeParamId,
@@ -23,8 +22,6 @@ use hir_def::{
use itertools::chain;
use triomphe::Arc;
-use crate::{Interner, Substitution, db::HirDatabase, lt_to_placeholder_idx, to_placeholder_idx};
-
pub fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
let (params, store) = db.generic_params_and_store(def);
@@ -230,50 +227,6 @@ impl Generics {
pub(crate) fn parent_generics(&self) -> Option<&Generics> {
self.parent_generics.as_deref()
}
-
- pub(crate) fn parent_or_self(&self) -> &Generics {
- self.parent_generics.as_deref().unwrap_or(self)
- }
-
- /// Returns a Substitution that replaces each parameter by a bound variable.
- pub(crate) fn bound_vars_subst(
- &self,
- db: &dyn HirDatabase,
- debruijn: DebruijnIndex,
- ) -> Substitution {
- Substitution::from_iter(
- Interner,
- self.iter_id().enumerate().map(|(idx, id)| match id {
- GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
- .to_const(Interner, db.const_param_ty(id))
- .cast(Interner),
- GenericParamId::TypeParamId(_) => {
- BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
- }
- GenericParamId::LifetimeParamId(_) => {
- BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
- }
- }),
- )
- }
-
- /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
- pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
- Substitution::from_iter(
- Interner,
- self.iter_id().enumerate().map(|(index, id)| match id {
- GenericParamId::TypeParamId(id) => {
- to_placeholder_idx(db, id.into(), index as u32).to_ty(Interner).cast(Interner)
- }
- GenericParamId::ConstParamId(id) => to_placeholder_idx(db, id.into(), index as u32)
- .to_const(Interner, db.const_param_ty(id))
- .cast(Interner),
- GenericParamId::LifetimeParamId(id) => {
- lt_to_placeholder_idx(db, id, index as u32).to_lifetime(Interner).cast(Interner)
- }
- }),
- )
- }
}
pub(crate) fn trait_self_param_idx(db: &dyn DefDatabase, def: GenericDefId) -> Option<usize> {
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index b2dd90a3d0..9891f3f248 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -63,8 +63,9 @@ use crate::{
expr::ExprIsRead,
unify::InferenceTable,
},
- lower::diagnostics::TyLoweringDiagnostic,
- lower_nextsolver::{ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind},
+ lower::{
+ ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic,
+ },
mir::MirSpan,
next_solver::{
AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region, Ty, TyKind,
@@ -1159,7 +1160,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
},
);
let return_ty = self.insert_type_vars(return_ty);
- if let Some(rpits) = self.db.return_type_impl_traits_ns(func) {
+ if let Some(rpits) = self.db.return_type_impl_traits(func) {
let mut mode = ImplTraitReplacingMode::ReturnPosition(FxHashSet::default());
let result = self.insert_inference_vars_for_impl_trait(return_ty, &mut mode);
if let ImplTraitReplacingMode::ReturnPosition(taits) = mode {
@@ -1234,7 +1235,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
return ty;
}
- (self.db.return_type_impl_traits_ns(def), idx)
+ (self.db.return_type_impl_traits(def), idx)
}
ImplTraitId::TypeAliasImplTrait(def, idx) => {
if let ImplTraitReplacingMode::ReturnPosition(taits) = mode {
@@ -1243,7 +1244,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
taits.insert(ty);
return ty;
}
- (self.db.type_alias_impl_traits_ns(def), idx)
+ (self.db.type_alias_impl_traits(def), idx)
}
_ => unreachable!(),
};
@@ -1604,8 +1605,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
match ty.kind() {
TyKind::Adt(adt_def, substs) => match adt_def.def_id().0 {
AdtId::StructId(struct_id) => {
- match self.db.field_types_ns(struct_id.into()).values().next_back().copied()
- {
+ match self.db.field_types(struct_id.into()).values().next_back().copied() {
Some(field) => {
ty = field.instantiate(self.interner(), substs);
}
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs
index 990281a7c8..c128977d7b 100644
--- a/crates/hir-ty/src/infer/cast.rs
+++ b/crates/hir-ty/src/infer/cast.rs
@@ -394,7 +394,7 @@ fn pointer_kind<'db>(
let struct_data = id.fields(ctx.db);
if let Some((last_field, _)) = struct_data.fields().iter().last() {
let last_field_ty =
- ctx.db.field_types_ns(id.into())[last_field].instantiate(ctx.interner(), subst);
+ ctx.db.field_types(id.into())[last_field].instantiate(ctx.interner(), subst);
pointer_kind(last_field_ty, ctx)
} else {
Ok(Some(PointerKind::Thin))
diff --git a/crates/hir-ty/src/infer/diagnostics.rs b/crates/hir-ty/src/infer/diagnostics.rs
index 39e70c262a..844eb02ab0 100644
--- a/crates/hir-ty/src/infer/diagnostics.rs
+++ b/crates/hir-ty/src/infer/diagnostics.rs
@@ -15,8 +15,8 @@ use la_arena::{Idx, RawIdx};
use crate::{
InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic,
db::HirDatabase,
- lower_nextsolver::path::{PathDiagnosticCallback, PathLoweringContext},
- lower_nextsolver::{LifetimeElisionKind, TyLoweringContext},
+ lower::path::{PathDiagnosticCallback, PathLoweringContext},
+ lower::{LifetimeElisionKind, TyLoweringContext},
};
// Unfortunately, this struct needs to use interior mutability (but we encapsulate it)
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index e1964608a3..efb7244ff6 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -37,7 +37,7 @@ use crate::{
pat::contains_explicit_ref_binding,
},
lang_items::lang_items_for_bin_op,
- lower_nextsolver::{
+ lower::{
LifetimeElisionKind, lower_mutability,
path::{GenericArgsLowerer, TypeLikeConst, substs_from_args_and_bindings},
},
@@ -564,7 +564,7 @@ impl<'db> InferenceContext<'_, 'db> {
match def_id {
_ if fields.is_empty() => {}
Some(def) => {
- let field_types = self.db.field_types_ns(def);
+ let field_types = self.db.field_types(def);
let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
for field in fields.iter() {
@@ -1622,7 +1622,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
return None;
}
- let ty = self.db.field_types_ns(field_id.parent)[field_id.local_id]
+ let ty = self.db.field_types(field_id.parent)[field_id.local_id]
.instantiate(interner, parameters);
Some((Either::Left(field_id), ty))
});
@@ -1637,7 +1637,7 @@ impl<'db> InferenceContext<'_, 'db> {
None => {
let (field_id, subst) = private_field?;
let adjustments = autoderef.adjust_steps();
- let ty = self.db.field_types_ns(field_id.parent)[field_id.local_id]
+ let ty = self.db.field_types(field_id.parent)[field_id.local_id]
.instantiate(self.interner(), subst);
let ty = self.process_remote_user_written_ty(ty);
@@ -2320,7 +2320,7 @@ impl<'db> InferenceContext<'_, 'db> {
let callable_ty = self.table.try_structurally_resolve_type(callable_ty);
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind() {
let generic_predicates =
- self.db.generic_predicates_ns(GenericDefId::from_callable(self.db, fn_def.0));
+ self.db.generic_predicates(GenericDefId::from_callable(self.db, fn_def.0));
if let Some(predicates) = generic_predicates.instantiate(self.interner(), parameters) {
let interner = self.interner();
let param_env = self.table.trait_env.env;
diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs
index 9edbc9dda0..71a9c94bf5 100644
--- a/crates/hir-ty/src/infer/mutability.rs
+++ b/crates/hir-ty/src/infer/mutability.rs
@@ -18,7 +18,7 @@ use crate::next_solver::{GenericArgs, TraitRef};
use crate::{
Adjust, Adjustment, AutoBorrow, OverloadedDeref,
infer::{Expectation, InferenceContext, expr::ExprIsRead},
- lower_nextsolver::lower_mutability,
+ lower::lower_mutability,
next_solver::TyKind,
};
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 61255d31d2..8019844b5d 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -19,7 +19,7 @@ use crate::{
AllowTwoPhase, BindingMode, Expectation, InferenceContext, TypeMismatch,
coerce::CoerceNever, expr::ExprIsRead,
},
- lower_nextsolver::lower_mutability,
+ lower::lower_mutability,
next_solver::{GenericArgs, Ty, TyKind},
};
@@ -59,7 +59,7 @@ impl<'db> InferenceContext<'_, 'db> {
match def {
_ if subs.is_empty() => {}
Some(def) => {
- let field_types = self.db.field_types_ns(def);
+ let field_types = self.db.field_types(def);
let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
@@ -128,7 +128,7 @@ impl<'db> InferenceContext<'_, 'db> {
match def {
_ if subs.len() == 0 => {}
Some(def) => {
- let field_types = self.db.field_types_ns(def);
+ let field_types = self.db.field_types(def);
let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 84d17db6c6..2dae7cb04f 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -13,7 +13,7 @@ use crate::{
InferenceDiagnostic, ValueTyDefId,
generics::generics,
infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext,
- lower_nextsolver::LifetimeElisionKind,
+ lower::LifetimeElisionKind,
method_resolution::{self, VisibleFromModule},
next_solver::{
GenericArg, GenericArgs, TraitRef, Ty,
@@ -221,7 +221,7 @@ impl<'db> InferenceContext<'_, 'db> {
def: GenericDefId,
subst: GenericArgs<'db>,
) {
- let predicates = self.db.generic_predicates_ns(def);
+ let predicates = self.db.generic_predicates(def);
let interner = self.interner();
let param_env = self.table.trait_env.env;
if let Some(predicates) = predicates.instantiate(self.interner(), subst) {
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index beb26f7d68..a18cdda559 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -800,7 +800,7 @@ impl<'db> InferenceTable<'db> {
while let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
let struct_data = id.fields(self.db);
if let Some((last_field, _)) = struct_data.fields().iter().next_back() {
- let last_field_ty = self.db.field_types_ns(id.into())[last_field]
+ let last_field_ty = self.db.field_types(id.into())[last_field]
.instantiate(self.interner(), subst);
if structs.contains(&ty) {
// A struct recursively contains itself as a tail field somewhere.
diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs
index 7ebc2df6f7..8aed2608d6 100644
--- a/crates/hir-ty/src/inhabitedness.rs
+++ b/crates/hir-ty/src/inhabitedness.rs
@@ -156,7 +156,7 @@ impl<'a, 'db> UninhabitedFrom<'a, 'db> {
}
let is_enum = matches!(variant, VariantId::EnumVariantId(..));
- let field_tys = self.db().field_types_ns(variant);
+ let field_tys = self.db().field_types(variant);
let field_vis = if is_enum { None } else { Some(self.db().field_visibilities(variant)) };
for (fid, _) in fields.iter() {
diff --git a/crates/hir-ty/src/interner.rs b/crates/hir-ty/src/interner.rs
deleted file mode 100644
index 57ef5523b4..0000000000
--- a/crates/hir-ty/src/interner.rs
+++ /dev/null
@@ -1,403 +0,0 @@
-//! Implementation of the Chalk `Interner` trait, which allows customizing the
-//! representation of the various objects Chalk deals with (types, goals etc.).
-
-use crate::{
- AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData, ConstScalar, FnAbi,
- FnDefId, GenericArg, GenericArgData, Goal, GoalData, InEnvironment, Lifetime, LifetimeData,
- OpaqueTy, OpaqueTyId, ProgramClause, ProjectionTy, QuantifiedWhereClause,
- QuantifiedWhereClauses, Substitution, Ty, TyKind, VariableKind, chalk_db, tls,
-};
-use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variance};
-use hir_def::TypeAliasId;
-use intern::{Interned, impl_internable};
-use smallvec::SmallVec;
-use std::fmt;
-use triomphe::Arc;
-
-type TyData = chalk_ir::TyData<Interner>;
-type VariableKinds = chalk_ir::VariableKinds<Interner>;
-type Goals = chalk_ir::Goals<Interner>;
-type ProgramClauseData = chalk_ir::ProgramClauseData<Interner>;
-type Constraint = chalk_ir::Constraint<Interner>;
-type Constraints = chalk_ir::Constraints<Interner>;
-type ProgramClauses = chalk_ir::ProgramClauses<Interner>;
-
-#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
-pub struct Interner;
-
-#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
-pub struct InternedWrapper<T>(pub(crate) T);
-
-impl<T: fmt::Debug> fmt::Debug for InternedWrapper<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Debug::fmt(&self.0, f)
- }
-}
-
-#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
-pub struct InternedWrapperNoDebug<T>(pub(crate) T);
-
-impl<T> std::ops::Deref for InternedWrapper<T> {
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
-
-impl_internable!(
- InternedWrapper<Vec<VariableKind>>,
- InternedWrapper<SmallVec<[GenericArg; 2]>>,
- InternedWrapper<TyData>,
- InternedWrapper<LifetimeData>,
- InternedWrapper<ConstData>,
- InternedWrapper<ConstScalar>,
- InternedWrapper<Vec<CanonicalVarKind>>,
- InternedWrapper<Box<[ProgramClause]>>,
- InternedWrapper<Vec<QuantifiedWhereClause>>,
- InternedWrapper<SmallVec<[Variance; 16]>>,
-);
-
-impl chalk_ir::interner::Interner for Interner {
- type InternedType = Interned<InternedWrapper<TyData>>;
- type InternedLifetime = Interned<InternedWrapper<LifetimeData>>;
- type InternedConst = Interned<InternedWrapper<ConstData>>;
- type InternedConcreteConst = ConstScalar;
- type InternedGenericArg = GenericArgData;
- // We could do the following, but that saves "only" 20mb on self while increasing inference
- // time by ~2.5%
- // type InternedGoal = Interned<InternedWrapper<GoalData>>;
- type InternedGoal = Arc<GoalData>;
- type InternedGoals = Vec<Goal>;
- type InternedSubstitution = Interned<InternedWrapper<SmallVec<[GenericArg; 2]>>>;
- type InternedProgramClauses = Interned<InternedWrapper<Box<[ProgramClause]>>>;
- type InternedProgramClause = ProgramClauseData;
- type InternedQuantifiedWhereClauses = Interned<InternedWrapper<Vec<QuantifiedWhereClause>>>;
- type InternedVariableKinds = Interned<InternedWrapper<Vec<VariableKind>>>;
- type InternedCanonicalVarKinds = Interned<InternedWrapper<Vec<CanonicalVarKind>>>;
- type InternedConstraints = Vec<InEnvironment<Constraint>>;
- type InternedVariances = SmallVec<[Variance; 16]>;
- type DefId = salsa::Id;
- type InternedAdtId = hir_def::AdtId;
- type Identifier = TypeAliasId;
- type FnAbi = FnAbi;
-
- fn debug_adt_id(
- type_kind_id: chalk_db::AdtId,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
- }
-
- fn debug_trait_id(
- type_kind_id: chalk_db::TraitId,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
- }
-
- fn debug_assoc_type_id(
- id: chalk_db::AssocTypeId,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
- }
-
- fn debug_opaque_ty_id(
- opaque_ty_id: OpaqueTyId,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "OpaqueTy#{:?}", opaque_ty_id.0))
- }
-
- fn debug_fn_def_id(fn_def_id: FnDefId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt)))
- }
-
- fn debug_closure_id(
- _fn_def_id: ClosureId,
- _fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- None
- }
-
- fn debug_alias(alias: &AliasTy, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- use std::fmt::Debug;
- match alias {
- AliasTy::Projection(projection_ty) => Interner::debug_projection_ty(projection_ty, fmt),
- AliasTy::Opaque(opaque_ty) => Some(opaque_ty.fmt(fmt)),
- }
- }
-
- fn debug_projection_ty(
- proj: &ProjectionTy,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt)))
- .or_else(|| Some(fmt.write_str("ProjectionTy")))
- }
-
- fn debug_opaque_ty(opaque_ty: &OpaqueTy, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id))
- }
-
- fn debug_ty(ty: &Ty, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", ty.data(Interner)))
- }
-
- fn debug_lifetime(lifetime: &Lifetime, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", lifetime.data(Interner)))
- }
-
- fn debug_const(constant: &Const, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", constant.data(Interner)))
- }
-
- fn debug_generic_arg(
- parameter: &GenericArg,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", parameter.data(Interner).inner_debug()))
- }
-
- fn debug_variable_kinds(
- variable_kinds: &VariableKinds,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", variable_kinds.as_slice(Interner)))
- }
-
- fn debug_variable_kinds_with_angles(
- variable_kinds: &VariableKinds,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", variable_kinds.inner_debug(Interner)))
- }
-
- fn debug_canonical_var_kinds(
- canonical_var_kinds: &CanonicalVarKinds,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", canonical_var_kinds.as_slice(Interner)))
- }
- fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- let goal_data = goal.data(Interner);
- Some(write!(fmt, "{goal_data:?}"))
- }
- fn debug_goals(goals: &Goals, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", goals.debug(Interner)))
- }
- fn debug_program_clause_implication(
- pci: &ProgramClauseImplication<Self>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", pci.debug(Interner)))
- }
- fn debug_program_clause(
- clause: &ProgramClause,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", clause.data(Interner)))
- }
- fn debug_program_clauses(
- clauses: &ProgramClauses,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", clauses.as_slice(Interner)))
- }
- fn debug_substitution(
- substitution: &Substitution,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", substitution.debug(Interner)))
- }
- fn debug_separator_trait_ref(
- separator_trait_ref: &SeparatorTraitRef<'_, Interner>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", separator_trait_ref.debug(Interner)))
- }
-
- fn debug_quantified_where_clauses(
- clauses: &QuantifiedWhereClauses,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", clauses.as_slice(Interner)))
- }
-
- fn debug_constraints(
- _clauses: &Constraints,
- _fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- None
- }
-
- fn intern_ty(self, kind: TyKind) -> Self::InternedType {
- let flags = kind.compute_flags(self);
- Interned::new(InternedWrapper(TyData { kind, flags }))
- }
-
- fn ty_data(self, ty: &Self::InternedType) -> &TyData {
- &ty.0
- }
-
- fn intern_lifetime(self, lifetime: LifetimeData) -> Self::InternedLifetime {
- Interned::new(InternedWrapper(lifetime))
- }
-
- fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &LifetimeData {
- &lifetime.0
- }
-
- fn intern_const(self, constant: ConstData) -> Self::InternedConst {
- Interned::new(InternedWrapper(constant))
- }
-
- fn const_data(self, constant: &Self::InternedConst) -> &ConstData {
- &constant.0
- }
-
- fn const_eq(
- self,
- _ty: &Self::InternedType,
- c1: &Self::InternedConcreteConst,
- c2: &Self::InternedConcreteConst,
- ) -> bool {
- !matches!(c1, ConstScalar::Bytes(..)) || !matches!(c2, ConstScalar::Bytes(..)) || (c1 == c2)
- }
-
- fn intern_generic_arg(self, parameter: GenericArgData) -> Self::InternedGenericArg {
- parameter
- }
-
- fn generic_arg_data(self, parameter: &Self::InternedGenericArg) -> &GenericArgData {
- parameter
- }
-
- fn intern_goal(self, goal: GoalData) -> Self::InternedGoal {
- Arc::new(goal)
- }
-
- fn goal_data(self, goal: &Self::InternedGoal) -> &GoalData {
- goal
- }
-
- fn intern_goals<E>(
- self,
- data: impl IntoIterator<Item = Result<Goal, E>>,
- ) -> Result<Self::InternedGoals, E> {
- // let hash =
- // std::hash::BuildHasher::hash_one(&BuildHasherDefault::<FxHasher>::default(), &goal);
- // Interned::new(InternedWrapper(PreHashedWrapper(goal, hash)))
- data.into_iter().collect()
- }
-
- fn goals_data(self, goals: &Self::InternedGoals) -> &[Goal] {
- goals
- }
-
- fn intern_substitution<E>(
- self,
- data: impl IntoIterator<Item = Result<GenericArg, E>>,
- ) -> Result<Self::InternedSubstitution, E> {
- Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
- }
-
- fn substitution_data(self, substitution: &Self::InternedSubstitution) -> &[GenericArg] {
- &substitution.as_ref().0
- }
-
- fn intern_program_clause(self, data: ProgramClauseData) -> Self::InternedProgramClause {
- data
- }
-
- fn program_clause_data(self, clause: &Self::InternedProgramClause) -> &ProgramClauseData {
- clause
- }
-
- fn intern_program_clauses<E>(
- self,
- data: impl IntoIterator<Item = Result<ProgramClause, E>>,
- ) -> Result<Self::InternedProgramClauses, E> {
- Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
- }
-
- fn program_clauses_data(self, clauses: &Self::InternedProgramClauses) -> &[ProgramClause] {
- clauses
- }
-
- fn intern_quantified_where_clauses<E>(
- self,
- data: impl IntoIterator<Item = Result<QuantifiedWhereClause, E>>,
- ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
- Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
- }
-
- fn quantified_where_clauses_data(
- self,
- clauses: &Self::InternedQuantifiedWhereClauses,
- ) -> &[QuantifiedWhereClause] {
- clauses
- }
-
- fn intern_generic_arg_kinds<E>(
- self,
- data: impl IntoIterator<Item = Result<VariableKind, E>>,
- ) -> Result<Self::InternedVariableKinds, E> {
- Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
- }
-
- fn variable_kinds_data(self, parameter_kinds: &Self::InternedVariableKinds) -> &[VariableKind] {
- &parameter_kinds.as_ref().0
- }
-
- fn intern_canonical_var_kinds<E>(
- self,
- data: impl IntoIterator<Item = Result<CanonicalVarKind, E>>,
- ) -> Result<Self::InternedCanonicalVarKinds, E> {
- Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
- }
-
- fn canonical_var_kinds_data(
- self,
- canonical_var_kinds: &Self::InternedCanonicalVarKinds,
- ) -> &[CanonicalVarKind] {
- canonical_var_kinds
- }
- fn intern_constraints<E>(
- self,
- data: impl IntoIterator<Item = Result<InEnvironment<Constraint>, E>>,
- ) -> Result<Self::InternedConstraints, E> {
- data.into_iter().collect()
- }
- fn constraints_data(
- self,
- constraints: &Self::InternedConstraints,
- ) -> &[InEnvironment<Constraint>] {
- constraints
- }
-
- fn intern_variances<E>(
- self,
- data: impl IntoIterator<Item = Result<Variance, E>>,
- ) -> Result<Self::InternedVariances, E> {
- data.into_iter().collect::<Result<_, _>>()
- }
-
- fn variances_data(self, variances: &Self::InternedVariances) -> &[Variance] {
- variances
- }
-}
-
-impl chalk_ir::interner::HasInterner for Interner {
- type Interner = Self;
-}
-
-#[macro_export]
-macro_rules! has_interner {
- ($t:ty) => {
- impl HasInterner for $t {
- type Interner = $crate::Interner;
- }
- };
-}
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index a857602fa0..fc0b9d30b3 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -138,7 +138,7 @@ fn layout_of_simd_ty<'db>(
// * #[repr(simd)] struct S([T; 4])
//
// where T is a primitive scalar (integer/float/pointer).
- let fields = db.field_types_ns(id.into());
+ let fields = db.field_types(id.into());
let mut fields = fields.iter();
let Some(TyKind::Array(e_ty, e_len)) = fields
.next()
@@ -401,7 +401,7 @@ fn field_ty<'a>(
fd: LocalFieldId,
args: &GenericArgs<'a>,
) -> Ty<'a> {
- db.field_types_ns(def)[fd].instantiate(DbInterner::new_with(db, None, None), args)
+ db.field_types(def)[fd].instantiate(DbInterner::new_with(db, None, None), args)
}
fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar {
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index b698fd9a14..536c81ab03 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -23,23 +23,15 @@ extern crate ra_ap_rustc_next_trait_solver as rustc_next_trait_solver;
extern crate self as hir_ty;
-mod builder;
-mod chalk_db;
-mod chalk_ext;
mod infer;
mod inhabitedness;
-mod interner;
mod lower;
-mod lower_nextsolver;
-mod mapping;
pub mod next_solver;
mod target_feature;
-mod tls;
mod utils;
pub mod autoderef;
pub mod consteval;
-mod consteval_chalk;
pub mod db;
pub mod diagnostics;
pub mod display;
@@ -61,16 +53,11 @@ mod variance;
use std::hash::Hash;
-use chalk_ir::{
- VariableKinds,
- fold::{Shift, TypeFoldable},
- interner::HasInterner,
-};
-use hir_def::{CallableDefId, GeneralConstId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness};
+use hir_def::{CallableDefId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness};
use hir_expand::name::Name;
use indexmap::{IndexMap, map::Entry};
use intern::{Symbol, sym};
-use la_arena::{Arena, Idx};
+use la_arena::Idx;
use mir::{MirEvalError, VTableMap};
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
use rustc_type_ir::{
@@ -82,13 +69,14 @@ use traits::FnTrait;
use triomphe::Arc;
use crate::{
- builder::TyBuilder,
- chalk_ext::*,
db::HirDatabase,
display::{DisplayTarget, HirDisplay},
- generics::Generics,
infer::unify::InferenceTable,
- next_solver::DbInterner,
+ next_solver::{
+ AliasTy, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, Canonical,
+ CanonicalVarKind, CanonicalVars, Const, ConstKind, DbInterner, FnSig, PolyFnSig, Predicate,
+ Region, RegionKind, TraitRef, Ty, TyKind, Tys, abi,
+ },
};
pub use autoderef::autoderef;
@@ -99,15 +87,9 @@ pub use infer::{
closure::analysis::{CaptureKind, CapturedItem},
could_coerce, could_unify, could_unify_deeply,
};
-pub use interner::Interner;
-pub use lower::{ImplTraitLoweringMode, ParamLoweringMode, TyDefId, ValueTyDefId, diagnostics::*};
-pub use lower_nextsolver::{
- LifetimeElisionKind, TyLoweringContext, associated_type_shorthand_candidates,
-};
-pub use mapping::{
- ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
- lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
- to_foreign_def_id, to_placeholder_idx, to_placeholder_idx_no_index,
+pub use lower::{
+ LifetimeElisionKind, TyDefId, TyLoweringContext, ValueTyDefId,
+ associated_type_shorthand_candidates, diagnostics::*,
};
pub use method_resolution::check_orphan_rules;
pub use next_solver::interner::{attach_db, attach_db_allow_change, with_attached_db};
@@ -118,76 +100,6 @@ pub use utils::{
is_fn_unsafe_to_call, target_feature_is_safe_in_target,
};
-use chalk_ir::{BoundVar, DebruijnIndex, Safety, Scalar};
-
-pub(crate) type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
-pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
-pub(crate) type FnDefId = chalk_ir::FnDefId<Interner>;
-pub(crate) type ClosureId = chalk_ir::ClosureId<Interner>;
-pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
-pub(crate) type PlaceholderIndex = chalk_ir::PlaceholderIndex;
-
-pub(crate) type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
-
-pub(crate) type VariableKind = chalk_ir::VariableKind<Interner>;
-/// Represents generic parameters and an item bound by them. When the item has parent, the binders
-/// also contain the generic parameters for its parent. See chalk's documentation for details.
-///
-/// One thing to keep in mind when working with `Binders` (and `Substitution`s, which represent
-/// generic arguments) in rust-analyzer is that the ordering within *is* significant - the generic
-/// parameters/arguments for an item MUST come before those for its parent. This is to facilitate
-/// the integration with chalk-solve, which mildly puts constraints as such. See #13335 for its
-/// motivation in detail.
-pub(crate) type Binders<T> = chalk_ir::Binders<T>;
-/// Interned list of generic arguments for an item. When an item has parent, the `Substitution` for
-/// it contains generic arguments for both its parent and itself. See chalk's documentation for
-/// details.
-///
-/// See `Binders` for the constraint on the ordering.
-pub(crate) type Substitution = chalk_ir::Substitution<Interner>;
-pub(crate) type GenericArg = chalk_ir::GenericArg<Interner>;
-pub(crate) type GenericArgData = chalk_ir::GenericArgData<Interner>;
-
-pub(crate) type Ty = chalk_ir::Ty<Interner>;
-pub type TyKind = chalk_ir::TyKind<Interner>;
-pub(crate) type DynTy = chalk_ir::DynTy<Interner>;
-pub(crate) type FnPointer = chalk_ir::FnPointer<Interner>;
-pub(crate) use chalk_ir::FnSubst; // a re-export so we don't lose the tuple constructor
-
-pub type AliasTy = chalk_ir::AliasTy<Interner>;
-
-pub(crate) type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
-pub(crate) type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
-
-pub(crate) type Lifetime = chalk_ir::Lifetime<Interner>;
-pub(crate) type LifetimeData = chalk_ir::LifetimeData<Interner>;
-pub(crate) type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
-
-pub(crate) type ConstValue = chalk_ir::ConstValue<Interner>;
-
-pub(crate) type Const = chalk_ir::Const<Interner>;
-pub(crate) type ConstData = chalk_ir::ConstData<Interner>;
-
-pub(crate) type TraitRef = chalk_ir::TraitRef<Interner>;
-pub(crate) type QuantifiedWhereClause = Binders<WhereClause>;
-pub(crate) type Canonical<T> = chalk_ir::Canonical<T>;
-
-pub(crate) type ChalkTraitId = chalk_ir::TraitId<Interner>;
-pub(crate) type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;
-
-pub(crate) type FnSig = chalk_ir::FnSig<Interner>;
-
-pub(crate) type InEnvironment<T> = chalk_ir::InEnvironment<T>;
-pub type AliasEq = chalk_ir::AliasEq<Interner>;
-pub type WhereClause = chalk_ir::WhereClause<Interner>;
-
-pub(crate) type DomainGoal = chalk_ir::DomainGoal<Interner>;
-pub(crate) type Goal = chalk_ir::Goal<Interner>;
-
-pub(crate) type CanonicalVarKind = chalk_ir::CanonicalVarKind<Interner>;
-pub(crate) type GoalData = chalk_ir::GoalData<Interner>;
-pub(crate) type ProgramClause = chalk_ir::ProgramClause<Interner>;
-
/// A constant can have reference to other things. Memory map job is holding
/// the necessary bits of memory of the const eval session to keep the constant
/// meaningful.
@@ -221,7 +133,7 @@ impl ComplexMemoryMap<'_> {
}
impl<'db> MemoryMap<'db> {
- pub fn vtable_ty(&self, id: usize) -> Result<crate::next_solver::Ty<'db>, MirEvalError<'db>> {
+ pub fn vtable_ty(&self, id: usize) -> Result<Ty<'db>, MirEvalError<'db>> {
match self {
MemoryMap::Empty | MemoryMap::Simple(_) => Err(MirEvalError::InvalidVTableId(id)),
MemoryMap::Complex(cm) => cm.vtable.ty(id),
@@ -271,118 +183,11 @@ impl<'db> MemoryMap<'db> {
}
}
-// FIXME(next-solver): add a lifetime to this
-/// A concrete constant value
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum ConstScalar {
- Bytes(Box<[u8]>, MemoryMap<'static>),
- // FIXME: this is a hack to get around chalk not being able to represent unevaluatable
- // constants
- UnevaluatedConst(GeneralConstId, Substitution),
- /// Case of an unknown value that rustc might know but we don't
- // FIXME: this is a hack to get around chalk not being able to represent unevaluatable
- // constants
- // https://github.com/rust-lang/rust-analyzer/pull/8813#issuecomment-840679177
- // https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/Handling.20non.20evaluatable.20constants'.20equality/near/238386348
- Unknown,
-}
-
-impl Hash for ConstScalar {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- core::mem::discriminant(self).hash(state);
- if let ConstScalar::Bytes(b, _) = self {
- b.hash(state)
- }
- }
-}
-
-/// A concrete constant value
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum ConstScalarNs<'db> {
- Bytes(Box<[u8]>, MemoryMap<'db>),
- // FIXME: this is a hack to get around chalk not being able to represent unevaluatable
- // constants
- UnevaluatedConst(GeneralConstId, Substitution),
- /// Case of an unknown value that rustc might know but we don't
- // FIXME: this is a hack to get around chalk not being able to represent unevaluatable
- // constants
- // https://github.com/rust-lang/rust-analyzer/pull/8813#issuecomment-840679177
- // https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/Handling.20non.20evaluatable.20constants'.20equality/near/238386348
- Unknown,
-}
-
-impl Hash for ConstScalarNs<'_> {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- core::mem::discriminant(self).hash(state);
- if let ConstScalarNs::Bytes(b, _) = self {
- b.hash(state)
- }
- }
-}
-
/// Return an index of a parameter in the generic type parameter list by it's id.
pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> {
generics::generics(db, id.parent).type_or_const_param_idx(id)
}
-pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
-where
- T: TypeFoldable<Interner> + HasInterner<Interner = Interner>,
-{
- Binders::empty(Interner, value.shifted_in_from(Interner, DebruijnIndex::ONE))
-}
-
-pub(crate) fn make_single_type_binders<T: HasInterner<Interner = Interner>>(
- value: T,
-) -> Binders<T> {
- Binders::new(
- chalk_ir::VariableKinds::from_iter(
- Interner,
- std::iter::once(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)),
- ),
- value,
- )
-}
-
-pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
- db: &dyn HirDatabase,
- generics: &Generics,
- value: T,
-) -> Binders<T> {
- Binders::new(variable_kinds_from_iter(db, generics.iter_id()), value)
-}
-
-pub(crate) fn variable_kinds_from_iter(
- db: &dyn HirDatabase,
- iter: impl Iterator<Item = hir_def::GenericParamId>,
-) -> VariableKinds<Interner> {
- VariableKinds::from_iter(
- Interner,
- iter.map(|x| match x {
- hir_def::GenericParamId::ConstParamId(id) => {
- chalk_ir::VariableKind::Const(db.const_param_ty(id))
- }
- hir_def::GenericParamId::TypeParamId(_) => {
- chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
- }
- hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime,
- }),
- )
-}
-
-// FIXME: get rid of this, just replace it by FnPointer
-/// A function signature as seen by type inference: Several parameter types and
-/// one return type.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub(crate) struct CallableSig {
- params_and_return: Arc<[Ty]>,
- is_varargs: bool,
- safety: Safety,
- abi: FnAbi,
-}
-
-has_interner!(CallableSig);
-
#[derive(Debug, Copy, Clone, Eq)]
pub enum FnAbi {
Aapcs,
@@ -534,81 +339,21 @@ pub enum ImplTraitId {
}
#[derive(PartialEq, Eq, Debug, Hash)]
-pub struct ImplTraits {
- pub(crate) impl_traits: Arena<ImplTrait>,
-}
-
-has_interner!(ImplTraits);
-
-#[derive(PartialEq, Eq, Debug, Hash)]
-pub struct ImplTrait {
- pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
-}
+pub struct ImplTrait {}
pub type ImplTraitIdx = Idx<ImplTrait>;
-pub fn static_lifetime() -> Lifetime {
- LifetimeData::Static.intern(Interner)
-}
-
-pub fn error_lifetime() -> Lifetime {
- LifetimeData::Error.intern(Interner)
-}
-
-pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
- t: T,
- for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
- for_const: impl FnMut(Ty, BoundVar, DebruijnIndex) -> Const,
-) -> T {
- use chalk_ir::fold::TypeFolder;
-
- #[derive(chalk_derive::FallibleTypeFolder)]
- #[has_interner(Interner)]
- struct FreeVarFolder<
- F1: FnMut(BoundVar, DebruijnIndex) -> Ty,
- F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const,
- >(F1, F2);
- impl<F1: FnMut(BoundVar, DebruijnIndex) -> Ty, F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const>
- TypeFolder<Interner> for FreeVarFolder<F1, F2>
- {
- fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
-
- fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty {
- self.0(bound_var, outer_binder)
- }
-
- fn fold_free_var_const(
- &mut self,
- ty: Ty,
- bound_var: BoundVar,
- outer_binder: DebruijnIndex,
- ) -> Const {
- self.1(ty, bound_var, outer_binder)
- }
- }
- t.fold_with(&mut FreeVarFolder(for_ty, for_const), DebruijnIndex::INNERMOST)
-}
-
/// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
/// ensures there are no unbound variables or inference variables anywhere in
/// the `t`.
-pub fn replace_errors_with_variables<'db, T>(
- interner: DbInterner<'db>,
- t: &T,
-) -> crate::next_solver::Canonical<'db, T>
+pub fn replace_errors_with_variables<'db, T>(interner: DbInterner<'db>, t: &T) -> Canonical<'db, T>
where
T: rustc_type_ir::TypeFoldable<DbInterner<'db>> + Clone,
{
use rustc_type_ir::{FallibleTypeFolder, TypeSuperFoldable};
struct ErrorReplacer<'db> {
interner: DbInterner<'db>,
- vars: Vec<crate::next_solver::CanonicalVarKind<'db>>,
+ vars: Vec<CanonicalVarKind<'db>>,
binder: rustc_type_ir::DebruijnIndex,
}
impl<'db> FallibleTypeFolder<DbInterner<'db>> for ErrorReplacer<'db> {
@@ -621,10 +366,7 @@ where
self.interner
}
- fn try_fold_binder<T>(
- &mut self,
- t: crate::next_solver::Binder<'db, T>,
- ) -> Result<crate::next_solver::Binder<'db, T>, Self::Error>
+ fn try_fold_binder<T>(&mut self, t: Binder<'db, T>) -> Result<Binder<'db, T>, Self::Error>
where
T: rustc_type_ir::TypeFoldable<DbInterner<'db>>,
{
@@ -634,10 +376,7 @@ where
result
}
- fn try_fold_ty(
- &mut self,
- t: crate::next_solver::Ty<'db>,
- ) -> Result<crate::next_solver::Ty<'db>, Self::Error> {
+ fn try_fold_ty(&mut self, t: Ty<'db>) -> Result<Ty<'db>, Self::Error> {
if !t.has_type_flags(
rustc_type_ir::TypeFlags::HAS_ERROR
| rustc_type_ir::TypeFlags::HAS_TY_INFER
@@ -650,39 +389,28 @@ where
#[cfg(debug_assertions)]
let error = || Err(());
#[cfg(not(debug_assertions))]
- let error = || {
- Ok(crate::next_solver::Ty::new_error(
- self.interner,
- crate::next_solver::ErrorGuaranteed,
- ))
- };
+ let error = || Ok(Ty::new_error(self.interner, crate::next_solver::ErrorGuaranteed));
match t.kind() {
- crate::next_solver::TyKind::Error(_) => {
+ TyKind::Error(_) => {
let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
- self.vars.push(crate::next_solver::CanonicalVarKind::Ty {
+ self.vars.push(CanonicalVarKind::Ty {
ui: rustc_type_ir::UniverseIndex::ZERO,
sub_root: var,
});
- Ok(crate::next_solver::Ty::new_bound(
+ Ok(Ty::new_bound(
self.interner,
self.binder,
- crate::next_solver::BoundTy {
- var,
- kind: crate::next_solver::BoundTyKind::Anon,
- },
+ BoundTy { var, kind: BoundTyKind::Anon },
))
}
- crate::next_solver::TyKind::Infer(_) => error(),
- crate::next_solver::TyKind::Bound(index, _) if index > self.binder => error(),
+ TyKind::Infer(_) => error(),
+ TyKind::Bound(index, _) if index > self.binder => error(),
_ => t.try_super_fold_with(self),
}
}
- fn try_fold_const(
- &mut self,
- ct: crate::next_solver::Const<'db>,
- ) -> Result<crate::next_solver::Const<'db>, Self::Error> {
+ fn try_fold_const(&mut self, ct: Const<'db>) -> Result<Const<'db>, Self::Error> {
if !ct.has_type_flags(
rustc_type_ir::TypeFlags::HAS_ERROR
| rustc_type_ir::TypeFlags::HAS_TY_INFER
@@ -695,52 +423,38 @@ where
#[cfg(debug_assertions)]
let error = || Err(());
#[cfg(not(debug_assertions))]
- let error = || Ok(crate::next_solver::Const::error(self.interner));
+ let error = || Ok(Const::error(self.interner));
match ct.kind() {
- crate::next_solver::ConstKind::Error(_) => {
+ ConstKind::Error(_) => {
let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
- self.vars.push(crate::next_solver::CanonicalVarKind::Const(
- rustc_type_ir::UniverseIndex::ZERO,
- ));
- Ok(crate::next_solver::Const::new_bound(
- self.interner,
- self.binder,
- crate::next_solver::BoundConst { var },
- ))
+ self.vars.push(CanonicalVarKind::Const(rustc_type_ir::UniverseIndex::ZERO));
+ Ok(Const::new_bound(self.interner, self.binder, BoundConst { var }))
}
- crate::next_solver::ConstKind::Infer(_) => error(),
- crate::next_solver::ConstKind::Bound(index, _) if index > self.binder => error(),
+ ConstKind::Infer(_) => error(),
+ ConstKind::Bound(index, _) if index > self.binder => error(),
_ => ct.try_super_fold_with(self),
}
}
- fn try_fold_region(
- &mut self,
- region: crate::next_solver::Region<'db>,
- ) -> Result<crate::next_solver::Region<'db>, Self::Error> {
+ fn try_fold_region(&mut self, region: Region<'db>) -> Result<Region<'db>, Self::Error> {
#[cfg(debug_assertions)]
let error = || Err(());
#[cfg(not(debug_assertions))]
- let error = || Ok(crate::next_solver::Region::error(self.interner));
+ let error = || Ok(Region::error(self.interner));
match region.kind() {
- crate::next_solver::RegionKind::ReError(_) => {
+ RegionKind::ReError(_) => {
let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
- self.vars.push(crate::next_solver::CanonicalVarKind::Region(
- rustc_type_ir::UniverseIndex::ZERO,
- ));
- Ok(crate::next_solver::Region::new_bound(
+ self.vars.push(CanonicalVarKind::Region(rustc_type_ir::UniverseIndex::ZERO));
+ Ok(Region::new_bound(
self.interner,
self.binder,
- crate::next_solver::BoundRegion {
- var,
- kind: crate::next_solver::BoundRegionKind::Anon,
- },
+ BoundRegion { var, kind: BoundRegionKind::Anon },
))
}
- crate::next_solver::RegionKind::ReVar(_) => error(),
- crate::next_solver::RegionKind::ReBound(index, _) if index > self.binder => error(),
+ RegionKind::ReVar(_) => error(),
+ RegionKind::ReBound(index, _) if index > self.binder => error(),
_ => Ok(region),
}
}
@@ -752,18 +466,18 @@ where
Ok(t) => t,
Err(_) => panic!("Encountered unbound or inference vars in {t:?}"),
};
- crate::next_solver::Canonical {
+ Canonical {
value,
max_universe: rustc_type_ir::UniverseIndex::ZERO,
- variables: crate::next_solver::CanonicalVars::new_from_iter(interner, error_replacer.vars),
+ variables: CanonicalVars::new_from_iter(interner, error_replacer.vars),
}
}
pub fn callable_sig_from_fn_trait<'db>(
- self_ty: crate::next_solver::Ty<'db>,
+ self_ty: Ty<'db>,
trait_env: Arc<TraitEnvironment<'db>>,
db: &'db dyn HirDatabase,
-) -> Option<(FnTrait, crate::next_solver::PolyFnSig<'db>)> {
+) -> Option<(FnTrait, PolyFnSig<'db>)> {
let krate = trait_env.krate;
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
let output_assoc_type = fn_once_trait
@@ -771,54 +485,46 @@ pub fn callable_sig_from_fn_trait<'db>(
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
let mut table = InferenceTable::new(db, trait_env.clone());
- let b = TyBuilder::trait_ref(db, fn_once_trait);
- if b.remaining() != 2 {
- return None;
- }
// Register two obligations:
// - Self: FnOnce<?args_ty>
// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
let args_ty = table.next_ty_var();
let args = [self_ty, args_ty];
- let trait_ref = crate::next_solver::TraitRef::new(table.interner(), fn_once_trait.into(), args);
- let projection = crate::next_solver::Ty::new_alias(
+ let trait_ref = TraitRef::new(table.interner(), fn_once_trait.into(), args);
+ let projection = Ty::new_alias(
table.interner(),
rustc_type_ir::AliasTyKind::Projection,
- crate::next_solver::AliasTy::new(table.interner(), output_assoc_type.into(), args),
+ AliasTy::new(table.interner(), output_assoc_type.into(), args),
);
- let pred = crate::next_solver::Predicate::upcast_from(trait_ref, table.interner());
+ let pred = Predicate::upcast_from(trait_ref, table.interner());
if !table.try_obligation(pred).no_solution() {
table.register_obligation(pred);
let return_ty = table.normalize_alias_ty(projection);
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
let fn_x_trait = fn_x.get_id(db, krate)?;
- let trait_ref =
- crate::next_solver::TraitRef::new(table.interner(), fn_x_trait.into(), args);
+ let trait_ref = TraitRef::new(table.interner(), fn_x_trait.into(), args);
if !table
- .try_obligation(crate::next_solver::Predicate::upcast_from(
- trait_ref,
- table.interner(),
- ))
+ .try_obligation(Predicate::upcast_from(trait_ref, table.interner()))
.no_solution()
{
let ret_ty = table.resolve_completely(return_ty);
let args_ty = table.resolve_completely(args_ty);
- let crate::next_solver::TyKind::Tuple(params) = args_ty.kind() else {
+ let TyKind::Tuple(params) = args_ty.kind() else {
return None;
};
- let inputs_and_output = crate::next_solver::Tys::new_from_iter(
+ let inputs_and_output = Tys::new_from_iter(
table.interner(),
params.iter().chain(std::iter::once(ret_ty)),
);
return Some((
fn_x,
- crate::next_solver::Binder::dummy(crate::next_solver::FnSig {
+ Binder::dummy(FnSig {
inputs_and_output,
c_variadic: false,
- safety: crate::next_solver::abi::Safety::Safe,
+ safety: abi::Safety::Safe,
abi: FnAbi::RustCall,
}),
));
@@ -837,16 +543,16 @@ struct ParamCollector {
impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for ParamCollector {
type Result = ();
- fn visit_ty(&mut self, ty: crate::next_solver::Ty<'db>) -> Self::Result {
- if let crate::next_solver::TyKind::Param(param) = ty.kind() {
+ fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
+ if let TyKind::Param(param) = ty.kind() {
self.params.insert(param.id.into());
}
ty.super_visit_with(self);
}
- fn visit_const(&mut self, konst: crate::next_solver::Const<'db>) -> Self::Result {
- if let crate::next_solver::ConstKind::Param(param) = konst.kind() {
+ fn visit_const(&mut self, konst: Const<'db>) -> Self::Result {
+ if let ConstKind::Param(param) = konst.kind() {
self.params.insert(param.id.into());
}
@@ -865,7 +571,7 @@ where
}
pub fn known_const_to_ast<'db>(
- konst: crate::next_solver::Const<'db>,
+ konst: Const<'db>,
db: &'db dyn HirDatabase,
display_target: DisplayTarget,
) -> Option<ConstArg> {
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index b18d713c41..42f7290962 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -11,82 +11,93 @@ pub(crate) mod path;
use std::{
cell::OnceCell,
iter, mem,
- ops::{self, Not as _},
+ ops::{self, Deref, Not as _},
};
use base_db::Crate;
-use chalk_ir::{
- Mutability, Safety, TypeOutlives,
- cast::Cast,
- fold::{Shift, TypeFoldable},
- interner::HasInterner,
-};
-
use either::Either;
use hir_def::{
- AdtId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId,
- GenericParamId, LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId,
+ AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
+ FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
+ LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, TypeParamId,
UnionId, VariantId,
builtin_type::BuiltinType,
- expr_store::{ExpressionStore, path::Path},
- hir::generics::{GenericParamDataRef, TypeOrConstParamData, WherePredicate},
+ expr_store::{ExpressionStore, HygieneId, path::Path},
+ hir::generics::{
+ GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
+ },
+ item_tree::FieldsShape,
lang_item::LangItem,
- resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
- signatures::TraitFlags,
+ resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs},
+ signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
type_ref::{
- ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier, TypeBound, TypeRef,
- TypeRefId,
+ ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier,
+ TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId,
},
};
use hir_expand::name::Name;
-use la_arena::{Arena, ArenaMap};
+use la_arena::{Arena, ArenaMap, Idx};
+use path::{PathDiagnosticCallback, PathLoweringContext};
+use rustc_ast_ir::Mutability;
use rustc_hash::FxHashSet;
+use rustc_pattern_analysis::Captures;
+use rustc_type_ir::{
+ AliasTyKind, ConstKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection,
+ ExistentialTraitRef, FnSig, OutlivesPredicate,
+ TyKind::{self},
+ TypeVisitableExt,
+ inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _},
+};
+use salsa::plumbing::AsId;
+use smallvec::{SmallVec, smallvec};
use stdx::{impl_from, never};
use triomphe::{Arc, ThinArc};
use crate::{
- AliasTy, Binders, BoundVar, Const, DebruijnIndex, DynTy, FnAbi, FnPointer, FnSig, FnSubst,
- ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, LifetimeData, LifetimeOutlives,
- QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, TraitRef, TraitRefExt, Ty,
- TyBuilder, TyKind, WhereClause, all_super_traits,
- consteval_chalk::{intern_const_ref, path_to_const, unknown_const, unknown_const_as_generic},
+ FnAbi, ImplTraitId, TraitEnvironment, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
+ consteval::intern_const_ref,
db::HirDatabase,
- error_lifetime,
generics::{Generics, generics, trait_self_param_idx},
- lower::{
- diagnostics::*,
- path::{PathDiagnosticCallback, PathLoweringContext},
- },
- make_binders,
- mapping::{from_chalk_trait_id, lt_to_placeholder_idx},
next_solver::{
- DbInterner,
- mapping::{ChalkToNextSolver, NextSolverToChalk},
+ AliasTy, Binder, BoundExistentialPredicates, Clause, Clauses, Const, DbInterner,
+ EarlyBinder, EarlyParamRegion, ErrorGuaranteed, GenericArg, GenericArgs, ParamConst,
+ ParamEnv, PolyFnSig, Predicate, Region, SolverDefId, TraitPredicate, TraitRef, Ty, Tys,
+ UnevaluatedConst, abi::Safety,
},
- static_lifetime, to_chalk_trait_id, to_placeholder_idx,
- utils::all_super_trait_refs,
- variable_kinds_from_iter,
};
+pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId);
+
+#[derive(PartialEq, Eq, Debug, Hash)]
+pub struct ImplTraits<'db> {
+ pub(crate) impl_traits: Arena<ImplTrait<'db>>,
+}
+
+#[derive(PartialEq, Eq, Debug, Hash)]
+pub struct ImplTrait<'db> {
+ pub(crate) predicates: Vec<Clause<'db>>,
+}
+
+pub type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>;
+
#[derive(Debug, Default)]
-struct ImplTraitLoweringState {
+struct ImplTraitLoweringState<'db> {
/// When turning `impl Trait` into opaque types, we have to collect the
/// bounds at the same time to get the IDs correct (without becoming too
/// complicated).
mode: ImplTraitLoweringMode,
// This is structured as a struct with fields and not as an enum because it helps with the borrow checker.
- opaque_type_data: Arena<ImplTrait>,
+ opaque_type_data: Arena<ImplTrait<'db>>,
}
-impl ImplTraitLoweringState {
- fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState {
+
+impl<'db> ImplTraitLoweringState<'db> {
+ fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState<'db> {
Self { mode, opaque_type_data: Arena::new() }
}
}
-pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId);
-
#[derive(Debug, Clone)]
-pub(crate) enum LifetimeElisionKind {
+pub enum LifetimeElisionKind<'db> {
/// Create a new anonymous lifetime parameter and reference it.
///
/// If `report_in_path`, report an error when encountering lifetime elision in a path:
@@ -104,75 +115,109 @@ pub(crate) enum LifetimeElisionKind {
AnonymousCreateParameter { report_in_path: bool },
/// Replace all anonymous lifetimes by provided lifetime.
- Elided(Lifetime),
+ Elided(Region<'db>),
/// Give a hard error when either `&` or `'_` is written. Used to
/// rule out things like `where T: Foo<'_>`. Does not imply an
/// error on default object bounds (e.g., `Box<dyn Foo>`).
AnonymousReportError,
+ /// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope,
+ /// otherwise give a warning that the previous behavior of introducing a new early-bound
+ /// lifetime is a bug and will be removed (if `only_lint` is enabled).
+ StaticIfNoLifetimeInScope { only_lint: bool },
+
+ /// Signal we cannot find which should be the anonymous lifetime.
+ ElisionFailure,
+
/// Infer all elided lifetimes.
Infer,
}
-impl LifetimeElisionKind {
+impl<'db> LifetimeElisionKind<'db> {
#[inline]
- pub(crate) fn for_fn_ret() -> LifetimeElisionKind {
+ pub(crate) fn for_const(
+ interner: DbInterner<'db>,
+ const_parent: ItemContainerId,
+ ) -> LifetimeElisionKind<'db> {
+ match const_parent {
+ ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
+ LifetimeElisionKind::Elided(Region::new_static(interner))
+ }
+ ItemContainerId::ImplId(_) => {
+ LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true }
+ }
+ ItemContainerId::TraitId(_) => {
+ LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false }
+ }
+ }
+ }
+
+ #[inline]
+ pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind<'db> {
+ LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() }
+ }
+
+ #[inline]
+ pub(crate) fn for_fn_ret(interner: DbInterner<'db>) -> LifetimeElisionKind<'db> {
// FIXME: We should use the elided lifetime here, or `ElisionFailure`.
- LifetimeElisionKind::Elided(error_lifetime())
+ LifetimeElisionKind::Elided(Region::error(interner))
}
}
#[derive(Debug)]
-pub(crate) struct TyLoweringContext<'db> {
+pub struct TyLoweringContext<'db, 'a> {
pub db: &'db dyn HirDatabase,
- resolver: &'db Resolver<'db>,
- store: &'db ExpressionStore,
+ interner: DbInterner<'db>,
+ resolver: &'a Resolver<'db>,
+ store: &'a ExpressionStore,
def: GenericDefId,
generics: OnceCell<Generics>,
in_binders: DebruijnIndex,
- /// Note: Conceptually, it's thinkable that we could be in a location where
- /// some type params should be represented as placeholders, and others
- /// should be converted to variables. I think in practice, this isn't
- /// possible currently, so this should be fine for now.
- pub type_param_mode: ParamLoweringMode,
- impl_trait_mode: ImplTraitLoweringState,
+ impl_trait_mode: ImplTraitLoweringState<'db>,
/// Tracks types with explicit `?Sized` bounds.
- pub(crate) unsized_types: FxHashSet<Ty>,
+ pub(crate) unsized_types: FxHashSet<Ty<'db>>,
pub(crate) diagnostics: Vec<TyLoweringDiagnostic>,
- lifetime_elision: LifetimeElisionKind,
+ lifetime_elision: LifetimeElisionKind<'db>,
+ /// When lowering the defaults for generic params, this contains the index of the currently lowered param.
+ /// We disallow referring to later params, or to ADT's `Self`.
+ lowering_param_default: Option<u32>,
}
-impl<'db> TyLoweringContext<'db> {
- pub(crate) fn new(
+impl<'db, 'a> TyLoweringContext<'db, 'a> {
+ pub fn new(
db: &'db dyn HirDatabase,
- resolver: &'db Resolver<'db>,
- store: &'db ExpressionStore,
+ resolver: &'a Resolver<'db>,
+ store: &'a ExpressionStore,
def: GenericDefId,
- lifetime_elision: LifetimeElisionKind,
+ lifetime_elision: LifetimeElisionKind<'db>,
) -> Self {
let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
- let type_param_mode = ParamLoweringMode::Placeholder;
- let in_binders = DebruijnIndex::INNERMOST;
+ let in_binders = DebruijnIndex::ZERO;
Self {
db,
+ interner: DbInterner::new_with(db, Some(resolver.krate()), None),
resolver,
def,
generics: Default::default(),
store,
in_binders,
impl_trait_mode,
- type_param_mode,
unsized_types: FxHashSet::default(),
diagnostics: Vec::new(),
lifetime_elision,
+ lowering_param_default: None,
}
}
+ pub(crate) fn set_lifetime_elision(&mut self, lifetime_elision: LifetimeElisionKind<'db>) {
+ self.lifetime_elision = lifetime_elision;
+ }
+
pub(crate) fn with_debruijn<T>(
&mut self,
debruijn: DebruijnIndex,
- f: impl FnOnce(&mut TyLoweringContext<'_>) -> T,
+ f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
) -> T {
let old_debruijn = mem::replace(&mut self.in_binders, debruijn);
let result = f(self);
@@ -183,28 +228,22 @@ impl<'db> TyLoweringContext<'db> {
pub(crate) fn with_shifted_in<T>(
&mut self,
debruijn: DebruijnIndex,
- f: impl FnOnce(&mut TyLoweringContext<'_>) -> T,
+ f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
) -> T {
- self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f)
- }
-
- fn with_lifetime_elision<T>(
- &mut self,
- lifetime_elision: LifetimeElisionKind,
- f: impl FnOnce(&mut TyLoweringContext<'_>) -> T,
- ) -> T {
- let old_lifetime_elision = mem::replace(&mut self.lifetime_elision, lifetime_elision);
- let result = f(self);
- self.lifetime_elision = old_lifetime_elision;
- result
+ self.with_debruijn(self.in_binders.shifted_in(debruijn.as_u32()), f)
}
pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self }
}
- pub(crate) fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self {
- Self { type_param_mode, ..self }
+ pub(crate) fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self {
+ self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode);
+ self
+ }
+
+ pub(crate) fn lowering_param_default(&mut self, index: u32) {
+ self.lowering_param_default = Some(index);
}
pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
@@ -213,7 +252,7 @@ impl<'db> TyLoweringContext<'db> {
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
-pub enum ImplTraitLoweringMode {
+pub(crate) enum ImplTraitLoweringMode {
/// `impl Trait` gets lowered into an opaque type that doesn't unify with
/// anything except itself. This is used in places where values flow 'out',
/// i.e. for arguments of the function we're currently checking, and return
@@ -224,30 +263,17 @@ pub enum ImplTraitLoweringMode {
Disallowed,
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum ParamLoweringMode {
- Placeholder,
- Variable,
-}
-
-impl<'db> TyLoweringContext<'db> {
- pub(crate) fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty {
+impl<'db, 'a> TyLoweringContext<'db, 'a> {
+ pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
self.lower_ty_ext(type_ref).0
}
- pub(crate) fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const {
+ pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> {
let const_ref = &self.store[const_ref.expr];
match const_ref {
- hir_def::hir::Expr::Path(path) => path_to_const(
- self.db,
- self.resolver,
- path,
- self.type_param_mode,
- || self.generics(),
- self.in_binders,
- const_type.clone(),
- )
- .unwrap_or_else(|| unknown_const(const_type)),
+ hir_def::hir::Expr::Path(path) => {
+ self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
+ }
hir_def::hir::Expr::Literal(literal) => intern_const_ref(
self.db,
&match *literal {
@@ -290,32 +316,88 @@ impl<'db> TyLoweringContext<'db> {
}
}
- pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty) -> Const {
- path_to_const(
- self.db,
- self.resolver,
- path,
- self.type_param_mode,
- || self.generics(),
- self.in_binders,
- const_type.clone(),
- )
- .unwrap_or_else(|| unknown_const(const_type))
+ pub(crate) fn path_to_const(&mut self, path: &Path) -> Option<Const<'db>> {
+ match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) {
+ Some(ValueNs::GenericParam(p)) => {
+ let args = self.generics();
+ match args.type_or_const_param_idx(p.into()) {
+ Some(idx) => Some(self.const_param(p, idx as u32)),
+ None => {
+ never!(
+ "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
+ args,
+ path,
+ p
+ );
+ None
+ }
+ }
+ }
+ Some(ValueNs::ConstId(c)) => {
+ let args = GenericArgs::new_from_iter(self.interner, []);
+ Some(Const::new(
+ self.interner,
+ rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(
+ SolverDefId::ConstId(c),
+ args,
+ )),
+ ))
+ }
+ _ => None,
+ }
+ }
+
+ pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty<'db>) -> Const<'db> {
+ self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
}
fn generics(&self) -> &Generics {
self.generics.get_or_init(|| generics(self.db, self.def))
}
- pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) {
+ fn param_index_is_disallowed(&self, index: u32) -> bool {
+ self.lowering_param_default
+ .is_some_and(|disallow_params_after| index >= disallow_params_after)
+ }
+
+ fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> {
+ if self.param_index_is_disallowed(index) {
+ // FIXME: Report an error.
+ Ty::new_error(self.interner, ErrorGuaranteed)
+ } else {
+ Ty::new_param(self.interner, id, index)
+ }
+ }
+
+ fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> {
+ if self.param_index_is_disallowed(index) {
+ // FIXME: Report an error.
+ Const::error(self.interner)
+ } else {
+ Const::new_param(self.interner, ParamConst { id, index })
+ }
+ }
+
+ fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> {
+ if self.param_index_is_disallowed(index) {
+ // FIXME: Report an error.
+ Region::error(self.interner)
+ } else {
+ Region::new_early_param(self.interner, EarlyParamRegion { id, index })
+ }
+ }
+
+ #[tracing::instrument(skip(self), ret)]
+ pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) {
+ let interner = self.interner;
let mut res = None;
let type_ref = &self.store[type_ref_id];
+ tracing::debug!(?type_ref);
let ty = match type_ref {
- TypeRef::Never => TyKind::Never.intern(Interner),
+ TypeRef::Never => Ty::new(interner, TyKind::Never),
TypeRef::Tuple(inner) => {
let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr));
- TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
- .intern(Interner)
+ Ty::new_tup_from_iter(interner, inner_tys)
}
TypeRef::Path(path) => {
let (ty, res_) =
@@ -325,81 +407,61 @@ impl<'db> TyLoweringContext<'db> {
}
&TypeRef::TypeParam(type_param_id) => {
res = Some(TypeNs::GenericParam(type_param_id));
- match self.type_param_mode {
- ParamLoweringMode::Placeholder => {
- let generics = self.generics();
- let idx = generics.type_or_const_param_idx(type_param_id.into()).unwrap();
- TyKind::Placeholder(to_placeholder_idx(
- self.db,
- type_param_id.into(),
- idx as u32,
- ))
- }
- ParamLoweringMode::Variable => {
- let idx =
- self.generics().type_or_const_param_idx(type_param_id.into()).unwrap();
- TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
- }
- }
- .intern(Interner)
+
+ let generics = self.generics();
+ let (idx, _data) =
+ generics.type_or_const_param(type_param_id.into()).expect("matching generics");
+ self.type_param(type_param_id, idx as u32)
}
&TypeRef::RawPtr(inner, mutability) => {
let inner_ty = self.lower_ty(inner);
- TyKind::Raw(lower_to_chalk_mutability(mutability), inner_ty).intern(Interner)
+ Ty::new(interner, TyKind::RawPtr(inner_ty, lower_mutability(mutability)))
}
TypeRef::Array(array) => {
let inner_ty = self.lower_ty(array.ty);
- let const_len = self.lower_const(&array.len, TyBuilder::usize());
- TyKind::Array(inner_ty, const_len).intern(Interner)
+ let const_len = self.lower_const(array.len, Ty::new_usize(interner));
+ Ty::new_array_with_const_len(interner, inner_ty, const_len)
}
&TypeRef::Slice(inner) => {
let inner_ty = self.lower_ty(inner);
- TyKind::Slice(inner_ty).intern(Interner)
+ Ty::new_slice(interner, inner_ty)
}
TypeRef::Reference(ref_) => {
let inner_ty = self.lower_ty(ref_.ty);
- // FIXME: It should infer the eldided lifetimes instead of stubbing with static
+ // FIXME: It should infer the eldided lifetimes instead of stubbing with error
let lifetime = ref_
.lifetime
- .as_ref()
- .map_or_else(error_lifetime, |&lr| self.lower_lifetime(lr));
- TyKind::Ref(lower_to_chalk_mutability(ref_.mutability), lifetime, inner_ty)
- .intern(Interner)
+ .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr));
+ Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability))
}
- TypeRef::Placeholder => TyKind::Error.intern(Interner),
+ TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed),
TypeRef::Fn(fn_) => {
- let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
- let (params, ret) = fn_.split_params_and_ret();
- let mut subst = Vec::with_capacity(fn_.params.len());
- ctx.with_lifetime_elision(
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false },
- |ctx| {
- subst.extend(params.iter().map(|&(_, tr)| ctx.lower_ty(tr)));
- },
- );
- ctx.with_lifetime_elision(LifetimeElisionKind::for_fn_ret(), |ctx| {
- subst.push(ctx.lower_ty(ret));
- });
- Substitution::from_iter(Interner, subst)
- });
- TyKind::Function(FnPointer {
- num_binders: 0, // FIXME lower `for<'a> fn()` correctly
- sig: FnSig {
+ let substs = self.with_shifted_in(
+ DebruijnIndex::from_u32(1),
+ |ctx: &mut TyLoweringContext<'_, '_>| {
+ Tys::new_from_iter(
+ interner,
+ fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)),
+ )
+ },
+ );
+ Ty::new_fn_ptr(
+ interner,
+ Binder::dummy(FnSig {
abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
- variadic: fn_.is_varargs,
- },
- substitution: FnSubst(substs),
- })
- .intern(Interner)
+ c_variadic: fn_.is_varargs,
+ inputs_and_output: substs,
+ }),
+ )
}
TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
TypeRef::ImplTrait(bounds) => {
match self.impl_trait_mode.mode {
ImplTraitLoweringMode::Opaque => {
- let origin = match self.def {
- GenericDefId::FunctionId(it) => Either::Left(it),
- GenericDefId::TypeAliasId(it) => Either::Right(it),
+ let origin = match self.resolver.generic_def() {
+ Some(GenericDefId::FunctionId(it)) => Either::Left(it),
+ Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
_ => panic!(
"opaque impl trait lowering must be in function or type alias"
),
@@ -408,9 +470,19 @@ impl<'db> TyLoweringContext<'db> {
// this dance is to make sure the data is in the right
// place even if we encounter more opaque types while
// lowering the bounds
- let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait {
- bounds: crate::make_single_type_binders(Vec::default()),
- });
+ let idx = self
+ .impl_trait_mode
+ .opaque_type_data
+ .alloc(ImplTrait { predicates: Vec::default() });
+
+ // FIXME(next-solver): this from_raw/into_raw dance isn't nice, but it's minimal
+ let impl_trait_id = origin.either(
+ |f| ImplTraitId::ReturnTypeImplTrait(f, Idx::from_raw(idx.into_raw())),
+ |a| ImplTraitId::TypeAliasImplTrait(a, Idx::from_raw(idx.into_raw())),
+ );
+ let opaque_ty_id: SolverDefId =
+ self.db.intern_impl_trait_id(impl_trait_id).into();
+
// We don't want to lower the bounds inside the binders
// we're currently in, because they don't end up inside
// those binders. E.g. when we have `impl Trait<impl
@@ -421,27 +493,25 @@ impl<'db> TyLoweringContext<'db> {
// parameter of the outer function, it's just one binder
// away instead of two.
let actual_opaque_type_data = self
- .with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
- ctx.lower_impl_trait(bounds, self.resolver.krate())
+ .with_debruijn(DebruijnIndex::ZERO, |ctx| {
+ ctx.lower_impl_trait(opaque_ty_id, bounds, self.resolver.krate())
});
self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
- let impl_trait_id = origin.either(
- |f| ImplTraitId::ReturnTypeImplTrait(f, idx),
- |a| ImplTraitId::TypeAliasImplTrait(a, idx),
- );
- let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
- let generics = generics(self.db, origin.either(|f| f.into(), |a| a.into()));
- let parameters = generics.bound_vars_subst(self.db, self.in_binders);
- TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner)
+ let args = GenericArgs::identity_for_item(self.interner, opaque_ty_id);
+ Ty::new_alias(
+ self.interner,
+ AliasTyKind::Opaque,
+ AliasTy::new_from_args(self.interner, opaque_ty_id, args),
+ )
}
ImplTraitLoweringMode::Disallowed => {
// FIXME: report error
- TyKind::Error.intern(Interner)
+ Ty::new_error(self.interner, ErrorGuaranteed)
}
}
}
- TypeRef::Error => TyKind::Error.intern(Interner),
+ TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed),
};
(ty, res)
}
@@ -449,8 +519,8 @@ impl<'db> TyLoweringContext<'db> {
/// This is only for `generic_predicates_for_param`, where we can't just
/// lower the self types of the predicates since that could lead to cycles.
/// So we just check here if the `type_ref` resolves to a generic param, and which.
- fn lower_ty_only_param(&mut self, type_ref_id: TypeRefId) -> Option<TypeOrConstParamId> {
- let type_ref = &self.store[type_ref_id];
+ fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option<TypeOrConstParamId> {
+ let type_ref = &self.store[type_ref];
let path = match type_ref {
TypeRef::Path(path) => path,
&TypeRef::TypeParam(idx) => return Some(idx.into()),
@@ -462,9 +532,8 @@ impl<'db> TyLoweringContext<'db> {
if path.segments().len() > 1 {
return None;
}
- let mut ctx = self.at_path(PathId::from_type_ref_unchecked(type_ref_id));
- let resolution = match ctx.resolve_path_in_type_ns() {
- Some((it, None)) => it,
+ let resolution = match self.resolver.resolve_path_in_type_ns(self.db, path) {
+ Some((it, None, _)) => it,
_ => return None,
};
match resolution {
@@ -474,7 +543,7 @@ impl<'db> TyLoweringContext<'db> {
}
#[inline]
- fn on_path_diagnostic_callback<'a>(type_ref: TypeRefId) -> PathDiagnosticCallback<'a, 'db> {
+ fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> {
PathDiagnosticCallback {
data: Either::Left(PathDiagnosticCallbackData(type_ref)),
callback: |data, this, diag| {
@@ -485,7 +554,7 @@ impl<'db> TyLoweringContext<'db> {
}
#[inline]
- fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'db> {
+ fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a, 'db> {
PathLoweringContext::new(
self,
Self::on_path_diagnostic_callback(path_id.type_ref()),
@@ -493,7 +562,7 @@ impl<'db> TyLoweringContext<'db> {
)
}
- pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty, Option<TypeNs>) {
+ pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty<'db>, Option<TypeNs>) {
// Resolve the path (in type namespace)
if let Some(type_ref) = path.type_anchor() {
let (ty, res) = self.lower_ty_ext(type_ref);
@@ -504,7 +573,7 @@ impl<'db> TyLoweringContext<'db> {
let mut ctx = self.at_path(path_id);
let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() {
Some(it) => it,
- None => return (TyKind::Error.intern(Interner), None),
+ None => return (Ty::new_error(self.interner, ErrorGuaranteed), None),
};
if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
@@ -520,8 +589,8 @@ impl<'db> TyLoweringContext<'db> {
fn lower_trait_ref_from_path(
&mut self,
path_id: PathId,
- explicit_self_ty: Ty,
- ) -> Option<(TraitRef, PathLoweringContext<'_, 'db>)> {
+ explicit_self_ty: Ty<'db>,
+ ) -> Option<(TraitRef<'db>, PathLoweringContext<'_, 'a, 'db>)> {
let mut ctx = self.at_path(path_id);
let resolved = match ctx.resolve_path_in_type_ns_fully()? {
// FIXME(trait_alias): We need to handle trait alias here.
@@ -531,26 +600,57 @@ impl<'db> TyLoweringContext<'db> {
Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx))
}
- /// When lowering predicates from parents (impl, traits) for children defs (fns, consts, types), `generics` should
- /// contain the `Generics` for the **child**, while `predicate_owner` should contain the `GenericDefId` of the
- /// **parent**. This is important so we generate the correct bound var/placeholder.
+ fn lower_trait_ref(
+ &mut self,
+ trait_ref: &HirTraitRef,
+ explicit_self_ty: Ty<'db>,
+ ) -> Option<TraitRef<'db>> {
+ self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
+ }
+
pub(crate) fn lower_where_predicate<'b>(
&'b mut self,
where_predicate: &'b WherePredicate,
ignore_bindings: bool,
- ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'db, 'b> {
+ generics: &Generics,
+ predicate_filter: PredicateFilter,
+ ) -> impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'db> {
match where_predicate {
WherePredicate::ForLifetime { target, bound, .. }
| WherePredicate::TypeBound { target, bound } => {
+ if let PredicateFilter::SelfTrait = predicate_filter {
+ let target_type = &self.store[*target];
+ let self_type = 'is_self: {
+ if let TypeRef::Path(path) = target_type
+ && path.is_self_type()
+ {
+ break 'is_self true;
+ }
+ if let TypeRef::TypeParam(param) = target_type
+ && generics[param.local_id()].is_trait_self()
+ {
+ break 'is_self true;
+ }
+ false
+ };
+ if !self_type {
+ return Either::Left(Either::Left(iter::empty()));
+ }
+ }
let self_ty = self.lower_ty(*target);
- Either::Left(self.lower_type_bound(bound, self_ty, ignore_bindings))
+ Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings)))
+ }
+ &WherePredicate::Lifetime { bound, target } => {
+ Either::Right(iter::once(Clause(Predicate::new(
+ self.interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate(
+ self.lower_lifetime(bound),
+ self.lower_lifetime(target),
+ )),
+ )),
+ ))))
}
- &WherePredicate::Lifetime { bound, target } => Either::Right(iter::once(
- crate::wrap_empty_binders(WhereClause::LifetimeOutlives(LifetimeOutlives {
- a: self.lower_lifetime(bound),
- b: self.lower_lifetime(target),
- })),
- )),
}
.into_iter()
}
@@ -558,40 +658,40 @@ impl<'db> TyLoweringContext<'db> {
pub(crate) fn lower_type_bound<'b>(
&'b mut self,
bound: &'b TypeBound,
- self_ty: Ty,
+ self_ty: Ty<'db>,
ignore_bindings: bool,
- ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'db> {
+ ) -> impl Iterator<Item = Clause<'db>> + use<'b, 'a, 'db> {
+ let interner = self.interner;
let mut assoc_bounds = None;
let mut clause = None;
match bound {
&TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
// FIXME Don't silently drop the hrtb lifetimes here
- if let Some((trait_ref, mut ctx)) =
- self.lower_trait_ref_from_path(path, self_ty.clone())
- {
+ if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
// FIXME(sized-hierarchy): Remove this bound modifications once we have implemented
// sized-hierarchy correctly.
let meta_sized = LangItem::MetaSized
.resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
let pointee_sized = LangItem::PointeeSized
.resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
- let destruct = LangItem::Destruct
- .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
- let hir_trait_id = trait_ref.hir_trait_id();
- if meta_sized.is_some_and(|it| it == hir_trait_id)
- || destruct.is_some_and(|it| it == hir_trait_id)
- {
+ if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) {
// Ignore this bound
- } else if pointee_sized.is_some_and(|it| it == hir_trait_id) {
+ } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) {
// Regard this as `?Sized` bound
ctx.ty_ctx().unsized_types.insert(self_ty);
} else {
if !ignore_bindings {
- assoc_bounds =
- ctx.assoc_type_bindings_from_type_bound(trait_ref.clone());
+ assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref);
}
- clause =
- Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref)));
+ clause = Some(Clause(Predicate::new(
+ interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Trait(TraitPredicate {
+ trait_ref,
+ polarity: rustc_type_ir::PredicatePolarity::Positive,
+ }),
+ )),
+ )));
}
}
}
@@ -601,95 +701,137 @@ impl<'db> TyLoweringContext<'db> {
// `?Sized` has no of them.
// If we got another trait here ignore the bound completely.
let trait_id = self
- .lower_trait_ref_from_path(path, self_ty.clone())
- .map(|(trait_ref, _)| trait_ref.hir_trait_id());
+ .lower_trait_ref_from_path(path, self_ty)
+ .map(|(trait_ref, _)| trait_ref.def_id.0);
if trait_id == sized_trait {
self.unsized_types.insert(self_ty);
}
}
&TypeBound::Lifetime(l) => {
let lifetime = self.lower_lifetime(l);
- clause = Some(crate::wrap_empty_binders(WhereClause::TypeOutlives(TypeOutlives {
- ty: self_ty,
- lifetime,
- })));
+ clause = Some(Clause(Predicate::new(
+ self.interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate(
+ self_ty, lifetime,
+ )),
+ )),
+ )));
}
TypeBound::Use(_) | TypeBound::Error => {}
}
clause.into_iter().chain(assoc_bounds.into_iter().flatten())
}
- fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty {
- let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
+ fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> {
+ let interner = self.interner;
+ // FIXME: we should never create non-existential predicates in the first place
+ // For now, use an error type so we don't run into dummy binder issues
+ let self_ty = Ty::new_error(interner, ErrorGuaranteed);
// INVARIANT: The principal trait bound, if present, must come first. Others may be in any
// order but should be in the same order for the same set but possibly different order of
// bounds in the input.
// INVARIANT: If this function returns `DynTy`, there should be at least one trait bound.
// These invariants are utilized by `TyExt::dyn_trait()` and chalk.
let mut lifetime = None;
- let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
- let mut lowered_bounds = Vec::new();
+ let bounds = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
+ let mut lowered_bounds: Vec<
+ rustc_type_ir::Binder<DbInterner<'db>, ExistentialPredicate<DbInterner<'db>>>,
+ > = Vec::new();
for b in bounds {
- ctx.lower_type_bound(b, self_ty.clone(), false).for_each(|b| {
- let filter = match b.skip_binders() {
- WhereClause::Implemented(_) | WhereClause::AliasEq(_) => true,
- WhereClause::LifetimeOutlives(_) => false,
- WhereClause::TypeOutlives(t) => {
- lifetime = Some(t.lifetime.clone());
- false
- }
- };
- if filter {
- lowered_bounds.push(b);
+ let db = ctx.db;
+ ctx.lower_type_bound(b, self_ty, false).for_each(|b| {
+ if let Some(bound) = b
+ .kind()
+ .map_bound(|c| match c {
+ rustc_type_ir::ClauseKind::Trait(t) => {
+ let id = t.def_id();
+ let is_auto =
+ db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
+ if is_auto {
+ Some(ExistentialPredicate::AutoTrait(t.def_id()))
+ } else {
+ Some(ExistentialPredicate::Trait(
+ ExistentialTraitRef::new_from_args(
+ interner,
+ t.def_id(),
+ GenericArgs::new_from_iter(
+ interner,
+ t.trait_ref.args.iter().skip(1),
+ ),
+ ),
+ ))
+ }
+ }
+ rustc_type_ir::ClauseKind::Projection(p) => {
+ Some(ExistentialPredicate::Projection(
+ ExistentialProjection::new_from_args(
+ interner,
+ p.def_id(),
+ GenericArgs::new_from_iter(
+ interner,
+ p.projection_term.args.iter().skip(1),
+ ),
+ p.term,
+ ),
+ ))
+ }
+ rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => {
+ lifetime = Some(outlives_predicate.1);
+ None
+ }
+ rustc_type_ir::ClauseKind::RegionOutlives(_)
+ | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
+ | rustc_type_ir::ClauseKind::WellFormed(_)
+ | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
+ | rustc_type_ir::ClauseKind::HostEffect(_)
+ | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
+ })
+ .transpose()
+ {
+ lowered_bounds.push(bound);
}
- });
+ })
}
let mut multiple_regular_traits = false;
let mut multiple_same_projection = false;
lowered_bounds.sort_unstable_by(|lhs, rhs| {
use std::cmp::Ordering;
- match (lhs.skip_binders(), rhs.skip_binders()) {
- (WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => {
- let lhs_id = lhs.trait_id;
- let lhs_is_auto = ctx
- .db
- .trait_signature(from_chalk_trait_id(lhs_id))
- .flags
- .contains(TraitFlags::AUTO);
- let rhs_id = rhs.trait_id;
- let rhs_is_auto = ctx
- .db
- .trait_signature(from_chalk_trait_id(rhs_id))
- .flags
- .contains(TraitFlags::AUTO);
-
- if !lhs_is_auto && !rhs_is_auto {
- multiple_regular_traits = true;
- }
- // Note that the ordering here is important; this ensures the invariant
- // mentioned above.
- (lhs_is_auto, lhs_id).cmp(&(rhs_is_auto, rhs_id))
+ match ((*lhs).skip_binder(), (*rhs).skip_binder()) {
+ (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => {
+ multiple_regular_traits = true;
+ // Order doesn't matter - we error
+ Ordering::Equal
}
- (WhereClause::Implemented(_), _) => Ordering::Less,
- (_, WhereClause::Implemented(_)) => Ordering::Greater,
- (WhereClause::AliasEq(lhs), WhereClause::AliasEq(rhs)) => {
- match (&lhs.alias, &rhs.alias) {
- (AliasTy::Projection(lhs_proj), AliasTy::Projection(rhs_proj)) => {
- // We only compare the `associated_ty_id`s. We shouldn't have
- // multiple bounds for an associated type in the correct Rust code,
- // and if we do, we error out.
- if lhs_proj.associated_ty_id == rhs_proj.associated_ty_id {
- multiple_same_projection = true;
- }
- lhs_proj.associated_ty_id.cmp(&rhs_proj.associated_ty_id)
- }
- // We don't produce `AliasTy::Opaque`s yet.
+ (
+ ExistentialPredicate::AutoTrait(lhs_id),
+ ExistentialPredicate::AutoTrait(rhs_id),
+ ) => lhs_id.0.cmp(&rhs_id.0),
+ (ExistentialPredicate::Trait(_), _) => Ordering::Less,
+ (_, ExistentialPredicate::Trait(_)) => Ordering::Greater,
+ (ExistentialPredicate::AutoTrait(_), _) => Ordering::Less,
+ (_, ExistentialPredicate::AutoTrait(_)) => Ordering::Greater,
+ (
+ ExistentialPredicate::Projection(lhs),
+ ExistentialPredicate::Projection(rhs),
+ ) => {
+ let lhs_id = match lhs.def_id {
+ SolverDefId::TypeAliasId(id) => id,
_ => unreachable!(),
+ };
+ let rhs_id = match rhs.def_id {
+ SolverDefId::TypeAliasId(id) => id,
+ _ => unreachable!(),
+ };
+ // We only compare the `associated_ty_id`s. We shouldn't have
+ // multiple bounds for an associated type in the correct Rust code,
+ // and if we do, we error out.
+ if lhs_id == rhs_id {
+ multiple_same_projection = true;
}
+ lhs_id.as_id().index().cmp(&rhs_id.as_id().index())
}
- // `WhereClause::{TypeOutlives, LifetimeOutlives}` have been filtered out
- _ => unreachable!(),
}
});
@@ -697,183 +839,463 @@ impl<'db> TyLoweringContext<'db> {
return None;
}
- lowered_bounds.first().and_then(|b| b.trait_id())?;
+ if !lowered_bounds.first().map_or(false, |b| {
+ matches!(
+ b.as_ref().skip_binder(),
+ ExistentialPredicate::Trait(_) | ExistentialPredicate::AutoTrait(_)
+ )
+ }) {
+ return None;
+ }
// As multiple occurrences of the same auto traits *are* permitted, we deduplicate the
// bounds. We shouldn't have repeated elements besides auto traits at this point.
lowered_bounds.dedup();
- Some(QuantifiedWhereClauses::from_iter(Interner, lowered_bounds))
+ Some(BoundExistentialPredicates::new_from_iter(interner, lowered_bounds))
});
if let Some(bounds) = bounds {
- let bounds = crate::make_single_type_binders(bounds);
- TyKind::Dyn(DynTy {
- bounds,
- lifetime: match lifetime {
- Some(it) => match it.bound_var(Interner) {
- Some(bound_var) => bound_var
- .shifted_out_to(DebruijnIndex::new(2))
- .map(|bound_var| LifetimeData::BoundVar(bound_var).intern(Interner))
- .unwrap_or(it),
- None => it,
- },
- None => error_lifetime(),
+ let region = match lifetime {
+ Some(it) => match it.kind() {
+ rustc_type_ir::RegionKind::ReBound(db, var) => Region::new_bound(
+ self.interner,
+ db.shifted_out_to_binder(DebruijnIndex::from_u32(2)),
+ var,
+ ),
+ _ => it,
},
- })
- .intern(Interner)
+ None => Region::new_static(self.interner),
+ };
+ Ty::new_dynamic(self.interner, bounds, region)
} else {
// FIXME: report error
// (additional non-auto traits, associated type rebound, or no resolved trait)
- TyKind::Error.intern(Interner)
+ Ty::new_error(self.interner, ErrorGuaranteed)
}
}
- fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: Crate) -> ImplTrait {
+ fn lower_impl_trait(
+ &mut self,
+ def_id: SolverDefId,
+ bounds: &[TypeBound],
+ krate: Crate,
+ ) -> ImplTrait<'db> {
+ let interner = self.interner;
cov_mark::hit!(lower_rpit);
- let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
- let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
+ let args = GenericArgs::identity_for_item(interner, def_id);
+ let self_ty = Ty::new_alias(
+ self.interner,
+ rustc_type_ir::AliasTyKind::Opaque,
+ AliasTy::new_from_args(interner, def_id, args),
+ );
+ let predicates = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
let mut predicates = Vec::new();
for b in bounds {
- predicates.extend(ctx.lower_type_bound(b, self_ty.clone(), false));
+ predicates.extend(ctx.lower_type_bound(b, self_ty, false));
}
if !ctx.unsized_types.contains(&self_ty) {
- let sized_trait =
- LangItem::Sized.resolve_trait(ctx.db, krate).map(to_chalk_trait_id);
+ let sized_trait = LangItem::Sized.resolve_trait(self.db, krate);
let sized_clause = sized_trait.map(|trait_id| {
- let clause = WhereClause::Implemented(TraitRef {
- trait_id,
- substitution: Substitution::from1(Interner, self_ty.clone()),
- });
- crate::wrap_empty_binders(clause)
+ let trait_ref = TraitRef::new_from_args(
+ interner,
+ trait_id.into(),
+ GenericArgs::new_from_iter(interner, [self_ty.into()]),
+ );
+ Clause(Predicate::new(
+ interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Trait(TraitPredicate {
+ trait_ref,
+ polarity: rustc_type_ir::PredicatePolarity::Positive,
+ }),
+ )),
+ ))
});
predicates.extend(sized_clause);
}
predicates.shrink_to_fit();
predicates
});
- ImplTrait { bounds: crate::make_single_type_binders(predicates) }
+ ImplTrait { predicates }
}
- pub(crate) fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Lifetime {
+ pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> {
match self.resolver.resolve_lifetime(&self.store[lifetime]) {
Some(resolution) => match resolution {
- LifetimeNs::Static => static_lifetime(),
- LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
- ParamLoweringMode::Placeholder => {
- let generics = self.generics();
- let idx = generics.lifetime_idx(id).unwrap();
- LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id, idx as u32))
- }
- ParamLoweringMode::Variable => {
- let idx = match self.generics().lifetime_idx(id) {
- None => return error_lifetime(),
- Some(idx) => idx,
- };
-
- LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx))
- }
+ LifetimeNs::Static => Region::new_static(self.interner),
+ LifetimeNs::LifetimeParam(id) => {
+ let idx = match self.generics().lifetime_idx(id) {
+ None => return Region::error(self.interner),
+ Some(idx) => idx,
+ };
+ self.region_param(id, idx as u32)
}
- .intern(Interner),
},
- None => error_lifetime(),
+ None => Region::error(self.interner),
}
}
}
-fn named_associated_type_shorthand_candidates<R>(
- db: &dyn HirDatabase,
- // If the type parameter is defined in an impl and we're in a method, there
- // might be additional where clauses to consider
- def: GenericDefId,
- res: TypeNs,
- assoc_name: Option<Name>,
- // Do NOT let `cb` touch `TraitRef` outside of `TyLoweringContext`. Its substitution contains
- // free `BoundVar`s that need to be shifted and only `TyLoweringContext` knows how to do that
- // properly (see `TyLoweringContext::select_associated_type()`).
- mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
-) -> Option<R> {
- let mut search = |t| {
- all_super_trait_refs(db, t, |t| {
- let data = t.hir_trait_id().trait_items(db);
+pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
+ match m {
+ hir_def::type_ref::Mutability::Shared => Mutability::Not,
+ hir_def::type_ref::Mutability::Mut => Mutability::Mut,
+ }
+}
- for (name, assoc_id) in &data.items {
- if let AssocItemId::TypeAliasId(alias) = assoc_id
- && let Some(result) = cb(name, &t, *alias)
- {
- return Some(result);
- }
- }
- None
- })
- };
+fn unknown_const(_ty: Ty<'_>) -> Const<'_> {
+ Const::new(DbInterner::conjure(), ConstKind::Error(ErrorGuaranteed))
+}
+
+pub(crate) type Diagnostics = Option<ThinArc<(), TyLoweringDiagnostic>>;
+
+pub(crate) fn create_diagnostics(diagnostics: Vec<TyLoweringDiagnostic>) -> Diagnostics {
+ (!diagnostics.is_empty()).then(|| ThinArc::from_header_and_iter((), diagnostics.into_iter()))
+}
+
+pub(crate) fn impl_trait_query<'db>(
+ db: &'db dyn HirDatabase,
+ impl_id: ImplId,
+) -> Option<EarlyBinder<'db, TraitRef<'db>>> {
+ db.impl_trait_with_diagnostics(impl_id).map(|it| it.0)
+}
+
+pub(crate) fn impl_trait_with_diagnostics_query<'db>(
+ db: &'db dyn HirDatabase,
+ impl_id: ImplId,
+) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)> {
+ let impl_data = db.impl_signature(impl_id);
+ let resolver = impl_id.resolver(db);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &impl_data.store,
+ impl_id.into(),
+ LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
+ );
+ let self_ty = db.impl_self_ty(impl_id).skip_binder();
+ let target_trait = impl_data.target_trait.as_ref()?;
+ let trait_ref = EarlyBinder::bind(ctx.lower_trait_ref(target_trait, self_ty)?);
+ Some((trait_ref, create_diagnostics(ctx.diagnostics)))
+}
+pub(crate) fn return_type_impl_traits<'db>(
+ db: &'db dyn HirDatabase,
+ def: hir_def::FunctionId,
+) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>> {
+ // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
+ let data = db.function_signature(def);
+ let resolver = def.resolver(db);
+ let mut ctx_ret =
+ TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer)
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
+ if let Some(ret_type) = data.ret_type {
+ let _ret = ctx_ret.lower_ty(ret_type);
+ }
+ let 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 {
+ Some(Arc::new(EarlyBinder::bind(return_type_impl_traits)))
+ }
+}
+
+pub(crate) fn type_alias_impl_traits<'db>(
+ db: &'db dyn HirDatabase,
+ def: hir_def::TypeAliasId,
+) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>> {
+ let data = db.type_alias_signature(def);
+ let resolver = def.resolver(db);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &data.store,
+ def.into(),
+ LifetimeElisionKind::AnonymousReportError,
+ )
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
+ if let Some(type_ref) = data.ty {
+ let _ty = ctx.lower_ty(type_ref);
+ }
+ let 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 {
+ Some(Arc::new(EarlyBinder::bind(type_alias_impl_traits)))
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum TyDefId {
+ BuiltinType(BuiltinType),
+ AdtId(AdtId),
+ TypeAliasId(TypeAliasId),
+}
+impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId);
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
+pub enum ValueTyDefId {
+ FunctionId(FunctionId),
+ StructId(StructId),
+ UnionId(UnionId),
+ EnumVariantId(EnumVariantId),
+ ConstId(ConstId),
+ StaticId(StaticId),
+}
+impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
+
+impl ValueTyDefId {
+ pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> GenericDefId {
+ match self {
+ Self::FunctionId(id) => id.into(),
+ Self::StructId(id) => id.into(),
+ Self::UnionId(id) => id.into(),
+ Self::EnumVariantId(var) => var.lookup(db).parent.into(),
+ Self::ConstId(id) => id.into(),
+ Self::StaticId(id) => id.into(),
+ }
+ }
+}
+
+/// Build the declared type of an item. This depends on the namespace; e.g. for
+/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
+/// the constructor function `(usize) -> Foo` which lives in the values
+/// namespace.
+pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> {
let interner = DbInterner::new_with(db, None, None);
- match res {
- TypeNs::SelfType(impl_id) => {
- let trait_ref = db.impl_trait(impl_id)?;
+ match def {
+ TyDefId::BuiltinType(it) => EarlyBinder::bind(Ty::from_builtin_type(interner, it)),
+ TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt(
+ interner,
+ it,
+ GenericArgs::identity_for_item(interner, it.into()),
+ )),
+ TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0,
+ }
+}
- let impl_id_as_generic_def: GenericDefId = impl_id.into();
- if impl_id_as_generic_def != def {
- let subst = TyBuilder::subst_for_def(db, impl_id, None)
- .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
- .build();
- let args: crate::next_solver::GenericArgs<'_> = subst.to_nextsolver(interner);
- let trait_ref = trait_ref.instantiate(interner, args).to_chalk(interner);
- search(trait_ref)
- } else {
- search(trait_ref.skip_binder().to_chalk(interner))
- }
+/// Build the declared type of a function. This should not need to look at the
+/// function body.
+fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> {
+ let interner = DbInterner::new_with(db, None, None);
+ EarlyBinder::bind(Ty::new_fn_def(
+ interner,
+ CallableDefId::FunctionId(def).into(),
+ GenericArgs::identity_for_item(interner, def.into()),
+ ))
+}
+
+/// Build the declared type of a const.
+fn type_for_const<'db>(db: &'db dyn HirDatabase, def: ConstId) -> EarlyBinder<'db, Ty<'db>> {
+ let resolver = def.resolver(db);
+ let data = db.const_signature(def);
+ let parent = def.loc(db).container;
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &data.store,
+ def.into(),
+ LifetimeElisionKind::AnonymousReportError,
+ );
+ ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent));
+ EarlyBinder::bind(ctx.lower_ty(data.type_ref))
+}
+
+/// Build the declared type of a static.
+fn type_for_static<'db>(db: &'db dyn HirDatabase, def: StaticId) -> EarlyBinder<'db, Ty<'db>> {
+ let resolver = def.resolver(db);
+ let data = db.static_signature(def);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &data.store,
+ def.into(),
+ LifetimeElisionKind::AnonymousReportError,
+ );
+ ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner)));
+ EarlyBinder::bind(ctx.lower_ty(data.type_ref))
+}
+
+/// Build the type of a tuple struct constructor.
+fn type_for_struct_constructor<'db>(
+ db: &'db dyn HirDatabase,
+ def: StructId,
+) -> Option<EarlyBinder<'db, Ty<'db>>> {
+ let struct_data = def.fields(db);
+ match struct_data.shape {
+ FieldsShape::Record => None,
+ FieldsShape::Unit => Some(type_for_adt(db, def.into())),
+ FieldsShape::Tuple => {
+ let interner = DbInterner::new_with(db, None, None);
+ Some(EarlyBinder::bind(Ty::new_fn_def(
+ interner,
+ CallableDefId::StructId(def).into(),
+ GenericArgs::identity_for_item(interner, def.into()),
+ )))
}
- TypeNs::GenericParam(param_id) => {
- let predicates = db.generic_predicates_for_param(def, param_id.into(), assoc_name);
- let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() {
- // FIXME: how to correctly handle higher-ranked bounds here?
- WhereClause::Implemented(tr) => search(
- tr.clone()
- .shifted_out_to(Interner, DebruijnIndex::ONE)
- .expect("FIXME unexpected higher-ranked trait bound"),
- ),
- _ => None,
- });
- if res.is_some() {
- return res;
- }
- // Handle `Self::Type` referring to own associated type in trait definitions
- if let GenericDefId::TraitId(trait_id) = param_id.parent() {
- let trait_generics = generics(db, trait_id.into());
- if trait_generics[param_id.local_id()].is_trait_self() {
- let trait_ref = TyBuilder::trait_ref(db, trait_id)
- .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
- .build();
- return search(trait_ref);
- }
- }
- None
+ }
+}
+
+/// Build the type of a tuple enum variant constructor.
+fn type_for_enum_variant_constructor<'db>(
+ db: &'db dyn HirDatabase,
+ def: EnumVariantId,
+) -> Option<EarlyBinder<'db, Ty<'db>>> {
+ let struct_data = def.fields(db);
+ match struct_data.shape {
+ FieldsShape::Record => None,
+ FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())),
+ FieldsShape::Tuple => {
+ let interner = DbInterner::new_with(db, None, None);
+ Some(EarlyBinder::bind(Ty::new_fn_def(
+ interner,
+ CallableDefId::EnumVariantId(def).into(),
+ GenericArgs::identity_for_item(interner, def.loc(db).parent.into()),
+ )))
}
- _ => None,
}
}
-pub(crate) type Diagnostics = Option<ThinArc<(), TyLoweringDiagnostic>>;
+pub(crate) fn value_ty_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: ValueTyDefId,
+) -> Option<EarlyBinder<'db, Ty<'db>>> {
+ match def {
+ ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
+ ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
+ ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
+ ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
+ ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
+ ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
+ }
+}
-pub(crate) fn create_diagnostics(diagnostics: Vec<TyLoweringDiagnostic>) -> Diagnostics {
- (!diagnostics.is_empty()).then(|| ThinArc::from_header_and_iter((), diagnostics.into_iter()))
+pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>(
+ db: &'db dyn HirDatabase,
+ t: TypeAliasId,
+) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
+ let type_alias_data = db.type_alias_signature(t);
+ let mut diags = None;
+ let resolver = t.resolver(db);
+ let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
+ let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
+ EarlyBinder::bind(Ty::new_foreign(interner, t.into()))
+ } else {
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &type_alias_data.store,
+ t.into(),
+ LifetimeElisionKind::AnonymousReportError,
+ )
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
+ let res = EarlyBinder::bind(
+ type_alias_data
+ .ty
+ .map(|type_ref| ctx.lower_ty(type_ref))
+ .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)),
+ );
+ diags = create_diagnostics(ctx.diagnostics);
+ res
+ };
+ (inner, diags)
}
-pub(crate) fn field_types_query(
+pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>(
+ db: &'db dyn HirDatabase,
+ _adt: TypeAliasId,
+) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
+ (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None)
+}
+
+pub(crate) fn impl_self_ty_query<'db>(
+ db: &'db dyn HirDatabase,
+ impl_id: ImplId,
+) -> EarlyBinder<'db, Ty<'db>> {
+ db.impl_self_ty_with_diagnostics(impl_id).0
+}
+
+pub(crate) fn impl_self_ty_with_diagnostics_query<'db>(
+ db: &'db dyn HirDatabase,
+ impl_id: ImplId,
+) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
+ let resolver = impl_id.resolver(db);
+
+ let impl_data = db.impl_signature(impl_id);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &impl_data.store,
+ impl_id.into(),
+ LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
+ );
+ let ty = ctx.lower_ty(impl_data.self_ty);
+ assert!(!ty.has_escaping_bound_vars());
+ (EarlyBinder::bind(ty), create_diagnostics(ctx.diagnostics))
+}
+
+pub(crate) fn impl_self_ty_with_diagnostics_cycle_result(
db: &dyn HirDatabase,
+ _impl_id: ImplId,
+) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) {
+ (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None)
+}
+
+pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> {
+ db.const_param_ty_with_diagnostics(def).0
+}
+
+// returns None if def is a type arg
+pub(crate) fn const_param_ty_with_diagnostics_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: ConstParamId,
+) -> (Ty<'db>, Diagnostics) {
+ let (parent_data, store) = db.generic_params_and_store(def.parent());
+ let data = &parent_data[def.local_id()];
+ let resolver = def.parent().resolver(db);
+ let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ &store,
+ def.parent(),
+ LifetimeElisionKind::AnonymousReportError,
+ );
+ let ty = match data {
+ TypeOrConstParamData::TypeParamData(_) => {
+ never!();
+ Ty::new_error(interner, ErrorGuaranteed)
+ }
+ TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
+ };
+ (ty, create_diagnostics(ctx.diagnostics))
+}
+
+pub(crate) fn const_param_ty_with_diagnostics_cycle_result<'db>(
+ db: &'db dyn HirDatabase,
+ _: crate::db::HirDatabaseData,
+ def: ConstParamId,
+) -> (Ty<'db>, Diagnostics) {
+ let resolver = def.parent().resolver(db);
+ let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
+ (Ty::new_error(interner, ErrorGuaranteed), None)
+}
+
+pub(crate) fn field_types_query<'db>(
+ db: &'db dyn HirDatabase,
variant_id: VariantId,
-) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> {
- field_types_with_diagnostics_query(db, variant_id).0
+) -> Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>> {
+ db.field_types_with_diagnostics(variant_id).0
}
/// Build the type of all specific fields of a struct or enum variant.
-pub(crate) fn field_types_with_diagnostics_query(
- db: &dyn HirDatabase,
+pub(crate) fn field_types_with_diagnostics_query<'db>(
+ db: &'db dyn HirDatabase,
variant_id: VariantId,
-) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics) {
+) -> (Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>>, Diagnostics) {
let var_data = variant_id.fields(db);
let fields = var_data.fields();
if fields.is_empty() {
@@ -885,7 +1307,6 @@ pub(crate) fn field_types_with_diagnostics_query(
VariantId::UnionId(it) => (it.resolver(db), it.into()),
VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()),
};
- let generics = generics(db, def);
let mut res = ArenaMap::default();
let mut ctx = TyLoweringContext::new(
db,
@@ -893,10 +1314,9 @@ pub(crate) fn field_types_with_diagnostics_query(
&var_data.store,
def,
LifetimeElisionKind::AnonymousReportError,
- )
- .with_type_param_mode(ParamLoweringMode::Variable);
- for (field_id, field_data) in fields.iter() {
- res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
+ );
+ for (field_id, field_data) in var_data.fields().iter() {
+ res.insert(field_id, EarlyBinder::bind(ctx.lower_ty(field_data.type_ref)));
}
(Arc::new(res), create_diagnostics(ctx.diagnostics))
}
@@ -909,17 +1329,15 @@ pub(crate) fn field_types_with_diagnostics_query(
/// This is a query mostly to handle cycles somewhat gracefully; e.g. the
/// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but
/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
-pub(crate) fn generic_predicates_for_param_query(
- db: &dyn HirDatabase,
+#[tracing::instrument(skip(db), ret)]
+pub(crate) fn generic_predicates_for_param_query<'db>(
+ db: &'db dyn HirDatabase,
def: GenericDefId,
param_id: TypeOrConstParamId,
assoc_name: Option<Name>,
-) -> GenericPredicates {
+) -> GenericPredicates<'db> {
let generics = generics(db, def);
- if generics.has_no_predicates() && generics.is_empty() {
- return GenericPredicates(None);
- }
-
+ let interner = DbInterner::new_with(db, None, None);
let resolver = def.resolver(db);
let mut ctx = TyLoweringContext::new(
db,
@@ -927,11 +1345,10 @@ pub(crate) fn generic_predicates_for_param_query(
generics.store(),
def,
LifetimeElisionKind::AnonymousReportError,
- )
- .with_type_param_mode(ParamLoweringMode::Variable);
+ );
// we have to filter out all other predicates *first*, before attempting to lower them
- let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_>| match pred {
+ let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred {
WherePredicate::ForLifetime { target, bound, .. }
| WherePredicate::TypeBound { target, bound, .. } => {
let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
@@ -962,7 +1379,8 @@ pub(crate) fn generic_predicates_for_param_query(
}
}();
if lower {
- ctx.lower_where_predicate(pred, true).for_each(drop);
+ ctx.lower_where_predicate(pred, true, &generics, PredicateFilter::All)
+ .for_each(drop);
}
return false;
}
@@ -980,8 +1398,8 @@ pub(crate) fn generic_predicates_for_param_query(
return false;
};
- all_super_traits(db, tr).iter().any(|tr| {
- tr.trait_items(db).items.iter().any(|(name, item)| {
+ rustc_type_ir::elaborate::supertrait_def_ids(interner, tr.into()).any(|tr| {
+ tr.0.trait_items(db).items.iter().any(|(name, item)| {
matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
})
})
@@ -998,27 +1416,23 @@ pub(crate) fn generic_predicates_for_param_query(
ctx.store = maybe_parent_generics.store();
for pred in maybe_parent_generics.where_predicates() {
if predicate(pred, &mut ctx) {
- predicates.extend(
- ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p)),
- );
+ predicates.extend(ctx.lower_where_predicate(
+ pred,
+ true,
+ maybe_parent_generics,
+ PredicateFilter::All,
+ ));
}
}
}
- let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
- if !subst.is_empty(Interner) {
+ let args = GenericArgs::identity_for_item(interner, def.into());
+ if !args.is_empty() {
let explicitly_unsized_tys = ctx.unsized_types;
- if let Some(implicitly_sized_predicates) = implicitly_sized_clauses(
- db,
- param_id.parent,
- &explicitly_unsized_tys,
- &subst,
- &resolver,
- ) {
- predicates.extend(
- implicitly_sized_predicates
- .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))),
- );
+ if let Some(implicitly_sized_predicates) =
+ implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &args, &resolver)
+ {
+ predicates.extend(implicitly_sized_predicates);
};
}
GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
@@ -1029,53 +1443,206 @@ pub(crate) fn generic_predicates_for_param_cycle_result(
_def: GenericDefId,
_param_id: TypeOrConstParamId,
_assoc_name: Option<Name>,
-) -> GenericPredicates {
+) -> GenericPredicates<'_> {
GenericPredicates(None)
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct GenericPredicates(Option<Arc<[Binders<QuantifiedWhereClause>]>>);
+pub struct GenericPredicates<'db>(Option<Arc<[Clause<'db>]>>);
-impl ops::Deref for GenericPredicates {
- type Target = [Binders<crate::QuantifiedWhereClause>];
+impl<'db> GenericPredicates<'db> {
+ #[inline]
+ pub fn instantiate(
+ &self,
+ interner: DbInterner<'db>,
+ args: GenericArgs<'db>,
+ ) -> Option<impl Iterator<Item = Clause<'db>>> {
+ self.0
+ .as_ref()
+ .map(|it| EarlyBinder::bind(it.iter().copied()).iter_instantiated(interner, args))
+ }
+
+ #[inline]
+ pub fn instantiate_identity(&self) -> Option<impl Iterator<Item = Clause<'db>>> {
+ self.0.as_ref().map(|it| it.iter().copied())
+ }
+}
+
+impl<'db> ops::Deref for GenericPredicates<'db> {
+ type Target = [Clause<'db>];
fn deref(&self) -> &Self::Target {
self.0.as_deref().unwrap_or(&[])
}
}
-/// Resolve the where clause(s) of an item with generics.
-pub(crate) fn generic_predicates_query(
+pub(crate) fn trait_environment_for_body_query(
db: &dyn HirDatabase,
+ def: DefWithBodyId,
+) -> Arc<TraitEnvironment<'_>> {
+ let Some(def) = def.as_generic_def_id(db) else {
+ let krate = def.module(db).krate();
+ return TraitEnvironment::empty(krate);
+ };
+ db.trait_environment(def)
+}
+
+pub(crate) fn trait_environment_query<'db>(
+ db: &'db dyn HirDatabase,
def: GenericDefId,
-) -> GenericPredicates {
- generic_predicates_filtered_by(db, def, |_, _| true).0
+) -> Arc<TraitEnvironment<'db>> {
+ let generics = generics(db, def);
+ if generics.has_no_predicates() && generics.is_empty() {
+ return TraitEnvironment::empty(def.krate(db));
+ }
+
+ let resolver = def.resolver(db);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ &resolver,
+ generics.store(),
+ def,
+ LifetimeElisionKind::AnonymousReportError,
+ );
+ let mut traits_in_scope = Vec::new();
+ let mut clauses = Vec::new();
+ for maybe_parent_generics in
+ std::iter::successors(Some(&generics), |generics| generics.parent_generics())
+ {
+ ctx.store = maybe_parent_generics.store();
+ for pred in maybe_parent_generics.where_predicates() {
+ for pred in ctx.lower_where_predicate(pred, false, &generics, PredicateFilter::All) {
+ if let rustc_type_ir::ClauseKind::Trait(tr) = pred.kind().skip_binder() {
+ traits_in_scope.push((tr.self_ty(), tr.def_id().0));
+ }
+ clauses.push(pred);
+ }
+ }
+ }
+
+ if let Some(trait_id) = def.assoc_trait_container(db) {
+ // add `Self: Trait<T1, T2, ...>` to the environment in trait
+ // function default implementations (and speculative code
+ // inside consts or type aliases)
+ cov_mark::hit!(trait_self_implements_self);
+ let trait_ref = TraitRef::identity(ctx.interner, trait_id.into());
+ let clause = Clause(Predicate::new(
+ ctx.interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait(
+ TraitPredicate { trait_ref, polarity: rustc_type_ir::PredicatePolarity::Positive },
+ ))),
+ ));
+ clauses.push(clause);
+ }
+
+ let explicitly_unsized_tys = ctx.unsized_types;
+
+ let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate());
+ if let Some(sized_trait) = sized_trait {
+ let (mut generics, mut def_id) =
+ (crate::next_solver::generics::generics(db, def.into()), def);
+ loop {
+ let self_idx = trait_self_param_idx(db, def_id);
+ for (idx, p) in generics.own_params.iter().enumerate() {
+ if let Some(self_idx) = self_idx
+ && p.index() as usize == self_idx
+ {
+ continue;
+ }
+ let GenericParamId::TypeParamId(param_id) = p.id else {
+ continue;
+ };
+ let idx = idx as u32 + generics.parent_count as u32;
+ let param_ty = Ty::new_param(ctx.interner, param_id, idx);
+ if explicitly_unsized_tys.contains(&param_ty) {
+ continue;
+ }
+ let trait_ref = TraitRef::new_from_args(
+ ctx.interner,
+ sized_trait.into(),
+ GenericArgs::new_from_iter(ctx.interner, [param_ty.into()]),
+ );
+ let clause = Clause(Predicate::new(
+ ctx.interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Trait(TraitPredicate {
+ trait_ref,
+ polarity: rustc_type_ir::PredicatePolarity::Positive,
+ }),
+ )),
+ ));
+ clauses.push(clause);
+ }
+
+ if let Some(g) = generics.parent {
+ generics = crate::next_solver::generics::generics(db, g.into());
+ def_id = g;
+ } else {
+ break;
+ }
+ }
+ }
+
+ let clauses = rustc_type_ir::elaborate::elaborate(ctx.interner, clauses);
+ let clauses = Clauses::new_from_iter(ctx.interner, clauses);
+ let env = ParamEnv { clauses };
+
+ TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env)
+}
+
+#[derive(Copy, Clone, Debug)]
+pub(crate) enum PredicateFilter {
+ SelfTrait,
+ All,
+}
+
+/// Resolve the where clause(s) of an item with generics.
+#[tracing::instrument(skip(db))]
+pub(crate) fn generic_predicates_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: GenericDefId,
+) -> GenericPredicates<'db> {
+ generic_predicates_filtered_by(db, def, PredicateFilter::All, |_| true).0
+}
+
+pub(crate) fn generic_predicates_without_parent_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: GenericDefId,
+) -> GenericPredicates<'db> {
+ generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def).0
+}
+
+/// Resolve the where clause(s) of an item with generics,
+/// except the ones inherited from the parent
+pub(crate) fn generic_predicates_without_parent_with_diagnostics_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: GenericDefId,
+) -> (GenericPredicates<'db>, Diagnostics) {
+ generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def)
}
/// Resolve the where clause(s) of an item with generics,
/// with a given filter
-fn generic_predicates_filtered_by<F>(
- db: &dyn HirDatabase,
+#[tracing::instrument(skip(db, filter), ret)]
+pub(crate) fn generic_predicates_filtered_by<'db, F>(
+ db: &'db dyn HirDatabase,
def: GenericDefId,
+ predicate_filter: PredicateFilter,
filter: F,
-) -> (GenericPredicates, Diagnostics)
+) -> (GenericPredicates<'db>, Diagnostics)
where
- F: Fn(&WherePredicate, GenericDefId) -> bool,
+ F: Fn(GenericDefId) -> bool,
{
let generics = generics(db, def);
- if generics.has_no_predicates() && generics.is_empty() {
- return (GenericPredicates(None), None);
- }
-
let resolver = def.resolver(db);
+ let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
generics.store(),
def,
LifetimeElisionKind::AnonymousReportError,
- )
- .with_type_param_mode(ParamLoweringMode::Variable);
+ );
let mut predicates = Vec::new();
for maybe_parent_generics in
@@ -1083,29 +1650,71 @@ where
{
ctx.store = maybe_parent_generics.store();
for pred in maybe_parent_generics.where_predicates() {
- if filter(pred, maybe_parent_generics.def()) {
- // We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake!
- // If we use the parent generics
- predicates.extend(
- ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p)),
- );
+ tracing::debug!(?pred);
+ if filter(maybe_parent_generics.def()) {
+ predicates.extend(ctx.lower_where_predicate(
+ pred,
+ false,
+ maybe_parent_generics,
+ predicate_filter,
+ ));
}
}
}
- if !generics.is_empty() {
- let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
- let explicitly_unsized_tys = ctx.unsized_types;
- if let Some(implicitly_sized_predicates) =
- implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
- {
- predicates.extend(
- implicitly_sized_predicates
- .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))),
+ let explicitly_unsized_tys = ctx.unsized_types;
+
+ let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate());
+ if let Some(sized_trait) = sized_trait {
+ let mut add_sized_clause = |param_idx, param_id, param_data| {
+ let (
+ GenericParamId::TypeParamId(param_id),
+ GenericParamDataRef::TypeParamData(param_data),
+ ) = (param_id, param_data)
+ else {
+ return;
+ };
+
+ if param_data.provenance == TypeParamProvenance::TraitSelf {
+ return;
+ }
+
+ let param_ty = Ty::new_param(interner, param_id, param_idx);
+ if explicitly_unsized_tys.contains(&param_ty) {
+ return;
+ }
+ let trait_ref = TraitRef::new_from_args(
+ interner,
+ sized_trait.into(),
+ GenericArgs::new_from_iter(interner, [param_ty.into()]),
);
+ let clause = Clause(Predicate::new(
+ interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Trait(TraitPredicate {
+ trait_ref,
+ polarity: rustc_type_ir::PredicatePolarity::Positive,
+ }),
+ )),
+ ));
+ predicates.push(clause);
};
+ if generics.parent_generics().is_some_and(|parent| filter(parent.def())) {
+ generics.iter_parent().enumerate().for_each(|(param_idx, (param_id, param_data))| {
+ add_sized_clause(param_idx as u32, param_id, param_data);
+ });
+ }
+ if filter(def) {
+ let parent_params_len = generics.len_parent();
+ generics.iter_self().enumerate().for_each(|(param_idx, (param_id, param_data))| {
+ add_sized_clause((param_idx + parent_params_len) as u32, param_id, param_data);
+ });
+ }
}
+ // FIXME: rustc gathers more predicates by recursing through resulting trait predicates.
+ // See https://github.com/rust-lang/rust/blob/76c5ed2847cdb26ef2822a3a165d710f6b772217/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L689-L715
+
(
GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
create_diagnostics(ctx.diagnostics),
@@ -1114,49 +1723,61 @@ where
/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
/// Exception is Self of a trait def.
-fn implicitly_sized_clauses<'db, 'a, 'subst: 'a>(
+fn implicitly_sized_clauses<'a, 'subst, 'db>(
db: &'db dyn HirDatabase,
def: GenericDefId,
- explicitly_unsized_tys: &'a FxHashSet<Ty>,
- substitution: &'subst Substitution,
+ explicitly_unsized_tys: &'a FxHashSet<Ty<'db>>,
+ args: &'subst GenericArgs<'db>,
resolver: &Resolver<'db>,
-) -> Option<impl Iterator<Item = WhereClause>> {
- let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id)?;
+) -> Option<impl Iterator<Item = Clause<'db>> + Captures<'a> + Captures<'subst>> {
+ let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
+ let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?;
let trait_self_idx = trait_self_param_idx(db, def);
Some(
- substitution
- .iter(Interner)
+ args.iter()
.enumerate()
.filter_map(
move |(idx, generic_arg)| {
if Some(idx) == trait_self_idx { None } else { Some(generic_arg) }
},
)
- .filter_map(|generic_arg| generic_arg.ty(Interner))
- .filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty))
+ .filter_map(|generic_arg| generic_arg.as_type())
+ .filter(move |self_ty| !explicitly_unsized_tys.contains(self_ty))
.map(move |self_ty| {
- WhereClause::Implemented(TraitRef {
- trait_id: sized_trait,
- substitution: Substitution::from1(Interner, self_ty.clone()),
- })
+ let trait_ref = TraitRef::new_from_args(
+ interner,
+ sized_trait.into(),
+ GenericArgs::new_from_iter(interner, [self_ty.into()]),
+ );
+ Clause(Predicate::new(
+ interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Trait(TraitPredicate {
+ trait_ref,
+ polarity: rustc_type_ir::PredicatePolarity::Positive,
+ }),
+ )),
+ ))
}),
)
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct GenericDefaults(Option<Arc<[Binders<crate::GenericArg>]>>);
-
-impl ops::Deref for GenericDefaults {
- type Target = [Binders<crate::GenericArg>];
+pub struct GenericDefaults<'db>(Option<Arc<[Option<EarlyBinder<'db, GenericArg<'db>>>]>>);
- fn deref(&self) -> &Self::Target {
- self.0.as_deref().unwrap_or(&[])
+impl<'db> GenericDefaults<'db> {
+ #[inline]
+ pub fn get(&self, idx: usize) -> Option<EarlyBinder<'db, GenericArg<'db>>> {
+ self.0.as_ref()?[idx]
}
}
-pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults {
+pub(crate) fn generic_defaults_query(
+ db: &dyn HirDatabase,
+ def: GenericDefId,
+) -> GenericDefaults<'_> {
db.generic_defaults_with_diagnostics(def).0
}
@@ -1166,7 +1787,7 @@ pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) ->
pub(crate) fn generic_defaults_with_diagnostics_query(
db: &dyn HirDatabase,
def: GenericDefId,
-) -> (GenericDefaults, Diagnostics) {
+) -> (GenericDefaults<'_>, Diagnostics) {
let generic_params = generics(db, def);
if generic_params.is_empty() {
return (GenericDefaults(None), None);
@@ -1180,23 +1801,22 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
def,
LifetimeElisionKind::AnonymousReportError,
)
- .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
- .with_type_param_mode(ParamLoweringMode::Variable);
+ .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed);
let mut idx = 0;
let mut has_any_default = false;
let mut defaults = generic_params
.iter_parents_with_store()
- .map(|((id, p), store)| {
+ .map(|((_id, p), store)| {
ctx.store = store;
- let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params);
+ let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
has_any_default |= has_default;
idx += 1;
result
})
.collect::<Vec<_>>();
ctx.diagnostics.clear(); // Don't include diagnostics from the parent.
- defaults.extend(generic_params.iter_self().map(|(id, p)| {
- let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params);
+ defaults.extend(generic_params.iter_self().map(|(_id, p)| {
+ let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
has_any_default |= has_default;
idx += 1;
result
@@ -1209,47 +1829,26 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
};
return (defaults, diagnostics);
- fn handle_generic_param(
- ctx: &mut TyLoweringContext<'_>,
+ fn handle_generic_param<'db>(
+ ctx: &mut TyLoweringContext<'db, '_>,
idx: usize,
- id: GenericParamId,
p: GenericParamDataRef<'_>,
- generic_params: &Generics,
- ) -> (Binders<crate::GenericArg>, bool) {
- let binders = variable_kinds_from_iter(ctx.db, generic_params.iter_id().take(idx));
+ ) -> (Option<EarlyBinder<'db, GenericArg<'db>>>, bool) {
+ ctx.lowering_param_default(idx as u32);
match p {
GenericParamDataRef::TypeParamData(p) => {
- let ty = p.default.as_ref().map_or_else(
- || TyKind::Error.intern(Interner),
- |ty| {
- // Each default can only refer to previous parameters.
- // Type variable default referring to parameter coming
- // after it is forbidden (FIXME: report diagnostic)
- fallback_bound_vars(ctx.lower_ty(*ty), idx)
- },
- );
- (Binders::new(binders, ty.cast(Interner)), p.default.is_some())
+ let ty = p.default.map(|ty| ctx.lower_ty(ty));
+ (ty.map(|ty| EarlyBinder::bind(ty.into())), p.default.is_some())
}
GenericParamDataRef::ConstParamData(p) => {
- let GenericParamId::ConstParamId(id) = id else {
- unreachable!("Unexpected lifetime or type argument")
- };
-
- let mut val = p.default.as_ref().map_or_else(
- || unknown_const_as_generic(ctx.db.const_param_ty(id)),
- |c| {
- let param_ty = ctx.lower_ty(p.ty);
- let c = ctx.lower_const(c, param_ty);
- c.cast(Interner)
- },
- );
- // Each default can only refer to previous parameters, see above.
- val = fallback_bound_vars(val, idx);
- (Binders::new(binders, val), p.default.is_some())
- }
- GenericParamDataRef::LifetimeParamData(_) => {
- (Binders::new(binders, error_lifetime().cast(Interner)), false)
+ let val = p.default.map(|c| {
+ let param_ty = ctx.lower_ty(p.ty);
+ let c = ctx.lower_const(c, param_ty);
+ c.into()
+ });
+ (val.map(EarlyBinder::bind), p.default.is_some())
}
+ GenericParamDataRef::LifetimeParamData(_) => (None, false),
}
}
}
@@ -1257,161 +1856,323 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
pub(crate) fn generic_defaults_with_diagnostics_cycle_result(
_db: &dyn HirDatabase,
_def: GenericDefId,
-) -> (GenericDefaults, Diagnostics) {
+) -> (GenericDefaults<'_>, Diagnostics) {
(GenericDefaults(None), None)
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum TyDefId {
- BuiltinType(BuiltinType),
- AdtId(AdtId),
- TypeAliasId(TypeAliasId),
-}
-impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId);
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
-pub enum ValueTyDefId {
- FunctionId(FunctionId),
- StructId(StructId),
- UnionId(UnionId),
- EnumVariantId(EnumVariantId),
- ConstId(ConstId),
- StaticId(StaticId),
-}
-impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
-
-impl ValueTyDefId {
- pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> GenericDefId {
- match self {
- Self::FunctionId(id) => id.into(),
- Self::StructId(id) => id.into(),
- Self::UnionId(id) => id.into(),
- Self::EnumVariantId(var) => var.lookup(db).parent.into(),
- Self::ConstId(id) => id.into(),
- Self::StaticId(id) => id.into(),
- }
+/// Build the signature of a callable item (function, struct or enum variant).
+pub(crate) fn callable_item_signature_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: CallableDefId,
+) -> EarlyBinder<'db, PolyFnSig<'db>> {
+ match def {
+ CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
+ CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
+ CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
}
}
-pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
- const_param_ty_with_diagnostics_query(db, def).0
-}
-
-// returns None if def is a type arg
-pub(crate) fn const_param_ty_with_diagnostics_query(
- db: &dyn HirDatabase,
- def: ConstParamId,
-) -> (Ty, Diagnostics) {
- let (parent_data, store) = db.generic_params_and_store(def.parent());
- let data = &parent_data[def.local_id()];
- let resolver = def.parent().resolver(db);
- let mut ctx = TyLoweringContext::new(
+fn fn_sig_for_fn<'db>(
+ db: &'db dyn HirDatabase,
+ def: FunctionId,
+) -> EarlyBinder<'db, PolyFnSig<'db>> {
+ let data = db.function_signature(def);
+ let resolver = def.resolver(db);
+ let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
+ let mut ctx_params = TyLoweringContext::new(
db,
&resolver,
- &store,
- def.parent(),
- LifetimeElisionKind::AnonymousReportError,
+ &data.store,
+ def.into(),
+ LifetimeElisionKind::for_fn_params(&data),
);
- let ty = match data {
- TypeOrConstParamData::TypeParamData(_) => {
- never!();
- Ty::new(Interner, TyKind::Error)
+ let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
+
+ let ret = match data.ret_type {
+ Some(ret_type) => {
+ let mut ctx_ret = TyLoweringContext::new(
+ db,
+ &resolver,
+ &data.store,
+ def.into(),
+ LifetimeElisionKind::for_fn_ret(interner),
+ )
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
+ ctx_ret.lower_ty(ret_type)
}
- TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
+ None => Ty::new_tup(interner, &[]),
};
- (ty, create_diagnostics(ctx.diagnostics))
+
+ let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret)));
+ // If/when we track late bound vars, we need to switch this to not be `dummy`
+ EarlyBinder::bind(rustc_type_ir::Binder::dummy(FnSig {
+ abi: data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
+ c_variadic: data.is_varargs(),
+ safety: if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
+ inputs_and_output,
+ }))
}
-pub(crate) fn const_param_ty_cycle_result(
- _: &dyn HirDatabase,
- _: crate::db::HirDatabaseData,
- _: ConstParamId,
-) -> Ty {
- TyKind::Error.intern(Interner)
+fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> {
+ let interner = DbInterner::new_with(db, None, None);
+ let args = GenericArgs::identity_for_item(interner, adt.into());
+ let ty = Ty::new_adt(interner, adt, args);
+ EarlyBinder::bind(ty)
}
-pub(crate) fn return_type_impl_traits(
- db: &dyn HirDatabase,
- def: hir_def::FunctionId,
-) -> Option<Arc<Binders<ImplTraits>>> {
- // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
- let data = db.function_signature(def);
- let resolver = def.resolver(db);
- let mut ctx_ret =
- TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer)
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
- .with_type_param_mode(ParamLoweringMode::Variable);
- if let Some(ret_type) = data.ret_type {
- let _ret = ctx_ret.lower_ty(ret_type);
- }
- let generics = generics(db, def.into());
- let 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 {
- Some(Arc::new(make_binders(db, &generics, return_type_impl_traits)))
- }
+fn fn_sig_for_struct_constructor<'db>(
+ db: &'db dyn HirDatabase,
+ def: StructId,
+) -> EarlyBinder<'db, PolyFnSig<'db>> {
+ let field_tys = db.field_types(def.into());
+ let params = field_tys.iter().map(|(_, ty)| ty.skip_binder());
+ let ret = type_for_adt(db, def.into()).skip_binder();
+
+ let inputs_and_output =
+ Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret)));
+ EarlyBinder::bind(Binder::dummy(FnSig {
+ abi: FnAbi::RustCall,
+ c_variadic: false,
+ safety: Safety::Safe,
+ inputs_and_output,
+ }))
}
-pub(crate) fn type_alias_impl_traits(
- db: &dyn HirDatabase,
- def: hir_def::TypeAliasId,
-) -> Option<Arc<Binders<ImplTraits>>> {
- let data = db.type_alias_signature(def);
- let resolver = def.resolver(db);
+fn fn_sig_for_enum_variant_constructor<'db>(
+ db: &'db dyn HirDatabase,
+ def: EnumVariantId,
+) -> EarlyBinder<'db, PolyFnSig<'db>> {
+ let field_tys = db.field_types(def.into());
+ let params = field_tys.iter().map(|(_, ty)| 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_with(db, None, None), params.chain(Some(ret)));
+ EarlyBinder::bind(Binder::dummy(FnSig {
+ abi: FnAbi::RustCall,
+ c_variadic: false,
+ safety: Safety::Safe,
+ inputs_and_output,
+ }))
+}
+
+// FIXME(next-solver): should merge this with `explicit_item_bounds` in some way
+pub(crate) fn associated_ty_item_bounds<'db>(
+ db: &'db dyn HirDatabase,
+ type_alias: TypeAliasId,
+) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> {
+ let type_alias_data = db.type_alias_signature(type_alias);
+ let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
+ let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
- &data.store,
- def.into(),
+ &type_alias_data.store,
+ type_alias.into(),
LifetimeElisionKind::AnonymousReportError,
- )
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
- .with_type_param_mode(ParamLoweringMode::Variable);
- if let Some(type_ref) = data.ty {
- let _ty = ctx.lower_ty(type_ref);
+ );
+ // FIXME: we should never create non-existential predicates in the first place
+ // For now, use an error type so we don't run into dummy binder issues
+ let self_ty = Ty::new_error(interner, ErrorGuaranteed);
+
+ let mut bounds = Vec::new();
+ for bound in &type_alias_data.bounds {
+ ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| {
+ if let Some(bound) = pred
+ .kind()
+ .map_bound(|c| match c {
+ rustc_type_ir::ClauseKind::Trait(t) => {
+ let id = t.def_id();
+ let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
+ if is_auto {
+ Some(ExistentialPredicate::AutoTrait(t.def_id()))
+ } else {
+ Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args(
+ interner,
+ t.def_id(),
+ GenericArgs::new_from_iter(
+ interner,
+ t.trait_ref.args.iter().skip(1),
+ ),
+ )))
+ }
+ }
+ rustc_type_ir::ClauseKind::Projection(p) => Some(
+ ExistentialPredicate::Projection(ExistentialProjection::new_from_args(
+ interner,
+ p.def_id(),
+ GenericArgs::new_from_iter(
+ interner,
+ p.projection_term.args.iter().skip(1),
+ ),
+ p.term,
+ )),
+ ),
+ rustc_type_ir::ClauseKind::TypeOutlives(_) => None,
+ rustc_type_ir::ClauseKind::RegionOutlives(_)
+ | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
+ | rustc_type_ir::ClauseKind::WellFormed(_)
+ | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
+ | rustc_type_ir::ClauseKind::HostEffect(_)
+ | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
+ })
+ .transpose()
+ {
+ bounds.push(bound);
+ }
+ });
}
- let 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 {
- let generics = generics(db, def.into());
- Some(Arc::new(make_binders(db, &generics, type_alias_impl_traits)))
+
+ if !ctx.unsized_types.contains(&self_ty)
+ && let Some(sized_trait) = LangItem::Sized.resolve_trait(db, resolver.krate())
+ {
+ let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new(
+ interner,
+ sized_trait.into(),
+ [] as [GenericArg<'_>; 0],
+ )));
+ bounds.push(sized_clause);
}
+
+ EarlyBinder::bind(BoundExistentialPredicates::new_from_iter(interner, bounds))
}
-pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
- match m {
- hir_def::type_ref::Mutability::Shared => Mutability::Not,
- hir_def::type_ref::Mutability::Mut => Mutability::Mut,
- }
+pub(crate) fn associated_type_by_name_including_super_traits<'db>(
+ db: &'db dyn HirDatabase,
+ trait_ref: TraitRef<'db>,
+ name: &Name,
+) -> Option<(TraitRef<'db>, TypeAliasId)> {
+ let interner = DbInterner::new_with(db, None, None);
+ rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| {
+ let trait_id = t.as_ref().skip_binder().def_id.0;
+ let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?;
+ Some((t.skip_binder(), assoc_type))
+ })
}
-/// Replaces any 'free' `BoundVar`s in `s` by `TyKind::Error` from the perspective of generic
-/// parameter whose index is `param_index`. A `BoundVar` is free when it appears after the
-/// generic parameter of `param_index`.
-fn fallback_bound_vars<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
- s: T,
- param_index: usize,
-) -> T {
- let is_allowed = |index| (0..param_index).contains(&index);
-
- crate::fold_free_vars(
- s,
- |bound, binders| {
- if bound.index_if_innermost().is_none_or(is_allowed) {
- bound.shifted_in_from(binders).to_ty(Interner)
- } else {
- TyKind::Error.intern(Interner)
+pub fn associated_type_shorthand_candidates(
+ db: &dyn HirDatabase,
+ def: GenericDefId,
+ res: TypeNs,
+ mut cb: impl FnMut(&Name, TypeAliasId) -> bool,
+) -> Option<TypeAliasId> {
+ let interner = DbInterner::new_with(db, None, None);
+ named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| {
+ cb(name, id).then_some(id)
+ })
+}
+
+#[tracing::instrument(skip(interner, check_alias))]
+fn named_associated_type_shorthand_candidates<'db, R>(
+ interner: DbInterner<'db>,
+ // If the type parameter is defined in an impl and we're in a method, there
+ // might be additional where clauses to consider
+ def: GenericDefId,
+ res: TypeNs,
+ assoc_name: Option<Name>,
+ mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option<R>,
+) -> Option<R> {
+ let db = interner.db;
+ let mut search = |t: TraitRef<'db>| -> Option<R> {
+ let mut checked_traits = FxHashSet::default();
+ let mut check_trait = |trait_ref: TraitRef<'db>| {
+ let trait_id = trait_ref.def_id.0;
+ let name = &db.trait_signature(trait_id).name;
+ tracing::debug!(?trait_id, ?name);
+ if !checked_traits.insert(trait_id) {
+ return None;
}
- },
- |ty, bound, binders| {
- if bound.index_if_innermost().is_none_or(is_allowed) {
- bound.shifted_in_from(binders).to_const(Interner, ty)
- } else {
- unknown_const(ty)
+ let data = trait_id.trait_items(db);
+
+ tracing::debug!(?data.items);
+ for (name, assoc_id) in &data.items {
+ if let &AssocItemId::TypeAliasId(alias) = assoc_id
+ && let Some(ty) = check_alias(name, trait_ref, alias)
+ {
+ return Some(ty);
+ }
}
- },
- )
+ None
+ };
+ let mut stack: SmallVec<[_; 4]> = smallvec![t];
+ while let Some(trait_ref) = stack.pop() {
+ if let Some(alias) = check_trait(trait_ref) {
+ return Some(alias);
+ }
+ for pred in generic_predicates_filtered_by(
+ db,
+ GenericDefId::TraitId(trait_ref.def_id.0),
+ PredicateFilter::SelfTrait,
+ // We are likely in the midst of lowering generic predicates of `def`.
+ // So, if we allow `pred == def` we might fall into an infinite recursion.
+ // Actually, we have already checked for the case `pred == def` above as we started
+ // with a stack including `trait_id`
+ |pred| pred != def && pred == GenericDefId::TraitId(trait_ref.def_id.0),
+ )
+ .0
+ .deref()
+ {
+ tracing::debug!(?pred);
+ let sup_trait_ref = match pred.kind().skip_binder() {
+ rustc_type_ir::ClauseKind::Trait(pred) => pred.trait_ref,
+ _ => continue,
+ };
+ let sup_trait_ref =
+ EarlyBinder::bind(sup_trait_ref).instantiate(interner, trait_ref.args);
+ stack.push(sup_trait_ref);
+ }
+ tracing::debug!(?stack);
+ }
+
+ None
+ };
+
+ match res {
+ TypeNs::SelfType(impl_id) => {
+ let trait_ref = db.impl_trait(impl_id)?;
+
+ // FIXME(next-solver): same method in `lower` checks for impl or not
+ // Is that needed here?
+
+ // we're _in_ the impl -- the binders get added back later. Correct,
+ // but it would be nice to make this more explicit
+ search(trait_ref.skip_binder())
+ }
+ TypeNs::GenericParam(param_id) => {
+ // Handle `Self::Type` referring to own associated type in trait definitions
+ // This *must* be done first to avoid cycles with
+ // `generic_predicates_for_param`, but not sure that it's sufficient,
+ if let GenericDefId::TraitId(trait_id) = param_id.parent() {
+ let trait_name = &db.trait_signature(trait_id).name;
+ tracing::debug!(?trait_name);
+ let trait_generics = generics(db, trait_id.into());
+ tracing::debug!(?trait_generics);
+ if trait_generics[param_id.local_id()].is_trait_self() {
+ let args = GenericArgs::identity_for_item(interner, trait_id.into());
+ let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args);
+ tracing::debug!(?args, ?trait_ref);
+ return search(trait_ref);
+ }
+ }
+
+ let predicates =
+ db.generic_predicates_for_param(def, param_id.into(), assoc_name.clone());
+ predicates
+ .iter()
+ .find_map(|pred| match (*pred).kind().skip_binder() {
+ rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate),
+ _ => None,
+ })
+ .and_then(|trait_predicate| {
+ let trait_ref = trait_predicate.trait_ref;
+ assert!(
+ !trait_ref.has_escaping_bound_vars(),
+ "FIXME unexpected higher-ranked trait bound"
+ );
+ search(trait_ref)
+ })
+ }
+ _ => None,
+ }
}
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index 42723dc9e1..9ba0da6f49 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -1,42 +1,52 @@
//! A wrapper around [`TyLoweringContext`] specifically for lowering paths.
-use chalk_ir::{BoundVar, cast::Cast, fold::Shift};
use either::Either;
use hir_def::{
- GenericDefId, GenericParamId, TraitId,
+ GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId,
expr_store::{
- ExpressionStore,
- path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments},
+ ExpressionStore, HygieneId,
+ path::{
+ GenericArg as HirGenericArg, GenericArgs as HirGenericArgs, GenericArgsParentheses,
+ Path, PathSegment, PathSegments,
+ },
},
hir::generics::{
GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
},
- resolver::TypeNs,
+ resolver::{ResolveValueResult, TypeNs, ValueNs},
signatures::TraitFlags,
type_ref::{TypeRef, TypeRefId},
};
+use hir_expand::name::Name;
+use rustc_type_ir::{
+ AliasTerm, AliasTy, AliasTyKind,
+ inherent::{GenericArgs as _, Region as _, SliceLike, Ty as _},
+};
use smallvec::SmallVec;
use stdx::never;
use crate::{
- AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, IncorrectGenericsLenKind,
- Interner, ParamLoweringMode, PathGenericsSource, PathLoweringDiagnostic, ProjectionTy,
- QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind, WhereClause,
- consteval_chalk::{unknown_const, unknown_const_as_generic},
+ GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
+ PathLoweringDiagnostic, TyDefId, ValueTyDefId,
+ consteval::{unknown_const, unknown_const_as_generic},
db::HirDatabase,
- error_lifetime,
generics::{Generics, generics},
- lower::{LifetimeElisionKind, TyLoweringContext, named_associated_type_shorthand_candidates},
+ lower::{
+ LifetimeElisionKind, PathDiagnosticCallbackData, named_associated_type_shorthand_candidates,
+ },
next_solver::{
- DbInterner,
- mapping::{ChalkToNextSolver, NextSolverToChalk},
+ Binder, Clause, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Predicate,
+ ProjectionPredicate, Region, TraitRef, Ty,
},
- to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
- utils::associated_type_by_name_including_super_traits,
+};
+
+use super::{
+ ImplTraitLoweringMode, TyLoweringContext, associated_type_by_name_including_super_traits,
+ const_param_ty_query, ty_query,
};
type CallbackData<'a, 'db> = Either<
- super::PathDiagnosticCallbackData,
+ PathDiagnosticCallbackData,
crate::infer::diagnostics::PathDiagnosticCallbackData<'a, 'db>,
>;
@@ -45,12 +55,12 @@ type CallbackData<'a, 'db> = Either<
pub(crate) struct PathDiagnosticCallback<'a, 'db> {
pub(crate) data: CallbackData<'a, 'db>,
pub(crate) callback:
- fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic),
+ fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic),
}
-pub(crate) struct PathLoweringContext<'a, 'b> {
- ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a, 'b>,
+pub(crate) struct PathLoweringContext<'a, 'b, 'db> {
+ ctx: &'a mut TyLoweringContext<'db, 'b>,
+ on_diagnostic: PathDiagnosticCallback<'a, 'db>,
path: &'a Path,
segments: PathSegments<'a>,
current_segment_idx: usize,
@@ -58,11 +68,11 @@ pub(crate) struct PathLoweringContext<'a, 'b> {
current_or_prev_segment: PathSegment<'a>,
}
-impl<'a, 'b> PathLoweringContext<'a, 'b> {
+impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
#[inline]
pub(crate) fn new(
- ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a, 'b>,
+ ctx: &'a mut TyLoweringContext<'db, 'b>,
+ on_diagnostic: PathDiagnosticCallback<'a, 'db>,
path: &'a Path,
) -> Self {
let segments = path.segments();
@@ -84,7 +94,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
#[inline]
- pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'b> {
+ pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'db, 'b> {
self.ctx
}
@@ -110,10 +120,24 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
#[inline]
+ pub(crate) fn ignore_last_segment(&mut self) {
+ self.segments = self.segments.strip_last();
+ }
+
+ #[inline]
+ pub(crate) fn set_current_segment(&mut self, segment: usize) {
+ self.current_segment_idx = segment;
+ self.current_or_prev_segment = self
+ .segments
+ .get(segment)
+ .expect("invalid segment passed to PathLoweringContext::set_current_segment()");
+ }
+
+ #[inline]
fn with_lifetime_elision<T>(
&mut self,
- lifetime_elision: LifetimeElisionKind,
- f: impl FnOnce(&mut PathLoweringContext<'_, '_>) -> T,
+ lifetime_elision: LifetimeElisionKind<'db>,
+ f: impl FnOnce(&mut PathLoweringContext<'_, '_, 'db>) -> T,
) -> T {
let old_lifetime_elision =
std::mem::replace(&mut self.ctx.lifetime_elision, lifetime_elision);
@@ -124,12 +148,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
pub(crate) fn lower_ty_relative_path(
&mut self,
- ty: Ty,
+ ty: Ty<'db>,
// We need the original resolution to lower `Self::AssocTy` correctly
res: Option<TypeNs>,
infer_args: bool,
- ) -> (Ty, Option<TypeNs>) {
- match self.segments.len() - self.current_segment_idx {
+ ) -> (Ty<'db>, Option<TypeNs>) {
+ let remaining_segments = self.segments.len() - self.current_segment_idx;
+ match remaining_segments {
0 => (ty, res),
1 => {
// resolve unselected assoc types
@@ -137,7 +162,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
_ => {
// FIXME report error (ambiguous associated type)
- (TyKind::Error.intern(Interner), None)
+ (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None)
}
}
}
@@ -147,8 +172,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
&mut self,
resolution: TypeNs,
infer_args: bool,
- ) -> (Ty, Option<TypeNs>) {
+ ) -> (Ty<'db>, Option<TypeNs>) {
let remaining_segments = self.segments.skip(self.current_segment_idx + 1);
+ tracing::debug!(?remaining_segments);
+ let rem_seg_len = remaining_segments.len();
+ tracing::debug!(?rem_seg_len);
let ty = match resolution {
TypeNs::TraitId(trait_) => {
@@ -156,15 +184,17 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
1 => {
let trait_ref = self.lower_trait_ref_from_resolved_path(
trait_,
- TyKind::Error.intern(Interner),
- infer_args,
+ Ty::new_error(self.ctx.interner, ErrorGuaranteed),
+ false,
);
-
+ tracing::debug!(?trait_ref);
self.skip_resolved_segment();
let segment = self.current_or_prev_segment;
+ let trait_id = trait_ref.def_id.0;
let found =
- trait_.trait_items(self.ctx.db).associated_type_by_name(segment.name);
+ trait_id.trait_items(self.ctx.db).associated_type_by_name(segment.name);
+ tracing::debug!(?found);
match found {
Some(associated_ty) => {
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
@@ -173,27 +203,30 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
// this point (`trait_ref.substitution`).
let substitution = self.substs_from_path_segment(
associated_ty.into(),
- infer_args,
+ false,
None,
true,
);
- let substitution = Substitution::from_iter(
- Interner,
- trait_ref.substitution.iter(Interner).chain(
- substitution
- .iter(Interner)
- .skip(trait_ref.substitution.len(Interner)),
- ),
+ let args = GenericArgs::new_from_iter(
+ self.ctx.interner,
+ trait_ref
+ .args
+ .iter()
+ .chain(substitution.iter().skip(trait_ref.args.len())),
);
- TyKind::Alias(AliasTy::Projection(ProjectionTy {
- associated_ty_id: to_assoc_type_id(associated_ty),
- substitution,
- }))
- .intern(Interner)
+ Ty::new_alias(
+ self.ctx.interner,
+ AliasTyKind::Projection,
+ AliasTy::new_from_args(
+ self.ctx.interner,
+ associated_ty.into(),
+ args,
+ ),
+ )
}
None => {
// FIXME: report error (associated type not found)
- TyKind::Error.intern(Interner)
+ Ty::new_error(self.ctx.interner, ErrorGuaranteed)
}
}
}
@@ -201,73 +234,34 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
// Trait object type without dyn; this should be handled in upstream. See
// `lower_path()`.
stdx::never!("unexpected fully resolved trait path");
- TyKind::Error.intern(Interner)
+ Ty::new_error(self.ctx.interner, ErrorGuaranteed)
}
_ => {
// FIXME report error (ambiguous associated type)
- TyKind::Error.intern(Interner)
+ Ty::new_error(self.ctx.interner, ErrorGuaranteed)
}
};
return (ty, None);
}
- TypeNs::GenericParam(param_id) => match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => {
- let generics = self.ctx.generics();
- let idx = generics.type_or_const_param_idx(param_id.into()).unwrap();
- TyKind::Placeholder(to_placeholder_idx(
- self.ctx.db,
- param_id.into(),
- idx as u32,
- ))
- }
- ParamLoweringMode::Variable => {
- let idx = match self.ctx.generics().type_or_const_param_idx(param_id.into()) {
- None => {
- never!("no matching generics");
- return (TyKind::Error.intern(Interner), None);
- }
- Some(idx) => idx,
- };
-
- TyKind::BoundVar(BoundVar::new(self.ctx.in_binders, idx))
- }
- }
- .intern(Interner),
- TypeNs::SelfType(impl_id) => {
+ TypeNs::GenericParam(param_id) => {
let generics = self.ctx.generics();
-
- match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => {
- // `def` can be either impl itself or item within, and we need impl itself
- // now.
- let generics = generics.parent_or_self();
- let interner = DbInterner::new_with(self.ctx.db, None, None);
- let subst = generics.placeholder_subst(self.ctx.db);
- let args: crate::next_solver::GenericArgs<'_> =
- subst.to_nextsolver(interner);
- self.ctx
- .db
- .impl_self_ty(impl_id)
- .instantiate(interner, args)
- .to_chalk(interner)
+ let idx = generics.type_or_const_param_idx(param_id.into());
+ match idx {
+ None => {
+ never!("no matching generics");
+ Ty::new_error(self.ctx.interner, ErrorGuaranteed)
+ }
+ Some(idx) => {
+ let (pidx, _param) = generics.iter().nth(idx).unwrap();
+ assert_eq!(pidx, param_id.into());
+ self.ctx.type_param(param_id, idx as u32)
}
- ParamLoweringMode::Variable => TyBuilder::impl_self_ty(self.ctx.db, impl_id)
- .fill_with_bound_vars(self.ctx.in_binders, 0)
- .build(DbInterner::conjure())
- .to_chalk(DbInterner::conjure()),
}
}
+ TypeNs::SelfType(impl_id) => self.ctx.db.impl_self_ty(impl_id).skip_binder(),
TypeNs::AdtSelfType(adt) => {
- let generics = generics(self.ctx.db, adt.into());
- let substs = match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => generics.placeholder_subst(self.ctx.db),
- ParamLoweringMode::Variable => {
- generics.bound_vars_subst(self.ctx.db, self.ctx.in_binders)
- }
- };
- let interner = DbInterner::conjure();
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- self.ctx.db.ty(adt.into()).instantiate(interner, args).to_chalk(interner)
+ let args = GenericArgs::identity_for_item(self.ctx.interner, adt.into());
+ Ty::new_adt(self.ctx.interner, adt, args)
}
TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args),
@@ -275,15 +269,19 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args),
// FIXME: report error
TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => {
- return (TyKind::Error.intern(Interner), None);
+ return (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None);
}
};
+ tracing::debug!(?ty);
+
self.skip_resolved_segment();
self.lower_ty_relative_path(ty, Some(resolution), infer_args)
}
- fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) {
+ /// This returns whether to keep the resolution (`true`) of throw it (`false`).
+ #[must_use]
+ fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) -> bool {
let mut prohibit_generics_on_resolved = |reason| {
if self.current_or_prev_segment.args_and_bindings.is_some() {
let segment = self.current_segment_u32();
@@ -302,7 +300,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam)
}
TypeNs::AdtSelfType(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
+ prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy);
+
+ if self.ctx.lowering_param_default.is_some() {
+ // Generic defaults are not allowed to refer to `Self`.
+ // FIXME: Emit an error.
+ return false;
+ }
}
TypeNs::BuiltinType(_) => {
prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy)
@@ -315,6 +319,8 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
| TypeNs::TypeAliasId(_)
| TypeNs::TraitId(_) => {}
}
+
+ true
}
pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option<TypeNs> {
@@ -325,6 +331,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
Some(res)
}
+ #[tracing::instrument(skip(self), ret)]
pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option<usize>)> {
let (resolution, remaining_index, _, prefix_info) =
self.ctx.resolver.resolve_path_in_type_ns_with_prefix_info(self.ctx.db, self.path)?;
@@ -347,11 +354,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
self.current_or_prev_segment =
segments.get(resolved_segment_idx).expect("should have resolved segment");
- if matches!(self.path, Path::BarePath(..)) {
- // Bare paths cannot have generics, so skip them as an optimization.
- return Some((resolution, remaining_index));
- }
-
for (i, mod_segment) in module_segments.iter().enumerate() {
if mod_segment.args_and_bindings.is_some() {
self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
@@ -371,90 +373,233 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
});
}
- self.handle_type_ns_resolution(&resolution);
+ if !self.handle_type_ns_resolution(&resolution) {
+ return None;
+ }
Some((resolution, remaining_index))
}
- fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty {
- let Some(res) = res else {
- return TyKind::Error.intern(Interner);
- };
- let segment = self.current_or_prev_segment;
- let ty = named_associated_type_shorthand_candidates(
+ pub(crate) fn resolve_path_in_value_ns(
+ &mut self,
+ hygiene_id: HygieneId,
+ ) -> Option<ResolveValueResult> {
+ let (res, prefix_info) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info(
self.ctx.db,
- self.ctx.def,
- res,
- Some(segment.name.clone()),
- move |name, t, associated_ty| {
- if name != segment.name {
- return None;
- }
- let generics = self.ctx.generics();
+ self.path,
+ hygiene_id,
+ )?;
- let parent_subst = t.substitution.clone();
- let parent_subst = match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => {
- // if we're lowering to placeholders, we have to put them in now.
- let s = generics.placeholder_subst(self.ctx.db);
- s.apply(parent_subst, Interner)
- }
- ParamLoweringMode::Variable => {
- // We need to shift in the bound vars, since
- // `named_associated_type_shorthand_candidates` does not do that.
- parent_subst.shifted_in_from(Interner, self.ctx.in_binders)
+ let segments = self.segments;
+ if segments.is_empty() || matches!(self.path, Path::LangItem(..)) {
+ // `segments.is_empty()` can occur with `self`.
+ return Some(res);
+ }
+
+ let (mod_segments, enum_segment, resolved_segment_idx) = match res {
+ ResolveValueResult::Partial(_, unresolved_segment, _) => {
+ (segments.take(unresolved_segment - 1), None, unresolved_segment - 1)
+ }
+ ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _)
+ if prefix_info.enum_variant =>
+ {
+ (segments.strip_last_two(), segments.len().checked_sub(2), segments.len() - 1)
+ }
+ ResolveValueResult::ValueNs(..) => (segments.strip_last(), None, segments.len() - 1),
+ };
+
+ self.current_segment_idx = resolved_segment_idx;
+ self.current_or_prev_segment =
+ segments.get(resolved_segment_idx).expect("should have resolved segment");
+
+ for (i, mod_segment) in mod_segments.iter().enumerate() {
+ if mod_segment.args_and_bindings.is_some() {
+ self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
+ segment: i as u32,
+ reason: GenericArgsProhibitedReason::Module,
+ });
+ }
+ }
+
+ if let Some(enum_segment) = enum_segment
+ && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
+ && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
+ {
+ self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
+ segment: (enum_segment + 1) as u32,
+ reason: GenericArgsProhibitedReason::EnumVariant,
+ });
+ }
+
+ match &res {
+ ResolveValueResult::ValueNs(resolution, _) => {
+ let resolved_segment_idx = self.current_segment_u32();
+ let resolved_segment = self.current_or_prev_segment;
+
+ let mut prohibit_generics_on_resolved = |reason| {
+ if resolved_segment.args_and_bindings.is_some() {
+ self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
+ segment: resolved_segment_idx,
+ reason,
+ });
}
};
- // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
- // generic params. It's inefficient to splice the `Substitution`s, so we may want
- // that method to optionally take parent `Substitution` as we already know them at
- // this point (`t.substitution`).
- let substs =
- self.substs_from_path_segment(associated_ty.into(), infer_args, None, true);
-
- let substs = Substitution::from_iter(
- Interner,
- parent_subst
- .iter(Interner)
- .chain(substs.iter(Interner).skip(parent_subst.len(Interner))),
- );
+ match resolution {
+ ValueNs::ImplSelf(_) => {
+ prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy);
+ }
+ // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not
+ // E0109 (generic arguments provided for a type that doesn't accept them) for
+ // consts and statics, presumably as a defense against future in which consts
+ // and statics can be generic, or just because it was easier for rustc implementors.
+ // That means we'll show the wrong error code. Because of us it's easier to do it
+ // this way :)
+ ValueNs::GenericParam(_) => {
+ prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const)
+ }
+ ValueNs::StaticId(_) => {
+ prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static)
+ }
+ ValueNs::LocalBinding(_) => {
+ prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable)
+ }
+ ValueNs::FunctionId(_)
+ | ValueNs::StructId(_)
+ | ValueNs::EnumVariantId(_)
+ | ValueNs::ConstId(_) => {}
+ }
+ }
+ ResolveValueResult::Partial(resolution, _, _) => {
+ if !self.handle_type_ns_resolution(resolution) {
+ return None;
+ }
+ }
+ };
+ Some(res)
+ }
- Some(
- TyKind::Alias(AliasTy::Projection(ProjectionTy {
- associated_ty_id: to_assoc_type_id(associated_ty),
- substitution: substs,
- }))
- .intern(Interner),
- )
- },
- );
+ #[tracing::instrument(skip(self), ret)]
+ fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty<'db> {
+ let interner = self.ctx.interner;
+ let Some(res) = res else {
+ return Ty::new_error(self.ctx.interner, ErrorGuaranteed);
+ };
+ let def = self.ctx.def;
+ let segment = self.current_or_prev_segment;
+ let assoc_name = segment.name;
+ let check_alias = |name: &Name, t: TraitRef<'db>, associated_ty: TypeAliasId| {
+ if name != assoc_name {
+ return None;
+ }
- ty.unwrap_or_else(|| TyKind::Error.intern(Interner))
+ // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
+ // generic params. It's inefficient to splice the `Substitution`s, so we may want
+ // that method to optionally take parent `Substitution` as we already know them at
+ // this point (`t.substitution`).
+ let substs =
+ self.substs_from_path_segment(associated_ty.into(), infer_args, None, true);
+
+ let substs = GenericArgs::new_from_iter(
+ interner,
+ t.args.iter().chain(substs.iter().skip(t.args.len())),
+ );
+
+ Some(Ty::new_alias(
+ interner,
+ AliasTyKind::Projection,
+ AliasTy::new(interner, associated_ty.into(), substs),
+ ))
+ };
+ named_associated_type_shorthand_candidates(
+ interner,
+ def,
+ res,
+ Some(assoc_name.clone()),
+ check_alias,
+ )
+ .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed))
}
- fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty {
- let interner = DbInterner::conjure();
+ fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> {
let generic_def = match typeable {
- TyDefId::BuiltinType(builtin) => {
- return crate::next_solver::Ty::from_builtin_type(interner, builtin)
- .to_chalk(interner);
+ TyDefId::BuiltinType(builtinty) => {
+ return Ty::from_builtin_type(self.ctx.interner, builtinty);
}
TyDefId::AdtId(it) => it.into(),
TyDefId::TypeAliasId(it) => it.into(),
};
- let substs = self.substs_from_path_segment(generic_def, infer_args, None, false);
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- self.ctx.db.ty(typeable).instantiate(interner, args).to_chalk(interner)
+ let args = self.substs_from_path_segment(generic_def, infer_args, None, false);
+ let ty = ty_query(self.ctx.db, typeable);
+ ty.instantiate(self.ctx.interner, args)
+ }
+
+ /// Collect generic arguments from a path into a `Substs`. See also
+ /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
+ pub(crate) fn substs_from_path(
+ &mut self,
+ // Note that we don't call `db.value_type(resolved)` here,
+ // `ValueTyDefId` is just a convenient way to pass generics and
+ // special-case enum variants
+ resolved: ValueTyDefId,
+ infer_args: bool,
+ lowering_assoc_type_generics: bool,
+ ) -> GenericArgs<'db> {
+ let interner = self.ctx.interner;
+ let prev_current_segment_idx = self.current_segment_idx;
+ let prev_current_segment = self.current_or_prev_segment;
+
+ let generic_def = match resolved {
+ ValueTyDefId::FunctionId(it) => it.into(),
+ ValueTyDefId::StructId(it) => it.into(),
+ ValueTyDefId::UnionId(it) => it.into(),
+ ValueTyDefId::ConstId(it) => it.into(),
+ ValueTyDefId::StaticId(_) => {
+ return GenericArgs::new_from_iter(interner, []);
+ }
+ ValueTyDefId::EnumVariantId(var) => {
+ // the generic args for an enum variant may be either specified
+ // on the segment referring to the enum, or on the segment
+ // referring to the variant. So `Option::<T>::None` and
+ // `Option::None::<T>` are both allowed (though the former is
+ // FIXME: This isn't strictly correct, enum variants may be used not through the enum
+ // (via `use Enum::Variant`). The resolver returns whether they were, but we don't have its result
+ // available here. The worst that can happen is that we will show some confusing diagnostics to the user,
+ // if generics exist on the module and they don't match with the variant.
+ // preferred). See also `def_ids_for_path_segments` in rustc.
+ //
+ // `wrapping_sub(1)` will return a number which `get` will return None for if current_segment_idx<2.
+ // This simplifies the code a bit.
+ let penultimate_idx = self.current_segment_idx.wrapping_sub(1);
+ let penultimate = self.segments.get(penultimate_idx);
+ if let Some(penultimate) = penultimate
+ && self.current_or_prev_segment.args_and_bindings.is_none()
+ && penultimate.args_and_bindings.is_some()
+ {
+ self.current_segment_idx = penultimate_idx;
+ self.current_or_prev_segment = penultimate;
+ }
+ var.lookup(self.ctx.db).parent.into()
+ }
+ };
+ let result = self.substs_from_path_segment(
+ generic_def,
+ infer_args,
+ None,
+ lowering_assoc_type_generics,
+ );
+ self.current_segment_idx = prev_current_segment_idx;
+ self.current_or_prev_segment = prev_current_segment;
+ result
}
pub(crate) fn substs_from_path_segment(
&mut self,
def: GenericDefId,
infer_args: bool,
- explicit_self_ty: Option<Ty>,
+ explicit_self_ty: Option<Ty<'db>>,
lowering_assoc_type_generics: bool,
- ) -> Substitution {
+ ) -> GenericArgs<'db> {
let old_lifetime_elision = self.ctx.lifetime_elision.clone();
if let Some(args) = self.current_or_prev_segment.args_and_bindings
@@ -481,7 +626,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
);
- return TyBuilder::unknown_subst(self.ctx.db, def);
+ return unknown_subst(self.ctx.interner, def);
}
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
@@ -504,20 +649,20 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
pub(super) fn substs_from_args_and_bindings(
&mut self,
- args_and_bindings: Option<&GenericArgs>,
+ args_and_bindings: Option<&HirGenericArgs>,
def: GenericDefId,
infer_args: bool,
- explicit_self_ty: Option<Ty>,
+ explicit_self_ty: Option<Ty<'db>>,
generics_source: PathGenericsSource,
lowering_assoc_type_generics: bool,
- lifetime_elision: LifetimeElisionKind,
- ) -> Substitution {
- struct LowererCtx<'a, 'b, 'c> {
- ctx: &'a mut PathLoweringContext<'b, 'c>,
+ lifetime_elision: LifetimeElisionKind<'db>,
+ ) -> GenericArgs<'db> {
+ struct LowererCtx<'a, 'b, 'c, 'db> {
+ ctx: &'a mut PathLoweringContext<'b, 'c, 'db>,
generics_source: PathGenericsSource,
}
- impl GenericArgsLowerer for LowererCtx<'_, '_, '_> {
+ impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> {
fn report_len_mismatch(
&mut self,
def: GenericDefId,
@@ -552,23 +697,24 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
&mut self,
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::GenericArg {
- match (param, arg) {
- (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => {
- self.ctx.ctx.lower_lifetime(*lifetime).cast(Interner)
- }
- (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => {
- self.ctx.ctx.lower_ty(*type_ref).cast(Interner)
+ arg: &HirGenericArg,
+ ) -> GenericArg<'db> {
+ match (param, *arg) {
+ (
+ GenericParamDataRef::LifetimeParamData(_),
+ HirGenericArg::Lifetime(lifetime),
+ ) => self.ctx.ctx.lower_lifetime(lifetime).into(),
+ (GenericParamDataRef::TypeParamData(_), HirGenericArg::Type(type_ref)) => {
+ self.ctx.ctx.lower_ty(type_ref).into()
}
- (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => {
+ (GenericParamDataRef::ConstParamData(_), HirGenericArg::Const(konst)) => {
let GenericParamId::ConstParamId(const_id) = param_id else {
unreachable!("non-const param ID for const param");
};
self.ctx
.ctx
- .lower_const(konst, self.ctx.ctx.db.const_param_ty(const_id))
- .cast(Interner)
+ .lower_const(konst, const_param_ty_query(self.ctx.ctx.db, const_id))
+ .into()
}
_ => unreachable!("unmatching param kinds were passed to `provided_kind()`"),
}
@@ -576,9 +722,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
fn provided_type_like_const(
&mut self,
- const_ty: Ty,
+ const_ty: Ty<'db>,
arg: TypeLikeConst<'_>,
- ) -> crate::Const {
+ ) -> Const<'db> {
match arg {
TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty),
TypeLikeConst::Infer => unknown_const(const_ty),
@@ -591,18 +737,19 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
infer_args: bool,
- preceding_args: &[crate::GenericArg],
- ) -> crate::GenericArg {
- let default = || {
- self.ctx
- .ctx
- .db
- .generic_defaults(def)
- .get(preceding_args.len())
- .map(|default| default.clone().substitute(Interner, preceding_args))
- };
+ preceding_args: &[GenericArg<'db>],
+ ) -> GenericArg<'db> {
+ let default =
+ || {
+ self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(
+ |default| default.instantiate(self.ctx.ctx.interner, preceding_args),
+ )
+ };
match param {
- GenericParamDataRef::LifetimeParamData(_) => error_lifetime().cast(Interner),
+ GenericParamDataRef::LifetimeParamData(_) => {
+ Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
+ .into()
+ }
GenericParamDataRef::TypeParamData(param) => {
if !infer_args
&& param.default.is_some()
@@ -610,7 +757,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
{
return default;
}
- TyKind::Error.intern(Interner).cast(Interner)
+ Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
}
GenericParamDataRef::ConstParamData(param) => {
if !infer_args
@@ -622,19 +769,23 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
let GenericParamId::ConstParamId(const_id) = param_id else {
unreachable!("non-const param ID for const param");
};
- unknown_const_as_generic(self.ctx.ctx.db.const_param_ty(const_id))
- .cast(Interner)
+ unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id))
}
}
}
- fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg {
+ fn parent_arg(&mut self, param_id: GenericParamId) -> GenericArg<'db> {
match param_id {
- GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
+ GenericParamId::TypeParamId(_) => {
+ Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
+ }
GenericParamId::ConstParamId(const_id) => {
- unknown_const_as_generic(self.ctx.ctx.db.const_param_ty(const_id))
+ unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id))
+ }
+ GenericParamId::LifetimeParamId(_) => {
+ Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
+ .into()
}
- GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
}
}
@@ -652,6 +803,14 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
});
}
+ fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32) {
+ self.ctx.on_diagnostic(PathLoweringDiagnostic::ElisionFailure {
+ generics_source: self.generics_source,
+ def,
+ expected_count,
+ });
+ }
+
fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32) {
self.ctx.on_diagnostic(PathLoweringDiagnostic::MissingLifetime {
generics_source: self.generics_source,
@@ -677,38 +836,39 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
pub(crate) fn lower_trait_ref_from_resolved_path(
&mut self,
resolved: TraitId,
- explicit_self_ty: Ty,
+ explicit_self_ty: Ty<'db>,
infer_args: bool,
- ) -> TraitRef {
- let substs = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args);
- TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
+ ) -> TraitRef<'db> {
+ let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args);
+ TraitRef::new_from_args(self.ctx.interner, resolved.into(), args)
}
fn trait_ref_substs_from_path(
&mut self,
resolved: TraitId,
- explicit_self_ty: Ty,
+ explicit_self_ty: Ty<'db>,
infer_args: bool,
- ) -> Substitution {
+ ) -> GenericArgs<'db> {
self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false)
}
pub(super) fn assoc_type_bindings_from_type_bound<'c>(
mut self,
- trait_ref: TraitRef,
- ) -> Option<impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b, 'c>> {
+ trait_ref: TraitRef<'db>,
+ ) -> Option<impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'c, 'db>> {
+ let interner = self.ctx.interner;
self.current_or_prev_segment.args_and_bindings.map(|args_and_bindings| {
args_and_bindings.bindings.iter().enumerate().flat_map(move |(binding_idx, binding)| {
let found = associated_type_by_name_including_super_traits(
self.ctx.db,
- trait_ref.clone(),
+ trait_ref,
&binding.name,
);
let (super_trait_ref, associated_ty) = match found {
None => return SmallVec::new(),
Some(t) => t,
};
- let substitution =
+ let args =
self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| {
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
// generic params. It's inefficient to splice the `Substitution`s, so we may want
@@ -718,7 +878,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
binding.args.as_ref(),
associated_ty.into(),
false, // this is not relevant
- Some(super_trait_ref.self_type_parameter(Interner)),
+ Some(super_trait_ref.self_ty()),
PathGenericsSource::AssocType {
segment: this.current_segment_u32(),
assoc_type: binding_idx as u32,
@@ -727,27 +887,20 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
this.ctx.lifetime_elision.clone(),
)
});
- let substitution = Substitution::from_iter(
- Interner,
- super_trait_ref.substitution.iter(Interner).chain(
- substitution
- .iter(Interner)
- .skip(super_trait_ref.substitution.len(Interner)),
- ),
+ let args = GenericArgs::new_from_iter(
+ interner,
+ super_trait_ref.args.iter().chain(args.iter().skip(super_trait_ref.args.len())),
);
- let projection_ty = ProjectionTy {
- associated_ty_id: to_assoc_type_id(associated_ty),
- substitution,
- };
+ let projection_term =
+ AliasTerm::new_from_args(interner, associated_ty.into(), args);
let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity(
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
);
-
if let Some(type_ref) = binding.type_ref {
let lifetime_elision =
if args_and_bindings.parenthesized == GenericArgsParentheses::ParenSugar {
// `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def).
- LifetimeElisionKind::for_fn_ret()
+ LifetimeElisionKind::for_fn_ret(self.ctx.interner)
} else {
self.ctx.lifetime_elision.clone()
};
@@ -759,31 +912,33 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque,
) => {
let ty = this.ctx.lower_ty(type_ref);
- let alias_eq = AliasEq {
- alias: AliasTy::Projection(projection_ty.clone()),
- ty,
- };
- predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(
- alias_eq,
- )));
+ let pred = Clause(Predicate::new(
+ interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Projection(
+ ProjectionPredicate {
+ projection_term,
+ term: ty.into(),
+ },
+ ),
+ )),
+ ));
+ predicates.push(pred);
}
}
- });
+ })
+ }
+ for bound in binding.bounds.iter() {
+ predicates.extend(self.ctx.lower_type_bound(
+ bound,
+ Ty::new_alias(
+ self.ctx.interner,
+ AliasTyKind::Projection,
+ AliasTy::new_from_args(self.ctx.interner, associated_ty.into(), args),
+ ),
+ false,
+ ));
}
-
- self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| {
- for bound in binding.bounds.iter() {
- predicates.extend(
- this.ctx.lower_type_bound(
- bound,
- TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
- .intern(Interner),
- false,
- ),
- );
- }
- });
-
predicates
})
})
@@ -796,7 +951,7 @@ pub(crate) enum TypeLikeConst<'a> {
Path(&'a Path),
}
-pub(crate) trait GenericArgsLowerer {
+pub(crate) trait GenericArgsLowerer<'db> {
fn report_elided_lifetimes_in_path(
&mut self,
def: GenericDefId,
@@ -804,6 +959,8 @@ pub(crate) trait GenericArgsLowerer {
hard_error: bool,
);
+ fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32);
+
fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32);
fn report_len_mismatch(
@@ -820,10 +977,11 @@ pub(crate) trait GenericArgsLowerer {
&mut self,
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::GenericArg;
+ arg: &HirGenericArg,
+ ) -> GenericArg<'db>;
- fn provided_type_like_const(&mut self, const_ty: Ty, arg: TypeLikeConst<'_>) -> crate::Const;
+ fn provided_type_like_const(&mut self, const_ty: Ty<'db>, arg: TypeLikeConst<'_>)
+ -> Const<'db>;
fn inferred_kind(
&mut self,
@@ -831,21 +989,21 @@ pub(crate) trait GenericArgsLowerer {
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
infer_args: bool,
- preceding_args: &[crate::GenericArg],
- ) -> crate::GenericArg;
+ preceding_args: &[GenericArg<'db>],
+ ) -> GenericArg<'db>;
- fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg;
+ fn parent_arg(&mut self, param_id: GenericParamId) -> GenericArg<'db>;
}
/// Returns true if there was an error.
-fn check_generic_args_len(
- args_and_bindings: Option<&GenericArgs>,
+fn check_generic_args_len<'db>(
+ args_and_bindings: Option<&HirGenericArgs>,
def: GenericDefId,
def_generics: &Generics,
infer_args: bool,
- lifetime_elision: &LifetimeElisionKind,
+ lifetime_elision: &LifetimeElisionKind<'db>,
lowering_assoc_type_generics: bool,
- ctx: &mut impl GenericArgsLowerer,
+ ctx: &mut impl GenericArgsLowerer<'db>,
) -> bool {
let mut had_error = false;
@@ -854,8 +1012,10 @@ fn check_generic_args_len(
let args_no_self = &args_and_bindings.args[usize::from(args_and_bindings.has_self_type)..];
for arg in args_no_self {
match arg {
- GenericArg::Lifetime(_) => provided_lifetimes_count += 1,
- GenericArg::Type(_) | GenericArg::Const(_) => provided_types_and_consts_count += 1,
+ HirGenericArg::Lifetime(_) => provided_lifetimes_count += 1,
+ HirGenericArg::Type(_) | HirGenericArg::Const(_) => {
+ provided_types_and_consts_count += 1
+ }
}
}
}
@@ -876,6 +1036,13 @@ fn check_generic_args_len(
ctx.report_missing_lifetime(def, lifetime_args_len as u32);
had_error = true
}
+ LifetimeElisionKind::ElisionFailure => {
+ ctx.report_elision_failure(def, lifetime_args_len as u32);
+ had_error = true;
+ }
+ LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
+ // FIXME: Check there are other lifetimes in scope, and error/lint.
+ }
LifetimeElisionKind::Elided(_) => {
ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, false);
}
@@ -922,17 +1089,21 @@ fn check_generic_args_len(
had_error
}
-pub(crate) fn substs_from_args_and_bindings(
- db: &dyn HirDatabase,
+pub(crate) fn substs_from_args_and_bindings<'db>(
+ db: &'db dyn HirDatabase,
store: &ExpressionStore,
- args_and_bindings: Option<&GenericArgs>,
+ args_and_bindings: Option<&HirGenericArgs>,
def: GenericDefId,
mut infer_args: bool,
- lifetime_elision: LifetimeElisionKind,
+ lifetime_elision: LifetimeElisionKind<'db>,
lowering_assoc_type_generics: bool,
- explicit_self_ty: Option<Ty>,
- ctx: &mut impl GenericArgsLowerer,
-) -> Substitution {
+ explicit_self_ty: Option<Ty<'db>>,
+ ctx: &mut impl GenericArgsLowerer<'db>,
+) -> GenericArgs<'db> {
+ let interner = DbInterner::new_with(db, None, None);
+
+ tracing::debug!(?args_and_bindings);
+
// Order is
// - Parent parameters
// - Optional Self parameter
@@ -943,7 +1114,7 @@ pub(crate) fn substs_from_args_and_bindings(
// We do not allow inference if there are specified args, i.e. we do not allow partial inference.
let has_non_lifetime_args =
- args_slice.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_)));
+ args_slice.iter().any(|arg| !matches!(arg, HirGenericArg::Lifetime(_)));
infer_args &= !has_non_lifetime_args;
let had_count_error = check_generic_args_len(
@@ -984,7 +1155,7 @@ pub(crate) fn substs_from_args_and_bindings(
let (_, self_ty) = args.next().expect("has_self_type=true, should have Self type");
ctx.provided_kind(self_param_id, self_param, self_ty)
} else {
- explicit_self_ty.map(|it| it.cast(Interner)).unwrap_or_else(|| {
+ explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| {
ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs)
})
};
@@ -999,7 +1170,7 @@ pub(crate) fn substs_from_args_and_bindings(
// input. We try to handle both sensibly.
match (args.peek(), params.peek()) {
(Some(&(arg_idx, arg)), Some(&(param_id, param))) => match (arg, param) {
- (GenericArg::Type(_), GenericParamDataRef::TypeParamData(type_param))
+ (HirGenericArg::Type(_), GenericParamDataRef::TypeParamData(type_param))
if type_param.provenance == TypeParamProvenance::ArgumentImplTrait =>
{
// Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here
@@ -1007,15 +1178,15 @@ pub(crate) fn substs_from_args_and_bindings(
substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs));
params.next();
}
- (GenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_))
- | (GenericArg::Type(_), GenericParamDataRef::TypeParamData(_))
- | (GenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => {
+ (HirGenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_))
+ | (HirGenericArg::Type(_), GenericParamDataRef::TypeParamData(_))
+ | (HirGenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => {
substs.push(ctx.provided_kind(param_id, param, arg));
args.next();
params.next();
}
(
- GenericArg::Type(_) | GenericArg::Const(_),
+ HirGenericArg::Type(_) | HirGenericArg::Const(_),
GenericParamDataRef::LifetimeParamData(_),
) => {
// We expected a lifetime argument, but got a type or const
@@ -1024,13 +1195,13 @@ pub(crate) fn substs_from_args_and_bindings(
params.next();
force_infer_lt = Some((arg_idx as u32, param_id));
}
- (GenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => {
+ (HirGenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => {
if let Some(konst) = type_looks_like_const(store, *type_ref) {
let GenericParamId::ConstParamId(param_id) = param_id else {
panic!("unmatching param kinds");
};
- let const_ty = db.const_param_ty(param_id);
- substs.push(ctx.provided_type_like_const(const_ty, konst).cast(Interner));
+ let const_ty = const_param_ty_query(db, param_id);
+ substs.push(ctx.provided_type_like_const(const_ty, konst).into());
args.next();
params.next();
} else {
@@ -1069,7 +1240,7 @@ pub(crate) fn substs_from_args_and_bindings(
// after a type or const). We want to throw an error in this case.
if !had_count_error {
assert!(
- matches!(arg, GenericArg::Lifetime(_)),
+ matches!(arg, HirGenericArg::Lifetime(_)),
"the only possible situation here is incorrect lifetime order"
);
let (provided_arg_idx, param_id) =
@@ -1084,12 +1255,16 @@ pub(crate) fn substs_from_args_and_bindings(
// If there are fewer arguments than parameters, it means we're inferring the remaining arguments.
let param = if let GenericParamId::LifetimeParamId(_) = param_id {
match &lifetime_elision {
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }
+ LifetimeElisionKind::ElisionFailure
+ | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }
| LifetimeElisionKind::AnonymousReportError => {
assert!(had_count_error);
ctx.inferred_kind(def, param_id, param, infer_args, &substs)
}
- LifetimeElisionKind::Elided(lifetime) => lifetime.clone().cast(Interner),
+ LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
+ Region::new_static(interner).into()
+ }
+ LifetimeElisionKind::Elided(lifetime) => (*lifetime).into(),
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false }
| LifetimeElisionKind::Infer => {
// FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here
@@ -1108,7 +1283,7 @@ pub(crate) fn substs_from_args_and_bindings(
}
}
- Substitution::from_iter(Interner, substs)
+ GenericArgs::new_from_iter(interner, substs)
}
fn type_looks_like_const(
@@ -1127,3 +1302,17 @@ fn type_looks_like_const(
_ => None,
}
}
+
+fn unknown_subst<'db>(interner: DbInterner<'db>, def: impl Into<GenericDefId>) -> GenericArgs<'db> {
+ let params = generics(interner.db(), def.into());
+ GenericArgs::new_from_iter(
+ interner,
+ params.iter_id().map(|id| match id {
+ GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
+ GenericParamId::ConstParamId(id) => {
+ unknown_const_as_generic(const_param_ty_query(interner.db(), id))
+ }
+ GenericParamId::LifetimeParamId(_) => Region::error(interner).into(),
+ }),
+ )
+}
diff --git a/crates/hir-ty/src/lower_nextsolver.rs b/crates/hir-ty/src/lower_nextsolver.rs
deleted file mode 100644
index 76ee1a4f2d..0000000000
--- a/crates/hir-ty/src/lower_nextsolver.rs
+++ /dev/null
@@ -1,2138 +0,0 @@
-//! Methods for lowering the HIR to types. There are two main cases here:
-//!
-//! - Lowering a type reference like `&usize` or `Option<foo::bar::Baz>` to a
-//! type: The entry point for this is `TyLoweringContext::lower_ty`.
-//! - Building the type for an item: This happens through the `ty` query.
-//!
-//! This usually involves resolving names, collecting generic arguments etc.
-pub(crate) mod path;
-
-use std::{
- cell::OnceCell,
- iter, mem,
- ops::{self, Deref, Not as _},
-};
-
-use base_db::Crate;
-use either::Either;
-use hir_def::{
- AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
- FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
- LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, TypeParamId,
- VariantId,
- expr_store::{ExpressionStore, HygieneId, path::Path},
- hir::generics::{
- GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
- },
- item_tree::FieldsShape,
- lang_item::LangItem,
- resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs},
- signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
- type_ref::{
- ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier,
- TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId,
- },
-};
-use hir_expand::name::Name;
-use la_arena::{Arena, ArenaMap, Idx};
-use path::{PathDiagnosticCallback, PathLoweringContext};
-use rustc_ast_ir::Mutability;
-use rustc_hash::FxHashSet;
-use rustc_pattern_analysis::Captures;
-use rustc_type_ir::{
- AliasTyKind, ConstKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection,
- ExistentialTraitRef, FnSig, OutlivesPredicate,
- TyKind::{self},
- TypeVisitableExt,
- inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _},
-};
-use salsa::plumbing::AsId;
-use smallvec::{SmallVec, smallvec};
-use stdx::never;
-use triomphe::Arc;
-
-use crate::{
- FnAbi, ImplTraitId, TraitEnvironment, TyDefId, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
- ValueTyDefId,
- consteval::intern_const_ref,
- db::HirDatabase,
- generics::{Generics, generics, trait_self_param_idx},
- lower::{Diagnostics, PathDiagnosticCallbackData, create_diagnostics},
- next_solver::{
- AliasTy, Binder, BoundExistentialPredicates, Clause, Clauses, Const, DbInterner,
- EarlyBinder, EarlyParamRegion, ErrorGuaranteed, GenericArg, GenericArgs, ParamConst,
- ParamEnv, PolyFnSig, Predicate, Region, SolverDefId, TraitPredicate, TraitRef, Ty, Tys,
- UnevaluatedConst, abi::Safety,
- },
-};
-
-#[derive(PartialEq, Eq, Debug, Hash)]
-pub struct ImplTraits<'db> {
- pub(crate) impl_traits: Arena<ImplTrait<'db>>,
-}
-
-#[derive(PartialEq, Eq, Debug, Hash)]
-pub struct ImplTrait<'db> {
- pub(crate) predicates: Vec<Clause<'db>>,
-}
-
-pub type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>;
-
-#[derive(Debug, Default)]
-struct ImplTraitLoweringState<'db> {
- /// When turning `impl Trait` into opaque types, we have to collect the
- /// bounds at the same time to get the IDs correct (without becoming too
- /// complicated).
- mode: ImplTraitLoweringMode,
- // This is structured as a struct with fields and not as an enum because it helps with the borrow checker.
- opaque_type_data: Arena<ImplTrait<'db>>,
-}
-
-impl<'db> ImplTraitLoweringState<'db> {
- fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState<'db> {
- Self { mode, opaque_type_data: Arena::new() }
- }
-}
-
-#[derive(Debug, Clone)]
-pub enum LifetimeElisionKind<'db> {
- /// Create a new anonymous lifetime parameter and reference it.
- ///
- /// If `report_in_path`, report an error when encountering lifetime elision in a path:
- /// ```compile_fail
- /// struct Foo<'a> { x: &'a () }
- /// async fn foo(x: Foo) {}
- /// ```
- ///
- /// Note: the error should not trigger when the elided lifetime is in a pattern or
- /// expression-position path:
- /// ```
- /// struct Foo<'a> { x: &'a () }
- /// async fn foo(Foo { x: _ }: Foo<'_>) {}
- /// ```
- AnonymousCreateParameter { report_in_path: bool },
-
- /// Replace all anonymous lifetimes by provided lifetime.
- Elided(Region<'db>),
-
- /// Give a hard error when either `&` or `'_` is written. Used to
- /// rule out things like `where T: Foo<'_>`. Does not imply an
- /// error on default object bounds (e.g., `Box<dyn Foo>`).
- AnonymousReportError,
-
- /// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope,
- /// otherwise give a warning that the previous behavior of introducing a new early-bound
- /// lifetime is a bug and will be removed (if `only_lint` is enabled).
- StaticIfNoLifetimeInScope { only_lint: bool },
-
- /// Signal we cannot find which should be the anonymous lifetime.
- ElisionFailure,
-
- /// Infer all elided lifetimes.
- Infer,
-}
-
-impl<'db> LifetimeElisionKind<'db> {
- #[inline]
- pub(crate) fn for_const(
- interner: DbInterner<'db>,
- const_parent: ItemContainerId,
- ) -> LifetimeElisionKind<'db> {
- match const_parent {
- ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
- LifetimeElisionKind::Elided(Region::new_static(interner))
- }
- ItemContainerId::ImplId(_) => {
- LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true }
- }
- ItemContainerId::TraitId(_) => {
- LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false }
- }
- }
- }
-
- #[inline]
- pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind<'db> {
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() }
- }
-
- #[inline]
- pub(crate) fn for_fn_ret(interner: DbInterner<'db>) -> LifetimeElisionKind<'db> {
- // FIXME: We should use the elided lifetime here, or `ElisionFailure`.
- LifetimeElisionKind::Elided(Region::error(interner))
- }
-}
-
-#[derive(Debug)]
-pub struct TyLoweringContext<'db, 'a> {
- pub db: &'db dyn HirDatabase,
- interner: DbInterner<'db>,
- resolver: &'a Resolver<'db>,
- store: &'a ExpressionStore,
- def: GenericDefId,
- generics: OnceCell<Generics>,
- in_binders: DebruijnIndex,
- impl_trait_mode: ImplTraitLoweringState<'db>,
- /// Tracks types with explicit `?Sized` bounds.
- pub(crate) unsized_types: FxHashSet<Ty<'db>>,
- pub(crate) diagnostics: Vec<TyLoweringDiagnostic>,
- lifetime_elision: LifetimeElisionKind<'db>,
- /// When lowering the defaults for generic params, this contains the index of the currently lowered param.
- /// We disallow referring to later params, or to ADT's `Self`.
- lowering_param_default: Option<u32>,
-}
-
-impl<'db, 'a> TyLoweringContext<'db, 'a> {
- pub fn new(
- db: &'db dyn HirDatabase,
- resolver: &'a Resolver<'db>,
- store: &'a ExpressionStore,
- def: GenericDefId,
- lifetime_elision: LifetimeElisionKind<'db>,
- ) -> Self {
- let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
- let in_binders = DebruijnIndex::ZERO;
- Self {
- db,
- interner: DbInterner::new_with(db, Some(resolver.krate()), None),
- resolver,
- def,
- generics: Default::default(),
- store,
- in_binders,
- impl_trait_mode,
- unsized_types: FxHashSet::default(),
- diagnostics: Vec::new(),
- lifetime_elision,
- lowering_param_default: None,
- }
- }
-
- pub(crate) fn set_lifetime_elision(&mut self, lifetime_elision: LifetimeElisionKind<'db>) {
- self.lifetime_elision = lifetime_elision;
- }
-
- pub(crate) fn with_debruijn<T>(
- &mut self,
- debruijn: DebruijnIndex,
- f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
- ) -> T {
- let old_debruijn = mem::replace(&mut self.in_binders, debruijn);
- let result = f(self);
- self.in_binders = old_debruijn;
- result
- }
-
- pub(crate) fn with_shifted_in<T>(
- &mut self,
- debruijn: DebruijnIndex,
- f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
- ) -> T {
- self.with_debruijn(self.in_binders.shifted_in(debruijn.as_u32()), f)
- }
-
- pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
- Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self }
- }
-
- pub(crate) fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self {
- self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode);
- self
- }
-
- pub(crate) fn lowering_param_default(&mut self, index: u32) {
- self.lowering_param_default = Some(index);
- }
-
- pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
- self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind });
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
-pub(crate) enum ImplTraitLoweringMode {
- /// `impl Trait` gets lowered into an opaque type that doesn't unify with
- /// anything except itself. This is used in places where values flow 'out',
- /// i.e. for arguments of the function we're currently checking, and return
- /// types of functions we're calling.
- Opaque,
- /// `impl Trait` is disallowed and will be an error.
- #[default]
- Disallowed,
-}
-
-impl<'db, 'a> TyLoweringContext<'db, 'a> {
- pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
- self.lower_ty_ext(type_ref).0
- }
-
- pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> {
- let const_ref = &self.store[const_ref.expr];
- match const_ref {
- hir_def::hir::Expr::Path(path) => {
- self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
- }
- hir_def::hir::Expr::Literal(literal) => intern_const_ref(
- self.db,
- &match *literal {
- hir_def::hir::Literal::Float(_, _)
- | hir_def::hir::Literal::String(_)
- | hir_def::hir::Literal::ByteString(_)
- | hir_def::hir::Literal::CString(_) => LiteralConstRef::Unknown,
- hir_def::hir::Literal::Char(c) => LiteralConstRef::Char(c),
- hir_def::hir::Literal::Bool(b) => LiteralConstRef::Bool(b),
- hir_def::hir::Literal::Int(val, _) => LiteralConstRef::Int(val),
- hir_def::hir::Literal::Uint(val, _) => LiteralConstRef::UInt(val),
- },
- const_type,
- self.resolver.krate(),
- ),
- hir_def::hir::Expr::UnaryOp { expr: inner_expr, op: hir_def::hir::UnaryOp::Neg } => {
- if let hir_def::hir::Expr::Literal(literal) = &self.store[*inner_expr] {
- // Only handle negation for signed integers and floats
- match literal {
- hir_def::hir::Literal::Int(_, _) | hir_def::hir::Literal::Float(_, _) => {
- if let Some(negated_literal) = literal.clone().negate() {
- intern_const_ref(
- self.db,
- &negated_literal.into(),
- const_type,
- self.resolver.krate(),
- )
- } else {
- unknown_const(const_type)
- }
- }
- // For unsigned integers, chars, bools, etc., negation is not meaningful
- _ => unknown_const(const_type),
- }
- } else {
- unknown_const(const_type)
- }
- }
- _ => unknown_const(const_type),
- }
- }
-
- pub(crate) fn path_to_const(&mut self, path: &Path) -> Option<Const<'db>> {
- match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) {
- Some(ValueNs::GenericParam(p)) => {
- let args = self.generics();
- match args.type_or_const_param_idx(p.into()) {
- Some(idx) => Some(self.const_param(p, idx as u32)),
- None => {
- never!(
- "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
- args,
- path,
- p
- );
- None
- }
- }
- }
- Some(ValueNs::ConstId(c)) => {
- let args = GenericArgs::new_from_iter(self.interner, []);
- Some(Const::new(
- self.interner,
- rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(
- SolverDefId::ConstId(c),
- args,
- )),
- ))
- }
- _ => None,
- }
- }
-
- pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty<'db>) -> Const<'db> {
- self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
- }
-
- fn generics(&self) -> &Generics {
- self.generics.get_or_init(|| generics(self.db, self.def))
- }
-
- fn param_index_is_disallowed(&self, index: u32) -> bool {
- self.lowering_param_default
- .is_some_and(|disallow_params_after| index >= disallow_params_after)
- }
-
- fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> {
- if self.param_index_is_disallowed(index) {
- // FIXME: Report an error.
- Ty::new_error(self.interner, ErrorGuaranteed)
- } else {
- Ty::new_param(self.interner, id, index)
- }
- }
-
- fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> {
- if self.param_index_is_disallowed(index) {
- // FIXME: Report an error.
- Const::error(self.interner)
- } else {
- Const::new_param(self.interner, ParamConst { id, index })
- }
- }
-
- fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> {
- if self.param_index_is_disallowed(index) {
- // FIXME: Report an error.
- Region::error(self.interner)
- } else {
- Region::new_early_param(self.interner, EarlyParamRegion { id, index })
- }
- }
-
- #[tracing::instrument(skip(self), ret)]
- pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) {
- let interner = self.interner;
- let mut res = None;
- let type_ref = &self.store[type_ref_id];
- tracing::debug!(?type_ref);
- let ty = match type_ref {
- TypeRef::Never => Ty::new(interner, TyKind::Never),
- TypeRef::Tuple(inner) => {
- let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr));
- Ty::new_tup_from_iter(interner, inner_tys)
- }
- TypeRef::Path(path) => {
- let (ty, res_) =
- self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id));
- res = res_;
- ty
- }
- &TypeRef::TypeParam(type_param_id) => {
- res = Some(TypeNs::GenericParam(type_param_id));
-
- let generics = self.generics();
- let (idx, _data) =
- generics.type_or_const_param(type_param_id.into()).expect("matching generics");
- self.type_param(type_param_id, idx as u32)
- }
- &TypeRef::RawPtr(inner, mutability) => {
- let inner_ty = self.lower_ty(inner);
- Ty::new(interner, TyKind::RawPtr(inner_ty, lower_mutability(mutability)))
- }
- TypeRef::Array(array) => {
- let inner_ty = self.lower_ty(array.ty);
- let const_len = self.lower_const(array.len, Ty::new_usize(interner));
- Ty::new_array_with_const_len(interner, inner_ty, const_len)
- }
- &TypeRef::Slice(inner) => {
- let inner_ty = self.lower_ty(inner);
- Ty::new_slice(interner, inner_ty)
- }
- TypeRef::Reference(ref_) => {
- let inner_ty = self.lower_ty(ref_.ty);
- // FIXME: It should infer the eldided lifetimes instead of stubbing with error
- let lifetime = ref_
- .lifetime
- .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr));
- Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability))
- }
- TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed),
- TypeRef::Fn(fn_) => {
- let substs = self.with_shifted_in(
- DebruijnIndex::from_u32(1),
- |ctx: &mut TyLoweringContext<'_, '_>| {
- Tys::new_from_iter(
- interner,
- fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)),
- )
- },
- );
- Ty::new_fn_ptr(
- interner,
- Binder::dummy(FnSig {
- abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
- safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
- c_variadic: fn_.is_varargs,
- inputs_and_output: substs,
- }),
- )
- }
- TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
- TypeRef::ImplTrait(bounds) => {
- match self.impl_trait_mode.mode {
- ImplTraitLoweringMode::Opaque => {
- let origin = match self.resolver.generic_def() {
- Some(GenericDefId::FunctionId(it)) => Either::Left(it),
- Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
- _ => panic!(
- "opaque impl trait lowering must be in function or type alias"
- ),
- };
-
- // this dance is to make sure the data is in the right
- // place even if we encounter more opaque types while
- // lowering the bounds
- let idx = self
- .impl_trait_mode
- .opaque_type_data
- .alloc(ImplTrait { predicates: Vec::default() });
-
- // FIXME(next-solver): this from_raw/into_raw dance isn't nice, but it's minimal
- let impl_trait_id = origin.either(
- |f| ImplTraitId::ReturnTypeImplTrait(f, Idx::from_raw(idx.into_raw())),
- |a| ImplTraitId::TypeAliasImplTrait(a, Idx::from_raw(idx.into_raw())),
- );
- let opaque_ty_id: SolverDefId =
- self.db.intern_impl_trait_id(impl_trait_id).into();
-
- // We don't want to lower the bounds inside the binders
- // we're currently in, because they don't end up inside
- // those binders. E.g. when we have `impl Trait<impl
- // OtherTrait<T>>`, the `impl OtherTrait<T>` can't refer
- // to the self parameter from `impl Trait`, and the
- // bounds aren't actually stored nested within each
- // other, but separately. So if the `T` refers to a type
- // parameter of the outer function, it's just one binder
- // away instead of two.
- let actual_opaque_type_data = self
- .with_debruijn(DebruijnIndex::ZERO, |ctx| {
- ctx.lower_impl_trait(opaque_ty_id, bounds, self.resolver.krate())
- });
- self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
-
- let args = GenericArgs::identity_for_item(self.interner, opaque_ty_id);
- Ty::new_alias(
- self.interner,
- AliasTyKind::Opaque,
- AliasTy::new_from_args(self.interner, opaque_ty_id, args),
- )
- }
- ImplTraitLoweringMode::Disallowed => {
- // FIXME: report error
- Ty::new_error(self.interner, ErrorGuaranteed)
- }
- }
- }
- TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed),
- };
- (ty, res)
- }
-
- /// This is only for `generic_predicates_for_param`, where we can't just
- /// lower the self types of the predicates since that could lead to cycles.
- /// So we just check here if the `type_ref` resolves to a generic param, and which.
- fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option<TypeOrConstParamId> {
- let type_ref = &self.store[type_ref];
- let path = match type_ref {
- TypeRef::Path(path) => path,
- &TypeRef::TypeParam(idx) => return Some(idx.into()),
- _ => return None,
- };
- if path.type_anchor().is_some() {
- return None;
- }
- if path.segments().len() > 1 {
- return None;
- }
- let resolution = match self.resolver.resolve_path_in_type_ns(self.db, path) {
- Some((it, None, _)) => it,
- _ => return None,
- };
- match resolution {
- TypeNs::GenericParam(param_id) => Some(param_id.into()),
- _ => None,
- }
- }
-
- #[inline]
- fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> {
- PathDiagnosticCallback {
- data: Either::Left(PathDiagnosticCallbackData(type_ref)),
- callback: |data, this, diag| {
- let type_ref = data.as_ref().left().unwrap().0;
- this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag))
- },
- }
- }
-
- #[inline]
- fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a, 'db> {
- PathLoweringContext::new(
- self,
- Self::on_path_diagnostic_callback(path_id.type_ref()),
- &self.store[path_id],
- )
- }
-
- pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty<'db>, Option<TypeNs>) {
- // Resolve the path (in type namespace)
- if let Some(type_ref) = path.type_anchor() {
- let (ty, res) = self.lower_ty_ext(type_ref);
- let mut ctx = self.at_path(path_id);
- return ctx.lower_ty_relative_path(ty, res, false);
- }
-
- let mut ctx = self.at_path(path_id);
- let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() {
- Some(it) => it,
- None => return (Ty::new_error(self.interner, ErrorGuaranteed), None),
- };
-
- if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
- // trait object type without dyn
- let bound = TypeBound::Path(path_id, TraitBoundModifier::None);
- let ty = self.lower_dyn_trait(&[bound]);
- return (ty, None);
- }
-
- ctx.lower_partly_resolved_path(resolution, false)
- }
-
- fn lower_trait_ref_from_path(
- &mut self,
- path_id: PathId,
- explicit_self_ty: Ty<'db>,
- ) -> Option<(TraitRef<'db>, PathLoweringContext<'_, 'a, 'db>)> {
- let mut ctx = self.at_path(path_id);
- let resolved = match ctx.resolve_path_in_type_ns_fully()? {
- // FIXME(trait_alias): We need to handle trait alias here.
- TypeNs::TraitId(tr) => tr,
- _ => return None,
- };
- Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx))
- }
-
- fn lower_trait_ref(
- &mut self,
- trait_ref: &HirTraitRef,
- explicit_self_ty: Ty<'db>,
- ) -> Option<TraitRef<'db>> {
- self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
- }
-
- pub(crate) fn lower_where_predicate<'b>(
- &'b mut self,
- where_predicate: &'b WherePredicate,
- ignore_bindings: bool,
- generics: &Generics,
- predicate_filter: PredicateFilter,
- ) -> impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'db> {
- match where_predicate {
- WherePredicate::ForLifetime { target, bound, .. }
- | WherePredicate::TypeBound { target, bound } => {
- if let PredicateFilter::SelfTrait = predicate_filter {
- let target_type = &self.store[*target];
- let self_type = 'is_self: {
- if let TypeRef::Path(path) = target_type
- && path.is_self_type()
- {
- break 'is_self true;
- }
- if let TypeRef::TypeParam(param) = target_type
- && generics[param.local_id()].is_trait_self()
- {
- break 'is_self true;
- }
- false
- };
- if !self_type {
- return Either::Left(Either::Left(iter::empty()));
- }
- }
- let self_ty = self.lower_ty(*target);
- Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings)))
- }
- &WherePredicate::Lifetime { bound, target } => {
- Either::Right(iter::once(Clause(Predicate::new(
- self.interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate(
- self.lower_lifetime(bound),
- self.lower_lifetime(target),
- )),
- )),
- ))))
- }
- }
- .into_iter()
- }
-
- pub(crate) fn lower_type_bound<'b>(
- &'b mut self,
- bound: &'b TypeBound,
- self_ty: Ty<'db>,
- ignore_bindings: bool,
- ) -> impl Iterator<Item = Clause<'db>> + use<'b, 'a, 'db> {
- let interner = self.interner;
- let mut assoc_bounds = None;
- let mut clause = None;
- match bound {
- &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
- // FIXME Don't silently drop the hrtb lifetimes here
- if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
- // FIXME(sized-hierarchy): Remove this bound modifications once we have implemented
- // sized-hierarchy correctly.
- let meta_sized = LangItem::MetaSized
- .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
- let pointee_sized = LangItem::PointeeSized
- .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
- if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) {
- // Ignore this bound
- } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) {
- // Regard this as `?Sized` bound
- ctx.ty_ctx().unsized_types.insert(self_ty);
- } else {
- if !ignore_bindings {
- assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref);
- }
- clause = Some(Clause(Predicate::new(
- interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Trait(TraitPredicate {
- trait_ref,
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- }),
- )),
- )));
- }
- }
- }
- &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
- let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate());
- // Don't lower associated type bindings as the only possible relaxed trait bound
- // `?Sized` has no of them.
- // If we got another trait here ignore the bound completely.
- let trait_id = self
- .lower_trait_ref_from_path(path, self_ty)
- .map(|(trait_ref, _)| trait_ref.def_id.0);
- if trait_id == sized_trait {
- self.unsized_types.insert(self_ty);
- }
- }
- &TypeBound::Lifetime(l) => {
- let lifetime = self.lower_lifetime(l);
- clause = Some(Clause(Predicate::new(
- self.interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate(
- self_ty, lifetime,
- )),
- )),
- )));
- }
- TypeBound::Use(_) | TypeBound::Error => {}
- }
- clause.into_iter().chain(assoc_bounds.into_iter().flatten())
- }
-
- fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> {
- let interner = self.interner;
- // FIXME: we should never create non-existential predicates in the first place
- // For now, use an error type so we don't run into dummy binder issues
- let self_ty = Ty::new_error(interner, ErrorGuaranteed);
- // INVARIANT: The principal trait bound, if present, must come first. Others may be in any
- // order but should be in the same order for the same set but possibly different order of
- // bounds in the input.
- // INVARIANT: If this function returns `DynTy`, there should be at least one trait bound.
- // These invariants are utilized by `TyExt::dyn_trait()` and chalk.
- let mut lifetime = None;
- let bounds = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
- let mut lowered_bounds: Vec<
- rustc_type_ir::Binder<DbInterner<'db>, ExistentialPredicate<DbInterner<'db>>>,
- > = Vec::new();
- for b in bounds {
- let db = ctx.db;
- ctx.lower_type_bound(b, self_ty, false).for_each(|b| {
- if let Some(bound) = b
- .kind()
- .map_bound(|c| match c {
- rustc_type_ir::ClauseKind::Trait(t) => {
- let id = t.def_id();
- let is_auto =
- db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
- if is_auto {
- Some(ExistentialPredicate::AutoTrait(t.def_id()))
- } else {
- Some(ExistentialPredicate::Trait(
- ExistentialTraitRef::new_from_args(
- interner,
- t.def_id(),
- GenericArgs::new_from_iter(
- interner,
- t.trait_ref.args.iter().skip(1),
- ),
- ),
- ))
- }
- }
- rustc_type_ir::ClauseKind::Projection(p) => {
- Some(ExistentialPredicate::Projection(
- ExistentialProjection::new_from_args(
- interner,
- p.def_id(),
- GenericArgs::new_from_iter(
- interner,
- p.projection_term.args.iter().skip(1),
- ),
- p.term,
- ),
- ))
- }
- rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => {
- lifetime = Some(outlives_predicate.1);
- None
- }
- rustc_type_ir::ClauseKind::RegionOutlives(_)
- | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
- | rustc_type_ir::ClauseKind::WellFormed(_)
- | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
- | rustc_type_ir::ClauseKind::HostEffect(_)
- | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
- })
- .transpose()
- {
- lowered_bounds.push(bound);
- }
- })
- }
-
- let mut multiple_regular_traits = false;
- let mut multiple_same_projection = false;
- lowered_bounds.sort_unstable_by(|lhs, rhs| {
- use std::cmp::Ordering;
- match ((*lhs).skip_binder(), (*rhs).skip_binder()) {
- (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => {
- multiple_regular_traits = true;
- // Order doesn't matter - we error
- Ordering::Equal
- }
- (
- ExistentialPredicate::AutoTrait(lhs_id),
- ExistentialPredicate::AutoTrait(rhs_id),
- ) => lhs_id.0.cmp(&rhs_id.0),
- (ExistentialPredicate::Trait(_), _) => Ordering::Less,
- (_, ExistentialPredicate::Trait(_)) => Ordering::Greater,
- (ExistentialPredicate::AutoTrait(_), _) => Ordering::Less,
- (_, ExistentialPredicate::AutoTrait(_)) => Ordering::Greater,
- (
- ExistentialPredicate::Projection(lhs),
- ExistentialPredicate::Projection(rhs),
- ) => {
- let lhs_id = match lhs.def_id {
- SolverDefId::TypeAliasId(id) => id,
- _ => unreachable!(),
- };
- let rhs_id = match rhs.def_id {
- SolverDefId::TypeAliasId(id) => id,
- _ => unreachable!(),
- };
- // We only compare the `associated_ty_id`s. We shouldn't have
- // multiple bounds for an associated type in the correct Rust code,
- // and if we do, we error out.
- if lhs_id == rhs_id {
- multiple_same_projection = true;
- }
- lhs_id.as_id().index().cmp(&rhs_id.as_id().index())
- }
- }
- });
-
- if multiple_regular_traits || multiple_same_projection {
- return None;
- }
-
- if !lowered_bounds.first().map_or(false, |b| {
- matches!(
- b.as_ref().skip_binder(),
- ExistentialPredicate::Trait(_) | ExistentialPredicate::AutoTrait(_)
- )
- }) {
- return None;
- }
-
- // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the
- // bounds. We shouldn't have repeated elements besides auto traits at this point.
- lowered_bounds.dedup();
-
- Some(BoundExistentialPredicates::new_from_iter(interner, lowered_bounds))
- });
-
- if let Some(bounds) = bounds {
- let region = match lifetime {
- Some(it) => match it.kind() {
- rustc_type_ir::RegionKind::ReBound(db, var) => Region::new_bound(
- self.interner,
- db.shifted_out_to_binder(DebruijnIndex::from_u32(2)),
- var,
- ),
- _ => it,
- },
- None => Region::new_static(self.interner),
- };
- Ty::new_dynamic(self.interner, bounds, region)
- } else {
- // FIXME: report error
- // (additional non-auto traits, associated type rebound, or no resolved trait)
- Ty::new_error(self.interner, ErrorGuaranteed)
- }
- }
-
- fn lower_impl_trait(
- &mut self,
- def_id: SolverDefId,
- bounds: &[TypeBound],
- krate: Crate,
- ) -> ImplTrait<'db> {
- let interner = self.interner;
- cov_mark::hit!(lower_rpit);
- let args = GenericArgs::identity_for_item(interner, def_id);
- let self_ty = Ty::new_alias(
- self.interner,
- rustc_type_ir::AliasTyKind::Opaque,
- AliasTy::new_from_args(interner, def_id, args),
- );
- let predicates = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
- let mut predicates = Vec::new();
- for b in bounds {
- predicates.extend(ctx.lower_type_bound(b, self_ty, false));
- }
-
- if !ctx.unsized_types.contains(&self_ty) {
- let sized_trait = LangItem::Sized.resolve_trait(self.db, krate);
- let sized_clause = sized_trait.map(|trait_id| {
- let trait_ref = TraitRef::new_from_args(
- interner,
- trait_id.into(),
- GenericArgs::new_from_iter(interner, [self_ty.into()]),
- );
- Clause(Predicate::new(
- interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Trait(TraitPredicate {
- trait_ref,
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- }),
- )),
- ))
- });
- predicates.extend(sized_clause);
- }
- predicates.shrink_to_fit();
- predicates
- });
- ImplTrait { predicates }
- }
-
- pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> {
- match self.resolver.resolve_lifetime(&self.store[lifetime]) {
- Some(resolution) => match resolution {
- LifetimeNs::Static => Region::new_static(self.interner),
- LifetimeNs::LifetimeParam(id) => {
- let idx = match self.generics().lifetime_idx(id) {
- None => return Region::error(self.interner),
- Some(idx) => idx,
- };
- self.region_param(id, idx as u32)
- }
- },
- None => Region::error(self.interner),
- }
- }
-}
-
-pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
- match m {
- hir_def::type_ref::Mutability::Shared => Mutability::Not,
- hir_def::type_ref::Mutability::Mut => Mutability::Mut,
- }
-}
-
-fn unknown_const(_ty: Ty<'_>) -> Const<'_> {
- Const::new(DbInterner::conjure(), ConstKind::Error(ErrorGuaranteed))
-}
-
-pub(crate) fn impl_trait_query<'db>(
- db: &'db dyn HirDatabase,
- impl_id: ImplId,
-) -> Option<EarlyBinder<'db, TraitRef<'db>>> {
- db.impl_trait_with_diagnostics(impl_id).map(|it| it.0)
-}
-
-pub(crate) fn impl_trait_with_diagnostics_query<'db>(
- db: &'db dyn HirDatabase,
- impl_id: ImplId,
-) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)> {
- let impl_data = db.impl_signature(impl_id);
- let resolver = impl_id.resolver(db);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &impl_data.store,
- impl_id.into(),
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
- );
- let self_ty = db.impl_self_ty(impl_id).skip_binder();
- let target_trait = impl_data.target_trait.as_ref()?;
- let trait_ref = EarlyBinder::bind(ctx.lower_trait_ref(target_trait, self_ty)?);
- Some((trait_ref, create_diagnostics(ctx.diagnostics)))
-}
-
-pub(crate) fn return_type_impl_traits<'db>(
- db: &'db dyn HirDatabase,
- def: hir_def::FunctionId,
-) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>> {
- // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
- let data = db.function_signature(def);
- let resolver = def.resolver(db);
- let mut ctx_ret =
- TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer)
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
- if let Some(ret_type) = data.ret_type {
- let _ret = ctx_ret.lower_ty(ret_type);
- }
- let 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 {
- Some(Arc::new(EarlyBinder::bind(return_type_impl_traits)))
- }
-}
-
-pub(crate) fn type_alias_impl_traits<'db>(
- db: &'db dyn HirDatabase,
- def: hir_def::TypeAliasId,
-) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>> {
- let data = db.type_alias_signature(def);
- let resolver = def.resolver(db);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &data.store,
- def.into(),
- LifetimeElisionKind::AnonymousReportError,
- )
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
- if let Some(type_ref) = data.ty {
- let _ty = ctx.lower_ty(type_ref);
- }
- let 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 {
- Some(Arc::new(EarlyBinder::bind(type_alias_impl_traits)))
- }
-}
-
-/// Build the declared type of an item. This depends on the namespace; e.g. for
-/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
-/// the constructor function `(usize) -> Foo` which lives in the values
-/// namespace.
-pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> {
- let interner = DbInterner::new_with(db, None, None);
- match def {
- TyDefId::BuiltinType(it) => EarlyBinder::bind(Ty::from_builtin_type(interner, it)),
- TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt(
- interner,
- it,
- GenericArgs::identity_for_item(interner, it.into()),
- )),
- TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0,
- }
-}
-
-/// Build the declared type of a function. This should not need to look at the
-/// function body.
-fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> {
- let interner = DbInterner::new_with(db, None, None);
- EarlyBinder::bind(Ty::new_fn_def(
- interner,
- CallableDefId::FunctionId(def).into(),
- GenericArgs::identity_for_item(interner, def.into()),
- ))
-}
-
-/// Build the declared type of a const.
-fn type_for_const<'db>(db: &'db dyn HirDatabase, def: ConstId) -> EarlyBinder<'db, Ty<'db>> {
- let resolver = def.resolver(db);
- let data = db.const_signature(def);
- let parent = def.loc(db).container;
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &data.store,
- def.into(),
- LifetimeElisionKind::AnonymousReportError,
- );
- ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent));
- EarlyBinder::bind(ctx.lower_ty(data.type_ref))
-}
-
-/// Build the declared type of a static.
-fn type_for_static<'db>(db: &'db dyn HirDatabase, def: StaticId) -> EarlyBinder<'db, Ty<'db>> {
- let resolver = def.resolver(db);
- let data = db.static_signature(def);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &data.store,
- def.into(),
- LifetimeElisionKind::AnonymousReportError,
- );
- ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner)));
- EarlyBinder::bind(ctx.lower_ty(data.type_ref))
-}
-
-/// Build the type of a tuple struct constructor.
-fn type_for_struct_constructor<'db>(
- db: &'db dyn HirDatabase,
- def: StructId,
-) -> Option<EarlyBinder<'db, Ty<'db>>> {
- let struct_data = def.fields(db);
- match struct_data.shape {
- FieldsShape::Record => None,
- FieldsShape::Unit => Some(type_for_adt(db, def.into())),
- FieldsShape::Tuple => {
- let interner = DbInterner::new_with(db, None, None);
- Some(EarlyBinder::bind(Ty::new_fn_def(
- interner,
- CallableDefId::StructId(def).into(),
- GenericArgs::identity_for_item(interner, def.into()),
- )))
- }
- }
-}
-
-/// Build the type of a tuple enum variant constructor.
-fn type_for_enum_variant_constructor<'db>(
- db: &'db dyn HirDatabase,
- def: EnumVariantId,
-) -> Option<EarlyBinder<'db, Ty<'db>>> {
- let struct_data = def.fields(db);
- match struct_data.shape {
- FieldsShape::Record => None,
- FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())),
- FieldsShape::Tuple => {
- let interner = DbInterner::new_with(db, None, None);
- Some(EarlyBinder::bind(Ty::new_fn_def(
- interner,
- CallableDefId::EnumVariantId(def).into(),
- GenericArgs::identity_for_item(interner, def.loc(db).parent.into()),
- )))
- }
- }
-}
-
-pub(crate) fn value_ty_query<'db>(
- db: &'db dyn HirDatabase,
- def: ValueTyDefId,
-) -> Option<EarlyBinder<'db, Ty<'db>>> {
- match def {
- ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
- ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
- ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
- ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
- ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
- ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
- }
-}
-
-pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>(
- db: &'db dyn HirDatabase,
- t: TypeAliasId,
-) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
- let type_alias_data = db.type_alias_signature(t);
- let mut diags = None;
- let resolver = t.resolver(db);
- let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
- let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
- EarlyBinder::bind(Ty::new_foreign(interner, t.into()))
- } else {
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &type_alias_data.store,
- t.into(),
- LifetimeElisionKind::AnonymousReportError,
- )
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
- let res = EarlyBinder::bind(
- type_alias_data
- .ty
- .map(|type_ref| ctx.lower_ty(type_ref))
- .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)),
- );
- diags = create_diagnostics(ctx.diagnostics);
- res
- };
- (inner, diags)
-}
-
-pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>(
- db: &'db dyn HirDatabase,
- _adt: TypeAliasId,
-) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
- (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None)
-}
-
-pub(crate) fn impl_self_ty_query<'db>(
- db: &'db dyn HirDatabase,
- impl_id: ImplId,
-) -> EarlyBinder<'db, Ty<'db>> {
- db.impl_self_ty_with_diagnostics(impl_id).0
-}
-
-pub(crate) fn impl_self_ty_with_diagnostics_query<'db>(
- db: &'db dyn HirDatabase,
- impl_id: ImplId,
-) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
- let resolver = impl_id.resolver(db);
-
- let impl_data = db.impl_signature(impl_id);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &impl_data.store,
- impl_id.into(),
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
- );
- let ty = ctx.lower_ty(impl_data.self_ty);
- assert!(!ty.has_escaping_bound_vars());
- (EarlyBinder::bind(ty), create_diagnostics(ctx.diagnostics))
-}
-
-pub(crate) fn impl_self_ty_with_diagnostics_cycle_result(
- db: &dyn HirDatabase,
- _impl_id: ImplId,
-) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) {
- (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None)
-}
-
-pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> {
- db.const_param_ty_with_diagnostics(def).0
-}
-
-// returns None if def is a type arg
-pub(crate) fn const_param_ty_with_diagnostics_query<'db>(
- db: &'db dyn HirDatabase,
- def: ConstParamId,
-) -> (Ty<'db>, Diagnostics) {
- let (parent_data, store) = db.generic_params_and_store(def.parent());
- let data = &parent_data[def.local_id()];
- let resolver = def.parent().resolver(db);
- let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &store,
- def.parent(),
- LifetimeElisionKind::AnonymousReportError,
- );
- let ty = match data {
- TypeOrConstParamData::TypeParamData(_) => {
- never!();
- Ty::new_error(interner, ErrorGuaranteed)
- }
- TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
- };
- (ty, create_diagnostics(ctx.diagnostics))
-}
-
-pub(crate) fn const_param_ty_with_diagnostics_cycle_result<'db>(
- db: &'db dyn HirDatabase,
- _: crate::db::HirDatabaseData,
- def: ConstParamId,
-) -> (Ty<'db>, Diagnostics) {
- let resolver = def.parent().resolver(db);
- let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
- (Ty::new_error(interner, ErrorGuaranteed), None)
-}
-
-pub(crate) fn field_types_query<'db>(
- db: &'db dyn HirDatabase,
- variant_id: VariantId,
-) -> Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>> {
- db.field_types_with_diagnostics(variant_id).0
-}
-
-/// Build the type of all specific fields of a struct or enum variant.
-pub(crate) fn field_types_with_diagnostics_query<'db>(
- db: &'db dyn HirDatabase,
- variant_id: VariantId,
-) -> (Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>>, Diagnostics) {
- let var_data = variant_id.fields(db);
- let fields = var_data.fields();
- if fields.is_empty() {
- return (Arc::new(ArenaMap::default()), None);
- }
-
- let (resolver, def): (_, GenericDefId) = match variant_id {
- VariantId::StructId(it) => (it.resolver(db), it.into()),
- VariantId::UnionId(it) => (it.resolver(db), it.into()),
- VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()),
- };
- let mut res = ArenaMap::default();
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &var_data.store,
- def,
- LifetimeElisionKind::AnonymousReportError,
- );
- for (field_id, field_data) in var_data.fields().iter() {
- res.insert(field_id, EarlyBinder::bind(ctx.lower_ty(field_data.type_ref)));
- }
- (Arc::new(res), create_diagnostics(ctx.diagnostics))
-}
-
-/// This query exists only to be used when resolving short-hand associated types
-/// like `T::Item`.
-///
-/// See the analogous query in rustc and its comment:
-/// <https://github.com/rust-lang/rust/blob/9150f844e2624eb013ec78ca08c1d416e6644026/src/librustc_typeck/astconv.rs#L46>
-/// This is a query mostly to handle cycles somewhat gracefully; e.g. the
-/// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but
-/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
-#[tracing::instrument(skip(db), ret)]
-pub(crate) fn generic_predicates_for_param_query<'db>(
- db: &'db dyn HirDatabase,
- def: GenericDefId,
- param_id: TypeOrConstParamId,
- assoc_name: Option<Name>,
-) -> GenericPredicates<'db> {
- let generics = generics(db, def);
- let interner = DbInterner::new_with(db, None, None);
- let resolver = def.resolver(db);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- generics.store(),
- def,
- LifetimeElisionKind::AnonymousReportError,
- );
-
- // we have to filter out all other predicates *first*, before attempting to lower them
- let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred {
- WherePredicate::ForLifetime { target, bound, .. }
- | WherePredicate::TypeBound { target, bound, .. } => {
- let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
- if invalid_target {
- // FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented
- // sized-hierarchy correctly.
- // If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into
- // `ctx.unsized_types`
- let lower = || -> bool {
- match bound {
- TypeBound::Path(_, TraitBoundModifier::Maybe) => true,
- TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
- let TypeRef::Path(path) = &ctx.store[path.type_ref()] else {
- return false;
- };
- let Some(pointee_sized) =
- LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate())
- else {
- return false;
- };
- // Lower the path directly with `Resolver` instead of PathLoweringContext`
- // to prevent diagnostics duplications.
- ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and(
- |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized),
- )
- }
- _ => false,
- }
- }();
- if lower {
- ctx.lower_where_predicate(pred, true, &generics, PredicateFilter::All)
- .for_each(drop);
- }
- return false;
- }
-
- match bound {
- &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => {
- // Only lower the bound if the trait could possibly define the associated
- // type we're looking for.
- let path = &ctx.store[path];
-
- let Some(assoc_name) = &assoc_name else { return true };
- let Some(TypeNs::TraitId(tr)) =
- resolver.resolve_path_in_type_ns_fully(db, path)
- else {
- return false;
- };
-
- rustc_type_ir::elaborate::supertrait_def_ids(interner, tr.into()).any(|tr| {
- tr.0.trait_items(db).items.iter().any(|(name, item)| {
- matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
- })
- })
- }
- TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false,
- }
- }
- WherePredicate::Lifetime { .. } => false,
- };
- let mut predicates = Vec::new();
- for maybe_parent_generics in
- std::iter::successors(Some(&generics), |generics| generics.parent_generics())
- {
- ctx.store = maybe_parent_generics.store();
- for pred in maybe_parent_generics.where_predicates() {
- if predicate(pred, &mut ctx) {
- predicates.extend(ctx.lower_where_predicate(
- pred,
- true,
- maybe_parent_generics,
- PredicateFilter::All,
- ));
- }
- }
- }
-
- let args = GenericArgs::identity_for_item(interner, def.into());
- if !args.is_empty() {
- let explicitly_unsized_tys = ctx.unsized_types;
- if let Some(implicitly_sized_predicates) =
- implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &args, &resolver)
- {
- predicates.extend(implicitly_sized_predicates);
- };
- }
- GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
-}
-
-pub(crate) fn generic_predicates_for_param_cycle_result(
- _db: &dyn HirDatabase,
- _def: GenericDefId,
- _param_id: TypeOrConstParamId,
- _assoc_name: Option<Name>,
-) -> GenericPredicates<'_> {
- GenericPredicates(None)
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct GenericPredicates<'db>(Option<Arc<[Clause<'db>]>>);
-
-impl<'db> GenericPredicates<'db> {
- #[inline]
- pub fn instantiate(
- &self,
- interner: DbInterner<'db>,
- args: GenericArgs<'db>,
- ) -> Option<impl Iterator<Item = Clause<'db>>> {
- self.0
- .as_ref()
- .map(|it| EarlyBinder::bind(it.iter().copied()).iter_instantiated(interner, args))
- }
-
- #[inline]
- pub fn instantiate_identity(&self) -> Option<impl Iterator<Item = Clause<'db>>> {
- self.0.as_ref().map(|it| it.iter().copied())
- }
-}
-
-impl<'db> ops::Deref for GenericPredicates<'db> {
- type Target = [Clause<'db>];
-
- fn deref(&self) -> &Self::Target {
- self.0.as_deref().unwrap_or(&[])
- }
-}
-
-pub(crate) fn trait_environment_for_body_query(
- db: &dyn HirDatabase,
- def: DefWithBodyId,
-) -> Arc<TraitEnvironment<'_>> {
- let Some(def) = def.as_generic_def_id(db) else {
- let krate = def.module(db).krate();
- return TraitEnvironment::empty(krate);
- };
- db.trait_environment(def)
-}
-
-pub(crate) fn trait_environment_query<'db>(
- db: &'db dyn HirDatabase,
- def: GenericDefId,
-) -> Arc<TraitEnvironment<'db>> {
- let generics = generics(db, def);
- if generics.has_no_predicates() && generics.is_empty() {
- return TraitEnvironment::empty(def.krate(db));
- }
-
- let resolver = def.resolver(db);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- generics.store(),
- def,
- LifetimeElisionKind::AnonymousReportError,
- );
- let mut traits_in_scope = Vec::new();
- let mut clauses = Vec::new();
- for maybe_parent_generics in
- std::iter::successors(Some(&generics), |generics| generics.parent_generics())
- {
- ctx.store = maybe_parent_generics.store();
- for pred in maybe_parent_generics.where_predicates() {
- for pred in ctx.lower_where_predicate(pred, false, &generics, PredicateFilter::All) {
- if let rustc_type_ir::ClauseKind::Trait(tr) = pred.kind().skip_binder() {
- traits_in_scope.push((tr.self_ty(), tr.def_id().0));
- }
- clauses.push(pred);
- }
- }
- }
-
- if let Some(trait_id) = def.assoc_trait_container(db) {
- // add `Self: Trait<T1, T2, ...>` to the environment in trait
- // function default implementations (and speculative code
- // inside consts or type aliases)
- cov_mark::hit!(trait_self_implements_self);
- let trait_ref = TraitRef::identity(ctx.interner, trait_id.into());
- let clause = Clause(Predicate::new(
- ctx.interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait(
- TraitPredicate { trait_ref, polarity: rustc_type_ir::PredicatePolarity::Positive },
- ))),
- ));
- clauses.push(clause);
- }
-
- let explicitly_unsized_tys = ctx.unsized_types;
-
- let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate());
- if let Some(sized_trait) = sized_trait {
- let (mut generics, mut def_id) =
- (crate::next_solver::generics::generics(db, def.into()), def);
- loop {
- let self_idx = trait_self_param_idx(db, def_id);
- for (idx, p) in generics.own_params.iter().enumerate() {
- if let Some(self_idx) = self_idx
- && p.index() as usize == self_idx
- {
- continue;
- }
- let GenericParamId::TypeParamId(param_id) = p.id else {
- continue;
- };
- let idx = idx as u32 + generics.parent_count as u32;
- let param_ty = Ty::new_param(ctx.interner, param_id, idx);
- if explicitly_unsized_tys.contains(&param_ty) {
- continue;
- }
- let trait_ref = TraitRef::new_from_args(
- ctx.interner,
- sized_trait.into(),
- GenericArgs::new_from_iter(ctx.interner, [param_ty.into()]),
- );
- let clause = Clause(Predicate::new(
- ctx.interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Trait(TraitPredicate {
- trait_ref,
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- }),
- )),
- ));
- clauses.push(clause);
- }
-
- if let Some(g) = generics.parent {
- generics = crate::next_solver::generics::generics(db, g.into());
- def_id = g;
- } else {
- break;
- }
- }
- }
-
- let clauses = rustc_type_ir::elaborate::elaborate(ctx.interner, clauses);
- let clauses = Clauses::new_from_iter(ctx.interner, clauses);
- let env = ParamEnv { clauses };
-
- TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env)
-}
-
-#[derive(Copy, Clone, Debug)]
-pub(crate) enum PredicateFilter {
- SelfTrait,
- All,
-}
-
-/// Resolve the where clause(s) of an item with generics.
-#[tracing::instrument(skip(db))]
-pub(crate) fn generic_predicates_query<'db>(
- db: &'db dyn HirDatabase,
- def: GenericDefId,
-) -> GenericPredicates<'db> {
- generic_predicates_filtered_by(db, def, PredicateFilter::All, |_| true).0
-}
-
-pub(crate) fn generic_predicates_without_parent_query<'db>(
- db: &'db dyn HirDatabase,
- def: GenericDefId,
-) -> GenericPredicates<'db> {
- generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def).0
-}
-
-/// Resolve the where clause(s) of an item with generics,
-/// except the ones inherited from the parent
-pub(crate) fn generic_predicates_without_parent_with_diagnostics_query<'db>(
- db: &'db dyn HirDatabase,
- def: GenericDefId,
-) -> (GenericPredicates<'db>, Diagnostics) {
- generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def)
-}
-
-/// Resolve the where clause(s) of an item with generics,
-/// with a given filter
-#[tracing::instrument(skip(db, filter), ret)]
-pub(crate) fn generic_predicates_filtered_by<'db, F>(
- db: &'db dyn HirDatabase,
- def: GenericDefId,
- predicate_filter: PredicateFilter,
- filter: F,
-) -> (GenericPredicates<'db>, Diagnostics)
-where
- F: Fn(GenericDefId) -> bool,
-{
- let generics = generics(db, def);
- let resolver = def.resolver(db);
- let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- generics.store(),
- def,
- LifetimeElisionKind::AnonymousReportError,
- );
-
- let mut predicates = Vec::new();
- for maybe_parent_generics in
- std::iter::successors(Some(&generics), |generics| generics.parent_generics())
- {
- ctx.store = maybe_parent_generics.store();
- for pred in maybe_parent_generics.where_predicates() {
- tracing::debug!(?pred);
- if filter(maybe_parent_generics.def()) {
- predicates.extend(ctx.lower_where_predicate(
- pred,
- false,
- maybe_parent_generics,
- predicate_filter,
- ));
- }
- }
- }
-
- let explicitly_unsized_tys = ctx.unsized_types;
-
- let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate());
- if let Some(sized_trait) = sized_trait {
- let mut add_sized_clause = |param_idx, param_id, param_data| {
- let (
- GenericParamId::TypeParamId(param_id),
- GenericParamDataRef::TypeParamData(param_data),
- ) = (param_id, param_data)
- else {
- return;
- };
-
- if param_data.provenance == TypeParamProvenance::TraitSelf {
- return;
- }
-
- let param_ty = Ty::new_param(interner, param_id, param_idx);
- if explicitly_unsized_tys.contains(&param_ty) {
- return;
- }
- let trait_ref = TraitRef::new_from_args(
- interner,
- sized_trait.into(),
- GenericArgs::new_from_iter(interner, [param_ty.into()]),
- );
- let clause = Clause(Predicate::new(
- interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Trait(TraitPredicate {
- trait_ref,
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- }),
- )),
- ));
- predicates.push(clause);
- };
- if generics.parent_generics().is_some_and(|parent| filter(parent.def())) {
- generics.iter_parent().enumerate().for_each(|(param_idx, (param_id, param_data))| {
- add_sized_clause(param_idx as u32, param_id, param_data);
- });
- }
- if filter(def) {
- let parent_params_len = generics.len_parent();
- generics.iter_self().enumerate().for_each(|(param_idx, (param_id, param_data))| {
- add_sized_clause((param_idx + parent_params_len) as u32, param_id, param_data);
- });
- }
- }
-
- // FIXME: rustc gathers more predicates by recursing through resulting trait predicates.
- // See https://github.com/rust-lang/rust/blob/76c5ed2847cdb26ef2822a3a165d710f6b772217/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L689-L715
-
- (
- GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
- create_diagnostics(ctx.diagnostics),
- )
-}
-
-/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
-/// Exception is Self of a trait def.
-fn implicitly_sized_clauses<'a, 'subst, 'db>(
- db: &'db dyn HirDatabase,
- def: GenericDefId,
- explicitly_unsized_tys: &'a FxHashSet<Ty<'db>>,
- args: &'subst GenericArgs<'db>,
- resolver: &Resolver<'db>,
-) -> Option<impl Iterator<Item = Clause<'db>> + Captures<'a> + Captures<'subst>> {
- let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
- let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?;
-
- let trait_self_idx = trait_self_param_idx(db, def);
-
- Some(
- args.iter()
- .enumerate()
- .filter_map(
- move |(idx, generic_arg)| {
- if Some(idx) == trait_self_idx { None } else { Some(generic_arg) }
- },
- )
- .filter_map(|generic_arg| generic_arg.as_type())
- .filter(move |self_ty| !explicitly_unsized_tys.contains(self_ty))
- .map(move |self_ty| {
- let trait_ref = TraitRef::new_from_args(
- interner,
- sized_trait.into(),
- GenericArgs::new_from_iter(interner, [self_ty.into()]),
- );
- Clause(Predicate::new(
- interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Trait(TraitPredicate {
- trait_ref,
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- }),
- )),
- ))
- }),
- )
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct GenericDefaults<'db>(Option<Arc<[Option<EarlyBinder<'db, GenericArg<'db>>>]>>);
-
-impl<'db> GenericDefaults<'db> {
- #[inline]
- pub fn get(&self, idx: usize) -> Option<EarlyBinder<'db, GenericArg<'db>>> {
- self.0.as_ref()?[idx]
- }
-}
-
-pub(crate) fn generic_defaults_query(
- db: &dyn HirDatabase,
- def: GenericDefId,
-) -> GenericDefaults<'_> {
- db.generic_defaults_ns_with_diagnostics(def).0
-}
-
-/// Resolve the default type params from generics.
-///
-/// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents).
-pub(crate) fn generic_defaults_with_diagnostics_query(
- db: &dyn HirDatabase,
- def: GenericDefId,
-) -> (GenericDefaults<'_>, Diagnostics) {
- let generic_params = generics(db, def);
- if generic_params.is_empty() {
- return (GenericDefaults(None), None);
- }
- let resolver = def.resolver(db);
-
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- generic_params.store(),
- def,
- LifetimeElisionKind::AnonymousReportError,
- )
- .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed);
- let mut idx = 0;
- let mut has_any_default = false;
- let mut defaults = generic_params
- .iter_parents_with_store()
- .map(|((_id, p), store)| {
- ctx.store = store;
- let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
- has_any_default |= has_default;
- idx += 1;
- result
- })
- .collect::<Vec<_>>();
- ctx.diagnostics.clear(); // Don't include diagnostics from the parent.
- defaults.extend(generic_params.iter_self().map(|(_id, p)| {
- let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
- has_any_default |= has_default;
- idx += 1;
- result
- }));
- let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
- let defaults = if has_any_default {
- GenericDefaults(Some(Arc::from_iter(defaults)))
- } else {
- GenericDefaults(None)
- };
- return (defaults, diagnostics);
-
- fn handle_generic_param<'db>(
- ctx: &mut TyLoweringContext<'db, '_>,
- idx: usize,
- p: GenericParamDataRef<'_>,
- ) -> (Option<EarlyBinder<'db, GenericArg<'db>>>, bool) {
- ctx.lowering_param_default(idx as u32);
- match p {
- GenericParamDataRef::TypeParamData(p) => {
- let ty = p.default.map(|ty| ctx.lower_ty(ty));
- (ty.map(|ty| EarlyBinder::bind(ty.into())), p.default.is_some())
- }
- GenericParamDataRef::ConstParamData(p) => {
- let val = p.default.map(|c| {
- let param_ty = ctx.lower_ty(p.ty);
- let c = ctx.lower_const(c, param_ty);
- c.into()
- });
- (val.map(EarlyBinder::bind), p.default.is_some())
- }
- GenericParamDataRef::LifetimeParamData(_) => (None, false),
- }
- }
-}
-
-pub(crate) fn generic_defaults_with_diagnostics_cycle_result(
- _db: &dyn HirDatabase,
- _def: GenericDefId,
-) -> (GenericDefaults<'_>, Diagnostics) {
- (GenericDefaults(None), None)
-}
-
-/// Build the signature of a callable item (function, struct or enum variant).
-pub(crate) fn callable_item_signature_query<'db>(
- db: &'db dyn HirDatabase,
- def: CallableDefId,
-) -> EarlyBinder<'db, PolyFnSig<'db>> {
- match def {
- CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
- CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
- CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
- }
-}
-
-fn fn_sig_for_fn<'db>(
- db: &'db dyn HirDatabase,
- def: FunctionId,
-) -> EarlyBinder<'db, PolyFnSig<'db>> {
- let data = db.function_signature(def);
- let resolver = def.resolver(db);
- let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
- let mut ctx_params = TyLoweringContext::new(
- db,
- &resolver,
- &data.store,
- def.into(),
- LifetimeElisionKind::for_fn_params(&data),
- );
- let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
-
- let ret = match data.ret_type {
- Some(ret_type) => {
- let mut ctx_ret = TyLoweringContext::new(
- db,
- &resolver,
- &data.store,
- def.into(),
- LifetimeElisionKind::for_fn_ret(interner),
- )
- .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
- ctx_ret.lower_ty(ret_type)
- }
- None => Ty::new_tup(interner, &[]),
- };
-
- let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret)));
- // If/when we track late bound vars, we need to switch this to not be `dummy`
- EarlyBinder::bind(rustc_type_ir::Binder::dummy(FnSig {
- abi: data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
- c_variadic: data.is_varargs(),
- safety: if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
- inputs_and_output,
- }))
-}
-
-fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> {
- let interner = DbInterner::new_with(db, None, None);
- let args = GenericArgs::identity_for_item(interner, adt.into());
- let ty = Ty::new_adt(interner, adt, args);
- EarlyBinder::bind(ty)
-}
-
-fn fn_sig_for_struct_constructor<'db>(
- db: &'db dyn HirDatabase,
- def: StructId,
-) -> EarlyBinder<'db, PolyFnSig<'db>> {
- let field_tys = db.field_types_ns(def.into());
- let params = field_tys.iter().map(|(_, ty)| ty.skip_binder());
- let ret = type_for_adt(db, def.into()).skip_binder();
-
- let inputs_and_output =
- Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret)));
- EarlyBinder::bind(Binder::dummy(FnSig {
- abi: FnAbi::RustCall,
- c_variadic: false,
- safety: Safety::Safe,
- inputs_and_output,
- }))
-}
-
-fn fn_sig_for_enum_variant_constructor<'db>(
- db: &'db dyn HirDatabase,
- def: EnumVariantId,
-) -> EarlyBinder<'db, PolyFnSig<'db>> {
- let field_tys = db.field_types_ns(def.into());
- let params = field_tys.iter().map(|(_, ty)| 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_with(db, None, None), params.chain(Some(ret)));
- EarlyBinder::bind(Binder::dummy(FnSig {
- abi: FnAbi::RustCall,
- c_variadic: false,
- safety: Safety::Safe,
- inputs_and_output,
- }))
-}
-
-// FIXME(next-solver): should merge this with `explicit_item_bounds` in some way
-pub(crate) fn associated_ty_item_bounds<'db>(
- db: &'db dyn HirDatabase,
- type_alias: TypeAliasId,
-) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> {
- let type_alias_data = db.type_alias_signature(type_alias);
- let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
- let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
- let mut ctx = TyLoweringContext::new(
- db,
- &resolver,
- &type_alias_data.store,
- type_alias.into(),
- LifetimeElisionKind::AnonymousReportError,
- );
- // FIXME: we should never create non-existential predicates in the first place
- // For now, use an error type so we don't run into dummy binder issues
- let self_ty = Ty::new_error(interner, ErrorGuaranteed);
-
- let mut bounds = Vec::new();
- for bound in &type_alias_data.bounds {
- ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| {
- if let Some(bound) = pred
- .kind()
- .map_bound(|c| match c {
- rustc_type_ir::ClauseKind::Trait(t) => {
- let id = t.def_id();
- let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
- if is_auto {
- Some(ExistentialPredicate::AutoTrait(t.def_id()))
- } else {
- Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args(
- interner,
- t.def_id(),
- GenericArgs::new_from_iter(
- interner,
- t.trait_ref.args.iter().skip(1),
- ),
- )))
- }
- }
- rustc_type_ir::ClauseKind::Projection(p) => Some(
- ExistentialPredicate::Projection(ExistentialProjection::new_from_args(
- interner,
- p.def_id(),
- GenericArgs::new_from_iter(
- interner,
- p.projection_term.args.iter().skip(1),
- ),
- p.term,
- )),
- ),
- rustc_type_ir::ClauseKind::TypeOutlives(_) => None,
- rustc_type_ir::ClauseKind::RegionOutlives(_)
- | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
- | rustc_type_ir::ClauseKind::WellFormed(_)
- | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
- | rustc_type_ir::ClauseKind::HostEffect(_)
- | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
- })
- .transpose()
- {
- bounds.push(bound);
- }
- });
- }
-
- if !ctx.unsized_types.contains(&self_ty)
- && let Some(sized_trait) = LangItem::Sized.resolve_trait(db, resolver.krate())
- {
- let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new(
- interner,
- sized_trait.into(),
- [] as [GenericArg<'_>; 0],
- )));
- bounds.push(sized_clause);
- }
-
- EarlyBinder::bind(BoundExistentialPredicates::new_from_iter(interner, bounds))
-}
-
-pub(crate) fn associated_type_by_name_including_super_traits<'db>(
- db: &'db dyn HirDatabase,
- trait_ref: TraitRef<'db>,
- name: &Name,
-) -> Option<(TraitRef<'db>, TypeAliasId)> {
- let interner = DbInterner::new_with(db, None, None);
- rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| {
- let trait_id = t.as_ref().skip_binder().def_id.0;
- let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?;
- Some((t.skip_binder(), assoc_type))
- })
-}
-
-pub fn associated_type_shorthand_candidates(
- db: &dyn HirDatabase,
- def: GenericDefId,
- res: TypeNs,
- mut cb: impl FnMut(&Name, TypeAliasId) -> bool,
-) -> Option<TypeAliasId> {
- let interner = DbInterner::new_with(db, None, None);
- named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| {
- cb(name, id).then_some(id)
- })
-}
-
-#[tracing::instrument(skip(interner, check_alias))]
-fn named_associated_type_shorthand_candidates<'db, R>(
- interner: DbInterner<'db>,
- // If the type parameter is defined in an impl and we're in a method, there
- // might be additional where clauses to consider
- def: GenericDefId,
- res: TypeNs,
- assoc_name: Option<Name>,
- mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option<R>,
-) -> Option<R> {
- let db = interner.db;
- let mut search = |t: TraitRef<'db>| -> Option<R> {
- let mut checked_traits = FxHashSet::default();
- let mut check_trait = |trait_ref: TraitRef<'db>| {
- let trait_id = trait_ref.def_id.0;
- let name = &db.trait_signature(trait_id).name;
- tracing::debug!(?trait_id, ?name);
- if !checked_traits.insert(trait_id) {
- return None;
- }
- let data = trait_id.trait_items(db);
-
- tracing::debug!(?data.items);
- for (name, assoc_id) in &data.items {
- if let &AssocItemId::TypeAliasId(alias) = assoc_id
- && let Some(ty) = check_alias(name, trait_ref, alias)
- {
- return Some(ty);
- }
- }
- None
- };
- let mut stack: SmallVec<[_; 4]> = smallvec![t];
- while let Some(trait_ref) = stack.pop() {
- if let Some(alias) = check_trait(trait_ref) {
- return Some(alias);
- }
- for pred in generic_predicates_filtered_by(
- db,
- GenericDefId::TraitId(trait_ref.def_id.0),
- PredicateFilter::SelfTrait,
- // We are likely in the midst of lowering generic predicates of `def`.
- // So, if we allow `pred == def` we might fall into an infinite recursion.
- // Actually, we have already checked for the case `pred == def` above as we started
- // with a stack including `trait_id`
- |pred| pred != def && pred == GenericDefId::TraitId(trait_ref.def_id.0),
- )
- .0
- .deref()
- {
- tracing::debug!(?pred);
- let sup_trait_ref = match pred.kind().skip_binder() {
- rustc_type_ir::ClauseKind::Trait(pred) => pred.trait_ref,
- _ => continue,
- };
- let sup_trait_ref =
- EarlyBinder::bind(sup_trait_ref).instantiate(interner, trait_ref.args);
- stack.push(sup_trait_ref);
- }
- tracing::debug!(?stack);
- }
-
- None
- };
-
- match res {
- TypeNs::SelfType(impl_id) => {
- let trait_ref = db.impl_trait(impl_id)?;
-
- // FIXME(next-solver): same method in `lower` checks for impl or not
- // Is that needed here?
-
- // we're _in_ the impl -- the binders get added back later. Correct,
- // but it would be nice to make this more explicit
- search(trait_ref.skip_binder())
- }
- TypeNs::GenericParam(param_id) => {
- // Handle `Self::Type` referring to own associated type in trait definitions
- // This *must* be done first to avoid cycles with
- // `generic_predicates_for_param`, but not sure that it's sufficient,
- if let GenericDefId::TraitId(trait_id) = param_id.parent() {
- let trait_name = &db.trait_signature(trait_id).name;
- tracing::debug!(?trait_name);
- let trait_generics = generics(db, trait_id.into());
- tracing::debug!(?trait_generics);
- if trait_generics[param_id.local_id()].is_trait_self() {
- let args = GenericArgs::identity_for_item(interner, trait_id.into());
- let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args);
- tracing::debug!(?args, ?trait_ref);
- return search(trait_ref);
- }
- }
-
- let predicates =
- db.generic_predicates_for_param_ns(def, param_id.into(), assoc_name.clone());
- predicates
- .iter()
- .find_map(|pred| match (*pred).kind().skip_binder() {
- rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate),
- _ => None,
- })
- .and_then(|trait_predicate| {
- let trait_ref = trait_predicate.trait_ref;
- assert!(
- !trait_ref.has_escaping_bound_vars(),
- "FIXME unexpected higher-ranked trait bound"
- );
- search(trait_ref)
- })
- }
- _ => None,
- }
-}
diff --git a/crates/hir-ty/src/lower_nextsolver/path.rs b/crates/hir-ty/src/lower_nextsolver/path.rs
deleted file mode 100644
index a4ff47e389..0000000000
--- a/crates/hir-ty/src/lower_nextsolver/path.rs
+++ /dev/null
@@ -1,1327 +0,0 @@
-//! A wrapper around [`TyLoweringContext`] specifically for lowering paths.
-
-use either::Either;
-use hir_def::{
- GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId,
- expr_store::{
- ExpressionStore, HygieneId,
- path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments},
- },
- hir::generics::{
- GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
- },
- resolver::{ResolveValueResult, TypeNs, ValueNs},
- signatures::TraitFlags,
- type_ref::{TypeRef, TypeRefId},
-};
-use hir_expand::name::Name;
-use rustc_type_ir::{
- AliasTerm, AliasTy, AliasTyKind,
- inherent::{GenericArgs as _, Region as _, SliceLike, Ty as _},
-};
-use smallvec::SmallVec;
-use stdx::never;
-
-use crate::{
- GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
- PathLoweringDiagnostic, TyDefId, ValueTyDefId,
- consteval::{unknown_const, unknown_const_as_generic},
- db::HirDatabase,
- generics::{Generics, generics},
- lower::PathDiagnosticCallbackData,
- lower_nextsolver::{LifetimeElisionKind, named_associated_type_shorthand_candidates},
- next_solver::{
- Binder, Clause, Const, DbInterner, ErrorGuaranteed, Predicate, ProjectionPredicate, Region,
- TraitRef, Ty,
- mapping::{ChalkToNextSolver, convert_binder_to_early_binder},
- },
-};
-
-use super::{
- ImplTraitLoweringMode, TyLoweringContext, associated_type_by_name_including_super_traits,
- const_param_ty_query, ty_query,
-};
-
-type CallbackData<'a, 'db> = Either<
- PathDiagnosticCallbackData,
- crate::infer::diagnostics::PathDiagnosticCallbackData<'a, 'db>,
->;
-
-// We cannot use `&mut dyn FnMut()` because of lifetime issues, and we don't want to use `Box<dyn FnMut()>`
-// because of the allocation, so we create a lifetime-less callback, tailored for our needs.
-pub(crate) struct PathDiagnosticCallback<'a, 'db> {
- pub(crate) data: CallbackData<'a, 'db>,
- pub(crate) callback:
- fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic),
-}
-
-pub(crate) struct PathLoweringContext<'a, 'b, 'db> {
- ctx: &'a mut TyLoweringContext<'db, 'b>,
- on_diagnostic: PathDiagnosticCallback<'a, 'db>,
- path: &'a Path,
- segments: PathSegments<'a>,
- current_segment_idx: usize,
- /// Contains the previous segment if `current_segment_idx == segments.len()`
- current_or_prev_segment: PathSegment<'a>,
-}
-
-impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
- #[inline]
- pub(crate) fn new(
- ctx: &'a mut TyLoweringContext<'db, 'b>,
- on_diagnostic: PathDiagnosticCallback<'a, 'db>,
- path: &'a Path,
- ) -> Self {
- let segments = path.segments();
- let first_segment = segments.first().unwrap_or(PathSegment::MISSING);
- Self {
- ctx,
- on_diagnostic,
- path,
- segments,
- current_segment_idx: 0,
- current_or_prev_segment: first_segment,
- }
- }
-
- #[inline]
- #[cold]
- fn on_diagnostic(&mut self, diag: PathLoweringDiagnostic) {
- (self.on_diagnostic.callback)(&self.on_diagnostic.data, self.ctx, diag);
- }
-
- #[inline]
- pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'db, 'b> {
- self.ctx
- }
-
- #[inline]
- fn current_segment_u32(&self) -> u32 {
- self.current_segment_idx as u32
- }
-
- #[inline]
- fn skip_resolved_segment(&mut self) {
- if !matches!(self.path, Path::LangItem(..)) {
- // In lang items, the resolved "segment" is not one of the segments. Perhaps we should've put it
- // point at -1, but I don't feel this is clearer.
- self.current_segment_idx += 1;
- }
- self.update_current_segment();
- }
-
- #[inline]
- fn update_current_segment(&mut self) {
- self.current_or_prev_segment =
- self.segments.get(self.current_segment_idx).unwrap_or(self.current_or_prev_segment);
- }
-
- #[inline]
- pub(crate) fn ignore_last_segment(&mut self) {
- self.segments = self.segments.strip_last();
- }
-
- #[inline]
- pub(crate) fn set_current_segment(&mut self, segment: usize) {
- self.current_segment_idx = segment;
- self.current_or_prev_segment = self
- .segments
- .get(segment)
- .expect("invalid segment passed to PathLoweringContext::set_current_segment()");
- }
-
- #[inline]
- fn with_lifetime_elision<T>(
- &mut self,
- lifetime_elision: LifetimeElisionKind<'db>,
- f: impl FnOnce(&mut PathLoweringContext<'_, '_, 'db>) -> T,
- ) -> T {
- let old_lifetime_elision =
- std::mem::replace(&mut self.ctx.lifetime_elision, lifetime_elision);
- let result = f(self);
- self.ctx.lifetime_elision = old_lifetime_elision;
- result
- }
-
- pub(crate) fn lower_ty_relative_path(
- &mut self,
- ty: Ty<'db>,
- // We need the original resolution to lower `Self::AssocTy` correctly
- res: Option<TypeNs>,
- infer_args: bool,
- ) -> (Ty<'db>, Option<TypeNs>) {
- let remaining_segments = self.segments.len() - self.current_segment_idx;
- match remaining_segments {
- 0 => (ty, res),
- 1 => {
- // resolve unselected assoc types
- (self.select_associated_type(res, infer_args), None)
- }
- _ => {
- // FIXME report error (ambiguous associated type)
- (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None)
- }
- }
- }
-
- // When calling this, the current segment is the resolved segment (we don't advance it yet).
- pub(crate) fn lower_partly_resolved_path(
- &mut self,
- resolution: TypeNs,
- infer_args: bool,
- ) -> (Ty<'db>, Option<TypeNs>) {
- let remaining_segments = self.segments.skip(self.current_segment_idx + 1);
- tracing::debug!(?remaining_segments);
- let rem_seg_len = remaining_segments.len();
- tracing::debug!(?rem_seg_len);
-
- let ty = match resolution {
- TypeNs::TraitId(trait_) => {
- let ty = match remaining_segments.len() {
- 1 => {
- let trait_ref = self.lower_trait_ref_from_resolved_path(
- trait_,
- Ty::new_error(self.ctx.interner, ErrorGuaranteed),
- false,
- );
- tracing::debug!(?trait_ref);
- self.skip_resolved_segment();
- let segment = self.current_or_prev_segment;
- let trait_id = trait_ref.def_id.0;
- let found =
- trait_id.trait_items(self.ctx.db).associated_type_by_name(segment.name);
-
- tracing::debug!(?found);
- match found {
- Some(associated_ty) => {
- // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
- // generic params. It's inefficient to splice the `Substitution`s, so we may want
- // that method to optionally take parent `Substitution` as we already know them at
- // this point (`trait_ref.substitution`).
- let substitution = self.substs_from_path_segment(
- associated_ty.into(),
- false,
- None,
- true,
- );
- let args = crate::next_solver::GenericArgs::new_from_iter(
- self.ctx.interner,
- trait_ref
- .args
- .iter()
- .chain(substitution.iter().skip(trait_ref.args.len())),
- );
- Ty::new_alias(
- self.ctx.interner,
- AliasTyKind::Projection,
- AliasTy::new_from_args(
- self.ctx.interner,
- associated_ty.into(),
- args,
- ),
- )
- }
- None => {
- // FIXME: report error (associated type not found)
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- }
- }
- 0 => {
- // Trait object type without dyn; this should be handled in upstream. See
- // `lower_path()`.
- stdx::never!("unexpected fully resolved trait path");
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- _ => {
- // FIXME report error (ambiguous associated type)
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- };
- return (ty, None);
- }
- TypeNs::GenericParam(param_id) => {
- let generics = self.ctx.generics();
- let idx = generics.type_or_const_param_idx(param_id.into());
- match idx {
- None => {
- never!("no matching generics");
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- Some(idx) => {
- let (pidx, _param) = generics.iter().nth(idx).unwrap();
- assert_eq!(pidx, param_id.into());
- self.ctx.type_param(param_id, idx as u32)
- }
- }
- }
- TypeNs::SelfType(impl_id) => self.ctx.db.impl_self_ty(impl_id).skip_binder(),
- TypeNs::AdtSelfType(adt) => {
- let args = crate::next_solver::GenericArgs::identity_for_item(
- self.ctx.interner,
- adt.into(),
- );
- Ty::new_adt(self.ctx.interner, adt, args)
- }
-
- TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args),
- TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args),
- TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args),
- // FIXME: report error
- TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => {
- return (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None);
- }
- };
-
- tracing::debug!(?ty);
-
- self.skip_resolved_segment();
- self.lower_ty_relative_path(ty, Some(resolution), infer_args)
- }
-
- /// This returns whether to keep the resolution (`true`) of throw it (`false`).
- #[must_use]
- fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) -> bool {
- let mut prohibit_generics_on_resolved = |reason| {
- if self.current_or_prev_segment.args_and_bindings.is_some() {
- let segment = self.current_segment_u32();
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment,
- reason,
- });
- }
- };
-
- match resolution {
- TypeNs::SelfType(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
- }
- TypeNs::GenericParam(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam)
- }
- TypeNs::AdtSelfType(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy);
-
- if self.ctx.lowering_param_default.is_some() {
- // Generic defaults are not allowed to refer to `Self`.
- // FIXME: Emit an error.
- return false;
- }
- }
- TypeNs::BuiltinType(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy)
- }
- TypeNs::ModuleId(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::Module)
- }
- TypeNs::AdtId(_)
- | TypeNs::EnumVariantId(_)
- | TypeNs::TypeAliasId(_)
- | TypeNs::TraitId(_) => {}
- }
-
- true
- }
-
- pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option<TypeNs> {
- let (res, unresolved) = self.resolve_path_in_type_ns()?;
- if unresolved.is_some() {
- return None;
- }
- Some(res)
- }
-
- #[tracing::instrument(skip(self), ret)]
- pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option<usize>)> {
- let (resolution, remaining_index, _, prefix_info) =
- self.ctx.resolver.resolve_path_in_type_ns_with_prefix_info(self.ctx.db, self.path)?;
-
- let segments = self.segments;
- if segments.is_empty() || matches!(self.path, Path::LangItem(..)) {
- // `segments.is_empty()` can occur with `self`.
- return Some((resolution, remaining_index));
- }
-
- let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index {
- None if prefix_info.enum_variant => {
- (segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2))
- }
- None => (segments.strip_last(), segments.len() - 1, None),
- Some(i) => (segments.take(i - 1), i - 1, None),
- };
-
- self.current_segment_idx = resolved_segment_idx;
- self.current_or_prev_segment =
- segments.get(resolved_segment_idx).expect("should have resolved segment");
-
- for (i, mod_segment) in module_segments.iter().enumerate() {
- if mod_segment.args_and_bindings.is_some() {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: i as u32,
- reason: GenericArgsProhibitedReason::Module,
- });
- }
- }
-
- if let Some(enum_segment) = enum_segment
- && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
- && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
- {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: (enum_segment + 1) as u32,
- reason: GenericArgsProhibitedReason::EnumVariant,
- });
- }
-
- if !self.handle_type_ns_resolution(&resolution) {
- return None;
- }
-
- Some((resolution, remaining_index))
- }
-
- pub(crate) fn resolve_path_in_value_ns(
- &mut self,
- hygiene_id: HygieneId,
- ) -> Option<ResolveValueResult> {
- let (res, prefix_info) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info(
- self.ctx.db,
- self.path,
- hygiene_id,
- )?;
-
- let segments = self.segments;
- if segments.is_empty() || matches!(self.path, Path::LangItem(..)) {
- // `segments.is_empty()` can occur with `self`.
- return Some(res);
- }
-
- let (mod_segments, enum_segment, resolved_segment_idx) = match res {
- ResolveValueResult::Partial(_, unresolved_segment, _) => {
- (segments.take(unresolved_segment - 1), None, unresolved_segment - 1)
- }
- ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _)
- if prefix_info.enum_variant =>
- {
- (segments.strip_last_two(), segments.len().checked_sub(2), segments.len() - 1)
- }
- ResolveValueResult::ValueNs(..) => (segments.strip_last(), None, segments.len() - 1),
- };
-
- self.current_segment_idx = resolved_segment_idx;
- self.current_or_prev_segment =
- segments.get(resolved_segment_idx).expect("should have resolved segment");
-
- for (i, mod_segment) in mod_segments.iter().enumerate() {
- if mod_segment.args_and_bindings.is_some() {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: i as u32,
- reason: GenericArgsProhibitedReason::Module,
- });
- }
- }
-
- if let Some(enum_segment) = enum_segment
- && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
- && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
- {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: (enum_segment + 1) as u32,
- reason: GenericArgsProhibitedReason::EnumVariant,
- });
- }
-
- match &res {
- ResolveValueResult::ValueNs(resolution, _) => {
- let resolved_segment_idx = self.current_segment_u32();
- let resolved_segment = self.current_or_prev_segment;
-
- let mut prohibit_generics_on_resolved = |reason| {
- if resolved_segment.args_and_bindings.is_some() {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: resolved_segment_idx,
- reason,
- });
- }
- };
-
- match resolution {
- ValueNs::ImplSelf(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy);
- }
- // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not
- // E0109 (generic arguments provided for a type that doesn't accept them) for
- // consts and statics, presumably as a defense against future in which consts
- // and statics can be generic, or just because it was easier for rustc implementors.
- // That means we'll show the wrong error code. Because of us it's easier to do it
- // this way :)
- ValueNs::GenericParam(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const)
- }
- ValueNs::StaticId(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static)
- }
- ValueNs::LocalBinding(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable)
- }
- ValueNs::FunctionId(_)
- | ValueNs::StructId(_)
- | ValueNs::EnumVariantId(_)
- | ValueNs::ConstId(_) => {}
- }
- }
- ResolveValueResult::Partial(resolution, _, _) => {
- if !self.handle_type_ns_resolution(resolution) {
- return None;
- }
- }
- };
- Some(res)
- }
-
- #[tracing::instrument(skip(self), ret)]
- fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty<'db> {
- let interner = self.ctx.interner;
- let Some(res) = res else {
- return Ty::new_error(self.ctx.interner, ErrorGuaranteed);
- };
- let def = self.ctx.def;
- let segment = self.current_or_prev_segment;
- let assoc_name = segment.name;
- let check_alias = |name: &Name, t: TraitRef<'db>, associated_ty: TypeAliasId| {
- if name != assoc_name {
- return None;
- }
-
- // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
- // generic params. It's inefficient to splice the `Substitution`s, so we may want
- // that method to optionally take parent `Substitution` as we already know them at
- // this point (`t.substitution`).
- let substs =
- self.substs_from_path_segment(associated_ty.into(), infer_args, None, true);
-
- let substs = crate::next_solver::GenericArgs::new_from_iter(
- interner,
- t.args.iter().chain(substs.iter().skip(t.args.len())),
- );
-
- Some(Ty::new_alias(
- interner,
- AliasTyKind::Projection,
- AliasTy::new(interner, associated_ty.into(), substs),
- ))
- };
- named_associated_type_shorthand_candidates(
- interner,
- def,
- res,
- Some(assoc_name.clone()),
- check_alias,
- )
- .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed))
- }
-
- fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> {
- let generic_def = match typeable {
- TyDefId::BuiltinType(builtinty) => {
- return Ty::from_builtin_type(self.ctx.interner, builtinty);
- }
- TyDefId::AdtId(it) => it.into(),
- TyDefId::TypeAliasId(it) => it.into(),
- };
- let args = self.substs_from_path_segment(generic_def, infer_args, None, false);
- let ty = ty_query(self.ctx.db, typeable);
- ty.instantiate(self.ctx.interner, args)
- }
-
- /// Collect generic arguments from a path into a `Substs`. See also
- /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
- pub(crate) fn substs_from_path(
- &mut self,
- // Note that we don't call `db.value_type(resolved)` here,
- // `ValueTyDefId` is just a convenient way to pass generics and
- // special-case enum variants
- resolved: ValueTyDefId,
- infer_args: bool,
- lowering_assoc_type_generics: bool,
- ) -> crate::next_solver::GenericArgs<'db> {
- let interner = self.ctx.interner;
- let prev_current_segment_idx = self.current_segment_idx;
- let prev_current_segment = self.current_or_prev_segment;
-
- let generic_def = match resolved {
- ValueTyDefId::FunctionId(it) => it.into(),
- ValueTyDefId::StructId(it) => it.into(),
- ValueTyDefId::UnionId(it) => it.into(),
- ValueTyDefId::ConstId(it) => it.into(),
- ValueTyDefId::StaticId(_) => {
- return crate::next_solver::GenericArgs::new_from_iter(interner, []);
- }
- ValueTyDefId::EnumVariantId(var) => {
- // the generic args for an enum variant may be either specified
- // on the segment referring to the enum, or on the segment
- // referring to the variant. So `Option::<T>::None` and
- // `Option::None::<T>` are both allowed (though the former is
- // FIXME: This isn't strictly correct, enum variants may be used not through the enum
- // (via `use Enum::Variant`). The resolver returns whether they were, but we don't have its result
- // available here. The worst that can happen is that we will show some confusing diagnostics to the user,
- // if generics exist on the module and they don't match with the variant.
- // preferred). See also `def_ids_for_path_segments` in rustc.
- //
- // `wrapping_sub(1)` will return a number which `get` will return None for if current_segment_idx<2.
- // This simplifies the code a bit.
- let penultimate_idx = self.current_segment_idx.wrapping_sub(1);
- let penultimate = self.segments.get(penultimate_idx);
- if let Some(penultimate) = penultimate
- && self.current_or_prev_segment.args_and_bindings.is_none()
- && penultimate.args_and_bindings.is_some()
- {
- self.current_segment_idx = penultimate_idx;
- self.current_or_prev_segment = penultimate;
- }
- var.lookup(self.ctx.db).parent.into()
- }
- };
- let result = self.substs_from_path_segment(
- generic_def,
- infer_args,
- None,
- lowering_assoc_type_generics,
- );
- self.current_segment_idx = prev_current_segment_idx;
- self.current_or_prev_segment = prev_current_segment;
- result
- }
-
- pub(crate) fn substs_from_path_segment(
- &mut self,
- def: GenericDefId,
- infer_args: bool,
- explicit_self_ty: Option<Ty<'db>>,
- lowering_assoc_type_generics: bool,
- ) -> crate::next_solver::GenericArgs<'db> {
- let old_lifetime_elision = self.ctx.lifetime_elision.clone();
-
- if let Some(args) = self.current_or_prev_segment.args_and_bindings
- && args.parenthesized != GenericArgsParentheses::No
- {
- let prohibit_parens = match def {
- GenericDefId::TraitId(trait_) => {
- // RTN is prohibited anyways if we got here.
- let is_rtn = args.parenthesized == GenericArgsParentheses::ReturnTypeNotation;
- let is_fn_trait = self
- .ctx
- .db
- .trait_signature(trait_)
- .flags
- .contains(TraitFlags::RUSTC_PAREN_SUGAR);
- is_rtn || !is_fn_trait
- }
- _ => true,
- };
-
- if prohibit_parens {
- let segment = self.current_segment_u32();
- self.on_diagnostic(
- PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
- );
-
- return unknown_subst(self.ctx.interner, def);
- }
-
- // `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
- self.ctx.lifetime_elision =
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
- }
-
- let result = self.substs_from_args_and_bindings(
- self.current_or_prev_segment.args_and_bindings,
- def,
- infer_args,
- explicit_self_ty,
- PathGenericsSource::Segment(self.current_segment_u32()),
- lowering_assoc_type_generics,
- self.ctx.lifetime_elision.clone(),
- );
- self.ctx.lifetime_elision = old_lifetime_elision;
- result
- }
-
- pub(super) fn substs_from_args_and_bindings(
- &mut self,
- args_and_bindings: Option<&GenericArgs>,
- def: GenericDefId,
- infer_args: bool,
- explicit_self_ty: Option<Ty<'db>>,
- generics_source: PathGenericsSource,
- lowering_assoc_type_generics: bool,
- lifetime_elision: LifetimeElisionKind<'db>,
- ) -> crate::next_solver::GenericArgs<'db> {
- struct LowererCtx<'a, 'b, 'c, 'db> {
- ctx: &'a mut PathLoweringContext<'b, 'c, 'db>,
- generics_source: PathGenericsSource,
- }
-
- impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> {
- fn report_len_mismatch(
- &mut self,
- def: GenericDefId,
- provided_count: u32,
- expected_count: u32,
- kind: IncorrectGenericsLenKind,
- ) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::IncorrectGenericsLen {
- generics_source: self.generics_source,
- provided_count,
- expected_count,
- kind,
- def,
- });
- }
-
- fn report_arg_mismatch(
- &mut self,
- param_id: GenericParamId,
- arg_idx: u32,
- has_self_arg: bool,
- ) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::IncorrectGenericsOrder {
- generics_source: self.generics_source,
- param_id,
- arg_idx,
- has_self_arg,
- });
- }
-
- fn provided_kind(
- &mut self,
- param_id: GenericParamId,
- param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::next_solver::GenericArg<'db> {
- match (param, *arg) {
- (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => {
- self.ctx.ctx.lower_lifetime(lifetime).into()
- }
- (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => {
- self.ctx.ctx.lower_ty(type_ref).into()
- }
- (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => {
- let GenericParamId::ConstParamId(const_id) = param_id else {
- unreachable!("non-const param ID for const param");
- };
- self.ctx
- .ctx
- .lower_const(konst, const_param_ty_query(self.ctx.ctx.db, const_id))
- .into()
- }
- _ => unreachable!("unmatching param kinds were passed to `provided_kind()`"),
- }
- }
-
- fn provided_type_like_const(
- &mut self,
- const_ty: Ty<'db>,
- arg: TypeLikeConst<'_>,
- ) -> crate::next_solver::Const<'db> {
- match arg {
- TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty),
- TypeLikeConst::Infer => unknown_const(const_ty),
- }
- }
-
- fn inferred_kind(
- &mut self,
- def: GenericDefId,
- param_id: GenericParamId,
- param: GenericParamDataRef<'_>,
- infer_args: bool,
- preceding_args: &[crate::next_solver::GenericArg<'db>],
- ) -> crate::next_solver::GenericArg<'db> {
- let default = || {
- self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(|default| {
- convert_binder_to_early_binder(
- self.ctx.ctx.interner,
- def,
- default.to_nextsolver(self.ctx.ctx.interner),
- )
- .instantiate(self.ctx.ctx.interner, preceding_args)
- })
- };
- match param {
- GenericParamDataRef::LifetimeParamData(_) => {
- Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
- .into()
- }
- GenericParamDataRef::TypeParamData(param) => {
- if !infer_args
- && param.default.is_some()
- && let Some(default) = default()
- {
- return default;
- }
- Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
- }
- GenericParamDataRef::ConstParamData(param) => {
- if !infer_args
- && param.default.is_some()
- && let Some(default) = default()
- {
- return default;
- }
- let GenericParamId::ConstParamId(const_id) = param_id else {
- unreachable!("non-const param ID for const param");
- };
- unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id))
- }
- }
- }
-
- fn parent_arg(
- &mut self,
- param_id: GenericParamId,
- ) -> crate::next_solver::GenericArg<'db> {
- match param_id {
- GenericParamId::TypeParamId(_) => {
- Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
- }
- GenericParamId::ConstParamId(const_id) => {
- unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id))
- }
- GenericParamId::LifetimeParamId(_) => {
- Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
- .into()
- }
- }
- }
-
- fn report_elided_lifetimes_in_path(
- &mut self,
- def: GenericDefId,
- expected_count: u32,
- hard_error: bool,
- ) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::ElidedLifetimesInPath {
- generics_source: self.generics_source,
- def,
- expected_count,
- hard_error,
- });
- }
-
- fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::ElisionFailure {
- generics_source: self.generics_source,
- def,
- expected_count,
- });
- }
-
- fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::MissingLifetime {
- generics_source: self.generics_source,
- def,
- expected_count,
- });
- }
- }
-
- substs_from_args_and_bindings(
- self.ctx.db,
- self.ctx.store,
- args_and_bindings,
- def,
- infer_args,
- lifetime_elision,
- lowering_assoc_type_generics,
- explicit_self_ty,
- &mut LowererCtx { ctx: self, generics_source },
- )
- }
-
- pub(crate) fn lower_trait_ref_from_resolved_path(
- &mut self,
- resolved: TraitId,
- explicit_self_ty: Ty<'db>,
- infer_args: bool,
- ) -> TraitRef<'db> {
- let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args);
- TraitRef::new_from_args(self.ctx.interner, resolved.into(), args)
- }
-
- fn trait_ref_substs_from_path(
- &mut self,
- resolved: TraitId,
- explicit_self_ty: Ty<'db>,
- infer_args: bool,
- ) -> crate::next_solver::GenericArgs<'db> {
- self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false)
- }
-
- pub(super) fn assoc_type_bindings_from_type_bound<'c>(
- mut self,
- trait_ref: TraitRef<'db>,
- ) -> Option<impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'c, 'db>> {
- let interner = self.ctx.interner;
- self.current_or_prev_segment.args_and_bindings.map(|args_and_bindings| {
- args_and_bindings.bindings.iter().enumerate().flat_map(move |(binding_idx, binding)| {
- let found = associated_type_by_name_including_super_traits(
- self.ctx.db,
- trait_ref,
- &binding.name,
- );
- let (super_trait_ref, associated_ty) = match found {
- None => return SmallVec::new(),
- Some(t) => t,
- };
- let args =
- self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| {
- // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
- // generic params. It's inefficient to splice the `Substitution`s, so we may want
- // that method to optionally take parent `Substitution` as we already know them at
- // this point (`super_trait_ref.substitution`).
- this.substs_from_args_and_bindings(
- binding.args.as_ref(),
- associated_ty.into(),
- false, // this is not relevant
- Some(super_trait_ref.self_ty()),
- PathGenericsSource::AssocType {
- segment: this.current_segment_u32(),
- assoc_type: binding_idx as u32,
- },
- false,
- this.ctx.lifetime_elision.clone(),
- )
- });
- let args = crate::next_solver::GenericArgs::new_from_iter(
- interner,
- super_trait_ref.args.iter().chain(args.iter().skip(super_trait_ref.args.len())),
- );
- let projection_term =
- AliasTerm::new_from_args(interner, associated_ty.into(), args);
- let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity(
- binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
- );
- if let Some(type_ref) = binding.type_ref {
- let lifetime_elision =
- if args_and_bindings.parenthesized == GenericArgsParentheses::ParenSugar {
- // `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def).
- LifetimeElisionKind::for_fn_ret(self.ctx.interner)
- } else {
- self.ctx.lifetime_elision.clone()
- };
- self.with_lifetime_elision(lifetime_elision, |this| {
- match (&this.ctx.store[type_ref], this.ctx.impl_trait_mode.mode) {
- (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (),
- (
- _,
- ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque,
- ) => {
- let ty = this.ctx.lower_ty(type_ref);
- let pred = Clause(Predicate::new(
- interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Projection(
- ProjectionPredicate {
- projection_term,
- term: ty.into(),
- },
- ),
- )),
- ));
- predicates.push(pred);
- }
- }
- })
- }
- for bound in binding.bounds.iter() {
- predicates.extend(self.ctx.lower_type_bound(
- bound,
- Ty::new_alias(
- self.ctx.interner,
- AliasTyKind::Projection,
- AliasTy::new_from_args(self.ctx.interner, associated_ty.into(), args),
- ),
- false,
- ));
- }
- predicates
- })
- })
- }
-}
-
-/// A const that were parsed like a type.
-pub(crate) enum TypeLikeConst<'a> {
- Infer,
- Path(&'a Path),
-}
-
-pub(crate) trait GenericArgsLowerer<'db> {
- fn report_elided_lifetimes_in_path(
- &mut self,
- def: GenericDefId,
- expected_count: u32,
- hard_error: bool,
- );
-
- fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32);
-
- fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32);
-
- fn report_len_mismatch(
- &mut self,
- def: GenericDefId,
- provided_count: u32,
- expected_count: u32,
- kind: IncorrectGenericsLenKind,
- );
-
- fn report_arg_mismatch(&mut self, param_id: GenericParamId, arg_idx: u32, has_self_arg: bool);
-
- fn provided_kind(
- &mut self,
- param_id: GenericParamId,
- param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::next_solver::GenericArg<'db>;
-
- fn provided_type_like_const(&mut self, const_ty: Ty<'db>, arg: TypeLikeConst<'_>)
- -> Const<'db>;
-
- fn inferred_kind(
- &mut self,
- def: GenericDefId,
- param_id: GenericParamId,
- param: GenericParamDataRef<'_>,
- infer_args: bool,
- preceding_args: &[crate::next_solver::GenericArg<'db>],
- ) -> crate::next_solver::GenericArg<'db>;
-
- fn parent_arg(&mut self, param_id: GenericParamId) -> crate::next_solver::GenericArg<'db>;
-}
-
-/// Returns true if there was an error.
-fn check_generic_args_len<'db>(
- args_and_bindings: Option<&GenericArgs>,
- def: GenericDefId,
- def_generics: &Generics,
- infer_args: bool,
- lifetime_elision: &LifetimeElisionKind<'db>,
- lowering_assoc_type_generics: bool,
- ctx: &mut impl GenericArgsLowerer<'db>,
-) -> bool {
- let mut had_error = false;
-
- let (mut provided_lifetimes_count, mut provided_types_and_consts_count) = (0usize, 0usize);
- if let Some(args_and_bindings) = args_and_bindings {
- let args_no_self = &args_and_bindings.args[usize::from(args_and_bindings.has_self_type)..];
- for arg in args_no_self {
- match arg {
- GenericArg::Lifetime(_) => provided_lifetimes_count += 1,
- GenericArg::Type(_) | GenericArg::Const(_) => provided_types_and_consts_count += 1,
- }
- }
- }
-
- let lifetime_args_len = def_generics.len_lifetimes_self();
- if provided_lifetimes_count == 0
- && lifetime_args_len > 0
- && (!lowering_assoc_type_generics || infer_args)
- {
- // In generic associated types, we never allow inferring the lifetimes, but only in type context, that is
- // when `infer_args == false`. In expression/pattern context we always allow inferring them, even for GATs.
- match lifetime_elision {
- &LifetimeElisionKind::AnonymousCreateParameter { report_in_path } => {
- ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, report_in_path);
- had_error |= report_in_path;
- }
- LifetimeElisionKind::AnonymousReportError => {
- ctx.report_missing_lifetime(def, lifetime_args_len as u32);
- had_error = true
- }
- LifetimeElisionKind::ElisionFailure => {
- ctx.report_elision_failure(def, lifetime_args_len as u32);
- had_error = true;
- }
- LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
- // FIXME: Check there are other lifetimes in scope, and error/lint.
- }
- LifetimeElisionKind::Elided(_) => {
- ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, false);
- }
- LifetimeElisionKind::Infer => {
- // Allow eliding lifetimes.
- }
- }
- } else if lifetime_args_len != provided_lifetimes_count {
- ctx.report_len_mismatch(
- def,
- provided_lifetimes_count as u32,
- lifetime_args_len as u32,
- IncorrectGenericsLenKind::Lifetimes,
- );
- had_error = true;
- }
-
- let defaults_count =
- def_generics.iter_self_type_or_consts().filter(|(_, param)| param.has_default()).count();
- let named_type_and_const_params_count = def_generics
- .iter_self_type_or_consts()
- .filter(|(_, param)| match param {
- TypeOrConstParamData::TypeParamData(param) => {
- param.provenance == TypeParamProvenance::TypeParamList
- }
- TypeOrConstParamData::ConstParamData(_) => true,
- })
- .count();
- let expected_max = named_type_and_const_params_count;
- let expected_min =
- if infer_args { 0 } else { named_type_and_const_params_count - defaults_count };
- if provided_types_and_consts_count < expected_min
- || expected_max < provided_types_and_consts_count
- {
- ctx.report_len_mismatch(
- def,
- provided_types_and_consts_count as u32,
- named_type_and_const_params_count as u32,
- IncorrectGenericsLenKind::TypesAndConsts,
- );
- had_error = true;
- }
-
- had_error
-}
-
-pub(crate) fn substs_from_args_and_bindings<'db>(
- db: &'db dyn HirDatabase,
- store: &ExpressionStore,
- args_and_bindings: Option<&GenericArgs>,
- def: GenericDefId,
- mut infer_args: bool,
- lifetime_elision: LifetimeElisionKind<'db>,
- lowering_assoc_type_generics: bool,
- explicit_self_ty: Option<Ty<'db>>,
- ctx: &mut impl GenericArgsLowerer<'db>,
-) -> crate::next_solver::GenericArgs<'db> {
- let interner = DbInterner::new_with(db, None, None);
-
- tracing::debug!(?args_and_bindings);
-
- // Order is
- // - Parent parameters
- // - Optional Self parameter
- // - Lifetime parameters
- // - Type or Const parameters
- let def_generics = generics(db, def);
- let args_slice = args_and_bindings.map(|it| &*it.args).unwrap_or_default();
-
- // We do not allow inference if there are specified args, i.e. we do not allow partial inference.
- let has_non_lifetime_args =
- args_slice.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_)));
- infer_args &= !has_non_lifetime_args;
-
- let had_count_error = check_generic_args_len(
- args_and_bindings,
- def,
- &def_generics,
- infer_args,
- &lifetime_elision,
- lowering_assoc_type_generics,
- ctx,
- );
-
- let mut substs = Vec::with_capacity(def_generics.len());
-
- substs.extend(def_generics.iter_parent_id().map(|id| ctx.parent_arg(id)));
-
- let mut args = args_slice.iter().enumerate().peekable();
- let mut params = def_generics.iter_self().peekable();
-
- // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
- // If we later encounter a lifetime, we know that the arguments were provided in the
- // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
- // inferred, so we can use it for diagnostics later.
- let mut force_infer_lt = None;
-
- let has_self_arg = args_and_bindings.is_some_and(|it| it.has_self_type);
- // First, handle `Self` parameter. Consume it from the args if provided, otherwise from `explicit_self_ty`,
- // and lastly infer it.
- if let Some(&(
- self_param_id,
- self_param @ GenericParamDataRef::TypeParamData(TypeParamData {
- provenance: TypeParamProvenance::TraitSelf,
- ..
- }),
- )) = params.peek()
- {
- let self_ty = if has_self_arg {
- let (_, self_ty) = args.next().expect("has_self_type=true, should have Self type");
- ctx.provided_kind(self_param_id, self_param, self_ty)
- } else {
- explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| {
- ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs)
- })
- };
- params.next();
- substs.push(self_ty);
- }
-
- loop {
- // We're going to iterate through the generic arguments that the user
- // provided, matching them with the generic parameters we expect.
- // Mismatches can occur as a result of elided lifetimes, or for malformed
- // input. We try to handle both sensibly.
- match (args.peek(), params.peek()) {
- (Some(&(arg_idx, arg)), Some(&(param_id, param))) => match (arg, param) {
- (GenericArg::Type(_), GenericParamDataRef::TypeParamData(type_param))
- if type_param.provenance == TypeParamProvenance::ArgumentImplTrait =>
- {
- // Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here
- // we will handle it as if it was specified, instead of inferring it.
- substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs));
- params.next();
- }
- (GenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_))
- | (GenericArg::Type(_), GenericParamDataRef::TypeParamData(_))
- | (GenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => {
- substs.push(ctx.provided_kind(param_id, param, arg));
- args.next();
- params.next();
- }
- (
- GenericArg::Type(_) | GenericArg::Const(_),
- GenericParamDataRef::LifetimeParamData(_),
- ) => {
- // We expected a lifetime argument, but got a type or const
- // argument. That means we're inferring the lifetime.
- substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs));
- params.next();
- force_infer_lt = Some((arg_idx as u32, param_id));
- }
- (GenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => {
- if let Some(konst) = type_looks_like_const(store, *type_ref) {
- let GenericParamId::ConstParamId(param_id) = param_id else {
- panic!("unmatching param kinds");
- };
- let const_ty = const_param_ty_query(db, param_id);
- substs.push(ctx.provided_type_like_const(const_ty, konst).into());
- args.next();
- params.next();
- } else {
- // See the `_ => { ... }` branch.
- if !had_count_error {
- ctx.report_arg_mismatch(param_id, arg_idx as u32, has_self_arg);
- }
- while args.next().is_some() {}
- }
- }
- _ => {
- // We expected one kind of parameter, but the user provided
- // another. This is an error. However, if we already know that
- // the arguments don't match up with the parameters, we won't issue
- // an additional error, as the user already knows what's wrong.
- if !had_count_error {
- ctx.report_arg_mismatch(param_id, arg_idx as u32, has_self_arg);
- }
-
- // We've reported the error, but we want to make sure that this
- // problem doesn't bubble down and create additional, irrelevant
- // errors. In this case, we're simply going to ignore the argument
- // and any following arguments. The rest of the parameters will be
- // inferred.
- while args.next().is_some() {}
- }
- },
-
- (Some(&(_, arg)), None) => {
- // We should never be able to reach this point with well-formed input.
- // There are two situations in which we can encounter this issue.
- //
- // 1. The number of arguments is incorrect. In this case, an error
- // will already have been emitted, and we can ignore it.
- // 2. We've inferred some lifetimes, which have been provided later (i.e.
- // after a type or const). We want to throw an error in this case.
- if !had_count_error {
- assert!(
- matches!(arg, GenericArg::Lifetime(_)),
- "the only possible situation here is incorrect lifetime order"
- );
- let (provided_arg_idx, param_id) =
- force_infer_lt.expect("lifetimes ought to have been inferred");
- ctx.report_arg_mismatch(param_id, provided_arg_idx, has_self_arg);
- }
-
- break;
- }
-
- (None, Some(&(param_id, param))) => {
- // If there are fewer arguments than parameters, it means we're inferring the remaining arguments.
- let param = if let GenericParamId::LifetimeParamId(_) = param_id {
- match &lifetime_elision {
- LifetimeElisionKind::ElisionFailure
- | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }
- | LifetimeElisionKind::AnonymousReportError => {
- assert!(had_count_error);
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
- }
- LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
- Region::new_static(interner).into()
- }
- LifetimeElisionKind::Elided(lifetime) => (*lifetime).into(),
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false }
- | LifetimeElisionKind::Infer => {
- // FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here
- // (but this will probably be done in hir-def lowering instead).
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
- }
- }
- } else {
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
- };
- substs.push(param);
- params.next();
- }
-
- (None, None) => break,
- }
- }
-
- crate::next_solver::GenericArgs::new_from_iter(interner, substs)
-}
-
-fn type_looks_like_const(
- store: &ExpressionStore,
- type_ref: TypeRefId,
-) -> Option<TypeLikeConst<'_>> {
- // A path/`_` const will be parsed as a type, instead of a const, because when parsing/lowering
- // in hir-def we don't yet know the expected argument kind. rustc does this a bit differently,
- // when lowering to HIR it resolves the path, and if it doesn't resolve to the type namespace
- // it is lowered as a const. Our behavior could deviate from rustc when the value is resolvable
- // in both the type and value namespaces, but I believe we only allow more code.
- let type_ref = &store[type_ref];
- match type_ref {
- TypeRef::Path(path) => Some(TypeLikeConst::Path(path)),
- TypeRef::Placeholder => Some(TypeLikeConst::Infer),
- _ => None,
- }
-}
-
-fn unknown_subst<'db>(
- interner: DbInterner<'db>,
- def: impl Into<GenericDefId>,
-) -> crate::next_solver::GenericArgs<'db> {
- let params = generics(interner.db(), def.into());
- crate::next_solver::GenericArgs::new_from_iter(
- interner,
- params.iter_id().map(|id| match id {
- GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
- GenericParamId::ConstParamId(id) => {
- unknown_const_as_generic(const_param_ty_query(interner.db(), id))
- }
- GenericParamId::LifetimeParamId(_) => {
- crate::next_solver::Region::error(interner).into()
- }
- }),
- )
-}
diff --git a/crates/hir-ty/src/mapping.rs b/crates/hir-ty/src/mapping.rs
deleted file mode 100644
index 5125a38825..0000000000
--- a/crates/hir-ty/src/mapping.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-//! This module contains the implementations of the `ToChalk` trait, which
-//! handles conversion between our data types and their corresponding types in
-//! Chalk (in both directions); plus some helper functions for more specialized
-//! conversions.
-
-use hir_def::{LifetimeParamId, TraitId, TypeAliasId, TypeOrConstParamId};
-use salsa::{
- Id,
- plumbing::{AsId, FromId},
-};
-
-use crate::{
- AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, Interner, OpaqueTyId,
- PlaceholderIndex, chalk_db,
- db::{HirDatabase, InternedLifetimeParamId, InternedTypeOrConstParamId},
-};
-
-pub trait ToChalk {
- type Chalk;
- fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk;
- fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self;
-}
-
-pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T
-where
- T: ToChalk<Chalk = ChalkT>,
-{
- T::from_chalk(db, chalk)
-}
-
-impl ToChalk for hir_def::ImplId {
- type Chalk = chalk_db::ImplId;
-
- fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::ImplId {
- chalk_ir::ImplId(self.as_id())
- }
-
- fn from_chalk(_db: &dyn HirDatabase, impl_id: chalk_db::ImplId) -> hir_def::ImplId {
- FromId::from_id(impl_id.0.as_id())
- }
-}
-
-impl ToChalk for CallableDefId {
- type Chalk = FnDefId;
-
- fn to_chalk(self, _db: &dyn HirDatabase) -> FnDefId {
- chalk_ir::FnDefId(salsa::plumbing::AsId::as_id(&self))
- }
-
- fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
- salsa::plumbing::FromIdWithDb::from_id(fn_def_id.0, db.zalsa())
- }
-}
-
-impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
- fn from(id: OpaqueTyId) -> Self {
- FromId::from_id(id.0)
- }
-}
-
-impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
- fn from(id: crate::db::InternedOpaqueTyId) -> Self {
- chalk_ir::OpaqueTyId(id.as_id())
- }
-}
-
-impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
- fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
- FromId::from_id(id.0)
- }
-}
-
-impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
- fn from(id: crate::db::InternedClosureId) -> Self {
- chalk_ir::ClosureId(id.as_id())
- }
-}
-
-impl From<chalk_ir::CoroutineId<Interner>> for crate::db::InternedCoroutineId {
- fn from(id: chalk_ir::CoroutineId<Interner>) -> Self {
- Self::from_id(id.0)
- }
-}
-
-impl From<crate::db::InternedCoroutineId> for chalk_ir::CoroutineId<Interner> {
- fn from(id: crate::db::InternedCoroutineId) -> Self {
- chalk_ir::CoroutineId(id.as_id())
- }
-}
-
-pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
- chalk_ir::ForeignDefId(id.as_id())
-}
-
-pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
- FromId::from_id(id.0)
-}
-
-pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
- chalk_ir::AssocTypeId(id.as_id())
-}
-
-pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
- FromId::from_id(id.0)
-}
-
-pub fn from_placeholder_idx(
- db: &dyn HirDatabase,
- idx: PlaceholderIndex,
-) -> (TypeOrConstParamId, u32) {
- assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
- // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
- let interned_id =
- InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) });
- interned_id.loc(db)
-}
-
-pub fn to_placeholder_idx(
- db: &dyn HirDatabase,
- id: TypeOrConstParamId,
- idx: u32,
-) -> PlaceholderIndex {
- let interned_id = InternedTypeOrConstParamId::new(db, (id, idx));
- PlaceholderIndex {
- ui: chalk_ir::UniverseIndex::ROOT,
- idx: interned_id.as_id().index() as usize,
- }
-}
-
-pub fn to_placeholder_idx_no_index(
- db: &dyn HirDatabase,
- id: TypeOrConstParamId,
-) -> PlaceholderIndex {
- let index = crate::generics::generics(db, id.parent)
- .type_or_const_param_idx(id)
- .expect("param not found");
- to_placeholder_idx(db, id, index as u32)
-}
-
-pub fn lt_from_placeholder_idx(
- db: &dyn HirDatabase,
- idx: PlaceholderIndex,
-) -> (LifetimeParamId, u32) {
- assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
- // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
- let interned_id =
- InternedLifetimeParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) });
- interned_id.loc(db)
-}
-
-pub fn lt_to_placeholder_idx(
- db: &dyn HirDatabase,
- id: LifetimeParamId,
- idx: u32,
-) -> PlaceholderIndex {
- let interned_id = InternedLifetimeParamId::new(db, (id, idx));
- PlaceholderIndex {
- ui: chalk_ir::UniverseIndex::ROOT,
- idx: interned_id.as_id().index() as usize,
- }
-}
-
-pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
- chalk_ir::TraitId(id.as_id())
-}
-
-pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
- FromId::from_id(id.0)
-}
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index bce1790503..cec6356633 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -25,10 +25,8 @@ use smallvec::{SmallVec, smallvec};
use stdx::never;
use triomphe::Arc;
-use crate::next_solver::infer::InferCtxt;
-use crate::next_solver::infer::select::ImplSource;
use crate::{
- TraitEnvironment, TyBuilder,
+ TraitEnvironment,
autoderef::{self, AutoderefKind},
db::HirDatabase,
infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable},
@@ -37,7 +35,8 @@ use crate::{
Canonical, DbInterner, ErrorGuaranteed, GenericArgs, Goal, Predicate, Region, SolverDefId,
TraitRef, Ty, TyKind, TypingMode,
infer::{
- DbInternerInferExt,
+ DbInternerInferExt, InferCtxt,
+ select::ImplSource,
traits::{Obligation, ObligationCause, PredicateObligation},
},
obligation_ctxt::ObligationCtxt,
@@ -1597,9 +1596,9 @@ fn is_valid_impl_method_candidate<'db>(
return IsValidCandidate::NotVisible;
}
let self_ty_matches = table.run_in_snapshot(|table| {
- let expected_self_ty = TyBuilder::impl_self_ty(db, impl_id)
- .fill_with_inference_vars(table)
- .build(table.interner());
+ let impl_args = table.fresh_args_for_item(impl_id.into());
+ let expected_self_ty =
+ db.impl_self_ty(impl_id).instantiate(table.interner(), impl_args);
table.unify(expected_self_ty, self_ty)
});
if !self_ty_matches {
@@ -1727,7 +1726,7 @@ fn is_valid_impl_fn_candidate<'db>(
// We need to consider the bounds on the impl to distinguish functions of the same name
// for a type.
- let predicates = db.generic_predicates_ns(impl_id.into());
+ let predicates = db.generic_predicates(impl_id.into());
let Some(predicates) = predicates.instantiate(table.interner(), impl_subst) else {
return IsValidCandidate::Yes;
};
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index 936895fb7f..7aebe17e5b 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -196,7 +196,7 @@ impl<V, T> ProjectionElem<V, T> {
},
ProjectionElem::Field(Either::Left(f)) => match base.kind() {
TyKind::Adt(_, subst) => {
- db.field_types_ns(f.parent)[f.local_id].instantiate(interner, subst)
+ db.field_types(f.parent)[f.local_id].instantiate(interner, subst)
}
ty => {
never!("Only adt has field, found {:?}", ty);
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 444336ca3f..6e62bcbbdd 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -1696,7 +1696,7 @@ impl<'db> Evaluator<'db> {
if let TyKind::Adt(adt_ef, subst) = kind
&& let AdtId::StructId(struct_id) = adt_ef.def_id().0
{
- let field_types = self.db.field_types_ns(struct_id.into());
+ let field_types = self.db.field_types(struct_id.into());
if let Some(ty) =
field_types.iter().last().map(|it| it.1.instantiate(self.interner(), subst))
{
@@ -1775,9 +1775,9 @@ impl<'db> Evaluator<'db> {
else {
not_supported!("unsizing struct without field");
};
- let target_last_field = self.db.field_types_ns(id.into())[last_field]
+ let target_last_field = self.db.field_types(id.into())[last_field]
.instantiate(self.interner(), target_subst);
- let current_last_field = self.db.field_types_ns(id.into())[last_field]
+ let current_last_field = self.db.field_types(id.into())[last_field]
.instantiate(self.interner(), current_subst);
return self.unsizing_ptr_from_addr(
target_last_field,
@@ -2268,7 +2268,7 @@ impl<'db> Evaluator<'db> {
AdtId::StructId(s) => {
let data = s.fields(this.db);
let layout = this.layout(ty)?;
- let field_types = this.db.field_types_ns(s.into());
+ let field_types = this.db.field_types(s.into());
for (f, _) in data.fields().iter() {
let offset = layout
.fields
@@ -2296,7 +2296,7 @@ impl<'db> Evaluator<'db> {
e,
) {
let data = v.fields(this.db);
- let field_types = this.db.field_types_ns(v.into());
+ let field_types = this.db.field_types(v.into());
for (f, _) in data.fields().iter() {
let offset =
l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
@@ -2373,7 +2373,7 @@ impl<'db> Evaluator<'db> {
}
TyKind::Adt(id, args) => match id.def_id().0 {
AdtId::StructId(s) => {
- for (i, (_, ty)) in self.db.field_types_ns(s.into()).iter().enumerate() {
+ for (i, (_, ty)) in self.db.field_types(s.into()).iter().enumerate() {
let offset = layout.fields.offset(i).bytes_usize();
let ty = ty.instantiate(self.interner(), args);
self.patch_addresses(
@@ -2394,7 +2394,7 @@ impl<'db> Evaluator<'db> {
self.read_memory(addr, layout.size.bytes_usize())?,
e,
) {
- for (i, (_, ty)) in self.db.field_types_ns(ev.into()).iter().enumerate() {
+ for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() {
let offset = layout.fields.offset(i).bytes_usize();
let ty = ty.instantiate(self.interner(), args);
self.patch_addresses(
@@ -2895,7 +2895,7 @@ impl<'db> Evaluator<'db> {
let variant_fields = s.fields(self.db);
match variant_fields.shape {
FieldsShape::Record | FieldsShape::Tuple => {
- let field_types = self.db.field_types_ns(s.into());
+ let field_types = self.db.field_types(s.into());
for (field, _) in variant_fields.fields().iter() {
let offset = layout
.fields
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index c45ae9dcc3..4b1adecf8c 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -1383,7 +1383,7 @@ impl<'db> Evaluator<'db> {
AdtId::StructId(s) => s,
_ => not_supported!("unsized enum or union"),
};
- let field_types = self.db.field_types_ns(id.into());
+ let field_types = self.db.field_types(id.into());
let last_field_ty =
field_types.iter().next_back().unwrap().1.instantiate(self.interner(), subst);
let sized_part_size =
diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs
index ade94b94c0..4c64a70a7a 100644
--- a/crates/hir-ty/src/mir/eval/shim/simd.rs
+++ b/crates/hir-ty/src/mir/eval/shim/simd.rs
@@ -34,7 +34,7 @@ impl<'db> Evaluator<'db> {
let Some((first_field, _)) = fields.iter().next() else {
not_supported!("simd type with no field");
};
- let field_ty = self.db.field_types_ns(id.into())[first_field]
+ let field_ty = self.db.field_types(id.into())[first_field]
.instantiate(self.interner(), subst);
return Ok((fields.len(), field_ty));
}
diff --git a/crates/hir-ty/src/next_solver.rs b/crates/hir-ty/src/next_solver.rs
index f5b4fa1e2a..1fb9a82ac9 100644
--- a/crates/hir-ty/src/next_solver.rs
+++ b/crates/hir-ty/src/next_solver.rs
@@ -32,7 +32,7 @@ pub use region::*;
pub use solver::*;
pub use ty::*;
-pub use crate::lower_nextsolver::ImplTraitIdx;
+pub use crate::lower::ImplTraitIdx;
pub use rustc_ast_ir::Mutability;
pub type Binder<'db, T> = rustc_type_ir::Binder<DbInterner<'db>, T>;
diff --git a/crates/hir-ty/src/next_solver/consts.rs b/crates/hir-ty/src/next_solver/consts.rs
index 8d81a382c3..c28af948bf 100644
--- a/crates/hir-ty/src/next_solver/consts.rs
+++ b/crates/hir-ty/src/next_solver/consts.rs
@@ -14,8 +14,7 @@ use rustc_type_ir::{
use crate::{
MemoryMap,
- interner::InternedWrapperNoDebug,
- next_solver::{ClauseKind, ParamEnv},
+ next_solver::{ClauseKind, ParamEnv, interner::InternedWrapperNoDebug},
};
use super::{BoundVarKind, DbInterner, ErrorGuaranteed, GenericArgs, Placeholder, Ty};
diff --git a/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs
index b2632ba637..24f22bcb0c 100644
--- a/crates/hir-ty/src/next_solver/generic_arg.rs
+++ b/crates/hir-ty/src/next_solver/generic_arg.rs
@@ -207,7 +207,7 @@ impl<'db> GenericArgs<'db> {
where
F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
{
- let defaults = interner.db.generic_defaults_ns(def_id);
+ let defaults = interner.db.generic_defaults(def_id);
Self::for_item(interner, def_id.into(), |idx, id, prev| match defaults.get(idx as usize) {
Some(default) => default.instantiate(interner, prev),
None => fallback(idx, id, prev),
@@ -240,7 +240,7 @@ impl<'db> GenericArgs<'db> {
where
F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
{
- let defaults = interner.db.generic_defaults_ns(def_id);
+ let defaults = interner.db.generic_defaults(def_id);
Self::fill_rest(interner, def_id.into(), first, |idx, id, prev| {
defaults
.get(idx as usize)
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index 331bcdcb26..42f1d926d7 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -32,8 +32,8 @@ use crate::{
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,
+ CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, ImplIdWrapper, RegionAssumptions,
+ SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper,
util::{ContainsTypeErrors, explicit_item_bounds, for_trait_impls},
},
};
@@ -53,6 +53,9 @@ use super::{
util::sizedness_constraint_for_ty,
};
+#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
+pub struct InternedWrapperNoDebug<T>(pub(crate) T);
+
#[macro_export]
#[doc(hidden)]
macro_rules! _interned_vec_nolifetime_salsa {
@@ -611,7 +614,7 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
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)
}
@@ -623,7 +626,7 @@ impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
let db = interner.db();
// FIXME: this is disabled just to match the behavior with chalk right now
let _field_tys = |id: VariantId| {
- db.field_types_ns(id).iter().map(|(_, ty)| ty.skip_binder()).collect::<Vec<_>>()
+ db.field_types(id).iter().map(|(_, ty)| ty.skip_binder()).collect::<Vec<_>>()
};
let field_tys = |_id: VariantId| vec![];
let tys: Vec<_> = match self.inner().id {
@@ -1284,7 +1287,7 @@ 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 = self.db().generic_predicates(def_id.try_into().unwrap());
let predicates: Vec<_> = predicates.iter().cloned().collect();
EarlyBinder::bind(predicates.into_iter())
}
@@ -1311,7 +1314,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> {
let predicates: Vec<(Clause<'db>, Span)> = self
.db()
- .generic_predicates_ns(def_id.0.into())
+ .generic_predicates(def_id.0.into())
.iter()
.filter(|p| match p.kind().skip_binder() {
// rustc has the following assertion:
@@ -1345,7 +1348,7 @@ 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())
+ .generic_predicates(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()),
@@ -1765,7 +1768,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() {
diff --git a/crates/hir-ty/src/next_solver/mapping.rs b/crates/hir-ty/src/next_solver/mapping.rs
index 671f06f1b8..2b29561393 100644
--- a/crates/hir-ty/src/next_solver/mapping.rs
+++ b/crates/hir-ty/src/next_solver/mapping.rs
@@ -1,1736 +1,13 @@
//! Things useful for mapping to/from Chalk and next-trait-solver types.
-use chalk_ir::{
- InferenceVar, Substitution, TyVariableKind, WellFormed, cast::Cast, fold::Shift,
- interner::HasInterner,
-};
-use hir_def::{CallableDefId, ConstParamId, GeneralConstId, TypeParamId, signatures::TraitFlags};
-use hir_def::{GenericDefId, GenericParamId};
-use rustc_type_ir::{
- AliasTerm, BoundVar, DebruijnIndex, ExistentialProjection, ExistentialTraitRef,
- OutlivesPredicate, ProjectionPredicate, TypeFoldable, TypeSuperFoldable, TypeVisitable,
- UniverseIndex, elaborate,
- inherent::{BoundVarLike, IntoKind, SliceLike, Ty as _},
- shift_vars,
- solve::Goal,
-};
+use crate::next_solver::interner::DbInterner;
-use crate::next_solver::BoundConst;
-use crate::{
- ConstScalar, Interner, MemoryMap,
- db::{InternedClosureId, InternedCoroutineId, InternedOpaqueTyId},
- from_assoc_type_id, from_chalk_trait_id,
- mapping::ToChalk,
- next_solver::{
- Binder, ClauseKind, ConstBytes, TraitPredicate, UnevaluatedConst,
- interner::{AdtDef, BoundVarKind, BoundVarKinds, DbInterner},
- },
- to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id,
-};
-use crate::{
- from_placeholder_idx, lt_from_placeholder_idx, lt_to_placeholder_idx, to_placeholder_idx,
-};
-
-use super::{
- BoundExistentialPredicates, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, Canonical,
- CanonicalVars, Clause, Clauses, Const, EarlyParamRegion, ErrorGuaranteed, ExistentialPredicate,
- GenericArg, GenericArgs, ParamConst, ParamEnv, ParamTy, Predicate, PredicateKind, Region,
- SolverDefId, SubtypePredicate, Term, TraitRef, Ty, Tys, ValueConst,
-};
-
-// FIXME: This should urgently go (as soon as we finish the migration off Chalk, that is).
-pub fn convert_binder_to_early_binder<'db, T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
- interner: DbInterner<'db>,
- def: GenericDefId,
- binder: rustc_type_ir::Binder<DbInterner<'db>, T>,
-) -> rustc_type_ir::EarlyBinder<DbInterner<'db>, T> {
- let mut folder = BinderToEarlyBinder {
- interner,
- debruijn: rustc_type_ir::DebruijnIndex::ZERO,
- params: crate::generics::generics(interner.db, def).iter_id().collect(),
- };
- rustc_type_ir::EarlyBinder::bind(binder.skip_binder().fold_with(&mut folder))
-}
-
-struct BinderToEarlyBinder<'db> {
- interner: DbInterner<'db>,
- debruijn: rustc_type_ir::DebruijnIndex,
- params: Vec<GenericParamId>,
-}
-
-impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> for BinderToEarlyBinder<'db> {
- fn cx(&self) -> DbInterner<'db> {
- self.interner
- }
-
- fn fold_binder<T>(
- &mut self,
- t: rustc_type_ir::Binder<DbInterner<'db>, T>,
- ) -> rustc_type_ir::Binder<DbInterner<'db>, T>
- where
- T: TypeFoldable<DbInterner<'db>>,
- {
- self.debruijn.shift_in(1);
- let result = t.super_fold_with(self);
- self.debruijn.shift_out(1);
- result
- }
-
- fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
- match t.kind() {
- rustc_type_ir::TyKind::Bound(debruijn, bound_ty) if self.debruijn == debruijn => {
- let var: rustc_type_ir::BoundVar = bound_ty.var();
- let GenericParamId::TypeParamId(id) = self.params[bound_ty.var.as_usize()] else {
- unreachable!()
- };
- Ty::new(
- self.cx(),
- rustc_type_ir::TyKind::Param(ParamTy { index: var.as_u32(), id }),
- )
- }
- _ => t.super_fold_with(self),
- }
- }
-
- fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
- match r.kind() {
- rustc_type_ir::ReBound(debruijn, bound_region) if self.debruijn == debruijn => {
- let var: rustc_type_ir::BoundVar = bound_region.var();
- let GenericParamId::LifetimeParamId(id) = self.params[bound_region.var.as_usize()]
- else {
- unreachable!()
- };
- Region::new(
- self.cx(),
- rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion {
- index: var.as_u32(),
- id,
- }),
- )
- }
- _ => r,
- }
- }
-
- fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
- match c.kind() {
- rustc_type_ir::ConstKind::Bound(debruijn, var) if self.debruijn == debruijn => {
- let GenericParamId::ConstParamId(id) = self.params[var.var.as_usize()] else {
- unreachable!()
- };
- Const::new(
- self.cx(),
- rustc_type_ir::ConstKind::Param(ParamConst { index: var.var.as_u32(), id }),
- )
- }
- _ => c.super_fold_with(self),
- }
- }
-}
-
-pub trait ChalkToNextSolver<'db, Out> {
+pub(crate) trait ChalkToNextSolver<'db, Out> {
fn to_nextsolver(&self, interner: DbInterner<'db>) -> Out;
}
-impl<'db, A, OutA, B, OutB> ChalkToNextSolver<'db, (OutA, OutB)> for (A, B)
-where
- A: ChalkToNextSolver<'db, OutA>,
- B: ChalkToNextSolver<'db, OutB>,
-{
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> (OutA, OutB) {
- (self.0.to_nextsolver(interner), self.1.to_nextsolver(interner))
- }
-}
-
-pub trait NextSolverToChalk<'db, Out> {
- fn to_chalk(self, interner: DbInterner<'db>) -> Out;
-}
-
-impl<'db, T, Out> NextSolverToChalk<'db, Option<Out>> for Option<T>
-where
- T: NextSolverToChalk<'db, Out>,
-{
- fn to_chalk(self, interner: DbInterner<'db>) -> Option<Out> {
- self.map(|it| it.to_chalk(interner))
- }
-}
-
-impl NextSolverToChalk<'_, chalk_ir::Mutability> for rustc_ast_ir::Mutability {
- fn to_chalk(self, _interner: DbInterner<'_>) -> chalk_ir::Mutability {
- match self {
- rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not,
- rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut,
- }
- }
-}
-
-impl NextSolverToChalk<'_, chalk_ir::Safety> for crate::next_solver::abi::Safety {
- fn to_chalk(self, _interner: DbInterner<'_>) -> chalk_ir::Safety {
- match self {
- crate::next_solver::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe,
- crate::next_solver::abi::Safety::Safe => chalk_ir::Safety::Safe,
- }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> Ty<'db> {
- Ty::new(
- interner,
- match self.kind(Interner) {
- chalk_ir::TyKind::Adt(adt_id, substitution) => {
- let def = AdtDef::new(adt_id.0, interner);
- let args = substitution.to_nextsolver(interner);
- rustc_type_ir::TyKind::Adt(def, args)
- }
- chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution) => {
- let def_id = SolverDefId::TypeAliasId(from_assoc_type_id(*assoc_type_id));
- let args: GenericArgs<'db> = substitution.to_nextsolver(interner);
- let alias_ty = rustc_type_ir::AliasTy::new(interner, def_id, args.iter());
- rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Projection, alias_ty)
- }
- chalk_ir::TyKind::Scalar(scalar) => match scalar {
- chalk_ir::Scalar::Bool => rustc_type_ir::TyKind::Bool,
- chalk_ir::Scalar::Char => rustc_type_ir::TyKind::Char,
- chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize) => {
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::Isize)
- }
- chalk_ir::Scalar::Int(chalk_ir::IntTy::I8) => {
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I8)
- }
- chalk_ir::Scalar::Int(chalk_ir::IntTy::I16) => {
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I16)
- }
- chalk_ir::Scalar::Int(chalk_ir::IntTy::I32) => {
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I32)
- }
- chalk_ir::Scalar::Int(chalk_ir::IntTy::I64) => {
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I64)
- }
- chalk_ir::Scalar::Int(chalk_ir::IntTy::I128) => {
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I128)
- }
- chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize) => {
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::Usize)
- }
- chalk_ir::Scalar::Uint(chalk_ir::UintTy::U8) => {
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U8)
- }
- chalk_ir::Scalar::Uint(chalk_ir::UintTy::U16) => {
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U16)
- }
- chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32) => {
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U32)
- }
- chalk_ir::Scalar::Uint(chalk_ir::UintTy::U64) => {
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U64)
- }
- chalk_ir::Scalar::Uint(chalk_ir::UintTy::U128) => {
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U128)
- }
- chalk_ir::Scalar::Float(chalk_ir::FloatTy::F16) => {
- rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F16)
- }
- chalk_ir::Scalar::Float(chalk_ir::FloatTy::F32) => {
- rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F32)
- }
- chalk_ir::Scalar::Float(chalk_ir::FloatTy::F64) => {
- rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F64)
- }
- chalk_ir::Scalar::Float(chalk_ir::FloatTy::F128) => {
- rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F128)
- }
- },
- chalk_ir::TyKind::Tuple(_, substitution) => {
- let args = substitution.to_nextsolver(interner);
- rustc_type_ir::TyKind::Tuple(args)
- }
- chalk_ir::TyKind::Array(ty, len) => rustc_type_ir::TyKind::Array(
- ty.to_nextsolver(interner),
- len.to_nextsolver(interner),
- ),
- chalk_ir::TyKind::Slice(ty) => {
- rustc_type_ir::TyKind::Slice(ty.to_nextsolver(interner))
- }
- chalk_ir::TyKind::Raw(mutability, ty) => rustc_type_ir::RawPtr(
- ty.to_nextsolver(interner),
- mutability.to_nextsolver(interner),
- ),
- chalk_ir::TyKind::Ref(mutability, lifetime, ty) => rustc_type_ir::TyKind::Ref(
- lifetime.to_nextsolver(interner),
- ty.to_nextsolver(interner),
- mutability.to_nextsolver(interner),
- ),
- chalk_ir::TyKind::OpaqueType(def_id, substitution) => {
- let id: InternedOpaqueTyId = (*def_id).into();
- let args: GenericArgs<'db> = substitution.to_nextsolver(interner);
- let alias_ty = rustc_type_ir::AliasTy::new(interner, id.into(), args);
- rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Opaque, alias_ty)
- }
- chalk_ir::TyKind::FnDef(fn_def_id, substitution) => {
- let def_id = CallableDefId::from_chalk(interner.db(), *fn_def_id);
- rustc_type_ir::TyKind::FnDef(
- def_id.into(),
- substitution.to_nextsolver(interner),
- )
- }
- chalk_ir::TyKind::Str => rustc_type_ir::TyKind::Str,
- chalk_ir::TyKind::Never => rustc_type_ir::TyKind::Never,
- chalk_ir::TyKind::Closure(closure_id, substitution) => {
- let id: InternedClosureId = (*closure_id).into();
- rustc_type_ir::TyKind::Closure(id.into(), substitution.to_nextsolver(interner))
- }
- chalk_ir::TyKind::Coroutine(coroutine_id, substitution) => {
- let id: InternedCoroutineId = (*coroutine_id).into();
- rustc_type_ir::TyKind::Coroutine(
- id.into(),
- substitution.to_nextsolver(interner),
- )
- }
- chalk_ir::TyKind::CoroutineWitness(coroutine_id, substitution) => {
- let id: InternedCoroutineId = (*coroutine_id).into();
- rustc_type_ir::TyKind::CoroutineWitness(
- id.into(),
- substitution.to_nextsolver(interner),
- )
- }
- chalk_ir::TyKind::Foreign(foreign_def_id) => rustc_type_ir::TyKind::Foreign(
- crate::from_foreign_def_id(*foreign_def_id).into(),
- ),
- chalk_ir::TyKind::Error => rustc_type_ir::TyKind::Error(ErrorGuaranteed),
- chalk_ir::TyKind::Dyn(dyn_ty) => {
- // exists<type> { for<...> ^1.0: ... }
- let bounds = BoundExistentialPredicates::new_from_iter(
- interner,
- dyn_ty.bounds.skip_binders().iter(Interner).filter_map(|pred| {
- // for<...> ^1.0: ...
- let (val, binders) = pred.clone().into_value_and_skipped_binders();
- let bound_vars = binders.to_nextsolver(interner);
- let clause = match val {
- chalk_ir::WhereClause::Implemented(trait_ref) => {
- let trait_id = from_chalk_trait_id(trait_ref.trait_id);
- if interner
- .db()
- .trait_signature(trait_id)
- .flags
- .contains(TraitFlags::AUTO)
- {
- ExistentialPredicate::AutoTrait(trait_id.into())
- } else {
- let args = GenericArgs::new_from_iter(
- interner,
- trait_ref
- .substitution
- .iter(Interner)
- .skip(1)
- .map(|a| a.clone().shifted_out(Interner).unwrap())
- .map(|a| a.to_nextsolver(interner)),
- );
- let trait_ref = ExistentialTraitRef::new_from_args(
- interner, trait_id.into(), args,
- );
- ExistentialPredicate::Trait(trait_ref)
- }
- }
- chalk_ir::WhereClause::AliasEq(alias_eq) => {
- let (def_id, args) = match &alias_eq.alias {
- chalk_ir::AliasTy::Projection(projection) => {
- let id =
- from_assoc_type_id(projection.associated_ty_id);
- let def_id = SolverDefId::TypeAliasId(id);
- let substs = projection.substitution.iter(Interner).skip(1);
-
- let args = GenericArgs::new_from_iter(
- interner,
- substs
- .map(|a| {
- a.clone().shifted_out(Interner).unwrap()
- })
- .map(|a| a.to_nextsolver(interner)),
- );
- (def_id, args)
- }
- chalk_ir::AliasTy::Opaque(_opaque_ty) => {
- panic!("Invalid ExistentialPredicate (opaques can't be named).");
- }
- };
- let term = alias_eq
- .ty
- .clone()
- .shifted_out(Interner)
- .unwrap()
- .to_nextsolver(interner)
- .into();
- let projection = ExistentialProjection::new_from_args(
- interner, def_id, args, term,
- );
- ExistentialPredicate::Projection(projection)
- }
- chalk_ir::WhereClause::LifetimeOutlives(_lifetime_outlives) => {
- return None;
- }
- chalk_ir::WhereClause::TypeOutlives(_type_outlives) => return None,
- };
-
- Some(Binder::bind_with_vars(clause, bound_vars))
- }),
- );
- let region = dyn_ty.lifetime.to_nextsolver(interner);
- rustc_type_ir::TyKind::Dynamic(bounds, region)
- }
- chalk_ir::TyKind::Alias(alias_ty) => match alias_ty {
- chalk_ir::AliasTy::Projection(projection_ty) => {
- let def_id = SolverDefId::TypeAliasId(from_assoc_type_id(
- projection_ty.associated_ty_id,
- ));
- let alias_ty = rustc_type_ir::AliasTy::new_from_args(
- interner,
- def_id,
- projection_ty.substitution.to_nextsolver(interner),
- );
- rustc_type_ir::TyKind::Alias(
- rustc_type_ir::AliasTyKind::Projection,
- alias_ty,
- )
- }
- chalk_ir::AliasTy::Opaque(opaque_ty) => {
- let id: InternedOpaqueTyId = opaque_ty.opaque_ty_id.into();
- let def_id = SolverDefId::InternedOpaqueTyId(id);
- let alias_ty = rustc_type_ir::AliasTy::new_from_args(
- interner,
- def_id,
- opaque_ty.substitution.to_nextsolver(interner),
- );
- rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Opaque, alias_ty)
- }
- },
- chalk_ir::TyKind::Function(fn_pointer) => {
- let sig_tys = fn_pointer.clone().into_binders(Interner).to_nextsolver(interner);
- let header = rustc_type_ir::FnHeader {
- abi: fn_pointer.sig.abi,
- c_variadic: fn_pointer.sig.variadic,
- safety: match fn_pointer.sig.safety {
- chalk_ir::Safety::Safe => super::abi::Safety::Safe,
- chalk_ir::Safety::Unsafe => super::abi::Safety::Unsafe,
- },
- };
-
- rustc_type_ir::TyKind::FnPtr(sig_tys, header)
- }
- // The schema here is quite confusing.
- // The new solver, like rustc, uses `Param` and `EarlyBinder` for generic params. It uses `BoundVar`
- // and `Placeholder` together with `Binder` for HRTB, which we mostly don't handle.
- // Chalk uses `Placeholder` for generic params and `BoundVar` quite liberally, and this is quite a
- // problem. `chalk_ir::TyKind::BoundVar` can represent either HRTB or generic params, depending on the
- // context. When returned from signature queries, the outer `Binders` represent the generic params.
- // But there are also inner `Binders` for HRTB.
- // AFAIK there is no way to tell which of the meanings is relevant, so we just use `rustc_type_ir::Bound`
- // here, and hope for the best. If you are working with new solver types, therefore, use the new solver
- // lower queries.
- // Hopefully sooner than later Chalk will be ripped from the codebase and we can avoid that problem.
- // For details about the rustc setup, read: https://rustc-dev-guide.rust-lang.org/generic_parameters_summary.html
- // and the following chapters.
- chalk_ir::TyKind::Placeholder(placeholder_index) => {
- let (id, index) = from_placeholder_idx(interner.db, *placeholder_index);
- rustc_type_ir::TyKind::Param(ParamTy {
- id: TypeParamId::from_unchecked(id),
- index,
- })
- }
- chalk_ir::TyKind::BoundVar(bound_var) => rustc_type_ir::TyKind::Bound(
- bound_var.debruijn.to_nextsolver(interner),
- BoundTy {
- var: rustc_type_ir::BoundVar::from_usize(bound_var.index),
- kind: BoundTyKind::Anon,
- },
- ),
- chalk_ir::TyKind::InferenceVar(inference_var, ty_variable_kind) => {
- rustc_type_ir::TyKind::Infer(
- (*inference_var, *ty_variable_kind).to_nextsolver(interner),
- )
- }
- },
- )
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::Ty<Interner>> for Ty<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Ty<Interner> {
- convert_ty_for_result(interner, self)
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, Region<'db>> for chalk_ir::Lifetime<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> Region<'db> {
- Region::new(
- interner,
- match self.data(Interner) {
- chalk_ir::LifetimeData::BoundVar(bound_var) => rustc_type_ir::RegionKind::ReBound(
- bound_var.debruijn.to_nextsolver(interner),
- BoundRegion {
- var: rustc_type_ir::BoundVar::from_u32(bound_var.index as u32),
- kind: BoundRegionKind::Anon,
- },
- ),
- chalk_ir::LifetimeData::InferenceVar(inference_var) => {
- rustc_type_ir::RegionKind::ReVar(rustc_type_ir::RegionVid::from_u32(
- inference_var.index(),
- ))
- }
- chalk_ir::LifetimeData::Placeholder(placeholder_index) => {
- let (id, index) = lt_from_placeholder_idx(interner.db, *placeholder_index);
- rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion { id, index })
- }
- chalk_ir::LifetimeData::Static => rustc_type_ir::RegionKind::ReStatic,
- chalk_ir::LifetimeData::Erased => rustc_type_ir::RegionKind::ReErased,
- chalk_ir::LifetimeData::Phantom(_, _) => {
- unreachable!()
- }
- chalk_ir::LifetimeData::Error => {
- rustc_type_ir::RegionKind::ReError(ErrorGuaranteed)
- }
- },
- )
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::Lifetime<Interner>> for Region<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Lifetime<Interner> {
- convert_region_for_result(interner, self)
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, Const<'db>> for chalk_ir::Const<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> Const<'db> {
- let data = self.data(Interner);
- Const::new(
- interner,
- match &data.value {
- chalk_ir::ConstValue::BoundVar(bound_var) => rustc_type_ir::ConstKind::Bound(
- bound_var.debruijn.to_nextsolver(interner),
- BoundConst { var: rustc_type_ir::BoundVar::from_usize(bound_var.index) },
- ),
- chalk_ir::ConstValue::InferenceVar(inference_var) => {
- rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var(
- rustc_type_ir::ConstVid::from_u32(inference_var.index()),
- ))
- }
- chalk_ir::ConstValue::Placeholder(placeholder_index) => {
- let (id, index) = from_placeholder_idx(interner.db, *placeholder_index);
- rustc_type_ir::ConstKind::Param(ParamConst {
- id: ConstParamId::from_unchecked(id),
- index,
- })
- }
- chalk_ir::ConstValue::Concrete(concrete_const) => match &concrete_const.interned {
- ConstScalar::Bytes(bytes, memory) => {
- rustc_type_ir::ConstKind::Value(ValueConst::new(
- data.ty.to_nextsolver(interner),
- ConstBytes { memory: bytes.clone(), memory_map: memory.clone() },
- ))
- }
- ConstScalar::UnevaluatedConst(c, subst) => {
- let def = match *c {
- GeneralConstId::ConstId(id) => SolverDefId::ConstId(id),
- GeneralConstId::StaticId(id) => SolverDefId::StaticId(id),
- };
- let args = subst.to_nextsolver(interner);
- rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(def, args))
- }
- ConstScalar::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed),
- },
- },
- )
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::Const<Interner>> for Const<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Const<Interner> {
- convert_const_for_result(interner, self)
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, rustc_type_ir::FnSigTys<DbInterner<'db>>>
- for chalk_ir::FnSubst<Interner>
-{
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::FnSigTys<DbInterner<'db>> {
- rustc_type_ir::FnSigTys {
- inputs_and_output: Tys::new_from_iter(
- interner,
- self.0.iter(Interner).map(|g| g.assert_ty_ref(Interner).to_nextsolver(interner)),
- ),
- }
- }
-}
-
-impl<
- 'db,
- U: TypeVisitable<DbInterner<'db>>,
- T: Clone + ChalkToNextSolver<'db, U> + HasInterner<Interner = Interner>,
-> ChalkToNextSolver<'db, rustc_type_ir::Binder<DbInterner<'db>, U>> for chalk_ir::Binders<T>
-{
- fn to_nextsolver(
- &self,
- interner: DbInterner<'db>,
- ) -> rustc_type_ir::Binder<DbInterner<'db>, U> {
- let (val, binders) = self.clone().into_value_and_skipped_binders();
- rustc_type_ir::Binder::bind_with_vars(
- val.to_nextsolver(interner),
- binders.to_nextsolver(interner),
- )
- }
-}
-
-impl<'db, T: NextSolverToChalk<'db, U>, U: HasInterner<Interner = Interner>>
- NextSolverToChalk<'db, chalk_ir::Binders<U>> for rustc_type_ir::Binder<DbInterner<'db>, T>
-{
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Binders<U> {
- chalk_ir::Binders::new(
- self.bound_vars().to_chalk(interner),
- self.skip_binder().to_chalk(interner),
- )
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, BoundVarKinds<'db>> for chalk_ir::VariableKinds<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> BoundVarKinds<'db> {
- BoundVarKinds::new_from_iter(
- interner,
- self.iter(Interner).map(|v| v.to_nextsolver(interner)),
- )
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::VariableKinds<Interner>> for BoundVarKinds<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::VariableKinds<Interner> {
- chalk_ir::VariableKinds::from_iter(Interner, self.iter().map(|v| v.to_chalk(interner)))
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, BoundVarKind> for chalk_ir::VariableKind<Interner> {
- fn to_nextsolver(&self, _interner: DbInterner<'db>) -> BoundVarKind {
- match self {
- chalk_ir::VariableKind::Ty(_ty_variable_kind) => BoundVarKind::Ty(BoundTyKind::Anon),
- chalk_ir::VariableKind::Lifetime => BoundVarKind::Region(BoundRegionKind::Anon),
- chalk_ir::VariableKind::Const(_ty) => BoundVarKind::Const,
- }
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::VariableKind<Interner>> for BoundVarKind {
- fn to_chalk(self, _interner: DbInterner<'db>) -> chalk_ir::VariableKind<Interner> {
- match self {
- BoundVarKind::Ty(_) => chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
- BoundVarKind::Region(_) => chalk_ir::VariableKind::Lifetime,
- BoundVarKind::Const => {
- chalk_ir::VariableKind::Const(chalk_ir::TyKind::Error.intern(Interner))
- }
- }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, GenericArg<'db>> for chalk_ir::GenericArg<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArg<'db> {
- match self.data(Interner) {
- chalk_ir::GenericArgData::Ty(ty) => ty.to_nextsolver(interner).into(),
- chalk_ir::GenericArgData::Lifetime(lifetime) => lifetime.to_nextsolver(interner).into(),
- chalk_ir::GenericArgData::Const(const_) => const_.to_nextsolver(interner).into(),
- }
- }
-}
-
-impl<'db> NextSolverToChalk<'db, crate::GenericArg> for GenericArg<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> crate::GenericArg {
- match self {
- GenericArg::Ty(ty) => ty.to_chalk(interner).cast(Interner),
- GenericArg::Lifetime(region) => region.to_chalk(interner).cast(Interner),
- GenericArg::Const(konst) => konst.to_chalk(interner).cast(Interner),
- }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, GenericArgs<'db>> for chalk_ir::Substitution<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArgs<'db> {
- GenericArgs::new_from_iter(
- interner,
- self.iter(Interner).map(|arg| -> GenericArg<'db> { arg.to_nextsolver(interner) }),
- )
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, crate::lower_nextsolver::ImplTraitIdx<'db>>
- for crate::ImplTraitIdx
-{
- fn to_nextsolver(
- &self,
- _interner: DbInterner<'db>,
- ) -> crate::lower_nextsolver::ImplTraitIdx<'db> {
- crate::lower_nextsolver::ImplTraitIdx::from_raw(self.into_raw())
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::Substitution<Interner>> for GenericArgs<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Substitution<Interner> {
- convert_args_for_result(interner, self.as_slice())
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, Tys<'db>> for chalk_ir::Substitution<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> Tys<'db> {
- Tys::new_from_iter(
- interner,
- self.iter(Interner).map(|arg| -> Ty<'db> {
- match arg.data(Interner) {
- chalk_ir::GenericArgData::Ty(ty) => ty.to_nextsolver(interner),
- chalk_ir::GenericArgData::Lifetime(_) => unreachable!(),
- chalk_ir::GenericArgData::Const(_) => unreachable!(),
- }
- }),
- )
- }
-}
-
-impl<'db> NextSolverToChalk<'db, crate::Substitution> for Tys<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> crate::Substitution {
- Substitution::from_iter(
- Interner,
- self.inner().iter().map(|ty| ty.to_chalk(interner).cast(Interner)),
- )
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, rustc_type_ir::DebruijnIndex> for chalk_ir::DebruijnIndex {
- fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_type_ir::DebruijnIndex {
- rustc_type_ir::DebruijnIndex::from_u32(self.depth())
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::DebruijnIndex> for rustc_type_ir::DebruijnIndex {
- fn to_chalk(self, _interner: DbInterner<'db>) -> chalk_ir::DebruijnIndex {
- chalk_ir::DebruijnIndex::new(self.index() as u32)
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, rustc_type_ir::UniverseIndex> for chalk_ir::UniverseIndex {
- fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_type_ir::UniverseIndex {
- rustc_type_ir::UniverseIndex::from_u32(self.counter as u32)
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::UniverseIndex> for rustc_type_ir::UniverseIndex {
- fn to_chalk(self, _interner: DbInterner<'db>) -> chalk_ir::UniverseIndex {
- chalk_ir::UniverseIndex { counter: self.index() }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, rustc_type_ir::InferTy>
- for (chalk_ir::InferenceVar, chalk_ir::TyVariableKind)
-{
- fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_type_ir::InferTy {
- match self.1 {
- chalk_ir::TyVariableKind::General => {
- rustc_type_ir::InferTy::TyVar(rustc_type_ir::TyVid::from_u32(self.0.index()))
- }
- chalk_ir::TyVariableKind::Integer => {
- rustc_type_ir::InferTy::IntVar(rustc_type_ir::IntVid::from_u32(self.0.index()))
- }
- chalk_ir::TyVariableKind::Float => {
- rustc_type_ir::InferTy::FloatVar(rustc_type_ir::FloatVid::from_u32(self.0.index()))
- }
- }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, rustc_ast_ir::Mutability> for chalk_ir::Mutability {
- fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_ast_ir::Mutability {
- match self {
- chalk_ir::Mutability::Mut => rustc_ast_ir::Mutability::Mut,
- chalk_ir::Mutability::Not => rustc_ast_ir::Mutability::Not,
- }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, Goal<DbInterner<'db>, Predicate<'db>>>
- for chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>
-{
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> Goal<DbInterner<'db>, Predicate<'db>> {
- Goal::new(
- interner,
- self.environment.to_nextsolver(interner),
- self.goal.to_nextsolver(interner),
- )
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>>
- for Goal<DbInterner<'db>, Predicate<'db>>
-{
- fn to_chalk(
- self,
- interner: DbInterner<'db>,
- ) -> chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> {
- chalk_ir::InEnvironment {
- environment: self.param_env.to_chalk(interner),
- goal: self.predicate.to_chalk(interner),
- }
- }
-}
-
-impl<'db, T: HasInterner<Interner = Interner> + ChalkToNextSolver<'db, U>, U>
- ChalkToNextSolver<'db, Canonical<'db, U>> for chalk_ir::Canonical<T>
-{
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> Canonical<'db, U> {
- let variables = CanonicalVars::new_from_iter(
- interner,
- self.binders.iter(Interner).map(|k| match &k.kind {
- chalk_ir::VariableKind::Ty(ty_variable_kind) => match ty_variable_kind {
- // FIXME(next-solver): the info is incorrect, but we have no way to store the information in Chalk.
- TyVariableKind::General => rustc_type_ir::CanonicalVarKind::Ty {
- ui: UniverseIndex::ROOT,
- sub_root: BoundVar::from_u32(0),
- },
- TyVariableKind::Integer => rustc_type_ir::CanonicalVarKind::Int,
- TyVariableKind::Float => rustc_type_ir::CanonicalVarKind::Float,
- },
- chalk_ir::VariableKind::Lifetime => {
- rustc_type_ir::CanonicalVarKind::Region(UniverseIndex::ROOT)
- }
- chalk_ir::VariableKind::Const(_ty) => {
- rustc_type_ir::CanonicalVarKind::Const(UniverseIndex::ROOT)
- }
- }),
- );
- Canonical {
- max_universe: UniverseIndex::ROOT,
- value: self.value.to_nextsolver(interner),
- variables,
- }
- }
-}
-
-impl<'db, T: NextSolverToChalk<'db, U>, U: HasInterner<Interner = Interner>>
- NextSolverToChalk<'db, chalk_ir::Canonical<U>> for Canonical<'db, T>
-{
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Canonical<U> {
- let binders = chalk_ir::CanonicalVarKinds::from_iter(
- Interner,
- self.variables.iter().map(|v| match v {
- rustc_type_ir::CanonicalVarKind::Ty { ui, sub_root: _ } => {
- chalk_ir::CanonicalVarKind::new(
- chalk_ir::VariableKind::Ty(TyVariableKind::General),
- chalk_ir::UniverseIndex { counter: ui.as_usize() },
- )
- }
- rustc_type_ir::CanonicalVarKind::Int => chalk_ir::CanonicalVarKind::new(
- chalk_ir::VariableKind::Ty(TyVariableKind::Integer),
- chalk_ir::UniverseIndex::root(),
- ),
- rustc_type_ir::CanonicalVarKind::Float => chalk_ir::CanonicalVarKind::new(
- chalk_ir::VariableKind::Ty(TyVariableKind::Float),
- chalk_ir::UniverseIndex::root(),
- ),
- rustc_type_ir::CanonicalVarKind::Region(ui) => chalk_ir::CanonicalVarKind::new(
- chalk_ir::VariableKind::Lifetime,
- chalk_ir::UniverseIndex { counter: ui.as_usize() },
- ),
- rustc_type_ir::CanonicalVarKind::Const(ui) => chalk_ir::CanonicalVarKind::new(
- chalk_ir::VariableKind::Const(chalk_ir::TyKind::Error.intern(Interner)),
- chalk_ir::UniverseIndex { counter: ui.as_usize() },
- ),
- rustc_type_ir::CanonicalVarKind::PlaceholderTy(_) => unimplemented!(),
- rustc_type_ir::CanonicalVarKind::PlaceholderRegion(_) => unimplemented!(),
- rustc_type_ir::CanonicalVarKind::PlaceholderConst(_) => unimplemented!(),
- }),
- );
- let value = self.value.to_chalk(interner);
- chalk_ir::Canonical { binders, value }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, Predicate<'db>> for chalk_ir::Goal<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> Predicate<'db> {
- match self.data(Interner) {
- chalk_ir::GoalData::Quantified(_quantifier_kind, binders) => {
- if !binders.binders.is_empty(Interner) {
- panic!("Should not be constructed.");
- }
- let (val, _) = binders.clone().into_value_and_skipped_binders();
- val.shifted_out(Interner).unwrap().to_nextsolver(interner)
- }
- chalk_ir::GoalData::Implies(_program_clauses, _goal) => {
- panic!("Should not be constructed.")
- }
- chalk_ir::GoalData::All(_goals) => panic!("Should not be constructed."),
- chalk_ir::GoalData::Not(_goal) => panic!("Should not be constructed."),
- chalk_ir::GoalData::EqGoal(eq_goal) => {
- let arg_to_term = |g: &chalk_ir::GenericArg<Interner>| match g.data(Interner) {
- chalk_ir::GenericArgData::Ty(ty) => Term::Ty(ty.to_nextsolver(interner)),
- chalk_ir::GenericArgData::Const(const_) => {
- Term::Const(const_.to_nextsolver(interner))
- }
- chalk_ir::GenericArgData::Lifetime(_lifetime) => unreachable!(),
- };
- let pred_kind = PredicateKind::AliasRelate(
- arg_to_term(&eq_goal.a),
- arg_to_term(&eq_goal.b),
- rustc_type_ir::AliasRelationDirection::Equate,
- );
- let pred_kind =
- Binder::bind_with_vars(pred_kind, BoundVarKinds::new_from_iter(interner, []));
- Predicate::new(interner, pred_kind)
- }
- chalk_ir::GoalData::SubtypeGoal(subtype_goal) => {
- let subtype_predicate = SubtypePredicate {
- a: subtype_goal.a.to_nextsolver(interner),
- b: subtype_goal.b.to_nextsolver(interner),
- a_is_expected: true,
- };
- let pred_kind = PredicateKind::Subtype(subtype_predicate);
- let pred_kind = Binder::bind_with_vars(
- shift_vars(interner, pred_kind, 1),
- BoundVarKinds::new_from_iter(interner, []),
- );
- Predicate::new(interner, pred_kind)
- }
- chalk_ir::GoalData::DomainGoal(domain_goal) => {
- let pred_kind = domain_goal.to_nextsolver(interner);
- let pred_kind = Binder::bind_with_vars(
- shift_vars(interner, pred_kind, 1),
- BoundVarKinds::new_from_iter(interner, []),
- );
- Predicate::new(interner, pred_kind)
- }
- chalk_ir::GoalData::CannotProve => panic!("Should not be constructed."),
- }
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::Goal<Interner>> for Predicate<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Goal<Interner> {
- chalk_ir::Goal::new(Interner, self.kind().skip_binder().to_chalk(interner))
- }
-}
-
-impl<'db> NextSolverToChalk<'db, crate::ProjectionTy> for crate::next_solver::AliasTy<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> crate::ProjectionTy {
- let SolverDefId::TypeAliasId(assoc_id) = self.def_id else { unreachable!() };
- crate::ProjectionTy {
- associated_ty_id: to_assoc_type_id(assoc_id),
- substitution: self.args.to_chalk(interner),
- }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, ParamEnv<'db>> for chalk_ir::Environment<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> ParamEnv<'db> {
- let clauses = Clauses::new_from_iter(
- interner,
- self.clauses.iter(Interner).map(|c| c.to_nextsolver(interner)),
- );
- let clauses =
- Clauses::new_from_iter(interner, elaborate::elaborate(interner, clauses.iter()));
- ParamEnv { clauses }
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::Environment<Interner>> for ParamEnv<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Environment<Interner> {
- let clauses = chalk_ir::ProgramClauses::from_iter(
- Interner,
- self.clauses.iter().filter_map(|c| -> Option<chalk_ir::ProgramClause<Interner>> {
- c.to_chalk(interner)
- }),
- );
- chalk_ir::Environment { clauses }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, Clause<'db>> for chalk_ir::ProgramClause<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> Clause<'db> {
- Clause(Predicate::new(interner, self.data(Interner).0.to_nextsolver(interner)))
- }
-}
-
-impl<'db> NextSolverToChalk<'db, Option<chalk_ir::ProgramClause<Interner>>> for Clause<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> Option<chalk_ir::ProgramClause<Interner>> {
- let value: chalk_ir::ProgramClauseImplication<Interner> =
- <PredicateKind<'db> as NextSolverToChalk<
- 'db,
- Option<chalk_ir::ProgramClauseImplication<Interner>>,
- >>::to_chalk(self.0.kind().skip_binder(), interner)?;
- Some(chalk_ir::ProgramClause::new(
- Interner,
- chalk_ir::ProgramClauseData(chalk_ir::Binders::empty(Interner, value)),
- ))
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>>
- for chalk_ir::ProgramClauseImplication<Interner>
-{
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> {
- assert!(self.conditions.is_empty(Interner));
- assert!(self.constraints.is_empty(Interner));
- self.consequence.to_nextsolver(interner)
- }
-}
-
-impl<'db> NextSolverToChalk<'db, Option<chalk_ir::ProgramClauseImplication<Interner>>>
- for PredicateKind<'db>
-{
- fn to_chalk(
- self,
- interner: DbInterner<'db>,
- ) -> Option<chalk_ir::ProgramClauseImplication<Interner>> {
- let chalk_ir::GoalData::DomainGoal(consequence) = self.to_chalk(interner) else {
- return None;
- };
-
- Some(chalk_ir::ProgramClauseImplication {
- consequence,
- conditions: chalk_ir::Goals::empty(Interner),
- constraints: chalk_ir::Constraints::empty(Interner),
- priority: chalk_ir::ClausePriority::High,
- })
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> for chalk_ir::DomainGoal<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> {
- match self {
- chalk_ir::DomainGoal::Holds(where_clause) => match where_clause {
- chalk_ir::WhereClause::Implemented(trait_ref) => {
- let predicate = TraitPredicate {
- trait_ref: trait_ref.to_nextsolver(interner),
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- };
- PredicateKind::Clause(ClauseKind::Trait(predicate))
- }
- chalk_ir::WhereClause::AliasEq(alias_eq) => match &alias_eq.alias {
- chalk_ir::AliasTy::Projection(p) => {
- let def_id =
- SolverDefId::TypeAliasId(from_assoc_type_id(p.associated_ty_id));
- let args = p.substitution.to_nextsolver(interner);
- let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner);
- let term: Term<'db> = term.into();
- let predicate = ProjectionPredicate {
- projection_term: AliasTerm::new_from_args(interner, def_id, args),
- term,
- };
- PredicateKind::Clause(ClauseKind::Projection(predicate))
- }
- chalk_ir::AliasTy::Opaque(opaque) => {
- let id: InternedOpaqueTyId = opaque.opaque_ty_id.into();
- let def_id = SolverDefId::InternedOpaqueTyId(id);
- let args = opaque.substitution.to_nextsolver(interner);
- let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner);
- let term: Term<'db> = term.into();
- let opaque_ty = Ty::new(
- interner,
- rustc_type_ir::TyKind::Alias(
- rustc_type_ir::AliasTyKind::Opaque,
- rustc_type_ir::AliasTy::new_from_args(interner, def_id, args),
- ),
- )
- .into();
- PredicateKind::AliasRelate(
- opaque_ty,
- term,
- rustc_type_ir::AliasRelationDirection::Equate,
- )
- }
- },
- chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => {
- let predicate = OutlivesPredicate(
- lifetime_outlives.a.to_nextsolver(interner),
- lifetime_outlives.b.to_nextsolver(interner),
- );
- PredicateKind::Clause(ClauseKind::RegionOutlives(predicate))
- }
- chalk_ir::WhereClause::TypeOutlives(type_outlives) => {
- let predicate = OutlivesPredicate(
- type_outlives.ty.to_nextsolver(interner),
- type_outlives.lifetime.to_nextsolver(interner),
- );
- PredicateKind::Clause(ClauseKind::TypeOutlives(predicate))
- }
- },
- chalk_ir::DomainGoal::Normalize(normalize) => {
- let proj_ty = match &normalize.alias {
- chalk_ir::AliasTy::Projection(proj) => proj,
- _ => unimplemented!(),
- };
- let args: GenericArgs<'db> = proj_ty.substitution.to_nextsolver(interner);
- let alias = Ty::new(
- interner,
- rustc_type_ir::TyKind::Alias(
- rustc_type_ir::AliasTyKind::Projection,
- rustc_type_ir::AliasTy::new(
- interner,
- from_assoc_type_id(proj_ty.associated_ty_id).into(),
- args,
- ),
- ),
- )
- .into();
- let term = normalize.ty.to_nextsolver(interner).into();
- PredicateKind::AliasRelate(
- alias,
- term,
- rustc_type_ir::AliasRelationDirection::Equate,
- )
- }
- chalk_ir::DomainGoal::WellFormed(well_formed) => {
- let term = match well_formed {
- WellFormed::Trait(_) => panic!("Should not be constructed."),
- WellFormed::Ty(ty) => Term::Ty(ty.to_nextsolver(interner)),
- };
- PredicateKind::Clause(rustc_type_ir::ClauseKind::WellFormed(term))
- }
- chalk_ir::DomainGoal::FromEnv(from_env) => match from_env {
- chalk_ir::FromEnv::Trait(trait_ref) => {
- let predicate = TraitPredicate {
- trait_ref: trait_ref.to_nextsolver(interner),
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- };
- PredicateKind::Clause(ClauseKind::Trait(predicate))
- }
- chalk_ir::FromEnv::Ty(ty) => PredicateKind::Clause(ClauseKind::WellFormed(
- Term::Ty(ty.to_nextsolver(interner)),
- )),
- },
- chalk_ir::DomainGoal::IsLocal(_ty) => panic!("Should not be constructed."),
- chalk_ir::DomainGoal::IsUpstream(_ty) => panic!("Should not be constructed."),
- chalk_ir::DomainGoal::IsFullyVisible(_ty) => panic!("Should not be constructed."),
- chalk_ir::DomainGoal::LocalImplAllowed(_trait_ref) => {
- panic!("Should not be constructed.")
- }
- chalk_ir::DomainGoal::Compatible => panic!("Should not be constructed."),
- chalk_ir::DomainGoal::DownstreamType(_ty) => panic!("Should not be constructed."),
- chalk_ir::DomainGoal::Reveal => panic!("Should not be constructed."),
- chalk_ir::DomainGoal::ObjectSafe(_trait_id) => panic!("Should not be constructed."),
- }
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::GoalData<Interner>> for PredicateKind<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::GoalData<Interner> {
- match self {
- rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait(trait_pred)) => {
- let trait_ref = trait_pred.trait_ref.to_chalk(interner);
- let where_clause = chalk_ir::WhereClause::Implemented(trait_ref);
- chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause))
- }
- rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Projection(
- proj_predicate,
- )) => {
- let associated_ty_id = match proj_predicate.def_id() {
- SolverDefId::TypeAliasId(id) => to_assoc_type_id(id),
- _ => unreachable!(),
- };
- let substitution = proj_predicate.projection_term.args.to_chalk(interner);
- let alias = chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
- associated_ty_id,
- substitution,
- });
- let ty = match proj_predicate.term.kind() {
- rustc_type_ir::TermKind::Ty(ty) => ty,
- rustc_type_ir::TermKind::Const(_) => unimplemented!(),
- };
- let ty = ty.to_chalk(interner);
- let alias_eq = chalk_ir::AliasEq { alias, ty };
- let where_clause = chalk_ir::WhereClause::AliasEq(alias_eq);
- chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause))
- }
- rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::TypeOutlives(
- outlives,
- )) => {
- let lifetime = outlives.1.to_chalk(interner);
- let ty = outlives.0.to_chalk(interner);
- let where_clause =
- chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives { lifetime, ty });
- chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause))
- }
- rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::RegionOutlives(
- outlives,
- )) => {
- let a = outlives.0.to_chalk(interner);
- let b = outlives.1.to_chalk(interner);
- let where_clause =
- chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { a, b });
- chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause))
- }
- rustc_type_ir::PredicateKind::AliasRelate(
- alias_term,
- target_term,
- _alias_relation_direction,
- ) => {
- let term_to_generic_arg = |term: Term<'db>| match term {
- Term::Ty(ty) => chalk_ir::GenericArg::new(
- Interner,
- chalk_ir::GenericArgData::Ty(ty.to_chalk(interner)),
- ),
- Term::Const(const_) => chalk_ir::GenericArg::new(
- Interner,
- chalk_ir::GenericArgData::Const(const_.to_chalk(interner)),
- ),
- };
-
- chalk_ir::GoalData::EqGoal(chalk_ir::EqGoal {
- a: term_to_generic_arg(alias_term),
- b: term_to_generic_arg(target_term),
- })
- }
- rustc_type_ir::PredicateKind::Clause(_) => unimplemented!(),
- rustc_type_ir::PredicateKind::DynCompatible(_) => unimplemented!(),
- rustc_type_ir::PredicateKind::Subtype(_) => unimplemented!(),
- rustc_type_ir::PredicateKind::Coerce(_) => unimplemented!(),
- rustc_type_ir::PredicateKind::ConstEquate(_, _) => unimplemented!(),
- rustc_type_ir::PredicateKind::Ambiguous => unimplemented!(),
- rustc_type_ir::PredicateKind::NormalizesTo(_) => unimplemented!(),
- }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, TraitRef<'db>> for chalk_ir::TraitRef<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> TraitRef<'db> {
- let args = self.substitution.to_nextsolver(interner);
- TraitRef::new_from_args(interner, from_chalk_trait_id(self.trait_id).into(), args)
- }
-}
-
-impl<'db> NextSolverToChalk<'db, chalk_ir::TraitRef<Interner>> for TraitRef<'db> {
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::TraitRef<Interner> {
- let trait_id = to_chalk_trait_id(self.def_id.0);
- let substitution = self.args.to_chalk(interner);
- chalk_ir::TraitRef { trait_id, substitution }
- }
-}
-
-impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> for chalk_ir::WhereClause<Interner> {
- fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> {
- match self {
- chalk_ir::WhereClause::Implemented(trait_ref) => {
- let predicate = TraitPredicate {
- trait_ref: trait_ref.to_nextsolver(interner),
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- };
- PredicateKind::Clause(ClauseKind::Trait(predicate))
- }
- chalk_ir::WhereClause::AliasEq(alias_eq) => {
- let projection = match &alias_eq.alias {
- chalk_ir::AliasTy::Projection(p) => p,
- _ => unimplemented!(),
- };
- let def_id =
- SolverDefId::TypeAliasId(from_assoc_type_id(projection.associated_ty_id));
- let args = projection.substitution.to_nextsolver(interner);
- let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner);
- let term: Term<'db> = term.into();
- let predicate = ProjectionPredicate {
- projection_term: AliasTerm::new_from_args(interner, def_id, args),
- term,
- };
- PredicateKind::Clause(ClauseKind::Projection(predicate))
- }
- chalk_ir::WhereClause::TypeOutlives(type_outlives) => {
- let ty = type_outlives.ty.to_nextsolver(interner);
- let r = type_outlives.lifetime.to_nextsolver(interner);
- PredicateKind::Clause(ClauseKind::TypeOutlives(OutlivesPredicate(ty, r)))
- }
- chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => {
- let a = lifetime_outlives.a.to_nextsolver(interner);
- let b = lifetime_outlives.b.to_nextsolver(interner);
- PredicateKind::Clause(ClauseKind::RegionOutlives(OutlivesPredicate(a, b)))
- }
- }
- }
-}
-
-impl<'db, I> NextSolverToChalk<'db, chalk_ir::ConstrainedSubst<Interner>> for I
-where
- I: IntoIterator<Item = GenericArg<'db>>,
-{
- fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::ConstrainedSubst<Interner> {
- chalk_ir::ConstrainedSubst {
- constraints: chalk_ir::Constraints::empty(Interner),
- subst: GenericArgs::new_from_iter(interner, self).to_chalk(interner),
- }
- }
-}
-
-impl<'db> NextSolverToChalk<'db, crate::CallableSig> for rustc_type_ir::FnSig<DbInterner<'db>> {
- fn to_chalk(self, interner: DbInterner<'db>) -> crate::CallableSig {
- crate::CallableSig {
- abi: self.abi,
- is_varargs: self.c_variadic,
- safety: match self.safety {
- super::abi::Safety::Safe => chalk_ir::Safety::Safe,
- super::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe,
- },
- params_and_return: triomphe::Arc::from_iter(
- self.inputs_and_output.iter().map(|ty| convert_ty_for_result(interner, ty)),
- ),
- }
- }
-}
-
-pub fn convert_canonical_args_for_result<'db>(
- interner: DbInterner<'db>,
- args: Canonical<'db, Vec<GenericArg<'db>>>,
-) -> chalk_ir::Canonical<chalk_ir::ConstrainedSubst<Interner>> {
- args.to_chalk(interner)
-}
-
-pub fn convert_args_for_result<'db>(
- interner: DbInterner<'db>,
- args: &[GenericArg<'db>],
-) -> crate::Substitution {
- let mut substs = Vec::with_capacity(args.len());
- for arg in args {
- match (*arg).kind() {
- rustc_type_ir::GenericArgKind::Type(ty) => {
- let ty = convert_ty_for_result(interner, ty);
- substs.push(chalk_ir::GenericArgData::Ty(ty).intern(Interner));
- }
- rustc_type_ir::GenericArgKind::Lifetime(region) => {
- let lifetime = convert_region_for_result(interner, region);
- substs.push(chalk_ir::GenericArgData::Lifetime(lifetime).intern(Interner));
- }
- rustc_type_ir::GenericArgKind::Const(const_) => {
- substs.push(
- chalk_ir::GenericArgData::Const(convert_const_for_result(interner, const_))
- .intern(Interner),
- );
- }
- }
- }
- Substitution::from_iter(Interner, substs)
-}
-
-pub fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) -> crate::Ty {
- use crate::{Scalar, TyKind};
- use chalk_ir::{FloatTy, IntTy, UintTy};
- match ty.kind() {
- rustc_type_ir::TyKind::Bool => TyKind::Scalar(Scalar::Bool),
- rustc_type_ir::TyKind::Char => TyKind::Scalar(Scalar::Char),
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I8) => {
- TyKind::Scalar(Scalar::Int(IntTy::I8))
- }
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I16) => {
- TyKind::Scalar(Scalar::Int(IntTy::I16))
- }
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I32) => {
- TyKind::Scalar(Scalar::Int(IntTy::I32))
- }
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I64) => {
- TyKind::Scalar(Scalar::Int(IntTy::I64))
- }
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I128) => {
- TyKind::Scalar(Scalar::Int(IntTy::I128))
- }
- rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::Isize) => {
- TyKind::Scalar(Scalar::Int(IntTy::Isize))
- }
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U8) => {
- TyKind::Scalar(Scalar::Uint(UintTy::U8))
- }
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U16) => {
- TyKind::Scalar(Scalar::Uint(UintTy::U16))
- }
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U32) => {
- TyKind::Scalar(Scalar::Uint(UintTy::U32))
- }
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U64) => {
- TyKind::Scalar(Scalar::Uint(UintTy::U64))
- }
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U128) => {
- TyKind::Scalar(Scalar::Uint(UintTy::U128))
- }
- rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::Usize) => {
- TyKind::Scalar(Scalar::Uint(UintTy::Usize))
- }
- rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F16) => {
- TyKind::Scalar(Scalar::Float(FloatTy::F16))
- }
- rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F32) => {
- TyKind::Scalar(Scalar::Float(FloatTy::F32))
- }
- rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F64) => {
- TyKind::Scalar(Scalar::Float(FloatTy::F64))
- }
- rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F128) => {
- TyKind::Scalar(Scalar::Float(FloatTy::F128))
- }
- rustc_type_ir::TyKind::Str => TyKind::Str,
- rustc_type_ir::TyKind::Error(_) => TyKind::Error,
- rustc_type_ir::TyKind::Never => TyKind::Never,
-
- rustc_type_ir::TyKind::Adt(def, args) => {
- let adt_id = def.inner().id;
- let subst = convert_args_for_result(interner, args.as_slice());
- TyKind::Adt(chalk_ir::AdtId(adt_id), subst)
- }
-
- rustc_type_ir::TyKind::Infer(infer_ty) => {
- let (var, kind) = match infer_ty {
- rustc_type_ir::InferTy::TyVar(var) => {
- (InferenceVar::from(var.as_u32()), TyVariableKind::General)
- }
- rustc_type_ir::InferTy::IntVar(var) => {
- (InferenceVar::from(var.as_u32()), TyVariableKind::Integer)
- }
- rustc_type_ir::InferTy::FloatVar(var) => {
- (InferenceVar::from(var.as_u32()), TyVariableKind::Float)
- }
- rustc_type_ir::InferTy::FreshFloatTy(..)
- | rustc_type_ir::InferTy::FreshIntTy(..)
- | rustc_type_ir::InferTy::FreshTy(..) => {
- panic!("Freshening shouldn't happen.")
- }
- };
- TyKind::InferenceVar(var, kind)
- }
-
- rustc_type_ir::TyKind::Ref(r, ty, mutability) => {
- let mutability = match mutability {
- rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut,
- rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not,
- };
- let r = convert_region_for_result(interner, r);
- let ty = convert_ty_for_result(interner, ty);
- TyKind::Ref(mutability, r, ty)
- }
-
- rustc_type_ir::TyKind::Tuple(tys) => {
- let size = tys.len();
- let subst = Substitution::from_iter(
- Interner,
- tys.iter().map(|ty| {
- chalk_ir::GenericArgData::Ty(convert_ty_for_result(interner, ty))
- .intern(Interner)
- }),
- );
- TyKind::Tuple(size, subst)
- }
-
- rustc_type_ir::TyKind::Array(ty, const_) => {
- let ty = convert_ty_for_result(interner, ty);
- let const_ = convert_const_for_result(interner, const_);
- TyKind::Array(ty, const_)
- }
-
- rustc_type_ir::TyKind::Alias(alias_ty_kind, alias_ty) => match alias_ty_kind {
- rustc_type_ir::AliasTyKind::Projection => {
- let assoc_ty_id = match alias_ty.def_id {
- SolverDefId::TypeAliasId(id) => id,
- _ => unreachable!(),
- };
- let associated_ty_id = to_assoc_type_id(assoc_ty_id);
- let substitution = convert_args_for_result(interner, alias_ty.args.as_slice());
- TyKind::Alias(crate::AliasTy::Projection(crate::ProjectionTy {
- associated_ty_id,
- substitution,
- }))
- }
- rustc_type_ir::AliasTyKind::Opaque => {
- let opaque_ty_id = match alias_ty.def_id {
- SolverDefId::InternedOpaqueTyId(id) => id,
- _ => unreachable!(),
- };
- let substitution = convert_args_for_result(interner, alias_ty.args.as_slice());
- TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
- opaque_ty_id: opaque_ty_id.into(),
- substitution,
- }))
- }
- rustc_type_ir::AliasTyKind::Inherent => unimplemented!(),
- rustc_type_ir::AliasTyKind::Free => unimplemented!(),
- },
-
- // For `Placeholder`, `Bound` and `Param`, see the comment on the reverse conversion.
- rustc_type_ir::TyKind::Placeholder(_placeholder) => {
- unimplemented!(
- "A `rustc_type_ir::TyKind::Placeholder` doesn't have a direct \
- correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
- It therefore feels safer to leave it panicking, but if you hit this panic \
- feel free to do the same as in `rustc_type_ir::TyKind::Bound` here."
- )
- }
- rustc_type_ir::TyKind::Bound(debruijn_index, ty) => TyKind::BoundVar(chalk_ir::BoundVar {
- debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
- index: ty.var.as_usize(),
- }),
- rustc_type_ir::TyKind::Param(param) => {
- let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index);
- TyKind::Placeholder(placeholder)
- }
-
- rustc_type_ir::TyKind::FnPtr(bound_sig, fn_header) => {
- let num_binders = bound_sig.bound_vars().len();
- let sig = chalk_ir::FnSig {
- abi: fn_header.abi,
- safety: match fn_header.safety {
- crate::next_solver::abi::Safety::Safe => chalk_ir::Safety::Safe,
- crate::next_solver::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe,
- },
- variadic: fn_header.c_variadic,
- };
- let args = GenericArgs::new_from_iter(
- interner,
- bound_sig.skip_binder().inputs_and_output.iter().map(|a| a.into()),
- );
- let substitution = convert_args_for_result(interner, args.as_slice());
- let substitution = chalk_ir::FnSubst(substitution);
- let fnptr = chalk_ir::FnPointer { num_binders, sig, substitution };
- TyKind::Function(fnptr)
- }
-
- rustc_type_ir::TyKind::Dynamic(preds, region) => {
- let self_ty = Ty::new_bound(
- interner,
- DebruijnIndex::from_u32(1),
- BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_u32(0) },
- );
- let bounds = chalk_ir::QuantifiedWhereClauses::from_iter(
- Interner,
- preds.iter().map(|p| {
- let binders = chalk_ir::VariableKinds::from_iter(
- Interner,
- p.bound_vars().iter().map(|b| match b {
- BoundVarKind::Ty(_kind) => {
- chalk_ir::VariableKind::Ty(TyVariableKind::General)
- }
- BoundVarKind::Region(_kind) => chalk_ir::VariableKind::Lifetime,
- BoundVarKind::Const => {
- chalk_ir::VariableKind::Const(crate::TyKind::Error.intern(Interner))
- }
- }),
- );
-
- // Rust and chalk have slightly different
- // representation for trait objects.
- //
- // Chalk uses `for<T0> for<'a> T0: Trait<'a>` while rustc
- // uses `ExistentialPredicate`s, which do not have a self ty.
- // We need to shift escaping bound vars by 1 to accommodate
- // the newly introduced `for<T0>` binder.
- let p = shift_vars(interner, p, 1);
-
- let where_clause = match p.skip_binder() {
- rustc_type_ir::ExistentialPredicate::Trait(trait_ref) => {
- let trait_ref = TraitRef::new(
- interner,
- trait_ref.def_id,
- [self_ty.into()].into_iter().chain(trait_ref.args.iter()),
- );
- let trait_id = to_chalk_trait_id(trait_ref.def_id.0);
- let substitution =
- convert_args_for_result(interner, trait_ref.args.as_slice());
- let trait_ref = chalk_ir::TraitRef { trait_id, substitution };
- chalk_ir::WhereClause::Implemented(trait_ref)
- }
- rustc_type_ir::ExistentialPredicate::AutoTrait(trait_) => {
- let trait_id = to_chalk_trait_id(trait_.0);
- let substitution = chalk_ir::Substitution::from1(
- Interner,
- convert_ty_for_result(interner, self_ty),
- );
- let trait_ref = chalk_ir::TraitRef { trait_id, substitution };
- chalk_ir::WhereClause::Implemented(trait_ref)
- }
- rustc_type_ir::ExistentialPredicate::Projection(existential_projection) => {
- let projection = ProjectionPredicate {
- projection_term: AliasTerm::new(
- interner,
- existential_projection.def_id,
- [self_ty.into()]
- .iter()
- .chain(existential_projection.args.iter()),
- ),
- term: existential_projection.term,
- };
- let associated_ty_id = match projection.projection_term.def_id {
- SolverDefId::TypeAliasId(id) => to_assoc_type_id(id),
- _ => unreachable!(),
- };
- let substitution = convert_args_for_result(
- interner,
- projection.projection_term.args.as_slice(),
- );
- let alias = chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
- associated_ty_id,
- substitution,
- });
- let ty = match projection.term {
- Term::Ty(ty) => ty,
- _ => unreachable!(),
- };
- let ty = convert_ty_for_result(interner, ty);
- let alias_eq = chalk_ir::AliasEq { alias, ty };
- chalk_ir::WhereClause::AliasEq(alias_eq)
- }
- };
- chalk_ir::Binders::new(binders, where_clause)
- }),
- );
- let binders = chalk_ir::VariableKinds::from1(
- Interner,
- chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
- );
- let bounds = chalk_ir::Binders::new(binders, bounds);
- let dyn_ty =
- chalk_ir::DynTy { bounds, lifetime: convert_region_for_result(interner, region) };
- TyKind::Dyn(dyn_ty)
- }
-
- rustc_type_ir::TyKind::Slice(ty) => {
- let ty = convert_ty_for_result(interner, ty);
- TyKind::Slice(ty)
- }
-
- rustc_type_ir::TyKind::Foreign(foreign) => TyKind::Foreign(to_foreign_def_id(foreign.0)),
- rustc_type_ir::TyKind::Pat(_, _) => unimplemented!(),
- rustc_type_ir::TyKind::RawPtr(ty, mutability) => {
- let mutability = match mutability {
- rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut,
- rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not,
- };
- let ty = convert_ty_for_result(interner, ty);
- TyKind::Raw(mutability, ty)
- }
- rustc_type_ir::TyKind::FnDef(def_id, args) => {
- let subst = convert_args_for_result(interner, args.as_slice());
- TyKind::FnDef(def_id.0.to_chalk(interner.db()), subst)
- }
-
- rustc_type_ir::TyKind::Closure(def_id, args) => {
- let subst = convert_args_for_result(interner, args.as_slice());
- TyKind::Closure(def_id.0.into(), subst)
- }
- rustc_type_ir::TyKind::CoroutineClosure(_, _) => unimplemented!(),
- rustc_type_ir::TyKind::Coroutine(def_id, args) => {
- let subst = convert_args_for_result(interner, args.as_slice());
- TyKind::Coroutine(def_id.0.into(), subst)
- }
- rustc_type_ir::TyKind::CoroutineWitness(def_id, args) => {
- let subst = convert_args_for_result(interner, args.as_slice());
- TyKind::CoroutineWitness(def_id.0.into(), subst)
- }
-
- rustc_type_ir::TyKind::UnsafeBinder(_) => unimplemented!(),
- }
- .intern(Interner)
-}
-
-pub fn convert_const_for_result<'db>(
- interner: DbInterner<'db>,
- const_: Const<'db>,
-) -> crate::Const {
- let value: chalk_ir::ConstValue<Interner> = match const_.kind() {
- rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var(var)) => {
- chalk_ir::ConstValue::InferenceVar(chalk_ir::InferenceVar::from(var.as_u32()))
- }
- rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Fresh(_fresh)) => {
- panic!("Vars should not be freshened.")
- }
- rustc_type_ir::ConstKind::Param(param) => {
- let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index);
- chalk_ir::ConstValue::Placeholder(placeholder)
- }
- rustc_type_ir::ConstKind::Bound(debruijn_index, var) => {
- chalk_ir::ConstValue::BoundVar(chalk_ir::BoundVar::new(
- chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
- var.var.index(),
- ))
- }
- rustc_type_ir::ConstKind::Placeholder(_placeholder_const) => {
- unimplemented!(
- "A `rustc_type_ir::ConstKind::Placeholder` doesn't have a direct \
- correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
- It therefore feels safer to leave it panicking, but if you hit this panic \
- feel free to do the same as in `rustc_type_ir::ConstKind::Bound` here."
- )
- }
- rustc_type_ir::ConstKind::Unevaluated(unevaluated_const) => {
- let id = match unevaluated_const.def {
- SolverDefId::ConstId(id) => GeneralConstId::ConstId(id),
- SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
- _ => unreachable!(),
- };
- let subst = convert_args_for_result(interner, unevaluated_const.args.as_slice());
- chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
- interned: ConstScalar::UnevaluatedConst(id, subst),
- })
- }
- rustc_type_ir::ConstKind::Value(value_const) => {
- let bytes = value_const.value.inner();
- let value = chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
- // SAFETY: we will never actually use this without a database
- interned: ConstScalar::Bytes(bytes.memory.clone(), unsafe {
- std::mem::transmute::<MemoryMap<'db>, MemoryMap<'static>>(
- bytes.memory_map.clone(),
- )
- }),
- });
- return chalk_ir::ConstData {
- ty: convert_ty_for_result(interner, value_const.ty),
- value,
- }
- .intern(Interner);
- }
- rustc_type_ir::ConstKind::Error(_) => {
- chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
- interned: ConstScalar::Unknown,
- })
- }
- rustc_type_ir::ConstKind::Expr(_) => unimplemented!(),
- };
- chalk_ir::ConstData { ty: crate::TyKind::Error.intern(Interner), value }.intern(Interner)
-}
-
-pub fn convert_region_for_result<'db>(
- interner: DbInterner<'db>,
- region: Region<'db>,
-) -> crate::Lifetime {
- let lifetime = match region.kind() {
- rustc_type_ir::RegionKind::ReEarlyParam(early) => {
- let placeholder = lt_to_placeholder_idx(interner.db, early.id, early.index);
- chalk_ir::LifetimeData::Placeholder(placeholder)
- }
- rustc_type_ir::RegionKind::ReBound(db, bound) => {
- chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new(
- chalk_ir::DebruijnIndex::new(db.as_u32()),
- bound.var.as_usize(),
- ))
- }
- rustc_type_ir::RegionKind::RePlaceholder(_placeholder) => unimplemented!(
- "A `rustc_type_ir::RegionKind::RePlaceholder` doesn't have a direct \
- correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
- It therefore feels safer to leave it panicking, but if you hit this panic \
- feel free to do the same as in `rustc_type_ir::RegionKind::ReBound` here."
- ),
- rustc_type_ir::RegionKind::ReLateParam(_) => unimplemented!(),
- rustc_type_ir::RegionKind::ReStatic => chalk_ir::LifetimeData::Static,
- rustc_type_ir::RegionKind::ReVar(vid) => {
- chalk_ir::LifetimeData::InferenceVar(chalk_ir::InferenceVar::from(vid.as_u32()))
- }
- rustc_type_ir::RegionKind::ReErased => chalk_ir::LifetimeData::Erased,
- rustc_type_ir::RegionKind::ReError(_) => chalk_ir::LifetimeData::Error,
- };
- chalk_ir::Lifetime::new(Interner, lifetime)
-}
-
-pub trait InferenceVarExt {
- fn to_vid(self) -> rustc_type_ir::TyVid;
- fn from_vid(vid: rustc_type_ir::TyVid) -> InferenceVar;
-}
-
-impl InferenceVarExt for InferenceVar {
- fn to_vid(self) -> rustc_type_ir::TyVid {
- rustc_type_ir::TyVid::from_u32(self.index())
- }
- fn from_vid(vid: rustc_type_ir::TyVid) -> InferenceVar {
- InferenceVar::from(vid.as_u32())
+impl<'db> ChalkToNextSolver<'db, crate::lower::ImplTraitIdx<'db>> for crate::ImplTraitIdx {
+ fn to_nextsolver(&self, _interner: DbInterner<'db>) -> crate::lower::ImplTraitIdx<'db> {
+ crate::lower::ImplTraitIdx::from_raw(self.into_raw())
}
}
diff --git a/crates/hir-ty/src/next_solver/predicate.rs b/crates/hir-ty/src/next_solver/predicate.rs
index 70b6f20ede..3438b755fb 100644
--- a/crates/hir-ty/src/next_solver/predicate.rs
+++ b/crates/hir-ty/src/next_solver/predicate.rs
@@ -13,7 +13,7 @@ use rustc_type_ir::{
};
use smallvec::SmallVec;
-use crate::next_solver::TraitIdWrapper;
+use crate::next_solver::{InternedWrapperNoDebug, TraitIdWrapper};
use super::{Binder, BoundVarKinds, DbInterner, Region, Ty, interned_vec_db};
@@ -171,9 +171,6 @@ impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for BoundExistentialPre
}
}
-#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
-pub struct InternedWrapperNoDebug<T>(pub(crate) T);
-
#[salsa::interned(constructor = new_)]
pub struct Predicate<'db> {
#[returns(ref)]
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index 8932f51978..7cf23b82f6 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -26,11 +26,11 @@ use rustc_type_ir::{
use crate::{
ImplTraitId,
db::HirDatabase,
- interner::InternedWrapperNoDebug,
next_solver::{
AdtDef, Binder, CallableIdWrapper, Clause, ClauseKind, ClosureIdWrapper, Const,
CoroutineIdWrapper, FnSig, GenericArg, PolyFnSig, Region, TraitRef, TypeAliasIdWrapper,
abi::Safety,
+ interner::InternedWrapperNoDebug,
mapping::ChalkToNextSolver,
util::{CoroutineArgsExt, IntegerTypeExt},
},
@@ -531,7 +531,7 @@ impl<'db> Ty<'db> {
TyKind::Alias(AliasTyKind::Opaque, opaque_ty) => {
match db.lookup_intern_impl_trait_id(opaque_ty.def_id.expect_opaque_ty()) {
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
- db.return_type_impl_traits_ns(func).map(|it| {
+ db.return_type_impl_traits(func).map(|it| {
let data = (*it).as_ref().map_bound(|rpit| {
&rpit.impl_traits[idx.to_nextsolver(interner)].predicates
});
@@ -540,7 +540,7 @@ impl<'db> Ty<'db> {
})
}
ImplTraitId::TypeAliasImplTrait(alias, idx) => {
- db.type_alias_impl_traits_ns(alias).map(|it| {
+ db.type_alias_impl_traits(alias).map(|it| {
let data = (*it).as_ref().map_bound(|rpit| {
&rpit.impl_traits[idx.to_nextsolver(interner)].predicates
});
@@ -575,7 +575,7 @@ impl<'db> Ty<'db> {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
TypeParamProvenance::ArgumentImplTrait => {
let predicates = db
- .generic_predicates_ns(param.id.parent())
+ .generic_predicates(param.id.parent())
.instantiate_identity()
.into_iter()
.flatten()
diff --git a/crates/hir-ty/src/next_solver/util.rs b/crates/hir-ty/src/next_solver/util.rs
index 97f5363058..bb0d0552c7 100644
--- a/crates/hir-ty/src/next_solver/util.rs
+++ b/crates/hir-ty/src/next_solver/util.rs
@@ -1,46 +1,42 @@
//! Various utilities for the next-trait-solver.
-use std::iter;
-use std::ops::{self, ControlFlow};
+use std::{
+ iter,
+ ops::{self, ControlFlow},
+};
use base_db::Crate;
-use hir_def::lang_item::LangItem;
-use hir_def::{BlockId, HasModule};
+use hir_def::{BlockId, HasModule, lang_item::LangItem};
use intern::sym;
use la_arena::Idx;
use rustc_abi::{Float, HasDataLayout, Integer, IntegerType, Primitive, ReprOptions};
-use rustc_type_ir::data_structures::IndexMap;
-use rustc_type_ir::inherent::{
- AdtDef, GenericArg as _, GenericArgs as _, ParamEnv as _, SliceLike, Ty as _,
-};
-use rustc_type_ir::lang_items::SolverTraitLangItem;
-use rustc_type_ir::solve::SizedTraitKind;
-use rustc_type_ir::{
- BoundVar, Canonical, DebruijnIndex, GenericArgKind, INNERMOST, Interner, PredicatePolarity,
- TypeVisitableExt,
-};
use rustc_type_ir::{
- ConstKind, CoroutineArgs, FloatTy, IntTy, RegionKind, TypeFolder, TypeSuperFoldable,
- TypeSuperVisitable, TypeVisitor, UintTy, UniverseIndex, inherent::IntoKind,
+ ConstKind, CoroutineArgs, DebruijnIndex, FloatTy, GenericArgKind, INNERMOST, IntTy, Interner,
+ PredicatePolarity, RegionKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
+ TypeVisitableExt, TypeVisitor, UintTy, UniverseIndex,
+ inherent::{
+ AdtDef, GenericArg as _, GenericArgs as _, IntoKind, ParamEnv as _, SliceLike, Ty as _,
+ },
+ lang_items::SolverTraitLangItem,
+ solve::SizedTraitKind,
};
-use rustc_type_ir::{InferCtxtLike, TypeFoldable};
-use crate::lower_nextsolver::{LifetimeElisionKind, TyLoweringContext};
-use crate::next_solver::infer::InferCtxt;
-use crate::next_solver::{
- BoundConst, FxIndexMap, ParamEnv, Placeholder, PlaceholderConst, PlaceholderRegion,
-};
use crate::{
db::HirDatabase,
+ lower::{LifetimeElisionKind, TyLoweringContext},
method_resolution::{TraitImpls, TyFingerprint},
+ next_solver::{
+ BoundConst, FxIndexMap, ParamEnv, Placeholder, PlaceholderConst, PlaceholderRegion,
+ infer::InferCtxt,
+ },
};
-use super::fold::{BoundVarReplacer, FnMutDelegate};
use super::{
AliasTerm, AliasTy, Binder, BoundRegion, BoundTy, BoundTyKind, BoundVarKind, BoundVarKinds,
- CanonicalVars, Clause, ClauseKind, Clauses, Const, DbInterner, EarlyBinder, GenericArg,
- GenericArgs, Predicate, PredicateKind, ProjectionPredicate, Region, SolverContext, SolverDefId,
- Term, TraitPredicate, TraitRef, Ty, TyKind,
+ Clause, ClauseKind, Clauses, Const, DbInterner, EarlyBinder, GenericArgs, Predicate,
+ PredicateKind, ProjectionPredicate, Region, SolverDefId, Term, TraitPredicate, TraitRef, Ty,
+ TyKind,
+ fold::{BoundVarReplacer, FnMutDelegate},
};
#[derive(Clone, Debug)]
@@ -510,151 +506,6 @@ pub fn apply_args_to_binder<'db, T: TypeFoldable<DbInterner<'db>>>(
b.skip_binder().fold_with(&mut instantiate)
}
-pub(crate) fn mini_canonicalize<'db, T: TypeFoldable<DbInterner<'db>>>(
- mut context: SolverContext<'db>,
- val: T,
-) -> Canonical<DbInterner<'db>, T> {
- let mut canon = MiniCanonicalizer {
- context: &mut context,
- db: DebruijnIndex::ZERO,
- vars: IndexMap::default(),
- };
- let canon_val = val.fold_with(&mut canon);
- let vars = canon.vars;
- Canonical {
- value: canon_val,
- max_universe: UniverseIndex::from_u32(1),
- variables: CanonicalVars::new_from_iter(
- context.cx(),
- vars.iter().enumerate().map(|(idx, (k, _v))| match (*k).kind() {
- GenericArgKind::Type(ty) => match ty.kind() {
- TyKind::Int(..) | TyKind::Uint(..) => rustc_type_ir::CanonicalVarKind::Int,
- TyKind::Float(..) => rustc_type_ir::CanonicalVarKind::Float,
- _ => rustc_type_ir::CanonicalVarKind::Ty {
- ui: UniverseIndex::ZERO,
- sub_root: BoundVar::from_usize(idx),
- },
- },
- GenericArgKind::Lifetime(_) => {
- rustc_type_ir::CanonicalVarKind::Region(UniverseIndex::ZERO)
- }
- GenericArgKind::Const(_) => {
- rustc_type_ir::CanonicalVarKind::Const(UniverseIndex::ZERO)
- }
- }),
- ),
- }
-}
-
-struct MiniCanonicalizer<'a, 'db> {
- context: &'a mut SolverContext<'db>,
- db: DebruijnIndex,
- vars: IndexMap<GenericArg<'db>, usize>,
-}
-
-impl<'db> TypeFolder<DbInterner<'db>> for MiniCanonicalizer<'_, 'db> {
- fn cx(&self) -> DbInterner<'db> {
- self.context.cx()
- }
-
- fn fold_binder<T: TypeFoldable<DbInterner<'db>>>(
- &mut self,
- t: rustc_type_ir::Binder<DbInterner<'db>, T>,
- ) -> rustc_type_ir::Binder<DbInterner<'db>, T> {
- self.db.shift_in(1);
- let res = t.map_bound(|t| t.fold_with(self));
- self.db.shift_out(1);
- res
- }
-
- fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
- match t.kind() {
- rustc_type_ir::TyKind::Bound(db, _) => {
- if db >= self.db {
- panic!("Unexpected bound var");
- }
- t
- }
- rustc_type_ir::TyKind::Infer(infer) => {
- let t = match infer {
- rustc_type_ir::InferTy::TyVar(vid) => {
- self.context.opportunistic_resolve_ty_var(vid)
- }
- rustc_type_ir::InferTy::IntVar(vid) => {
- self.context.opportunistic_resolve_int_var(vid)
- }
- rustc_type_ir::InferTy::FloatVar(vid) => {
- self.context.opportunistic_resolve_float_var(vid)
- }
- _ => t,
- };
- let len = self.vars.len();
- let var = *self.vars.entry(t.into()).or_insert(len);
- Ty::new(
- self.cx(),
- TyKind::Bound(
- self.db,
- BoundTy { kind: super::BoundTyKind::Anon, var: BoundVar::from_usize(var) },
- ),
- )
- }
- _ => t.super_fold_with(self),
- }
- }
-
- fn fold_region(
- &mut self,
- r: <DbInterner<'db> as rustc_type_ir::Interner>::Region,
- ) -> <DbInterner<'db> as rustc_type_ir::Interner>::Region {
- match r.kind() {
- RegionKind::ReBound(db, _) => {
- if db >= self.db {
- panic!("Unexpected bound var");
- }
- r
- }
- RegionKind::ReVar(_vid) => {
- let len = self.vars.len();
- let var = *self.vars.entry(r.into()).or_insert(len);
- Region::new(
- self.cx(),
- RegionKind::ReBound(
- self.db,
- BoundRegion {
- kind: super::BoundRegionKind::Anon,
- var: BoundVar::from_usize(var),
- },
- ),
- )
- }
- _ => r,
- }
- }
-
- fn fold_const(
- &mut self,
- c: <DbInterner<'db> as rustc_type_ir::Interner>::Const,
- ) -> <DbInterner<'db> as rustc_type_ir::Interner>::Const {
- match c.kind() {
- ConstKind::Bound(db, _) => {
- if db >= self.db {
- panic!("Unexpected bound var");
- }
- c
- }
- ConstKind::Infer(_infer) => {
- let len = self.vars.len();
- let var = *self.vars.entry(c.into()).or_insert(len);
- Const::new(
- self.cx(),
- ConstKind::Bound(self.db, BoundConst { var: BoundVar::from_usize(var) }),
- )
- }
- _ => c.super_fold_with(self),
- }
- }
-}
-
pub fn explicit_item_bounds<'db>(
interner: DbInterner<'db>,
def_id: SolverDefId,
@@ -713,7 +564,7 @@ pub fn explicit_item_bounds<'db>(
match full_id {
crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
let datas = db
- .return_type_impl_traits_ns(func)
+ .return_type_impl_traits(func)
.expect("impl trait id without impl traits");
let datas = (*datas).as_ref().skip_binder();
let data = &datas.impl_traits[Idx::from_raw(idx.into_raw())];
@@ -721,7 +572,7 @@ pub fn explicit_item_bounds<'db>(
}
crate::ImplTraitId::TypeAliasImplTrait(alias, idx) => {
let datas = db
- .type_alias_impl_traits_ns(alias)
+ .type_alias_impl_traits(alias)
.expect("impl trait id without impl traits");
let datas = (*datas).as_ref().skip_binder();
let data = &datas.impl_traits[Idx::from_raw(idx.into_raw())];
diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs
index 76cd5f7ab3..bc4701970c 100644
--- a/crates/hir-ty/src/tests/incremental.rs
+++ b/crates/hir-ty/src/tests/incremental.rs
@@ -44,7 +44,7 @@ fn foo() -> i32 {
"body_shim",
"body_with_source_map_shim",
"trait_environment_shim",
- "return_type_impl_traits_ns_shim",
+ "return_type_impl_traits_shim",
"expr_scopes_shim",
"lang_item",
"crate_lang_items",
@@ -131,7 +131,7 @@ fn baz() -> i32 {
"body_shim",
"body_with_source_map_shim",
"trait_environment_shim",
- "return_type_impl_traits_ns_shim",
+ "return_type_impl_traits_shim",
"expr_scopes_shim",
"lang_item",
"crate_lang_items",
@@ -143,7 +143,7 @@ fn baz() -> i32 {
"body_shim",
"body_with_source_map_shim",
"trait_environment_shim",
- "return_type_impl_traits_ns_shim",
+ "return_type_impl_traits_shim",
"expr_scopes_shim",
"infer_shim",
"function_signature_shim",
@@ -151,7 +151,7 @@ fn baz() -> i32 {
"body_shim",
"body_with_source_map_shim",
"trait_environment_shim",
- "return_type_impl_traits_ns_shim",
+ "return_type_impl_traits_shim",
"expr_scopes_shim",
]
"#]],
@@ -585,8 +585,8 @@ fn main() {
"crate_lang_items",
"attrs_shim",
"attrs_shim",
- "generic_predicates_ns_shim",
- "return_type_impl_traits_ns_shim",
+ "generic_predicates_shim",
+ "return_type_impl_traits_shim",
"infer_shim",
"function_signature_shim",
"function_signature_with_source_map_shim",
@@ -594,7 +594,7 @@ fn main() {
"expr_scopes_shim",
"struct_signature_shim",
"struct_signature_with_source_map_shim",
- "generic_predicates_ns_shim",
+ "generic_predicates_shim",
"value_ty_shim",
"VariantFields::firewall_",
"VariantFields::query_",
@@ -608,9 +608,9 @@ fn main() {
"trait_impls_in_crate_shim",
"impl_trait_with_diagnostics_shim",
"impl_self_ty_with_diagnostics_shim",
- "generic_predicates_ns_shim",
+ "generic_predicates_shim",
"value_ty_shim",
- "generic_predicates_ns_shim",
+ "generic_predicates_shim",
]
"#]],
);
@@ -682,13 +682,13 @@ fn main() {
"attrs_shim",
"attrs_shim",
"attrs_shim",
- "generic_predicates_ns_shim",
- "return_type_impl_traits_ns_shim",
+ "generic_predicates_shim",
+ "return_type_impl_traits_shim",
"infer_shim",
"function_signature_with_source_map_shim",
"expr_scopes_shim",
"struct_signature_with_source_map_shim",
- "generic_predicates_ns_shim",
+ "generic_predicates_shim",
"VariantFields::query_",
"inherent_impls_in_crate_shim",
"impl_signature_with_source_map_shim",
@@ -697,8 +697,8 @@ fn main() {
"trait_impls_in_crate_shim",
"impl_trait_with_diagnostics_shim",
"impl_self_ty_with_diagnostics_shim",
- "generic_predicates_ns_shim",
- "generic_predicates_ns_shim",
+ "generic_predicates_shim",
+ "generic_predicates_shim",
]
"#]],
);
diff --git a/crates/hir-ty/src/tls.rs b/crates/hir-ty/src/tls.rs
deleted file mode 100644
index fe4cf7a3da..0000000000
--- a/crates/hir-ty/src/tls.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-//! Implementation of Chalk debug helper functions using TLS.
-use std::fmt::{self, Display};
-
-use itertools::Itertools;
-use span::Edition;
-
-use crate::{
- CallableDefId, Interner, ProjectionTyExt, chalk_db, db::HirDatabase, from_assoc_type_id,
- from_chalk_trait_id, mapping::from_chalk,
-};
-use hir_def::{AdtId, ItemContainerId, Lookup, TypeAliasId};
-
-#[allow(unused)]
-pub(crate) use unsafe_tls::{set_current_program, with_current_program};
-
-pub(crate) struct DebugContext<'a>(&'a dyn HirDatabase);
-
-impl DebugContext<'_> {
- pub(crate) fn debug_struct_id(
- &self,
- id: chalk_db::AdtId,
- f: &mut fmt::Formatter<'_>,
- ) -> Result<(), fmt::Error> {
- let name = match id.0 {
- AdtId::StructId(it) => self.0.struct_signature(it).name.clone(),
- AdtId::UnionId(it) => self.0.union_signature(it).name.clone(),
- AdtId::EnumId(it) => self.0.enum_signature(it).name.clone(),
- };
- name.display(self.0, Edition::LATEST).fmt(f)?;
- Ok(())
- }
-
- pub(crate) fn debug_trait_id(
- &self,
- id: chalk_db::TraitId,
- f: &mut fmt::Formatter<'_>,
- ) -> Result<(), fmt::Error> {
- let trait_: hir_def::TraitId = from_chalk_trait_id(id);
- let trait_data = self.0.trait_signature(trait_);
- trait_data.name.display(self.0, Edition::LATEST).fmt(f)?;
- Ok(())
- }
-
- pub(crate) fn debug_assoc_type_id(
- &self,
- id: chalk_db::AssocTypeId,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Result<(), fmt::Error> {
- let type_alias: TypeAliasId = from_assoc_type_id(id);
- let type_alias_data = self.0.type_alias_signature(type_alias);
- let trait_ = match type_alias.lookup(self.0).container {
- ItemContainerId::TraitId(t) => t,
- _ => panic!("associated type not in trait"),
- };
- let trait_data = self.0.trait_signature(trait_);
- write!(
- fmt,
- "{}::{}",
- trait_data.name.display(self.0, Edition::LATEST),
- type_alias_data.name.display(self.0, Edition::LATEST)
- )?;
- Ok(())
- }
-
- pub(crate) fn debug_projection_ty(
- &self,
- projection_ty: &chalk_ir::ProjectionTy<Interner>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Result<(), fmt::Error> {
- let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
- let type_alias_data = self.0.type_alias_signature(type_alias);
- let trait_ = match type_alias.lookup(self.0).container {
- ItemContainerId::TraitId(t) => t,
- _ => panic!("associated type not in trait"),
- };
- let trait_name = &self.0.trait_signature(trait_).name;
- let trait_ref = projection_ty.trait_ref(self.0);
- let trait_params = trait_ref.substitution.as_slice(Interner);
- let self_ty = trait_ref.self_type_parameter(Interner);
- write!(fmt, "<{self_ty:?} as {}", trait_name.display(self.0, Edition::LATEST))?;
- if trait_params.len() > 1 {
- write!(
- fmt,
- "<{}>",
- trait_params[1..].iter().format_with(", ", |x, f| f(&format_args!("{x:?}"))),
- )?;
- }
- write!(fmt, ">::{}", type_alias_data.name.display(self.0, Edition::LATEST))?;
-
- let proj_params = &projection_ty.substitution.as_slice(Interner)[trait_params.len()..];
- if !proj_params.is_empty() {
- write!(
- fmt,
- "<{}>",
- proj_params.iter().format_with(", ", |x, f| f(&format_args!("{x:?}"))),
- )?;
- }
-
- Ok(())
- }
-
- pub(crate) fn debug_fn_def_id(
- &self,
- fn_def_id: chalk_ir::FnDefId<Interner>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Result<(), fmt::Error> {
- let def: CallableDefId = from_chalk(self.0, fn_def_id);
- let name = match def {
- CallableDefId::FunctionId(ff) => self.0.function_signature(ff).name.clone(),
- CallableDefId::StructId(s) => self.0.struct_signature(s).name.clone(),
- CallableDefId::EnumVariantId(e) => {
- let loc = e.lookup(self.0);
- loc.parent.enum_variants(self.0).variants[loc.index as usize].1.clone()
- }
- };
- match def {
- CallableDefId::FunctionId(_) => {
- write!(fmt, "{{fn {}}}", name.display(self.0, Edition::LATEST))
- }
- CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {
- write!(fmt, "{{ctor {}}}", name.display(self.0, Edition::LATEST))
- }
- }
- }
-}
-
-mod unsafe_tls {
- use super::DebugContext;
- use crate::db::HirDatabase;
- use scoped_tls::scoped_thread_local;
-
- scoped_thread_local!(static PROGRAM: DebugContext<'_>);
-
- pub(crate) fn with_current_program<R>(
- op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R,
- ) -> R {
- if PROGRAM.is_set() { PROGRAM.with(|prog| op(Some(prog))) } else { op(None) }
- }
-
- #[allow(dead_code)]
- pub(crate) fn set_current_program<OP, R>(p: &dyn HirDatabase, op: OP) -> R
- where
- OP: FnOnce() -> R,
- {
- let ctx = DebugContext(p);
- // we're transmuting the lifetime in the DebugContext to static. This is
- // fine because we only keep the reference for the lifetime of this
- // function, *and* the only way to access the context is through
- // `with_current_program`, which hides the lifetime through the `for`
- // type.
- let static_p: &DebugContext<'static> =
- unsafe { std::mem::transmute::<&DebugContext<'_>, &DebugContext<'static>>(&ctx) };
- PROGRAM.set(static_p, op)
- }
-}
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 35c8a197f5..7f6d4ff17f 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -3,33 +3,26 @@
use core::fmt;
use std::hash::Hash;
-use chalk_ir::{DebruijnIndex, GoalData, fold::TypeFoldable};
-
use base_db::Crate;
use hir_def::{BlockId, TraitId, lang_item::LangItem};
use hir_expand::name::Name;
use intern::sym;
use rustc_next_trait_solver::solve::{HasChanged, SolverDelegateEvalExt};
use rustc_type_ir::{
- InferCtxtLike, TypingMode,
- inherent::{IntoKind, SliceLike, Span as _},
+ TypingMode,
+ inherent::{IntoKind, Span as _},
solve::Certainty,
};
-use span::Edition;
use triomphe::Arc;
use crate::{
- AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTyExt,
- TraitRefExt, TyKind, WhereClause,
db::HirDatabase,
next_solver::{
- DbInterner, GenericArg, ParamEnv, Predicate, SolverContext, Span,
+ Canonical, DbInterner, GenericArgs, Goal, ParamEnv, Predicate, SolverContext, Span, Ty,
+ TyKind,
infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause},
- mapping::{ChalkToNextSolver, convert_canonical_args_for_result},
obligation_ctxt::ObligationCtxt,
- util::mini_canonicalize,
},
- utils::UnevaluatedConstEvaluatorFolder,
};
/// A set of clauses that we assume to be true. E.g. if we are inside this function:
@@ -42,7 +35,7 @@ pub struct TraitEnvironment<'db> {
pub krate: Crate,
pub block: Option<BlockId>,
// FIXME make this a BTreeMap
- traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>,
+ traits_from_clauses: Box<[(Ty<'db>, TraitId)]>,
pub env: ParamEnv<'db>,
}
@@ -59,7 +52,7 @@ impl<'db> TraitEnvironment<'db> {
pub fn new(
krate: Crate,
block: Option<BlockId>,
- traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>,
+ traits_from_clauses: Box<[(Ty<'db>, TraitId)]>,
env: ParamEnv<'db>,
) -> Arc<Self> {
Arc::new(TraitEnvironment { krate, block, traits_from_clauses, env })
@@ -70,10 +63,7 @@ impl<'db> TraitEnvironment<'db> {
Arc::make_mut(this).block = Some(block);
}
- pub fn traits_in_scope_from_clauses(
- &self,
- ty: crate::next_solver::Ty<'db>,
- ) -> impl Iterator<Item = TraitId> + '_ {
+ pub fn traits_in_scope_from_clauses(&self, ty: Ty<'db>) -> impl Iterator<Item = TraitId> + '_ {
self.traits_from_clauses
.iter()
.filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id))
@@ -83,92 +73,19 @@ impl<'db> TraitEnvironment<'db> {
/// This should be used in `hir` only.
pub fn structurally_normalize_ty<'db>(
infcx: &InferCtxt<'db>,
- ty: crate::next_solver::Ty<'db>,
+ ty: Ty<'db>,
env: Arc<TraitEnvironment<'db>>,
-) -> crate::next_solver::Ty<'db> {
- let crate::next_solver::TyKind::Alias(..) = ty.kind() else { return ty };
+) -> Ty<'db> {
+ let TyKind::Alias(..) = ty.kind() else { return ty };
let mut ocx = ObligationCtxt::new(infcx);
let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty);
ty.replace_infer_with_error(infcx.interner)
}
-fn identity_subst(
- binders: chalk_ir::CanonicalVarKinds<Interner>,
-) -> chalk_ir::Canonical<chalk_ir::Substitution<Interner>> {
- let identity_subst = chalk_ir::Substitution::from_iter(
- Interner,
- binders.iter(Interner).enumerate().map(|(index, c)| {
- let index_db = chalk_ir::BoundVar::new(DebruijnIndex::INNERMOST, index);
- match &c.kind {
- chalk_ir::VariableKind::Ty(_) => {
- chalk_ir::GenericArgData::Ty(TyKind::BoundVar(index_db).intern(Interner))
- .intern(Interner)
- }
- chalk_ir::VariableKind::Lifetime => chalk_ir::GenericArgData::Lifetime(
- chalk_ir::LifetimeData::BoundVar(index_db).intern(Interner),
- )
- .intern(Interner),
- chalk_ir::VariableKind::Const(ty) => chalk_ir::GenericArgData::Const(
- chalk_ir::ConstData {
- ty: ty.clone(),
- value: chalk_ir::ConstValue::BoundVar(index_db),
- }
- .intern(Interner),
- )
- .intern(Interner),
- }
- }),
- );
- chalk_ir::Canonical { binders, value: identity_subst }
-}
-
-fn solve_nextsolver<'db>(
- db: &'db dyn HirDatabase,
- krate: Crate,
- block: Option<BlockId>,
- goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>>,
-) -> Result<
- (HasChanged, Certainty, rustc_type_ir::Canonical<DbInterner<'db>, Vec<GenericArg<'db>>>),
- rustc_type_ir::solve::NoSolution,
-> {
- // FIXME: should use analysis_in_body, but that needs GenericDefId::Block
- let context = SolverContext(
- DbInterner::new_with(db, Some(krate), block)
- .infer_ctxt()
- .build(TypingMode::non_body_analysis()),
- );
-
- match goal.canonical.value.goal.data(Interner) {
- // FIXME: args here should be...what? not empty
- GoalData::All(goals) if goals.is_empty(Interner) => {
- return Ok((HasChanged::No, Certainty::Yes, mini_canonicalize(context, vec![])));
- }
- _ => {}
- }
-
- let goal = goal.canonical.to_nextsolver(context.cx());
- tracing::info!(?goal);
-
- let (goal, var_values) = context.instantiate_canonical(&goal);
- tracing::info!(?var_values);
-
- let res = context.evaluate_root_goal(goal, Span::dummy(), None);
-
- let vars =
- var_values.var_values.iter().map(|g| context.0.resolve_vars_if_possible(g)).collect();
- let canonical_var_values = mini_canonicalize(context, vars);
-
- let res = res.map(|r| (r.has_changed, r.certainty, canonical_var_values));
-
- tracing::debug!("solve_nextsolver({:?}) => {:?}", goal, res);
-
- res
-}
-
#[derive(Clone, Debug, PartialEq)]
pub enum NextTraitSolveResult {
- Certain(chalk_ir::Canonical<chalk_ir::ConstrainedSubst<Interner>>),
- Uncertain(chalk_ir::Canonical<chalk_ir::Substitution<Interner>>),
+ Certain,
+ Uncertain,
NoSolution,
}
@@ -178,75 +95,17 @@ impl NextTraitSolveResult {
}
pub fn certain(&self) -> bool {
- matches!(self, NextTraitSolveResult::Certain(..))
+ matches!(self, NextTraitSolveResult::Certain)
}
pub fn uncertain(&self) -> bool {
- matches!(self, NextTraitSolveResult::Uncertain(..))
- }
-}
-
-pub fn next_trait_solve(
- db: &dyn HirDatabase,
- krate: Crate,
- block: Option<BlockId>,
- goal: Canonical<InEnvironment<Goal>>,
-) -> NextTraitSolveResult {
- let detail = match &goal.value.goal.data(Interner) {
- GoalData::DomainGoal(DomainGoal::Holds(WhereClause::Implemented(it))) => {
- db.trait_signature(it.hir_trait_id()).name.display(db, Edition::LATEST).to_string()
- }
- GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(_))) => "alias_eq".to_owned(),
- _ => "??".to_owned(),
- };
- let _p = tracing::info_span!("next_trait_solve", ?detail).entered();
- tracing::info!("next_trait_solve({:?})", goal.value.goal);
-
- if let GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
- alias: AliasTy::Projection(projection_ty),
- ..
- }))) = &goal.value.goal.data(Interner)
- && let TyKind::BoundVar(_) = projection_ty.self_type_parameter(db).kind(Interner)
- {
- // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
- // FIXME
- return NextTraitSolveResult::Uncertain(identity_subst(goal.binders.clone()));
- }
-
- // Chalk see `UnevaluatedConst` as a unique concrete value, but we see it as an alias for another const. So
- // we should get rid of it when talking to chalk.
- let goal = goal
- .try_fold_with(&mut UnevaluatedConstEvaluatorFolder { db }, DebruijnIndex::INNERMOST)
- .unwrap();
-
- // We currently don't deal with universes (I think / hope they're not yet
- // relevant for our use cases?)
- let u_canonical = chalk_ir::UCanonical { canonical: goal, universes: 1 };
- tracing::info!(?u_canonical);
-
- let next_solver_res = solve_nextsolver(db, krate, block, &u_canonical);
-
- match next_solver_res {
- Err(_) => NextTraitSolveResult::NoSolution,
- Ok((_, Certainty::Yes, args)) => NextTraitSolveResult::Certain(
- convert_canonical_args_for_result(DbInterner::new_with(db, Some(krate), block), args),
- ),
- Ok((_, Certainty::Maybe { .. }, args)) => {
- let subst = convert_canonical_args_for_result(
- DbInterner::new_with(db, Some(krate), block),
- args,
- );
- NextTraitSolveResult::Uncertain(chalk_ir::Canonical {
- binders: subst.binders,
- value: subst.value.subst,
- })
- }
+ matches!(self, NextTraitSolveResult::Uncertain)
}
}
pub fn next_trait_solve_canonical_in_ctxt<'db>(
infer_ctxt: &InferCtxt<'db>,
- goal: crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, Predicate<'db>>>,
+ goal: Canonical<'db, Goal<'db, Predicate<'db>>>,
) -> NextTraitSolveResult {
let context = SolverContext(infer_ctxt.clone());
@@ -257,33 +116,21 @@ pub fn next_trait_solve_canonical_in_ctxt<'db>(
let res = context.evaluate_root_goal(goal, Span::dummy(), None);
- let vars =
- var_values.var_values.iter().map(|g| context.0.resolve_vars_if_possible(g)).collect();
- let canonical_var_values = mini_canonicalize(context, vars);
-
- let res = res.map(|r| (r.has_changed, r.certainty, canonical_var_values));
+ let res = res.map(|r| (r.has_changed, r.certainty));
tracing::debug!("solve_nextsolver({:?}) => {:?}", goal, res);
match res {
Err(_) => NextTraitSolveResult::NoSolution,
- Ok((_, Certainty::Yes, args)) => NextTraitSolveResult::Certain(
- convert_canonical_args_for_result(infer_ctxt.interner, args),
- ),
- Ok((_, Certainty::Maybe { .. }, args)) => {
- let subst = convert_canonical_args_for_result(infer_ctxt.interner, args);
- NextTraitSolveResult::Uncertain(chalk_ir::Canonical {
- binders: subst.binders,
- value: subst.value.subst,
- })
- }
+ Ok((_, Certainty::Yes)) => NextTraitSolveResult::Certain,
+ Ok((_, Certainty::Maybe { .. })) => NextTraitSolveResult::Uncertain,
}
}
/// Solve a trait goal using next trait solver.
pub fn next_trait_solve_in_ctxt<'db, 'a>(
infer_ctxt: &'a InferCtxt<'db>,
- goal: crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>,
+ goal: Goal<'db, Predicate<'db>>,
) -> Result<(HasChanged, Certainty), rustc_type_ir::solve::NoSolution> {
tracing::info!(?goal);
@@ -377,7 +224,7 @@ impl FnTrait {
/// This should not be used in `hir-ty`, only in `hir`.
pub fn implements_trait_unique<'db>(
- ty: crate::next_solver::Ty<'db>,
+ ty: Ty<'db>,
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
trait_: TraitId,
@@ -392,7 +239,7 @@ pub fn implements_trait_unique_with_args<'db>(
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
trait_: TraitId,
- args: crate::next_solver::GenericArgs<'db>,
+ args: GenericArgs<'db>,
) -> bool {
implements_trait_unique_impl(db, env, trait_, &mut |_| args)
}
@@ -401,7 +248,7 @@ fn implements_trait_unique_impl<'db>(
db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment<'db>>,
trait_: TraitId,
- create_args: &mut dyn FnMut(&InferCtxt<'db>) -> crate::next_solver::GenericArgs<'db>,
+ create_args: &mut dyn FnMut(&InferCtxt<'db>) -> GenericArgs<'db>,
) -> bool {
let interner = DbInterner::new_with(db, Some(env.krate), env.block);
// FIXME(next-solver): I believe this should be `PostAnalysis`.
@@ -409,7 +256,7 @@ fn implements_trait_unique_impl<'db>(
let args = create_args(&infcx);
let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args);
- let goal = crate::next_solver::Goal::new(interner, env.env, trait_ref);
+ let goal = Goal::new(interner, env.env, trait_ref);
let result = crate::traits::next_trait_solve_in_ctxt(&infcx, goal);
matches!(result, Ok((_, Certainty::Yes)))
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 15359922c8..ca5e33fe6a 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -1,40 +1,30 @@
//! Helper functions for working with def, which don't need to be a separate
//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
-use std::{cell::LazyCell, iter};
+use std::cell::LazyCell;
use base_db::{
Crate,
target::{self, TargetData},
};
-use chalk_ir::{DebruijnIndex, fold::FallibleTypeFolder};
use hir_def::{
- EnumId, EnumVariantId, FunctionId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId,
+ EnumId, EnumVariantId, FunctionId, Lookup, TraitId,
db::DefDatabase,
hir::generics::WherePredicate,
lang_item::LangItem,
resolver::{HasResolver, TypeNs},
type_ref::{TraitBoundModifier, TypeRef},
};
-use hir_expand::name::Name;
use intern::sym;
use rustc_abi::TargetDataLayout;
-use rustc_hash::FxHashSet;
-use rustc_type_ir::inherent::{IntoKind, SliceLike};
use smallvec::{SmallVec, smallvec};
use span::Edition;
use crate::{
- ChalkTraitId, Const, ConstScalar, Interner, TargetFeatures, TraitRef, TraitRefExt,
- consteval::unknown_const,
+ TargetFeatures,
db::HirDatabase,
layout::{Layout, TagEncoding},
mir::pad16,
- next_solver::{
- DbInterner,
- mapping::{ChalkToNextSolver, NextSolverToChalk, convert_args_for_result},
- },
- to_chalk_trait_id,
};
pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator<Item = TraitId> + '_ {
@@ -75,49 +65,6 @@ pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[Trai
result
}
-/// Given a trait ref (`Self: Trait`), builds all the implied trait refs for
-/// super traits. The original trait ref will be included. So the difference to
-/// `all_super_traits` is that we keep track of type parameters; for example if
-/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
-/// `Self: OtherTrait<i32>`.
-pub(super) fn all_super_trait_refs<T>(
- db: &dyn HirDatabase,
- trait_ref: TraitRef,
- cb: impl FnMut(TraitRef) -> Option<T>,
-) -> Option<T> {
- let seen = iter::once(trait_ref.trait_id).collect();
- SuperTraits { db, seen, stack: vec![trait_ref] }.find_map(cb)
-}
-
-struct SuperTraits<'a> {
- db: &'a dyn HirDatabase,
- stack: Vec<TraitRef>,
- seen: FxHashSet<ChalkTraitId>,
-}
-
-impl SuperTraits<'_> {
- fn elaborate(&mut self, trait_ref: &TraitRef) {
- direct_super_trait_refs(self.db, trait_ref, |trait_ref| {
- if !self.seen.contains(&trait_ref.trait_id) {
- self.stack.push(trait_ref);
- }
- });
- }
-}
-
-impl Iterator for SuperTraits<'_> {
- type Item = TraitRef;
-
- fn next(&mut self) -> Option<Self::Item> {
- if let Some(next) = self.stack.pop() {
- self.elaborate(&next);
- Some(next)
- } else {
- None
- }
- }
-}
-
fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
let resolver = LazyCell::new(|| trait_.resolver(db));
let (generic_params, store) = db.generic_params_and_store(trait_.into());
@@ -148,49 +95,6 @@ fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(
.for_each(cb);
}
-fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef, cb: impl FnMut(TraitRef)) {
- let interner = DbInterner::new_with(db, None, None);
- let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
- let trait_self = match generic_params.trait_self_param() {
- Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p },
- None => return,
- };
- let trait_ref_args: crate::next_solver::GenericArgs<'_> =
- trait_ref.substitution.to_nextsolver(interner);
- db.generic_predicates_for_param_ns(trait_self.parent, trait_self, None)
- .iter()
- .filter_map(|pred| {
- let pred = pred.kind();
- // FIXME: how to correctly handle higher-ranked bounds here?
- let pred = pred.no_bound_vars().expect("FIXME unexpected higher-ranked trait bound");
- match pred {
- rustc_type_ir::ClauseKind::Trait(t) => {
- let t =
- rustc_type_ir::EarlyBinder::bind(t).instantiate(interner, trait_ref_args);
- let trait_id = to_chalk_trait_id(t.def_id().0);
-
- let substitution =
- convert_args_for_result(interner, t.trait_ref.args.as_slice());
- let tr = chalk_ir::TraitRef { trait_id, substitution };
- Some(tr)
- }
- _ => None,
- }
- })
- .for_each(cb);
-}
-
-pub(super) fn associated_type_by_name_including_super_traits(
- db: &dyn HirDatabase,
- trait_ref: TraitRef,
- name: &Name,
-) -> Option<(TraitRef, TypeAliasId)> {
- all_super_trait_refs(db, trait_ref, |t| {
- let assoc_type = t.hir_trait_id().trait_items(db).associated_type_by_name(name)?;
- Some((t, assoc_type))
- })
-}
-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Unsafety {
Safe,
@@ -263,41 +167,6 @@ pub fn is_fn_unsafe_to_call(
}
}
-pub(crate) struct UnevaluatedConstEvaluatorFolder<'a> {
- pub(crate) db: &'a dyn HirDatabase,
-}
-
-impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
- type Error = ();
-
- fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = ()> {
- self
- }
-
- fn interner(&self) -> Interner {
- Interner
- }
-
- fn try_fold_const(
- &mut self,
- constant: Const,
- _outer_binder: DebruijnIndex,
- ) -> Result<Const, Self::Error> {
- if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value
- && let ConstScalar::UnevaluatedConst(id, subst) = &c.interned
- {
- let interner = DbInterner::conjure();
- if let Ok(eval) = self.db.const_eval(*id, subst.to_nextsolver(interner), None) {
- return Ok(eval.to_chalk(interner));
- } else {
- return Ok(unknown_const(constant.data(Interner).ty.to_nextsolver(interner))
- .to_chalk(interner));
- }
- }
- Ok(constant)
- }
-}
-
pub(crate) fn detect_variant_from_bytes<'a>(
layout: &'a Layout,
db: &dyn HirDatabase,
diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs
index 46898ddeec..b57bf03f24 100644
--- a/crates/hir-ty/src/variance.rs
+++ b/crates/hir-ty/src/variance.rs
@@ -128,7 +128,7 @@ impl<'db> Context<'db> {
GenericDefId::AdtId(adt) => {
let db = self.db;
let mut add_constraints_from_variant = |variant| {
- for (_, field) in db.field_types_ns(variant).iter() {
+ for (_, field) in db.field_types(variant).iter() {
self.add_constraints_from_ty(
field.instantiate_identity(),
Variance::Covariant,
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index b31bb248e8..d61c2eca83 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -484,7 +484,7 @@ impl<'db> HirDisplay<'db> for TypeParam {
let param_data = &params[self.id.local_id()];
let krate = self.id.parent().krate(f.db).id;
let ty = self.ty(f.db).ty;
- let predicates = f.db.generic_predicates_ns(self.id.parent());
+ let predicates = f.db.generic_predicates(self.id.parent());
let predicates = predicates
.instantiate_identity()
.into_iter()
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 78b4533a94..48eafb0bd4 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1271,7 +1271,7 @@ impl<'db> InstantiatedField<'db> {
let interner = DbInterner::new_with(db, Some(krate.base()), None);
let var_id = self.inner.parent.into();
- let field = db.field_types_ns(var_id)[self.inner.id];
+ let field = db.field_types(var_id)[self.inner.id];
let ty = field.instantiate(interner, self.args);
TypeNs::new(db, var_id, ty)
}
@@ -1350,7 +1350,7 @@ impl Field {
/// context of the field definition.
pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
let var_id = self.parent.into();
- let ty = db.field_types_ns(var_id)[self.id].skip_binder();
+ let ty = db.field_types(var_id)[self.id].skip_binder();
TypeNs::new(db, var_id, ty)
}
@@ -1368,7 +1368,7 @@ impl Field {
};
let interner = DbInterner::new_with(db, None, None);
let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty));
- let ty = db.field_types_ns(var_id)[self.id].instantiate(interner, args);
+ let ty = db.field_types(var_id)[self.id].instantiate(interner, args);
Type::new(db, var_id, ty)
}
@@ -3693,7 +3693,7 @@ impl GenericDef {
};
expr_store_diagnostics(db, acc, &source_map);
- push_ty_diagnostics(db, acc, db.generic_defaults_ns_with_diagnostics(def).1, &source_map);
+ push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, &source_map);
push_ty_diagnostics(
db,
acc,
@@ -4192,7 +4192,7 @@ impl TypeParam {
/// parameter, not additional bounds that might be added e.g. by a method if
/// the parameter comes from an impl!
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
- db.generic_predicates_for_param_ns(self.id.parent(), self.id.into(), None)
+ db.generic_predicates_for_param(self.id.parent(), self.id.into(), None)
.iter()
.filter_map(|pred| match &pred.kind().skip_binder() {
ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)),
@@ -4282,7 +4282,7 @@ impl ConstParam {
fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> {
let local_idx = hir_ty::param_idx(db, id)?;
- let defaults = db.generic_defaults_ns(id.parent);
+ let defaults = db.generic_defaults(id.parent);
let ty = defaults.get(local_idx)?;
// FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
Some(ty.instantiate_identity())
@@ -4883,7 +4883,7 @@ impl<'db> Type<'db> {
if variant_data.fields().is_empty() {
vec![]
} else {
- let field_types = self.interner.db().field_types_ns(id);
+ let field_types = self.interner.db().field_types(id);
variant_data
.fields()
.iter()
@@ -5216,7 +5216,7 @@ impl<'db> Type<'db> {
_ => return Vec::new(),
};
- db.field_types_ns(variant_id)
+ db.field_types(variant_id)
.iter()
.map(|(local_id, ty)| {
let def = Field { parent: variant_id.into(), id: local_id };
@@ -6450,7 +6450,7 @@ fn generic_args_from_tys<'db>(
fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool {
let params = db.generic_params(generic_def);
- let defaults = db.generic_defaults_ns(generic_def);
+ let defaults = db.generic_defaults(generic_def);
params
.iter_type_or_consts()
.filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_)))
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 8d2ba7e604..15eab14b88 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -712,8 +712,7 @@ impl<'db> SourceAnalyzer<'db> {
let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?;
let variant_data = variant.fields(db);
let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
- let field_ty =
- (*db.field_types_ns(variant).get(field.local_id)?).instantiate(interner, subst);
+ let field_ty = (*db.field_types(variant).get(field.local_id)?).instantiate(interner, subst);
Some((
field.into(),
local,
@@ -735,8 +734,7 @@ impl<'db> SourceAnalyzer<'db> {
let variant_data = variant.fields(db);
let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
let (adt, subst) = self.infer()?[pat_id.as_pat()?].as_adt()?;
- let field_ty =
- (*db.field_types_ns(variant).get(field.local_id)?).instantiate(interner, subst);
+ let field_ty = (*db.field_types(variant).get(field.local_id)?).instantiate(interner, subst);
Some((
field.into(),
Type::new_with_resolver(db, &self.resolver, field_ty),
@@ -802,7 +800,7 @@ impl<'db> SourceAnalyzer<'db> {
|variant: VariantId, subst: GenericArgs<'db>, container: &mut _| {
let fields = variant.fields(db);
let field = fields.field(&field_name.as_name())?;
- let field_types = db.field_types_ns(variant);
+ let field_types = db.field_types(variant);
*container = Either::Right(field_types[field].instantiate(interner, subst));
let generic_def = match variant {
VariantId::EnumVariantId(it) => it.loc(db).parent.into(),
@@ -1255,7 +1253,7 @@ impl<'db> SourceAnalyzer<'db> {
missing_fields: Vec<LocalFieldId>,
) -> Vec<(Field, Type<'db>)> {
let interner = DbInterner::new_with(db, None, None);
- let field_types = db.field_types_ns(variant);
+ let field_types = db.field_types(variant);
missing_fields
.into_iter()
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index df3dc53f7c..91fb4d0a67 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -9393,7 +9393,7 @@ fn main(a$0: T) {}
*a*
```rust
- a: T<T>
+ a: T
```
---